All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bumptech.glide.load.data.ExifOrientationStream Maven / Gradle / Ivy

Go to download

A fast and efficient image loading library for Android focused on smooth scrolling.

There is a newer version: 5.0.0-rc01
Show newest version
package com.bumptech.glide.load.data;

import androidx.annotation.NonNull;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Adds an exif segment with an orientation attribute to a wrapped {@link InputStream} containing
 * image data.
 *
 * 

This class assumes that the wrapped stream contains an image format that can contain exif * information and performs no verification. */ public final class ExifOrientationStream extends FilterInputStream { /** Allow two bytes for the file format. */ private static final int SEGMENT_START_POSITION = 2; private static final byte[] EXIF_SEGMENT = new byte[] { /* segment start id. */ (byte) 0xFF, /* segment type. */ (byte) 0xE1, /* segmentLength. */ 0x00, (byte) 0x1C, /* exif identifier. */ 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, /* motorola byte order (big endian). */ (byte) 0x4D, (byte) 0x4D, /* filler? */ 0x00, 0x00, /* first id offset. */ 0x00, 0x00, 0x00, 0x08, /* tagCount. */ 0x00, 0x01, /* exif tag type. */ 0x01, 0x12, /* 2 byte format. */ 0x00, 0x02, /* component count. */ 0x00, 0x00, 0x00, 0x01, /* 2 byte orientation value, the first byte of which is always 0. */ 0x00, }; private static final int SEGMENT_LENGTH = EXIF_SEGMENT.length; private static final int ORIENTATION_POSITION = SEGMENT_LENGTH + SEGMENT_START_POSITION; private final byte orientation; private int position; public ExifOrientationStream(InputStream in, int orientation) { super(in); if (orientation < -1 || orientation > 8) { throw new IllegalArgumentException("Cannot add invalid orientation: " + orientation); } this.orientation = (byte) orientation; } @Override public boolean markSupported() { return false; } // No need for synchronized since all we do is throw. @SuppressWarnings("UnsynchronizedOverridesSynchronized") @Override public void mark(int readLimit) { throw new UnsupportedOperationException(); } @Override public int read() throws IOException { final int result; if (position < SEGMENT_START_POSITION || position > ORIENTATION_POSITION) { result = super.read(); } else if (position == ORIENTATION_POSITION) { result = orientation; } else { result = EXIF_SEGMENT[position - SEGMENT_START_POSITION] & 0xFF; } if (result != -1) { position++; } return result; } @Override public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException { int read; if (position > ORIENTATION_POSITION) { read = super.read(buffer, byteOffset, byteCount); } else if (position == ORIENTATION_POSITION) { buffer[byteOffset] = orientation; read = 1; } else if (position < SEGMENT_START_POSITION) { read = super.read(buffer, byteOffset, SEGMENT_START_POSITION - position); } else { read = Math.min(ORIENTATION_POSITION - position, byteCount); System.arraycopy(EXIF_SEGMENT, position - SEGMENT_START_POSITION, buffer, byteOffset, read); } if (read > 0) { position += read; } return read; } @Override public long skip(long byteCount) throws IOException { long skipped = super.skip(byteCount); if (skipped > 0) { // See https://errorprone.info/bugpattern/NarrowingCompoundAssignment. position = (int) (position + skipped); } return skipped; } // No need for synchronized since all we do is throw. @SuppressWarnings("UnsynchronizedOverridesSynchronized") @Override public void reset() throws IOException { throw new UnsupportedOperationException(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy