summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gallerycommon/src/com/android/gallery3d/common/ApiHelper.java9
-rw-r--r--src/com/android/gallery3d/app/GalleryAppImpl.java10
-rw-r--r--src/com/android/gallery3d/exif/ExifTag.java185
-rw-r--r--tests/src/com/android/gallery3d/exif/ExifParserTest.java260
-rw-r--r--tests/src/com/android/gallery3d/exif/ExifTestRunner.java56
5 files changed, 415 insertions, 105 deletions
diff --git a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
index 54b0587e8..fbe0fbbb5 100644
--- a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
+++ b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
@@ -38,6 +38,9 @@ public class ApiHelper {
public static final int JELLY_BEAN = 16;
}
+ public static final boolean ENABLE_PHOTO_EDITOR =
+ Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH;
+
public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE =
hasField(View.class, "SYSTEM_UI_FLAG_LAYOUT_STABLE");
@@ -63,6 +66,9 @@ public class ApiHelper {
public static final boolean HAS_RELEASE_SURFACE_TEXTURE = hasMethod(
"android.graphics.SurfaceTexture", "release");
+ public static final boolean HAS_SURFACE_TEXTURE =
+ Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+
public static final boolean HAS_MTP =
Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1;
@@ -149,6 +155,9 @@ public class ApiHelper {
public static final boolean HAS_MEDIA_PROVIDER_FILES_TABLE =
Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB;
+ public static final boolean HAS_SURFACE_TEXTURE_RECORDING =
+ Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
private static boolean hasField(Class<?> klass, String fieldName) {
try {
klass.getDeclaredField(fieldName);
diff --git a/src/com/android/gallery3d/app/GalleryAppImpl.java b/src/com/android/gallery3d/app/GalleryAppImpl.java
index f725ccf5a..0164bce65 100644
--- a/src/com/android/gallery3d/app/GalleryAppImpl.java
+++ b/src/com/android/gallery3d/app/GalleryAppImpl.java
@@ -17,12 +17,16 @@
package com.android.gallery3d.app;
import android.app.Application;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.data.DataManager;
import com.android.gallery3d.data.DownloadCache;
import com.android.gallery3d.data.ImageCacheService;
import com.android.gallery3d.gadget.WidgetUtils;
+import com.android.gallery3d.photoeditor.PhotoEditor;
import com.android.gallery3d.picasasource.PicasaSource;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.ThreadPool;
@@ -47,6 +51,12 @@ public class GalleryAppImpl extends Application implements GalleryApp {
GalleryUtils.initialize(this);
WidgetUtils.initialize(this);
PicasaSource.initialize(this);
+ int state = ApiHelper.ENABLE_PHOTO_EDITOR
+ ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ getPackageManager().setComponentEnabledSetting(
+ new ComponentName(this, PhotoEditor.class),
+ state, PackageManager.DONT_KILL_APP);
}
@Override
diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/src/com/android/gallery3d/exif/ExifTag.java
index 4f1db55cd..c11171c79 100644
--- a/src/com/android/gallery3d/exif/ExifTag.java
+++ b/src/com/android/gallery3d/exif/ExifTag.java
@@ -20,19 +20,36 @@ public class ExifTag {
public static interface TIFF_TAG {
public static final short TAG_IMAGE_WIDTH = 0x100;
public static final short TAG_IMAGE_HEIGHT = 0x101;
+ public static final short TAG_BITS_PER_SAMPLE = 0x102;
public static final short TAG_COMPRESSION = 0x103;
- public static final short TAG_MAKE = 0x10f;
+ public static final short TAG_PHOTOMETRIC_INTERPRETATION = 0x106;
+ public static final short TAG_IMAGE_DESCRIPTION = 0x10E;
+ public static final short TAG_MAKE = 0x10F;
public static final short TAG_MODEL = 0x110;
+ public static final short TAG_STRIP_OFFSETS = 0x111;
public static final short TAG_ORIENTATION = 0x112;
+ public static final short TAG_SAMPLES_PER_PIXEL = 0x115;
+ public static final short TAG_ROWS_PER_STRIP = 0x116;
+ public static final short TAG_STRIP_BYTE_COUNTS = 0x117;
public static final short TAG_X_RESOLUTION = 0x11A;
public static final short TAG_Y_RESOLUTION = 0x11B;
+ public static final short TAG_PLANAR_CONFIGURATION = 0x11C;
public static final short TAG_RESOLUTION_UNIT = 0x128;
+ public static final short TAG_TRANSFER_FUNCTION = 0x12D;
public static final short TAG_SOFTWARE = 0x131;
public static final short TAG_DATE_TIME = 0x132;
+ public static final short TAG_ARTIST = 0x13B;
+ public static final short TAG_WHITE_POINT = 0x13E;
+ public static final short TAG_PRIMARY_CHROMATICITIES = 0x13F;
public static final short TAG_JPEG_INTERCHANGE_FORMAT = 0x201;
public static final short TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x202;
+ public static final short TAG_Y_CB_CR_COEFFICIENTS = 0x211;
+ public static final short TAG_Y_CB_CR_SUB_SAMPLING = 0x212;
public static final short TAG_Y_CB_CR_POSITIONING = 0x213;
+ public static final short TAG_REFERENCE_BLACK_WHITE = 0x214;
+ public static final short TAG_COPYRIGHT = (short) 0x8298;
public static final short TAG_EXIF_IFD = (short) 0x8769;
+ public static final short TAG_GPS_IFD = (short) 0x8825;
public static final short ORIENTATION_TOP_LEFT = 1;
public static final short ORIENTATION_TOP_RIGHT = 2;
@@ -51,31 +68,72 @@ public class ExifTag {
public static final short RESOLUTION_UNIT_INCHES = 2;
public static final short RESOLUTION_UNIT_CENTIMETERS = 3;
+
+ public static final short PHOTOMETRIC_INTERPRETATION_RGB = 2;
+ public static final short PHOTOMETRIC_INTERPRETATION_YCBCR = 6;
+
+ public static final short PLANAR_CONFIGURATION_CHUNKY = 1;
+ public static final short PLANAR_CONFIGURATION_PLANAR = 2;
}
public static interface EXIF_TAG {
public static final short TAG_EXPOSURE_TIME = (short) 0x829A;
public static final short TAG_F_NUMBER = (short) 0x829D;
public static final short TAG_EXPOSURE_PROGRAM = (short) 0x8822;
+ public static final short TAG_SPECTRAL_SENSITIVITY = (short) 0x8824;
public static final short TAG_ISO_SPEED_RATINGS = (short) 0x8827;
+ public static final short TAG_OECF = (short) 0x8828;
public static final short TAG_EXIF_VERSION = (short) 0x9000;
public static final short TAG_DATE_TIME_ORIGINAL = (short) 0x9003;
public static final short TAG_DATE_TIME_DIGITIZED = (short) 0x9004;
+ public static final short TAG_COMPONENTS_CONFIGURATION = (short) 0x9101;
+ public static final short TAG_COMPRESSED_BITS_PER_PIXEL = (short) 0x9102;
public static final short TAG_SHUTTER_SPEED = (short) 0x9201;
public static final short TAG_APERTURE_VALUE = (short) 0x9202;
public static final short TAG_BRIGHTNESS_VALUE = (short) 0x9203;
public static final short TAG_EXPOSURE_BIAS_VALUE = (short) 0x9204;
public static final short TAG_MAX_APERTURE_VALUE = (short) 0x9205;
+ public static final short TAG_SUBJECT_DISTANCE = (short) 0x9206;
public static final short TAG_METERING_MODE = (short) 0x9207;
+ public static final short TAG_LIGHT_SOURCE = (short) 0x9208;
public static final short TAG_FLASH = (short) 0x9209;
public static final short TAG_FOCAL_LENGTH = (short) 0x920A;
+ public static final short TAG_SUBJECT_AREA = (short) 0x9214;
+ public static final short TAG_MARER_NOTE = (short) 0x927C;
public static final short TAG_USER_COMMENT = (short) 0x9286;
+ public static final short TAG_SUB_SEC_TIME = (short) 0x9290;
+ public static final short TAG_SUB_SEC_TIME_ORIGINAL = (short) 0x9291;
+ public static final short TAG_SUB_SEC_TIME_DIGITIZED = (short) 0x9292;
+ public static final short TAG_FLASHPIX_VERSION = (short) 0xA000;
public static final short TAG_COLOR_SPACE = (short) 0xA001;
public static final short TAG_PIXEL_X_DIMENSION = (short) 0xA002;
public static final short TAG_PIXEL_Y_DIMENSION = (short) 0xA003;
+ public static final short TAG_RELATED_SOUND_FILE = (short) 0xA004;
+ public static final short TAG_INTEROPERABILITY_IFD = (short) 0xA005;
+ public static final short TAG_FLASH_ENERGY = (short) 0xA20B;
+ public static final short TAG_SPATIAL_FREQUENCY_REPSONSE = (short) 0xA20C;
+ public static final short TAG_FOCAL_PLANE_X_RESOLUTION = (short) 0xA20E;
+ public static final short TAG_FOCAL_PLANE_Y_RESOLUTION = (short) 0xA20F;
+ public static final short TAG_FOCAL_PLANE_RESOLUTION_UNIT = (short) 0xA210;
+ public static final short TAG_SUBJECT_LOCATION = (short) 0xA214;
+ public static final short TAG_EXPOSURE_INDEX = (short) 0xA215;
+ public static final short TAG_SENSING_METHOD = (short) 0xA217;
+ public static final short TAG_FILE_SOURCE = (short) 0xA300;
+ public static final short TAG_SCENE_TYPE = (short) 0xA301;
+ public static final short TAG_CFA_PATTERN = (short) 0xA302;
+ public static final short TAG_CUSTOM_RENDERED = (short) 0xA401;
public static final short TAG_EXPOSURE_MODE = (short) 0xA402;
public static final short TAG_WHITH_BALANCE = (short) 0xA403;
+ public static final short TAG_DIGITAL_ZOOM_RATIO = (short) 0xA404;
+ public static final short TAG_FOCAL_LENGTH_IN_35_MM_FILE = (short) 0xA405;
public static final short TAG_SCENE_CAPTURE_TYPE = (short) 0xA406;
+ public static final short TAG_GAIN_CONTROL = (short) 0xA407;
+ public static final short TAG_CONTRAST = (short) 0xA408;
+ public static final short TAG_SATURATION = (short) 0xA409;
+ public static final short TAG_SHARPNESS = (short) 0xA40A;
+ public static final short TAG_DEVICE_SETTING_DESCRIPTION = (short) 0xA40B;
+ public static final short TAG_SUBJECT_DISTANCE_RANGE = (short) 0xA40C;
+ public static final short TAG_IMAGE_UNIQUE_ID = (short) 0xA420;
public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0;
public static final short EXPOSURE_PROGRAM_MANUAL = 1;
@@ -130,6 +188,131 @@ public class ExifTag {
public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1;
public static final short SCENE_CAPTURE_TYPE_PROTRAIT = 2;
public static final short SCENE_CAPTURE_TYPE_NIGHT_SCENE = 3;
+
+ public static final short COMPONENTS_CONFIGURATION_NOT_EXIST = 0;
+ public static final short COMPONENTS_CONFIGURATION_Y = 1;
+ public static final short COMPONENTS_CONFIGURATION_CB = 2;
+ public static final short COMPONENTS_CONFIGURATION_CR = 3;
+ public static final short COMPONENTS_CONFIGURATION_R = 4;
+ public static final short COMPONENTS_CONFIGURATION_G = 5;
+ public static final short COMPONENTS_CONFIGURATION_B = 6;
+
+ public static final short LIGHT_SOURCE_UNKNOWN = 0;
+ public static final short LIGHT_SOURCE_DAYLIGHT = 1;
+ public static final short LIGHT_SOURCE_FLUORESCENT = 2;
+ public static final short LIGHT_SOURCE_TUNGSTEN = 3;
+ public static final short LIGHT_SOURCE_FLASH = 4;
+ public static final short LIGHT_SOURCE_FINE_WEATHER = 9;
+ public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10;
+ public static final short LIGHT_SOURCE_SHADE = 11;
+ public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12;
+ public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13;
+ public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14;
+ public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15;
+ public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17;
+ public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18;
+ public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19;
+ public static final short LIGHT_SOURCE_D55 = 20;
+ public static final short LIGHT_SOURCE_D65 = 21;
+ public static final short LIGHT_SOURCE_D75 = 22;
+ public static final short LIGHT_SOURCE_D50 = 23;
+ public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24;
+ public static final short LIGHT_SOURCE_OTHER = 255;
+
+ public static final short SENSING_METHOD_NOT_DEFINED = 1;
+ public static final short SENSING_METHOD_ONE_CHIP_COLOR = 2;
+ public static final short SENSING_METHOD_TWO_CHIP_COLOR = 3;
+ public static final short SENSING_METHOD_THREE_CHIP_COLOR = 4;
+ public static final short SENSING_METHOD_COLOR_SEQUENTIAL_AREA = 5;
+ public static final short SENSING_METHOD_TRILINEAR = 7;
+ public static final short SENSING_METHOD_COLOR_SEQUENTIAL_LINEAR = 8;
+
+ public static final short FILE_SOURCE_DSC = 3;
+
+ public static final short SCENE_TYPE_DIRECT_PHOTOGRAPHED = 1;
+
+ public static final short GAIN_CONTROL_NONE = 0;
+ public static final short GAIN_CONTROL_LOW_UP = 1;
+ public static final short GAIN_CONTROL_HIGH_UP = 2;
+ public static final short GAIN_CONTROL_LOW_DOWN = 3;
+ public static final short GAIN_CONTROL_HIGH_DOWN = 4;
+
+ public static final short CONTRAST_NORMAL = 0;
+ public static final short CONTRAST_SOFT = 1;
+ public static final short CONTRAST_HARD = 2;
+
+ public static final short SATURATION_NORMAL = 0;
+ public static final short SATURATION_LOW = 1;
+ public static final short SATURATION_HIGH = 2;
+
+ public static final short SHARPNESS_NORMAL = 0;
+ public static final short SHARPNESS_SOFT = 1;
+ public static final short SHARPNESS_HARD = 2;
+
+ public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0;
+ public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1;
+ public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2;
+ public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3;
+ }
+
+ public static interface GPS_TAG {
+ public static final short GPS_VERSION_ID = 0;
+ public static final short GPS_LATITUDE_REF = 1;
+ public static final short GPS_LATITUDE = 2;
+ public static final short GPS_LONGITUDE_REF = 3;
+ public static final short GPS_LONGITUDE = 4;
+ public static final short GPS_ALTITUDE_REF = 5;
+ public static final short GPS_ALTITUDE = 6;
+ public static final short GPS_TIME_STAMP = 7;
+ public static final short GPS_SATTELLITES = 8;
+ public static final short GPS_STATUS = 9;
+ public static final short GPS_MEASURE_MODE = 10;
+ public static final short GPS_DOP = 11;
+ public static final short GPS_SPEED_REF = 12;
+ public static final short GPS_SPEED = 13;
+ public static final short GPS_TRACK_REF = 14;
+ public static final short GPS_TRACK = 15;
+ public static final short GPS_IMG_DIRECTION_REF = 16;
+ public static final short GPS_IMG_DIRECTION = 17;
+ public static final short GPS_MAP_DATUM = 18;
+ public static final short GPS_DEST_LATITUDE_REF = 19;
+ public static final short GPS_DEST_LATITUDE = 20;
+ public static final short GPS_DEST_LONGITUDE_REF = 21;
+ public static final short GPS_DEST_LONGITUDE = 22;
+ public static final short GPS_DEST_BEARING_REF = 23;
+ public static final short GPS_DEST_BEARING = 24;
+ public static final short GPS_DEST_DISTANCE_REF = 25;
+ public static final short GPS_DEST_DISTANCE = 26;
+ public static final short GPS_PROCESSING_METHOD = 27;
+ public static final short GPS_AREA_INFORMATION = 28;
+ public static final short GPS_DATA_STAMP = 29;
+ public static final short GPS_DIFFERENTIAL = 30;
+
+ public static final String GPS_REF_NORTH = "N";
+ public static final String GPS_REF_SOUTH = "S";
+
+ public static final String GPS_REF_EAST = "E";
+ public static final String GPS_REF_WEST = "W";
+
+ public static final short GPS_ALTITUDE_REF_SEA_LEVEL = 0;
+ public static final short GPS_ALTITUDE_REF_SEA_LEVEL_NEGATIVE = 1;
+
+ public static final String GPS_STATUS_IN_PROGRESS = "A";
+ public static final String GPS_STATUS_INTEROPERABILITY = "V";
+
+ public static final String GPS_MEASURE_MODE_2_DIMENSIONAL = "2";
+ public static final String GPS_MEASURE_MODE_3_DIMENSIONAL = "3";
+
+ public static final String GPS_REF_KILOMETERS = "K";
+ public static final String GPS_REF_MILES = "M";
+ public static final String GPS_REF_KNOTS = "N";
+
+ public static final String GPS_REF_TRUE_DIRECTION = "T";
+ public static final String GPS_REF_MAGNETIC_DIRECTION = "M";
+ }
+
+ public static interface INTEROPERABILITY_TAG {
+ public static final short INTEROPERABILITY_INDEX = 1;
}
public static final short TYPE_BYTE = 1;
diff --git a/tests/src/com/android/gallery3d/exif/ExifParserTest.java b/tests/src/com/android/gallery3d/exif/ExifParserTest.java
index a18a3f8db..34bbbda5f 100644
--- a/tests/src/com/android/gallery3d/exif/ExifParserTest.java
+++ b/tests/src/com/android/gallery3d/exif/ExifParserTest.java
@@ -16,11 +16,14 @@
package com.android.gallery3d.exif;
+import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.test.InstrumentationTestCase;
+import android.util.Log;
-import com.android.gallery3d.tests.R;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
@@ -28,83 +31,95 @@ import java.util.HashMap;
public class ExifParserTest extends InstrumentationTestCase {
private static final String TAG = "ExifParserTest";
- // The test image
- private static final int IMG_RESOURCE_ID = R.raw.test_galaxy_nexus;
- // IDF0 ground truth
- private static final HashMap<Short, String> IFD0_VALUE = new HashMap<Short, String>();
- static {
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_IMAGE_WIDTH, String.valueOf(2560));
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_IMAGE_HEIGHT, String.valueOf(1920));
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_MAKE, "google");
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_MODEL, "Nexus S");
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_ORIENTATION,
- String.valueOf(ExifTag.TIFF_TAG.ORIENTATION_TOP_LEFT));
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_SOFTWARE, "MASTER");
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_DATE_TIME, "2012:07:30 16:28:42");
- IFD0_VALUE.put(ExifTag.TIFF_TAG.TAG_Y_CB_CR_POSITIONING,
- String.valueOf(ExifTag.TIFF_TAG.Y_CB_CR_POSITIONING_CENTERED));
+ private final int mImageResourceId;
+ private final int mXmlResourceId;
+
+ private HashMap<Short, String> mIfd0Value = new HashMap<Short, String>();
+ private HashMap<Short, String> mIfd1Value = new HashMap<Short, String>();
+ private HashMap<Short, String> mExifIfdValue = new HashMap<Short, String>();
+ private HashMap<Short, String> mInteroperabilityIfdValue = new HashMap<Short, String>();
+
+ private InputStream mImageInputStream;
+
+ private static final String XML_EXIF_TAG = "exif";
+ private static final String XML_IFD_TAG = "ifd";
+ private static final String XML_IFD_NAME = "name";
+ private static final String XML_TAG = "tag";
+ private static final String XML_IFD0 = "ifd0";
+ private static final String XML_IFD1 = "ifd1";
+ private static final String XML_EXIF_IFD = "exif-ifd";
+ private static final String XML_INTEROPERABILITY_IFD = "interoperability-ifd";
+ private static final String XML_TAG_ID = "id";
+
+ public ExifParserTest(int imageResourceId, int xmlResourceId) {
+ mImageResourceId = imageResourceId;
+ mXmlResourceId = xmlResourceId;
}
- // IDF1 ground truth
- private static final HashMap<Short, String> IFD1_VALUE = new HashMap<Short, String>();
- static {
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_COMPRESSION,
- String.valueOf(ExifTag.TIFF_TAG.COMPRESSION_JPEG));
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_X_RESOLUTION, "72/1");
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_Y_RESOLUTION, "72/1");
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_RESOLUTION_UNIT,
- String.valueOf(ExifTag.TIFF_TAG.RESOLUTION_UNIT_INCHES));
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_IMAGE_WIDTH, String.valueOf(320));
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_IMAGE_HEIGHT, String.valueOf(240));
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_ORIENTATION,
- String.valueOf(ExifTag.TIFF_TAG.ORIENTATION_TOP_LEFT));
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT, String.valueOf(690));
- IFD1_VALUE.put(ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, String.valueOf(10447));
+ @Override
+ protected void setUp() throws Exception {
+ mImageInputStream = getInstrumentation()
+ .getContext().getResources().openRawResource(mImageResourceId);
+
+ XmlResourceParser parser =
+ getInstrumentation().getContext().getResources().getXml(mXmlResourceId);
+
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ if (parser.getEventType() == XmlPullParser.START_TAG) {
+ assert(parser.getName().equals(XML_EXIF_TAG));
+ readXml(parser);
+ break;
+ }
+ }
+ parser.close();
}
- // Exif-idf ground truth
- private static final HashMap<Short, String> EXIF_IFD_VALUE = new HashMap<Short, String>();
- static {
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_EXPOSURE_TIME, "1/40");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_F_NUMBER, "26/10");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_EXPOSURE_PROGRAM,
- String.valueOf(ExifTag.EXIF_TAG.EXPOSURE_PROGRAM_APERTURE_PRIORITY));
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_ISO_SPEED_RATINGS, "100");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_EXIF_VERSION, "48 50 50 48"); // 0220
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_DATE_TIME_ORIGINAL, "2012:07:30 16:28:42");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_DATE_TIME_DIGITIZED, "2012:07:30 16:28:42");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_SHUTTER_SPEED, "50/10");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_APERTURE_VALUE, "30/10");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_BRIGHTNESS_VALUE, "30/10");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_EXPOSURE_BIAS_VALUE, "0/0");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_MAX_APERTURE_VALUE, "30/10");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_METERING_MODE,
- String.valueOf(ExifTag.EXIF_TAG.METERING_MODE_CENTER_WEIGHTED_AVERAGE));
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_FLASH,
- String.valueOf(ExifTag.EXIF_TAG.FLASH_DID_NOT_FIRED));
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_FOCAL_LENGTH, "343/100");
- // User command is strange in test_galaxy_nexus, so a binary representation is used here
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_USER_COMMENT,
- "0 0 0 73 73 67 83 65 85 115 101 114 32 99 111 109 109 101 110 116 115 0");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_COLOR_SPACE,
- String.valueOf(ExifTag.EXIF_TAG.COLOR_SPACE_SRGB));
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_PIXEL_X_DIMENSION, "2560");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_PIXEL_Y_DIMENSION, "1920");
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_EXPOSURE_MODE,
- String.valueOf(ExifTag.EXIF_TAG.EXPOSURE_MODE_AUTO_EXPOSURE));
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_WHITH_BALANCE,
- String.valueOf(ExifTag.EXIF_TAG.WHITE_BALACE_MODE_AUTO));
- EXIF_IFD_VALUE.put(ExifTag.EXIF_TAG.TAG_SCENE_CAPTURE_TYPE,
- String.valueOf(ExifTag.EXIF_TAG.SCENE_CAPTURE_TYPE_STANDARD));
+ private void readXml(XmlPullParser parser) throws XmlPullParserException,
+ IOException {
+ parser.require(XmlPullParser.START_TAG, null, XML_EXIF_TAG);
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() == XmlPullParser.START_TAG) {
+ readXmlIfd(parser);
+ }
+ }
+ parser.require(XmlPullParser.END_TAG, null, XML_EXIF_TAG);
}
- private InputStream mImageInputStream;
+ private void readXmlIfd(XmlPullParser parser) throws XmlPullParserException, IOException {
+ parser.require(XmlPullParser.START_TAG, null, XML_IFD_TAG);
+ String name = parser.getAttributeValue(null, XML_IFD_NAME);
+ HashMap<Short, String> ifdData = null;
+ if (XML_IFD0.equals(name)) {
+ ifdData = mIfd0Value;
+ } else if (XML_IFD1.equals(name)) {
+ ifdData = mIfd1Value;
+ } else if (XML_EXIF_IFD.equals(name)) {
+ ifdData = mExifIfdValue;
+ } else if (XML_INTEROPERABILITY_IFD.equals(name)) {
+ ifdData = mInteroperabilityIfdValue;
+ } else {
+ throw new RuntimeException("Unknown IFD name in xml file: " + name);
+ }
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() == XmlPullParser.START_TAG) {
+ readXmlTag(parser, ifdData);
+ }
+ }
+ parser.require(XmlPullParser.END_TAG, null, XML_IFD_TAG);
+ }
- @Override
- protected void setUp() {
- mImageInputStream = getInstrumentation()
- .getContext().getResources().openRawResource(IMG_RESOURCE_ID);
+ private void readXmlTag(XmlPullParser parser, HashMap<Short, String> data)
+ throws XmlPullParserException, IOException {
+ parser.require(XmlPullParser.START_TAG, null, XML_TAG);
+ short id = Integer.decode(parser.getAttributeValue(null, XML_TAG_ID)).shortValue();
+ String value = "";
+ if (parser.next() == XmlPullParser.TEXT) {
+ value = parser.getText();
+ parser.next();
+ }
+ data.put(id, value);
+ parser.require(XmlPullParser.END_TAG, null, XML_TAG);
}
public void testParse() throws IOException, ExifInvalidFormatException {
@@ -125,7 +140,7 @@ public class ExifParserTest extends InstrumentationTestCase {
assertTrue(offset <= Integer.MAX_VALUE);
ifdParser.waitValueOfTag(tag, offset);
} else {
- checkTag(tag, ifdParser, IFD0_VALUE);
+ checkTag(tag, ifdParser, mIfd0Value);
tagNumber++;
}
break;
@@ -137,14 +152,14 @@ public class ExifParserTest extends InstrumentationTestCase {
if(tag.getTagId() == ExifTag.TIFF_TAG.TAG_EXIF_IFD) {
parseExifIfd(ifdParser.parseIfdBlock());
} else {
- checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, IFD0_VALUE);
+ checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, mIfd0Value);
tagNumber++;
}
break;
}
type = ifdParser.next();
}
- assertEquals(IFD0_VALUE.size(), tagNumber);
+ assertEquals(mIfd0Value.size(), tagNumber);
}
private void parseIfd1(IfdParser ifdParser) throws IOException,
@@ -160,7 +175,7 @@ public class ExifParserTest extends InstrumentationTestCase {
assertTrue(offset <= Integer.MAX_VALUE);
ifdParser.waitValueOfTag(tag, offset);
} else {
- checkTag(tag, ifdParser, IFD1_VALUE);
+ checkTag(tag, ifdParser, mIfd1Value);
tagNumber++;
}
break;
@@ -168,13 +183,13 @@ public class ExifParserTest extends InstrumentationTestCase {
fail("Find a ifd after ifd1");
break;
case IfdParser.TYPE_VALUE_OF_PREV_TAG:
- checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, IFD1_VALUE);
+ checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, mIfd1Value);
tagNumber++;
break;
}
type = ifdParser.next();
}
- assertEquals(IFD1_VALUE.size(), tagNumber);
+ assertEquals(mIfd1Value.size(), tagNumber);
}
private void parseExifIfd(IfdParser ifdParser) throws IOException,
@@ -185,12 +200,47 @@ public class ExifParserTest extends InstrumentationTestCase {
switch (type) {
case IfdParser.TYPE_NEW_TAG:
ExifTag tag = ifdParser.readTag();
+ if (tag.getDataSize() > 4
+ || tag.getTagId() == ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD) {
+ long offset = ifdParser.readUnsignedInt();
+ assertTrue(offset <= Integer.MAX_VALUE);
+ ifdParser.waitValueOfTag(tag, offset);
+ } else {
+ checkTag(tag, ifdParser, mExifIfdValue);
+ tagNumber++;
+ }
+ break;
+ case IfdParser.TYPE_NEXT_IFD:
+ fail("Find a ifd after exif ifd");
+ break;
+ case IfdParser.TYPE_VALUE_OF_PREV_TAG:
+ tag = ifdParser.getCorrespodingExifTag();
+ if (tag.getTagId() == ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD) {
+ parseInteroperabilityIfd(ifdParser.parseIfdBlock());
+ } else {
+ checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, mExifIfdValue);
+ tagNumber++;
+ }
+ break;
+ }
+ type = ifdParser.next();
+ }
+ assertEquals(mExifIfdValue.size(), tagNumber);
+ }
+ private void parseInteroperabilityIfd(IfdParser ifdParser) throws IOException,
+ ExifInvalidFormatException {
+ int type = ifdParser.next();
+ int tagNumber = 0;
+ while (type != IfdParser.TYPE_END) {
+ switch (type) {
+ case IfdParser.TYPE_NEW_TAG:
+ ExifTag tag = ifdParser.readTag();
if (tag.getDataSize() > 4) {
long offset = ifdParser.readUnsignedInt();
assertTrue(offset <= Integer.MAX_VALUE);
ifdParser.waitValueOfTag(tag, offset);
} else {
- checkTag(tag, ifdParser, EXIF_IFD_VALUE);
+ checkTag(tag, ifdParser, mInteroperabilityIfdValue);
tagNumber++;
}
break;
@@ -198,18 +248,27 @@ public class ExifParserTest extends InstrumentationTestCase {
fail("Find a ifd after exif ifd");
break;
case IfdParser.TYPE_VALUE_OF_PREV_TAG:
- checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, EXIF_IFD_VALUE);
+ checkTag(ifdParser.getCorrespodingExifTag(), ifdParser
+ , mInteroperabilityIfdValue);
tagNumber++;
break;
}
type = ifdParser.next();
}
- assertEquals(EXIF_IFD_VALUE.size(), tagNumber);
+ assertEquals(mInteroperabilityIfdValue.size(), tagNumber);
}
private void checkTag(ExifTag tag, IfdParser ifdParser, HashMap<Short, String> truth)
throws IOException {
- assertEquals(truth.get(tag.getTagId()), readValueToString(tag, ifdParser));
+ String truthString = truth.get(tag.getTagId());
+ if (truthString == null) {
+ fail(String.format("Unknown Tag %02x", tag.getTagId()));
+ }
+ String dataString = readValueToString(tag, ifdParser);
+ if (!truthString.equals(dataString)) {
+ fail(String.format("Tag %02x: expect %s but %s",
+ tag.getTagId(), truthString, dataString));
+ }
}
private String readValueToString(ExifTag tag, IfdParser parser) throws IOException {
@@ -220,11 +279,16 @@ public class ExifParserTest extends InstrumentationTestCase {
parser.read(buf);
for(int i = 0; i < tag.getComponentCount(); i++) {
if(i != 0) sbuilder.append(" ");
- sbuilder.append(buf[i]);
+ sbuilder.append(String.format("%02x", buf[i]));
}
break;
case ExifTag.TYPE_ASCII:
- sbuilder.append(parser.readString(tag.getComponentCount()));
+ buf = new byte[tag.getComponentCount()];
+ parser.read(buf);
+ int length = 0;
+ while (buf[length] != 0 && length < buf.length) length++;
+ // trim the string to fit the answer from xml
+ sbuilder.append(new String(buf, 0, length).trim());
break;
case ExifTag.TYPE_INT:
for(int i = 0; i < tag.getComponentCount(); i++) {
@@ -263,7 +327,7 @@ public class ExifParserTest extends InstrumentationTestCase {
parser.read(buffer);
for(int i = 0; i < tag.getComponentCount(); i++) {
if(i != 0) sbuilder.append(" ");
- sbuilder.append(buffer[i]);
+ sbuilder.append(String.format("%02x", buffer[i]));
}
break;
}
@@ -317,7 +381,7 @@ public class ExifParserTest extends InstrumentationTestCase {
if(tag.getTagId() == ExifTag.TIFF_TAG.TAG_EXIF_IFD) {
parseExifIfd(ifdParser.parseIfdBlock());
} else {
- checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, IFD0_VALUE);
+ checkTag(ifdParser.getCorrespodingExifTag(), ifdParser, mIfd0Value);
}
break;
}
@@ -332,14 +396,13 @@ public class ExifParserTest extends InstrumentationTestCase {
while (type != IfdParser.TYPE_END && type != IfdParser.TYPE_NEXT_IFD) {
type = ifdParser.next();
}
- // We should meet next_ifd before end
- assertTrue(type != IfdParser.TYPE_END);
-
+ if (type == IfdParser.TYPE_END) {
+ Log.i(TAG, "No Thumbnail");
+ return;
+ }
IfdParser ifd1Parser = ifdParser.parseIfdBlock();
int thumbOffset = 0;
int thumbSize = 0;
- int width = 0;
- int height = 0;
boolean isFinishRead = false;
while (!isFinishRead) {
switch (ifd1Parser.next()) {
@@ -354,20 +417,8 @@ public class ExifParserTest extends InstrumentationTestCase {
long unsignedInt = ifdParser.readUnsignedInt();
assertTrue(unsignedInt <= Integer.MAX_VALUE);
thumbSize = (int) unsignedInt;
- } else if (tag.getTagId() == ExifTag.TIFF_TAG.TAG_IMAGE_WIDTH) {
- long unsigned = tag.getDataType() == ExifTag.TYPE_INT ?
- ifd1Parser.readUnsignedInt() : ifd1Parser.readUnsignedShort();
- assertTrue(unsigned <= (tag.getDataType() == ExifTag.TYPE_INT ?
- Integer.MAX_VALUE: Short.MAX_VALUE));
- width = (int) unsigned;
- } else if (tag.getTagId() == ExifTag.TIFF_TAG.TAG_IMAGE_HEIGHT) {
- long unsigned = tag.getDataType() == ExifTag.TYPE_INT ?
- ifd1Parser.readUnsignedInt() : ifd1Parser.readUnsignedShort();
- assertTrue(unsigned <= (tag.getDataType() == ExifTag.TYPE_INT ?
- Integer.MAX_VALUE: Short.MAX_VALUE));
- height = (int) unsigned;
}
- isFinishRead = thumbOffset != 0 && thumbSize != 0 && width != 0 && height != 0;
+ isFinishRead = thumbOffset != 0 && thumbSize != 0;
break;
case IfdParser.TYPE_END:
fail("No thumbnail information found");
@@ -381,12 +432,13 @@ public class ExifParserTest extends InstrumentationTestCase {
Bitmap bmp = BitmapFactory.decodeByteArray(buf, 0, thumbSize);
// Check correctly decoded
assertTrue(bmp != null);
- assertEquals(width, bmp.getWidth());
- assertEquals(height, bmp.getHeight());
}
@Override
protected void tearDown() throws IOException {
mImageInputStream.close();
+ mIfd0Value.clear();
+ mIfd1Value.clear();
+ mExifIfdValue.clear();
}
}
diff --git a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java
new file mode 100644
index 000000000..7f7a228e5
--- /dev/null
+++ b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java
@@ -0,0 +1,56 @@
+/*
+ * 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.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+import com.android.gallery3d.tests.R;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.Method;
+
+public class ExifTestRunner extends InstrumentationTestRunner {
+ private static final int[] IMG_RESOURCE = {
+ R.raw.galaxy_nexus
+ };
+ private static final int[] EXIF_DATA_RESOURCE = {
+ R.xml.galaxy_nexus
+ };
+
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ for (Method method : ExifParserTest.class.getDeclaredMethods()) {
+ if (method.getName().startsWith("test") && method.getParameterTypes().length == 0) {
+ for (int i = 0; i < IMG_RESOURCE.length; i++) {
+ TestCase test = new ExifParserTest(IMG_RESOURCE[i], EXIF_DATA_RESOURCE[i]);
+ test.setName(method.getName());
+ suite.addTest(test);
+ }
+ }
+ }
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return ExifTestRunner.class.getClassLoader();
+ }
+}