From 96749c13218aa1b783709dc82a4e16657ce9753f Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Wed, 11 Dec 2013 15:41:28 +0100 Subject: Revert "Revert "Move wallpaper picker code to a separate directory"" This reverts commit 39de459a8621abfc91382ce7b4cdd37d09aaac12. --- .../com/android/gallery3d/exif/ExifModifier.java | 196 +++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 wallpaper_picker_src/com/android/gallery3d/exif/ExifModifier.java (limited to 'wallpaper_picker_src/com/android/gallery3d/exif/ExifModifier.java') diff --git a/wallpaper_picker_src/com/android/gallery3d/exif/ExifModifier.java b/wallpaper_picker_src/com/android/gallery3d/exif/ExifModifier.java new file mode 100644 index 000000000..f00362b6b --- /dev/null +++ b/wallpaper_picker_src/com/android/gallery3d/exif/ExifModifier.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2012 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.exif; + +import android.util.Log; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +class ExifModifier { + public static final String TAG = "ExifModifier"; + public static final boolean DEBUG = false; + private final ByteBuffer mByteBuffer; + private final ExifData mTagToModified; + private final List mTagOffsets = new ArrayList(); + private final ExifInterface mInterface; + private int mOffsetBase; + + private static class TagOffset { + final int mOffset; + final ExifTag mTag; + + TagOffset(ExifTag tag, int offset) { + mTag = tag; + mOffset = offset; + } + } + + protected ExifModifier(ByteBuffer byteBuffer, ExifInterface iRef) throws IOException, + ExifInvalidFormatException { + mByteBuffer = byteBuffer; + mOffsetBase = byteBuffer.position(); + mInterface = iRef; + InputStream is = null; + try { + is = new ByteBufferInputStream(byteBuffer); + // Do not require any IFD; + ExifParser parser = ExifParser.parse(is, mInterface); + mTagToModified = new ExifData(parser.getByteOrder()); + mOffsetBase += parser.getTiffStartPosition(); + mByteBuffer.position(0); + } finally { + ExifInterface.closeSilently(is); + } + } + + protected ByteOrder getByteOrder() { + return mTagToModified.getByteOrder(); + } + + protected boolean commit() throws IOException, ExifInvalidFormatException { + InputStream is = null; + try { + is = new ByteBufferInputStream(mByteBuffer); + int flag = 0; + IfdData[] ifdDatas = new IfdData[] { + mTagToModified.getIfdData(IfdId.TYPE_IFD_0), + mTagToModified.getIfdData(IfdId.TYPE_IFD_1), + mTagToModified.getIfdData(IfdId.TYPE_IFD_EXIF), + mTagToModified.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY), + mTagToModified.getIfdData(IfdId.TYPE_IFD_GPS) + }; + + if (ifdDatas[IfdId.TYPE_IFD_0] != null) { + flag |= ExifParser.OPTION_IFD_0; + } + if (ifdDatas[IfdId.TYPE_IFD_1] != null) { + flag |= ExifParser.OPTION_IFD_1; + } + if (ifdDatas[IfdId.TYPE_IFD_EXIF] != null) { + flag |= ExifParser.OPTION_IFD_EXIF; + } + if (ifdDatas[IfdId.TYPE_IFD_GPS] != null) { + flag |= ExifParser.OPTION_IFD_GPS; + } + if (ifdDatas[IfdId.TYPE_IFD_INTEROPERABILITY] != null) { + flag |= ExifParser.OPTION_IFD_INTEROPERABILITY; + } + + ExifParser parser = ExifParser.parse(is, flag, mInterface); + int event = parser.next(); + IfdData currIfd = null; + while (event != ExifParser.EVENT_END) { + switch (event) { + case ExifParser.EVENT_START_OF_IFD: + currIfd = ifdDatas[parser.getCurrentIfd()]; + if (currIfd == null) { + parser.skipRemainingTagsInCurrentIfd(); + } + break; + case ExifParser.EVENT_NEW_TAG: + ExifTag oldTag = parser.getTag(); + ExifTag newTag = currIfd.getTag(oldTag.getTagId()); + if (newTag != null) { + if (newTag.getComponentCount() != oldTag.getComponentCount() + || newTag.getDataType() != oldTag.getDataType()) { + return false; + } else { + mTagOffsets.add(new TagOffset(newTag, oldTag.getOffset())); + currIfd.removeTag(oldTag.getTagId()); + if (currIfd.getTagCount() == 0) { + parser.skipRemainingTagsInCurrentIfd(); + } + } + } + break; + } + event = parser.next(); + } + for (IfdData ifd : ifdDatas) { + if (ifd != null && ifd.getTagCount() > 0) { + return false; + } + } + modify(); + } finally { + ExifInterface.closeSilently(is); + } + return true; + } + + private void modify() { + mByteBuffer.order(getByteOrder()); + for (TagOffset tagOffset : mTagOffsets) { + writeTagValue(tagOffset.mTag, tagOffset.mOffset); + } + } + + private void writeTagValue(ExifTag tag, int offset) { + if (DEBUG) { + Log.v(TAG, "modifying tag to: \n" + tag.toString()); + Log.v(TAG, "at offset: " + offset); + } + mByteBuffer.position(offset + mOffsetBase); + switch (tag.getDataType()) { + case ExifTag.TYPE_ASCII: + byte buf[] = tag.getStringByte(); + if (buf.length == tag.getComponentCount()) { + buf[buf.length - 1] = 0; + mByteBuffer.put(buf); + } else { + mByteBuffer.put(buf); + mByteBuffer.put((byte) 0); + } + break; + case ExifTag.TYPE_LONG: + case ExifTag.TYPE_UNSIGNED_LONG: + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + mByteBuffer.putInt((int) tag.getValueAt(i)); + } + break; + case ExifTag.TYPE_RATIONAL: + case ExifTag.TYPE_UNSIGNED_RATIONAL: + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + Rational v = tag.getRational(i); + mByteBuffer.putInt((int) v.getNumerator()); + mByteBuffer.putInt((int) v.getDenominator()); + } + break; + case ExifTag.TYPE_UNDEFINED: + case ExifTag.TYPE_UNSIGNED_BYTE: + buf = new byte[tag.getComponentCount()]; + tag.getBytes(buf); + mByteBuffer.put(buf); + break; + case ExifTag.TYPE_UNSIGNED_SHORT: + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + mByteBuffer.putShort((short) tag.getValueAt(i)); + } + break; + } + } + + public void modifyTag(ExifTag tag) { + mTagToModified.addTag(tag); + } +} -- cgit v1.2.3