ExifModifierTest.java revision 6e6a524390d8ddebce5de0dcc8ae258e652ec80a
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gallery3d.exif;
18
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.FileOutputStream;
22import java.io.InputStream;
23import java.io.RandomAccessFile;
24import java.nio.MappedByteBuffer;
25import java.nio.channels.FileChannel.MapMode;
26import java.util.HashMap;
27import java.util.List;
28import java.util.Map;
29
30public class ExifModifierTest extends ExifXmlDataTestCase {
31
32    private File mTmpFile;
33    private List<Map<Short, List<String>>> mGroundTruth;
34    private ExifInterface mInterface;
35    private Map<Short, ExifTag> mTestTags;
36    ExifTag mVersionTag;
37    ExifTag mGpsVersionTag;
38    ExifTag mModelTag;
39    ExifTag mDateTimeTag;
40    ExifTag mCompressionTag;
41    ExifTag mThumbnailFormatTag;
42    ExifTag mLongitudeTag;
43    ExifTag mShutterTag;
44
45    @Override
46    public void setUp() throws Exception {
47        super.setUp();
48        mGroundTruth = ExifXmlReader.readXml(getXmlParser());
49        mTmpFile = File.createTempFile("exif_test", ".jpg");
50        FileOutputStream os = null;
51        InputStream is = getImageInputStream();
52        try {
53            os = new FileOutputStream(mTmpFile);
54            byte[] buf = new byte[1024];
55            int n;
56            while ((n = is.read(buf)) > 0) {
57                os.write(buf, 0, n);
58            }
59        } finally {
60            Util.closeSilently(os);
61        }
62
63        // TYPE_UNDEFINED with 4 components
64        mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] {
65                1, 2, 3, 4
66        });
67        // TYPE_UNSIGNED_BYTE with 4 components
68        mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] {
69                4, 3, 2, 1
70        });
71        // TYPE ASCII with arbitary length
72        mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "end-of-the-world");
73        // TYPE_ASCII with 20 components
74        mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2012:12:31 23:59:59");
75        // TYPE_UNSIGNED_SHORT with 1 components
76        mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100);
77        // TYPE_UNSIGNED_LONG with 1 components
78        mThumbnailFormatTag =
79                mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100);
80        // TYPE_UNSIGNED_RATIONAL with 3 components
81        mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] {
82                new Rational(1, 1), new Rational(10, 10),
83                new Rational(100, 100)
84        });
85        // TYPE_RATIONAL with 1 components
86        mShutterTag = mInterface
87                .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(1, 1));
88
89        mTestTags = new HashMap<Short, ExifTag>();
90
91        mTestTags.put(mVersionTag.getTagId(), mVersionTag);
92        mTestTags.put(mGpsVersionTag.getTagId(), mGpsVersionTag);
93        mTestTags.put(mModelTag.getTagId(), mModelTag);
94        mTestTags.put(mDateTimeTag.getTagId(), mDateTimeTag);
95        mTestTags.put(mCompressionTag.getTagId(), mCompressionTag);
96        mTestTags.put(mThumbnailFormatTag.getTagId(), mThumbnailFormatTag);
97        mTestTags.put(mLongitudeTag.getTagId(), mLongitudeTag);
98        mTestTags.put(mShutterTag.getTagId(), mShutterTag);
99    }
100
101    public ExifModifierTest(int imageRes, int xmlRes) {
102        super(imageRes, xmlRes);
103        mInterface = new ExifInterface();
104    }
105
106    public ExifModifierTest(String imagePath, String xmlPath) {
107        super(imagePath, xmlPath);
108        mInterface = new ExifInterface();
109    }
110
111    public void testModify() throws Exception {
112        Map<Short, Boolean> results = new HashMap<Short, Boolean>();
113
114        RandomAccessFile file = null;
115        try {
116            file = new RandomAccessFile(mTmpFile, "rw");
117            MappedByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());
118            for (ExifTag tag : mTestTags.values()) {
119                ExifModifier modifier = new ExifModifier(buf, mInterface);
120                modifier.modifyTag(tag);
121                boolean result = modifier.commit();
122                results.put(tag.getTagId(), result);
123                buf.force();
124                buf.position(0);
125
126                if (!result) {
127                    List<String> value = mGroundTruth.get(tag.getIfd()).get(tag.getTagId());
128                    assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
129                            value == null || tag.getTagId() == ExifInterface.TAG_MODEL);
130                }
131            }
132        } finally {
133            Util.closeSilently(file);
134        }
135
136        // Parse the new file and check the result
137        InputStream is = null;
138        try {
139            is = new FileInputStream(mTmpFile);
140            ExifData data = new ExifReader(mInterface).read(is);
141            for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
142                checkIfd(data.getIfdData(i), mGroundTruth.get(i), results);
143            }
144        } finally {
145            Util.closeSilently(is);
146        }
147
148    }
149
150    private void checkIfd(IfdData ifd, Map<Short, List<String>> ifdValue,
151            Map<Short, Boolean> results) {
152        if (ifd == null) {
153            assertEquals(getImageTitle(), 0, ifdValue.size());
154            return;
155        }
156        ExifTag[] tags = ifd.getAllTags();
157        for (ExifTag tag : tags) {
158            List<String> truth = ifdValue.get(tag.getTagId());
159            assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth);
160            if (truth.contains(null)) {
161                continue;
162            }
163
164            ExifTag newTag = mTestTags.get(tag.getTagId());
165            if (newTag != null
166                    && results.get(tag.getTagId())) {
167                assertEquals(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
168                        Util.tagValueToString(newTag), Util.tagValueToString(tag));
169            } else {
170                assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
171                        truth.contains(Util.tagValueToString(tag).trim()));
172            }
173        }
174        assertEquals(getImageTitle(), ifdValue.size(), tags.length);
175    }
176
177    @Override
178    public void tearDown() throws Exception {
179        super.tearDown();
180        mTmpFile.delete();
181    }
182}
183