diff options
Diffstat (limited to 'WallpaperPicker/src/com/android/gallery3d/common/ExifOrientation.java')
-rw-r--r-- | WallpaperPicker/src/com/android/gallery3d/common/ExifOrientation.java | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/ExifOrientation.java b/WallpaperPicker/src/com/android/gallery3d/common/ExifOrientation.java new file mode 100644 index 000000000..ad4370c37 --- /dev/null +++ b/WallpaperPicker/src/com/android/gallery3d/common/ExifOrientation.java @@ -0,0 +1,145 @@ +/** + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.gallery3d.common; + +import android.content.Context; +import android.media.ExifInterface; +import android.util.Log; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ExifOrientation { + private static final String TAG = "ExifOrientation"; + private static final boolean DEBUG = false; + + private static final short SOI = (short) 0xFFD8; // start of input + private static final short APP0 = (short) 0xFFE0; + private static final short APPF = (short) 0xFFEF; + private static final short APP1 = (short) 0xFFE1; + private static final short SOS = (short) 0xFFDA; // start of stream + private static final short EOI = (short) 0xFFD9; // end of input + + // The header is available in first 64 bytes, so reading upto 128 bytes + // should be more than enough. + private static final int MAX_BYTES_TO_READ = 128 * 1024; + + /** + * Parses the rotation of the JPEG image from the input stream. + */ + public static final int readRotation(InputStream in, Context context) { + // Since the platform implementation only takes file input, create a temporary file + // with just the image header. + File tempFile = null; + DataOutputStream tempOut = null; + + try { + DataInputStream din = new DataInputStream(in); + int pos = 0; + if (din.readShort() == SOI) { + pos += 2; + + short marker = din.readShort(); + pos += 2; + + while ((marker >= APP0 && marker <= APPF) && pos < MAX_BYTES_TO_READ) { + int length = din.readUnsignedShort(); + if (length < 2) { + throw new IOException("Invalid header size"); + } + + // We only want APP1 headers + if (length > 2) { + if (marker == APP1) { + // Copy the header + if (tempFile == null) { + tempFile = File.createTempFile(TAG, ".jpg", context.getCacheDir()); + tempOut = new DataOutputStream(new FileOutputStream(tempFile)); + tempOut.writeShort(SOI); + } + + tempOut.writeShort(marker); + tempOut.writeShort(length); + + byte[] header = new byte[length - 2]; + din.read(header); + tempOut.write(header); + } else { + din.skip(length - 2); + } + } + pos += length; + + marker = din.readShort(); + pos += 2; + } + + if (tempOut != null) { + // Write empty image data. + tempOut.writeShort(SOS); + // Write the frame size as 2. Since this includes the size bytes as well + // (short = 2 bytes), it implies there is 0 byte of image data. + tempOut.writeShort(2); + + // End of input + tempOut.writeShort(EOI); + tempOut.close(); + + return readRotation(tempFile.getAbsolutePath()); + } + } + } catch (IOException e) { + if (DEBUG) { + Log.d(TAG, "Error parsing input stream", e); + } + } finally { + Utils.closeSilently(in); + Utils.closeSilently(tempOut); + if (tempFile != null) { + tempFile.delete(); + } + } + return 0; + } + + /** + * Parses the rotation of the JPEG image. + */ + public static final int readRotation(String filePath) { + try { + ExifInterface exif = new ExifInterface(filePath); + switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) { + case ExifInterface.ORIENTATION_ROTATE_90: + return 90; + case ExifInterface.ORIENTATION_ROTATE_270: + return 270; + case ExifInterface.ORIENTATION_ROTATE_180: + return 180; + default: + return 0; + } + } catch (IOException e) { + if (DEBUG) { + Log.d(TAG, "Error reading file", e); + } + } + return 0; + } +} |