Changeset 10862 in josm for trunk/src/com/drew/imaging
- Timestamp:
- 2016-08-20T20:58:03+02:00 (8 years ago)
- Location:
- trunk/src/com/drew/imaging
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/com/drew/imaging/ImageProcessingException.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/PhotographicConversions.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/jpeg/JpegMetadataReader.java
r8243 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 39 39 import com.drew.metadata.iptc.IptcReader; 40 40 //import com.drew.metadata.jfif.JfifReader; 41 //import com.drew.metadata.jfxx.JfxxReader; 41 42 import com.drew.metadata.jpeg.JpegCommentReader; 42 43 import com.drew.metadata.jpeg.JpegReader; 44 //import com.drew.metadata.photoshop.DuckyReader; 43 45 //import com.drew.metadata.photoshop.PhotoshopReader; 44 46 //import com.drew.metadata.xmp.XmpReader; … … 55 57 new JpegCommentReader(), 56 58 //new JfifReader(), 59 //new JfxxReader(), 57 60 new ExifReader(), 58 61 //new XmpReader(), 59 62 //new IccReader(), 60 63 //new PhotoshopReader(), 64 //new DuckyReader(), 61 65 new IptcReader()//, 62 66 //new AdobeJpegReader() -
trunk/src/com/drew/imaging/jpeg/JpegProcessingException.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/jpeg/JpegSegmentData.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 52 52 * @param segmentBytes the byte array holding data for the segment being added 53 53 */ 54 @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})55 54 public void addSegment(byte segmentType, @NotNull byte[] segmentBytes) 56 55 { … … 207 206 * @param occurrence the zero-based index of the segment occurrence to remove. 208 207 */ 209 @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})210 208 public void removeSegmentOccurrence(@NotNull JpegSegmentType segmentType, int occurrence) 211 209 { … … 220 218 * @param occurrence the zero-based index of the segment occurrence to remove. 221 219 */ 222 @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})223 220 public void removeSegmentOccurrence(byte segmentType, int occurrence) 224 221 { -
trunk/src/com/drew/imaging/jpeg/JpegSegmentReader.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 43 43 public class JpegSegmentReader 44 44 { 45 /** 46 * The 0xFF byte that signals the start of a segment. 47 */ 48 private static final byte SEGMENT_IDENTIFIER = (byte) 0xFF; 49 45 50 /** 46 51 * Private, because this segment crashes my algorithm, and searching for it doesn't work (yet). … … 112 117 // by a 0xFF and then a byte not equal to 0x00 or 0xFF. 113 118 114 final short segmentIdentifier = reader.getUInt8(); 119 byte segmentIdentifier = reader.getInt8(); 120 byte segmentType = reader.getInt8(); 115 121 116 // We must have at least one 0xFF byte 117 if (segmentIdentifier != 0xFF) 118 throw new JpegProcessingException("Expected JPEG segment start identifier 0xFF, not 0x" + Integer.toHexString(segmentIdentifier).toUpperCase()); 119 120 // Read until we have a non-0xFF byte. This identifies the segment type. 121 byte segmentType = reader.getInt8(); 122 while (segmentType == (byte)0xFF) 123 segmentType = reader.getInt8(); 124 125 if (segmentType == 0) 126 throw new JpegProcessingException("Expected non-zero byte as part of JPEG marker identifier"); 122 // Read until we have a 0xFF byte followed by a byte that is not 0xFF or 0x00 123 while (segmentIdentifier != SEGMENT_IDENTIFIER || segmentType == SEGMENT_IDENTIFIER || segmentType == 0) { 124 segmentIdentifier = segmentType; 125 segmentType = reader.getInt8(); 126 } 127 127 128 128 if (segmentType == SEGMENT_SOS) { -
trunk/src/com/drew/imaging/jpeg/JpegSegmentType.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 30 30 * An enumeration of the known segment types found in JPEG files. 31 31 * 32 * <ul> 33 * <li>http://www.ozhiker.com/electronics/pjmt/jpeg_info/app_segments.html</li> 34 * <li>http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html</li> 35 * </ul> 36 * 32 37 * @author Drew Noakes https://drewnoakes.com 33 38 */ 34 39 public enum JpegSegmentType 35 40 { 36 /** APP0 JPEG segment identifier -- JFIF data (also JFXX apparently). */41 /** APP0 JPEG segment identifier. Commonly contains JFIF, JFXX. */ 37 42 APP0((byte)0xE0, true), 38 43 39 /** APP1 JPEG segment identifier -- where Exif data is kept.XMP data is also kept in here, though usually in a second instance. */44 /** APP1 JPEG segment identifier. Commonly contains Exif. XMP data is also kept in here, though usually in a second instance. */ 40 45 APP1((byte)0xE1, true), 41 46 42 /** APP2 JPEG segment identifier. */47 /** APP2 JPEG segment identifier. Commonly contains ICC. */ 43 48 APP2((byte)0xE2, true), 44 49 … … 64 69 APP9((byte)0xE9, true), 65 70 66 /** APPA (App10) JPEG segment identifier -- can hold Unicodecomments. */71 /** APPA (App10) JPEG segment identifier. Can contain Unicode comments, though {@link JpegSegmentType#COM} is more commonly used for comments. */ 67 72 APPA((byte)0xEA, true), 68 73 … … 73 78 APPC((byte)0xEC, true), 74 79 75 /** APPD (App13) JPEG segment identifier -- IPTC data in here. */80 /** APPD (App13) JPEG segment identifier. Commonly contains IPTC, Photoshop data. */ 76 81 APPD((byte)0xED, true), 77 82 78 /** APPE (App14) JPEG segment identifier. */83 /** APPE (App14) JPEG segment identifier. Commonly contains Adobe data. */ 79 84 APPE((byte)0xEE, true), 80 85 -
trunk/src/com/drew/imaging/jpeg/package.html
r8132 r10862 1 1 <!-- 2 ~ Copyright 2002-201 5Drew Noakes2 ~ Copyright 2002-2016 Drew Noakes 3 3 ~ 4 4 ~ Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/package.html
r8132 r10862 1 1 <!-- 2 ~ Copyright 2002-201 5Drew Noakes2 ~ Copyright 2002-2016 Drew Noakes 3 3 ~ 4 4 ~ Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/tiff/TiffDataFormat.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/tiff/TiffHandler.java
r8243 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 24 24 import com.drew.lang.Rational; 25 25 import com.drew.lang.annotations.NotNull; 26 import com.drew.lang.annotations.Nullable; 26 27 27 28 import java.io.IOException; … … 46 47 void setTiffMarker(int marker) throws TiffProcessingException; 47 48 48 boolean isTagIfdPointer(int tagType);49 boolean tryEnterSubIfd(int tagId); 49 50 boolean hasFollowerIfd(); 50 51 … … 52 53 53 54 void completed(@NotNull final RandomAccessReader reader, final int tiffHeaderOffset); 55 56 @Nullable 57 Long tryCustomProcessFormat(int tagId, int formatCode, long componentCount); 54 58 55 59 boolean customProcessTag(int tagOffset, -
trunk/src/com/drew/imaging/tiff/TiffProcessingException.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); -
trunk/src/com/drew/imaging/tiff/TiffReader.java
r8132 r10862 1 1 /* 2 * Copyright 2002-201 5Drew Noakes2 * Copyright 2002-2016 Drew Noakes 3 3 * 4 4 * Licensed under the Apache License, Version 2.0 (the "License"); … … 110 110 final int tiffHeaderOffset) throws IOException 111 111 { 112 Boolean resetByteOrder = null; 112 113 try { 113 114 // check for directories we've already visited to avoid stack overflows when recursive/cyclic directory structures exist … … 126 127 // First two bytes in the IFD are the number of tags in this directory 127 128 int dirTagCount = reader.getUInt16(ifdOffset); 129 130 // Some software modifies the byte order of the file, but misses some IFDs (such as makernotes). 131 // The entire test image repository doesn't contain a single IFD with more than 255 entries. 132 // Here we detect switched bytes that suggest this problem, and temporarily swap the byte order. 133 // This was discussed in GitHub issue #136. 134 if (dirTagCount > 0xFF && (dirTagCount & 0xFF) == 0) { 135 resetByteOrder = reader.isMotorolaByteOrder(); 136 dirTagCount >>= 8; 137 reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder()); 138 } 128 139 129 140 int dirLength = (2 + (12 * dirTagCount) + 4); … … 147 158 final TiffDataFormat format = TiffDataFormat.fromTiffFormatCode(formatCode); 148 159 160 // 4 bytes dictate the number of components in this tag's data 161 final long componentCount = reader.getUInt32(tagOffset + 4); 162 163 final long byteCount; 149 164 if (format == null) { 150 // This error suggests that we are processing at an incorrect index and will generate 151 // rubbish until we go out of bounds (which may be a while). Exit now. 152 handler.error("Invalid TIFF tag format code: " + formatCode); 153 // TODO specify threshold as a parameter, or provide some other external control over this behaviour 154 if (++invalidTiffFormatCodeCount > 5) { 155 handler.error("Stopping processing as too many errors seen in TIFF IFD"); 156 return; 165 Long byteCountOverride = handler.tryCustomProcessFormat(tagId, formatCode, componentCount); 166 if (byteCountOverride == null) { 167 // This error suggests that we are processing at an incorrect index and will generate 168 // rubbish until we go out of bounds (which may be a while). Exit now. 169 handler.error(String.format("Invalid TIFF tag format code %d for tag 0x%04X", formatCode, tagId)); 170 // TODO specify threshold as a parameter, or provide some other external control over this behaviour 171 if (++invalidTiffFormatCodeCount > 5) { 172 handler.error("Stopping processing as too many errors seen in TIFF IFD"); 173 return; 174 } 175 continue; 157 176 } 158 continue; 159 } 160 161 // 4 bytes dictate the number of components in this tag's data 162 final int componentCount = reader.getInt32(tagOffset + 4); 163 if (componentCount < 0) { 164 handler.error("Negative TIFF tag component count"); 165 continue; 166 } 167 168 final int byteCount = componentCount * format.getComponentSizeBytes(); 169 170 final int tagValueOffset; 177 byteCount = byteCountOverride; 178 } else { 179 byteCount = componentCount * format.getComponentSizeBytes(); 180 } 181 182 final long tagValueOffset; 171 183 if (byteCount > 4) { 172 184 // If it's bigger than 4 bytes, the dir entry contains an offset. 173 final int offsetVal = reader.getInt32(tagOffset + 8);185 final long offsetVal = reader.getUInt32(tagOffset + 8); 174 186 if (offsetVal + byteCount > reader.getLength()) { 175 187 // Bogus pointer offset and / or byteCount value … … 195 207 } 196 208 197 // 198 // Special handling for tags that point to other IFDs199 //200 if (byteCount == 4 && handler.isTagIfdPointer(tagId)) {201 final int subDirOffset = tiffHeaderOffset + reader.getInt32(tagValueOffset);202 processIfd(handler, reader, processedIfdOffsets, subDirOffset, tiffHeaderOffset);203 } else {204 if (!handler.customProcessTag(tagValueOffset, processedIfdOffsets, tiffHeaderOffset, reader, tagId, byteCount)) {205 processTag(handler, tagId, tagValueOffset, componentCount, formatCode, reader);209 // Some tags point to one or more additional IFDs to process 210 boolean isIfdPointer = false; 211 if (byteCount == 4 * componentCount) { 212 for (int i = 0; i < componentCount; i++) { 213 if (handler.tryEnterSubIfd(tagId)) { 214 isIfdPointer = true; 215 int subDirOffset = tiffHeaderOffset + reader.getInt32((int) (tagValueOffset + i * 4)); 216 processIfd(handler, reader, processedIfdOffsets, subDirOffset, tiffHeaderOffset); 217 } 206 218 } 219 } 220 221 // If it wasn't an IFD pointer, allow custom tag processing to occur 222 if (!isIfdPointer && !handler.customProcessTag((int) tagValueOffset, processedIfdOffsets, tiffHeaderOffset, reader, tagId, (int) byteCount)) { 223 // If no custom processing occurred, process the tag in the standard fashion 224 processTag(handler, tagId, (int) tagValueOffset, (int) componentCount, formatCode, reader); 207 225 } 208 226 } … … 229 247 } finally { 230 248 handler.endingIFD(); 249 if (resetByteOrder != null) 250 reader.setMotorolaByteOrder(resetByteOrder); 231 251 } 232 252 } … … 350 370 break; 351 371 default: 352 handler.error(String.format(" Unknown format code %d for tag %d", formatCode, tagId));372 handler.error(String.format("Invalid TIFF tag format code %d for tag 0x%04X", formatCode, tagId)); 353 373 } 354 374 } -
trunk/src/com/drew/imaging/tiff/package.html
r8132 r10862 1 1 <!-- 2 ~ Copyright 2002-201 5Drew Noakes2 ~ Copyright 2002-2016 Drew Noakes 3 3 ~ 4 4 ~ Licensed under the Apache License, Version 2.0 (the "License");
Note:
See TracChangeset
for help on using the changeset viewer.