@Test public void testIssue387() throws IOException { InputStream is = TestResourceUtil.openResource(getClass(), "issue387_rotated_jpeg.jpg"); assertThat(new DefaultImageHeaderParser().getOrientation(is, byteArrayPool)).isEqualTo(6); }
@NonNull @Override public ImageType getType(@NonNull InputStream is) throws IOException { return getType(new StreamReader(Preconditions.checkNotNull(is))); }
/** * Parse the orientation from the image header. If it doesn't handle this image type (or this is * not an image) it will return a default value rather than throwing an exception. * * @return The exif orientation if present or -1 if the header couldn't be parsed or doesn't * contain an orientation */ private int getOrientation(Reader reader, ArrayPool byteArrayPool) throws IOException { final int magicNumber = reader.getUInt16(); if (!handles(magicNumber)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Parser doesn't handle magic number: " + magicNumber); } return UNKNOWN_ORIENTATION; } else { int exifSegmentLength = moveToExifSegmentAndGetLength(reader); if (exifSegmentLength == -1) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Failed to parse exif segment length, or exif segment not found"); } return UNKNOWN_ORIENTATION; } byte[] exifData = byteArrayPool.get(exifSegmentLength, byte[].class); try { return parseExifSegment(reader, exifData, exifSegmentLength); } finally { byteArrayPool.put(exifData); } } }
private int parseExifSegment(Reader reader, byte[] tempArray, int exifSegmentLength) throws IOException { int read = reader.read(tempArray, exifSegmentLength); if (read != exifSegmentLength) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Unable to read exif segment data" + ", length: " + exifSegmentLength + ", actually read: " + read); } return UNKNOWN_ORIENTATION; } boolean hasJpegExifPreamble = hasJpegExifPreamble(tempArray, exifSegmentLength); if (hasJpegExifPreamble) { return parseExifSegment(new RandomAccessReader(tempArray, exifSegmentLength)); } else { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Missing jpeg exif preamble"); } return UNKNOWN_ORIENTATION; } }
public ThumbnailStreamOpener get() { List<ImageHeaderParser> parsers = new ArrayList<>(); parsers.add(new DefaultImageHeaderParser()); return new ThumbnailStreamOpener( parsers, service, query, byteArrayPool, getContentResolver()); } }
@Test public void testHandlesSometimesZeroSkips() throws IOException { InputStream is = new ByteArrayInputStream( new byte[] { (byte) 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }); DefaultImageHeaderParser parser = new DefaultImageHeaderParser(); assertEquals(ImageType.PNG, parser.getType(new SometimesZeroSkipInputStream(is))); }
@Override public int getOrientation(@NonNull InputStream is, @NonNull ArrayPool byteArrayPool) throws IOException { return getOrientation(new StreamReader(Preconditions.checkNotNull(is)), Preconditions.checkNotNull(byteArrayPool)); }
int tagCount = segmentData.getInt16(firstIfdOffset); for (int i = 0; i < tagCount; i++) { final int tagOffset = calcTagOffset(firstIfdOffset, i);
private static void runTest(byte[] data, ParserTestCase test) throws IOException { InputStream is = new ByteArrayInputStream(data); DefaultImageHeaderParser parser = new DefaultImageHeaderParser(); test.run(parser, is, new LruArrayPool()); ByteBuffer buffer = ByteBuffer.wrap(data); parser = new DefaultImageHeaderParser(); test.run(parser, buffer, new LruArrayPool()); }
@Override public int getOrientation(@NonNull ByteBuffer byteBuffer, @NonNull ArrayPool byteArrayPool) throws IOException { return getOrientation(new ByteBufferReader(Preconditions.checkNotNull(byteBuffer)), Preconditions.checkNotNull(byteArrayPool)); }
private int parseExifSegment(Reader reader, byte[] tempArray, int exifSegmentLength) throws IOException { int read = reader.read(tempArray, exifSegmentLength); if (read != exifSegmentLength) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Unable to read exif segment data" + ", length: " + exifSegmentLength + ", actually read: " + read); } return UNKNOWN_ORIENTATION; } boolean hasJpegExifPreamble = hasJpegExifPreamble(tempArray, exifSegmentLength); if (hasJpegExifPreamble) { return parseExifSegment(new RandomAccessReader(tempArray, exifSegmentLength)); } else { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Missing jpeg exif preamble"); } return UNKNOWN_ORIENTATION; } }
tagOffset = calcTagOffset(firstIfdOffset, i); tagType = segmentData.getInt16(tagOffset);
private void assertOrientation(String filePrefix, int expectedOrientation) { InputStream is = null; try { is = open(filePrefix + "_" + expectedOrientation + ".jpg"); assertEquals(new DefaultImageHeaderParser().getOrientation(is, byteArrayPool), expectedOrientation); } catch (IOException e) { throw new RuntimeException(e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { // Do nothing. } } } }
@NonNull @Override public ImageType getType(@NonNull ByteBuffer byteBuffer) throws IOException { return getType(new ByteBufferReader(Preconditions.checkNotNull(byteBuffer))); }
private static Downsampler buildDownsampler() { List<ImageHeaderParser> parsers = Collections.<ImageHeaderParser>singletonList(new DefaultImageHeaderParser()); DisplayMetrics displayMetrics = new DisplayMetrics(); // XHDPI. displayMetrics.densityDpi = 320; BitmapPool bitmapPool = new BitmapPoolAdapter(); ArrayPool arrayPool = new LruArrayPool(); return new Downsampler(parsers, displayMetrics, bitmapPool, arrayPool); }
final int magicNumber = reader.getUInt16(); if (!handles(magicNumber)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Parser doesn't handle magic number: " + magicNumber); int exifSegmentLength = moveToExifSegmentAndGetLength(reader); if (exifSegmentLength == -1) { if (Log.isLoggable(TAG, Log.DEBUG)) { return parseExifSegment(reader, exifData, exifSegmentLength); } finally { byteArrayPool.put(exifData, byte[].class);
@Override public void run(DefaultImageHeaderParser parser, ByteBuffer byteBuffer, ArrayPool byteArrayPool) throws IOException { assertEquals(-1, parser.getOrientation(byteBuffer, byteArrayPool)); } });
@Test public void getOrientation_withExifSegmentLessThanLength_returnsUnknown() throws IOException { ByteBuffer jpegHeaderBytes = getExifMagicNumber(); byte[] data = new byte[] { jpegHeaderBytes.get(0), jpegHeaderBytes.get(1), (byte) DefaultImageHeaderParser.SEGMENT_START_ID, (byte) DefaultImageHeaderParser.EXIF_SEGMENT_TYPE, // SEGMENT_LENGTH (byte) 0xFF, (byte) 0xFF, }; ByteBuffer byteBuffer = ByteBuffer.wrap(data); DefaultImageHeaderParser parser = new DefaultImageHeaderParser(); assertEquals(ImageHeaderParser.UNKNOWN_ORIENTATION, parser.getOrientation(byteBuffer, byteArrayPool)); }
@Override public void run(DefaultImageHeaderParser parser, InputStream is, ArrayPool byteArrayPool) throws IOException { assertEquals(ImageType.PNG, parser.getType(is)); } @Override
@Before public void setUp() { MockitoAnnotations.initMocks(this); List<ImageHeaderParser> parsers = new ArrayList<>(); parsers.add(new DefaultImageHeaderParser()); decoder = new StreamGifDecoder(parsers, byteBufferDecoder, new LruArrayPool()); options = new Options(); }