main.c revision 7a314dab81f01bac02d617ffca9dbf7b6cc00700
134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectCopyright (c) 2008, The Android Open Source Project 434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectAll rights reserved. 534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectRedistribution and use in source and binary forms, with or without 734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectmodification, are permitted provided that the following conditions 834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectare met: 934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Redistributions of source code must retain the above copyright 1034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project notice, this list of conditions and the following disclaimer. 1134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Redistributions in binary form must reproduce the above copyright 1234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project notice, this list of conditions and the following disclaimer in 13db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync the documentation and/or other materials provided with the 1434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project distribution. 1534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Neither the name of Google, Inc. nor the names of its contributors 1634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project may be used to endorse or promote products derived from this 1734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project software without specific prior written permission. 1834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectFOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 2334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectCOPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 26db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo syncOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectAND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectOF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectSUCH DAMAGE. 3134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 3234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project*/ 3334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 3434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <nativehelper/JNIHelp.h> 3534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <nativehelper/jni.h> 3634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 3734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <assert.h> 38189fc1d078bf9bb74fa74645b6d6c4e3b58da001Dongwon Kang#include <ctype.h> 3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <dlfcn.h> 4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <stdio.h> 4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <string.h> 4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <sys/stat.h> 4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <utils/Log.h> 4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h" 4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifndef NELEM 4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0]))) 4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 5034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Define the line below to turn on poor man's debugging output 5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef SUPERDEBUG 5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Various tests 5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef REALLOCTEST 5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef OUTOFMEMORYTEST1 5734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void addExifAttibute(JNIEnv *env, jmethodID putMethod, jobject hashMap, char* key, char* value) { 5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jstring jkey = (*env)->NewStringUTF(env, key); 6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jstring jvalue = (*env)->NewStringUTF(env, value); 6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, putMethod, jkey, jvalue); 6334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jkey, key); 6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jvalue, value); 6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectextern void ResetJpgfile(); 6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int loadExifInfo(const char* FileName, int readJPG) { 7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 727a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("loadExifInfo"); 7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int Modified = FALSE; 7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ReadMode_t ReadMode = READ_METADATA; 7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (readJPG) { 7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Must add READ_IMAGE else we can't write the JPG back out. 7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ReadMode |= READ_IMAGE; 7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 827a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("ResetJpgfile"); 8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 8434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ResetJpgfile(); 8534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Start with an empty image information structure. 8734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memset(&ImageInfo, 0, sizeof(ImageInfo)); 8834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FlashUsed = -1; 8934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.MeteringMode = -1; 9034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.Whitebalance = -1; 91db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 9234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Store file date/time. 9334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 9434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project struct stat st; 9534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (stat(FileName, &st) >= 0) { 9634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FileDateTime = st.st_mtime; 9734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FileSize = st.st_size; 9834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 9934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 10034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.FileName, FileName, PATH_MAX); 10234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1037a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("ReadJpegFile"); 10434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 10534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return ReadJpegFile(FileName, ReadMode); 10634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 10734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void saveJPGFile(const char* filename) { 10934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char backupName[400]; 11034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project struct stat buf; 11134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1137a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("Modified: %s\n", filename); 11434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 11534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(backupName, filename, 395); 11734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcat(backupName, ".t"); 11834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Remove any .old file name that may pre-exist 12034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1217a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("removing backup %s", backupName); 12234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 12334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unlink(backupName); 12434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 12534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Rename the old file. 12634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1277a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("rename %s to %s", filename, backupName); 12834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 12934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project rename(filename, backupName); 13034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 13134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Write the new file. 13234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1337a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("WriteJpegFile %s", filename); 13434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 13534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (WriteJpegFile(filename)) { 136db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 13734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Copy the access rights from original file 13834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1397a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("stating old file %s", backupName); 14034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 14134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (stat(backupName, &buf) == 0){ 14234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // set Unix access rights and time to new file 14334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project struct utimbuf mtime; 14434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project chmod(filename, buf.st_mode); 145db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 14634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project mtime.actime = buf.st_mtime; 14734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project mtime.modtime = buf.st_mtime; 148db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 14934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project utime(filename, &mtime); 15034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 151db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 15234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Now that we are done, remove original file. 15334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1547a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("unlinking old file %s", backupName); 15534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 15634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unlink(backupName); 15734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1587a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("returning from saveJPGFile"); 15934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 16034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 16134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1627a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("WriteJpegFile failed, restoring from backup file"); 16334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 16434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // move back the backup file 16534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project rename(backupName, filename); 16634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 16734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 16834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 16934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid copyThumbnailData(uchar* thumbnailData, int thumbnailLen) { 17034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1717a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("******************************** copyThumbnailData\n"); 17234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 17334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Section_t* ExifSection = FindSection(M_EXIF); 17434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection == NULL) { 17534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 17634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 17734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int NewExifSize = ImageInfo.ThumbnailOffset+8+thumbnailLen; 17834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Data = (uchar *)realloc(ExifSection->Data, NewExifSize); 17934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection->Data == NULL) { 18034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 18134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 18234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* ThumbnailPointer = ExifSection->Data+ImageInfo.ThumbnailOffset+8; 18334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(ThumbnailPointer, thumbnailData, thumbnailLen); 18534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailSize = thumbnailLen; 18734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(ExifSection->Data+ImageInfo.ThumbnailSizeOffset+8, thumbnailLen); 18934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 19034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Data[0] = (uchar)(NewExifSize >> 8); 19134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Data[1] = (uchar)NewExifSize; 19234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Size = NewExifSize; 19334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 19434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 19534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void saveAttributes(JNIEnv *env, jobject jobj, jstring jfilename, jstring jattributes) 19634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 19734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 1987a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("******************************** saveAttributes\n"); 19934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 20034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // format of attributes string passed from java: 20134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // "attrCnt attr1=valueLen value1attr2=value2Len value2..." 20234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // example input: "4 ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO" 20334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifElement_t* exifElementTable = NULL; 20434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = NULL; 20534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* thumbnailData = NULL; 20634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int attrCnt = 0; 20734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* attributes = (*env)->GetStringUTFChars(env, jattributes, NULL); 20834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (attributes == NULL) { 20934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 21034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 21134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2127a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("attributes %s\n", attributes); 21334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 21434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 21534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Get the number of attributes - it's the first number in the string. 21634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrCnt = atoi(attributes); 21734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* attrPtr = strchr(attributes, ' ') + 1; 21834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2197a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("attribute count %d attrPtr %s\n", attrCnt, attrPtr); 22034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 22134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 22234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Load all the hash exif elements into a more c-like structure 22334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable = malloc(sizeof(ExifElement_t) * attrCnt); 22434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifElementTable == NULL) { 22534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 22634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 22734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef OUTOFMEMORYTEST1 22834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 22934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 23034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 23134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int i; 23234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char tag[100]; 23334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int gpsTagCount = 0; 23434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int exifTagCount = 0; 23534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 23634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < attrCnt; i++) { 23734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // get an element from the attribute string and add it to the c structure 23834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // first, extract the attribute name 23934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* tagEnd = strchr(attrPtr, '='); 24034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (tagEnd == 0) { 24134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2427a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("saveAttributes: couldn't find end of tag"); 24334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 24434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 24534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 24634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (tagEnd - attrPtr > 99) { 24734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2487a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("saveAttributes: attribute tag way too long"); 24934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 25034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 25134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 25234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(tag, attrPtr, tagEnd - attrPtr); 25334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project tag[tagEnd - attrPtr] = 0; 25434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 25534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (IsGpsTag(tag)) { 25634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].GpsTag = TRUE; 25734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Tag = GpsTagNameToValue(tag); 25834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++gpsTagCount; 25934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 26034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].GpsTag = FALSE; 26134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Tag = TagNameToValue(tag); 26234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++exifTagCount; 26334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 26434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrPtr = tagEnd + 1; 26534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 26634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // next get the length of the attribute value 26734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int valueLen = atoi(attrPtr); 26834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrPtr = strchr(attrPtr, ' ') + 1; 26934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (attrPtr == 0) { 27034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2717a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("saveAttributes: couldn't find end of value len"); 27234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 27334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 27434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 27534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Value = malloc(valueLen + 1); 27634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifElementTable[i].Value == NULL) { 27734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 27834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 27934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(exifElementTable[i].Value, attrPtr, valueLen); 28034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Value[valueLen] = 0; 28134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].DataLength = valueLen; 28234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 28334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrPtr += valueLen; 28434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 28534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2867a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("tag %s id %d value %s data length=%d isGps=%d", tag, exifElementTable[i].Tag, 28734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Value, exifElementTable[i].DataLength, exifElementTable[i].GpsTag); 28834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 28934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 29034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 29134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 29234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 2937a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("Call loadAttributes() with filename is %s. Loading exif info\n", filename); 29434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 29534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project loadExifInfo(filename, TRUE); 29634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 29734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 29834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// DumpExifMap = TRUE; 29934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowTags = TRUE; 30034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 3017a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("create exif 2"); 30234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 30334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 30434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If the jpg file has a thumbnail, preserve it. 30534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int thumbnailLength = ImageInfo.ThumbnailSize; 30634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ThumbnailOffset) { 30734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Section_t* ExifSection = FindSection(M_EXIF); 30834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection) { 30934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8; 31034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project thumbnailData = (uchar*)malloc(ImageInfo.ThumbnailSize); 31134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // if the malloc fails, we just won't copy the thumbnail 31234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailData) { 31334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(thumbnailData, thumbnailPointer, thumbnailLength); 31434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 31834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project create_EXIF(exifElementTable, exifTagCount, gpsTagCount); 31934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 32034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailData) { 32134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project copyThumbnailData(thumbnailData, thumbnailLength); 32234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 32334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 32434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectexit: 32534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 3267a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("cleaning up now in saveAttributes"); 32734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 32834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // try to clean up resources 32934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (attributes) { 33034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jattributes, attributes); 33134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 33334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 33434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifElementTable) { 33634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // free the table 33734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < attrCnt; i++) { 33834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(exifElementTable[i].Value); 33934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 34034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(exifElementTable); 34134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 34234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailData) { 34334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(thumbnailData); 34434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 34534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 3467a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("returning from saveAttributes"); 34734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 34834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 34934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Temporarily saving these commented out lines because they represent a lot of figuring out 35034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// patterns for JNI. 35134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "entrySet" 35234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID entrySetMethod = (*env)->GetMethodID(env, jclass_of_hashmap, "entrySet", "()Ljava/util/Set;"); 35334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 35434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Invoke the "entrySet" method on the HashMap object 35534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, entrySetMethod); 35634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 35734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get the Set Class 35834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jclass jclass_of_set = (*env)->FindClass(env, "java/util/Set"); 35934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 36034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// if (jclass_of_set == 0) { 36134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// printf("java/util/Set lookup failed\n"); 36234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// return; 36334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// } 36434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 36534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "iterator" 36634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID iteratorMethod = (*env)->GetMethodID(env, jclass_of_set, "iterator", "()Ljava/util/Iterator;"); 36734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 36834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Invoke the "iterator" method on the jobject_of_entryset variable of type Set 36934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jobject jobject_of_iterator = (*env)->CallObjectMethod(env, jobject_of_entryset, iteratorMethod); 37034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 37134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get the "Iterator" class 37234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jclass jclass_of_iterator = (*env)->FindClass(env, "java/util/Iterator"); 37334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 37434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "hasNext" 37534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID hasNextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "hasNext", "()Z"); 37634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 37734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Invoke - Get the value hasNextMethod 37834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jboolean bHasNext = (*env)->CallBooleanMethod(env, jobject_of_iterator, hasNextMethod); 37934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 38034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "hasNext" 38134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID nextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "next", "()Ljava/util/Map/Entry;"); 38234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 38334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jclass jclass_of_mapentry = (*env)->FindClass(env, "java/util/Map/Entry"); 38434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 38534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID getKeyMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getKey", "()Ljava/lang/Object"); 38634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 38734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID getValueMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getValue", "()Ljava/lang/Object"); 38834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 38934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 39034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jboolean appendThumbnail(JNIEnv *env, jobject jobj, jstring jfilename, jstring jthumbnailfilename) 39134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 39234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 3937a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("******************************** appendThumbnail\n"); 39434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 39534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 39634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 39734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename == NULL) { 39834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 39934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 40034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* thumbnailfilename = (*env)->GetStringUTFChars(env, jthumbnailfilename, NULL); 40134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailfilename == NULL) { 40234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 40334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 40434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #ifdef SUPERDEBUG 4057a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("*******before actual call to ReplaceThumbnail\n"); 40634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 40734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #endif 40834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ReplaceThumbnail(thumbnailfilename); 40934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #ifdef SUPERDEBUG 41034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 41134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #endif 41234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 41334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jthumbnailfilename, thumbnailfilename); 414db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 41534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DiscardData(); 41634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_TRUE; 41734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 41834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 41934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void commitChanges(JNIEnv *env, jobject jobj, jstring jfilename) 42034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 42134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 4227a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("******************************** commitChanges\n"); 42334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 42434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 42534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 42634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project saveJPGFile(filename); 4276a3cf8f158c6f0f7e069f8aeb0825a3fefeabd02Chih-Chung Chang DiscardData(); 42834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 42934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 43034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 43134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jbyteArray getThumbnail(JNIEnv *env, jobject jobj, jstring jfilename) 43334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 43434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 4357a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("******************************** getThumbnail\n"); 43634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 43734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 43934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 44034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project loadExifInfo(filename, FALSE); 44134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Section_t* ExifSection = FindSection(M_EXIF); 44234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection == NULL || ImageInfo.ThumbnailSize == 0) { 44334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 4447a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("no exif section or size == 0, so no thumbnail\n"); 44534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 44634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto noThumbnail; 44734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 44834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8; 44934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 45034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jbyteArray byteArray = (*env)->NewByteArray(env, ImageInfo.ThumbnailSize); 45134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (byteArray == NULL) { 45234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 4537a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("couldn't allocate thumbnail memory, so no thumbnail\n"); 45434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 45534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto noThumbnail; 45634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 45734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->SetByteArrayRegion(env, byteArray, 0, ImageInfo.ThumbnailSize, thumbnailPointer); 45834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 4597a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("thumbnail size %d\n", ImageInfo.ThumbnailSize); 46034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 46134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 462eb7bd1066e19b5ef048fda5f756c4bb0bc891f30Jiangping Wu DiscardData(); 46334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return byteArray; 46434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 46534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectnoThumbnail: 46634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 46734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 46834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 46934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DiscardData(); 47034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 47134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 47234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 47334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int attributeCount; // keep track of how many attributes we've added 47434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 47534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length 47634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueString(char** buf, int bufLen, const char* key, const char* value) { 47734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Appends to buf like this: "ImageLength=4 1024" 47834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 47934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char valueLen[15]; 48034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(valueLen, 15, "=%d ", (int)strlen(value)); 48134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 48234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // check to see if buf has enough room to append 48334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int len = strlen(key) + strlen(valueLen) + strlen(value); 48434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int newLen = strlen(*buf) + len; 48534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (newLen >= bufLen) { 48634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef REALLOCTEST 48734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = newLen + 5; 4887a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("reallocing to %d", bufLen); 48934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#else 49034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = newLen + 500; 49134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 49234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project *buf = realloc(*buf, bufLen); 49334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (*buf == NULL) { 49434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return 0; 49534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 49634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 49734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // append the new attribute and value 49834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(*buf + strlen(*buf), bufLen, "%s%s%s", key, valueLen, value); 49934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 5007a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("buf %s", *buf); 50134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 50234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++attributeCount; 50334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return bufLen; 50434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 50534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 50634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length 50734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueInt(char** buf, int bufLen, const char* key, int value) { 50834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char valueStr[20]; 50934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(valueStr, 20, "%d", value); 51034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 51134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return addKeyValueString(buf, bufLen, key, valueStr); 51234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 51334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 51434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length 51534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueDouble(char** buf, int bufLen, const char* key, double value, const char* format) { 51634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char valueStr[30]; 51734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(valueStr, 30, format, value); 51834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 51934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return addKeyValueString(buf, bufLen, key, valueStr); 52034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 52134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 522574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li// Returns new buffer length. Rational value will be appended as "numerator/denominator". 523574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Listatic int addKeyValueRational(char** buf, int bufLen, const char* key, rat_t value) { 524574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li char valueStr[25]; 525574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li snprintf(valueStr, sizeof(valueStr), "%u/%u", value.num, value.denom); 526574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li return addKeyValueString(buf, bufLen, key, valueStr); 527574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li} 528574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li 52934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jstring getAttributes(JNIEnv *env, jobject jobj, jstring jfilename) 53034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 53134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 5327a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("******************************** getAttributes\n"); 53334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 53434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 53534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project loadExifInfo(filename, FALSE); 53634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 53734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 53834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 53934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 54034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 54134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attributeCount = 0; 54234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef REALLOCTEST 54334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int bufLen = 5; 54434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#else 54534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int bufLen = 1000; 54634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 54734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* buf = malloc(bufLen); 54834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (buf == NULL) { 54934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 55034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 55134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project *buf = 0; // start the string out at zero length 55234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 55334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // save a fake "hasThumbnail" tag to pass to the java ExifInterface 55434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "hasThumbnail", 55534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailOffset == 0 || ImageInfo.ThumbnailAtEnd == FALSE || ImageInfo.ThumbnailSize == 0 ? 55634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "false" : "true"); 55734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 55834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 55934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.CameraMake[0]) { 56034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "Make", ImageInfo.CameraMake); 56134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 56234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 56334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.CameraModel[0]) { 56434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "Model", ImageInfo.CameraModel); 56534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 56634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 56734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.DateTime[0]) { 56834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "DateTime", ImageInfo.DateTime); 56934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 57134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ImageWidth", ImageInfo.Width); 57234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 57434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ImageLength", ImageInfo.Height); 57534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 57734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "Orientation", ImageInfo.Orientation); 57834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5802856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen if (ImageInfo.FlashUsed >= 0) { 5812856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen bufLen = addKeyValueInt(&buf, bufLen, "Flash", ImageInfo.FlashUsed); 5822856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen if (bufLen == 0) return NULL; 5832856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen } 58434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 585574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li if (ImageInfo.FocalLength.num != 0 && ImageInfo.FocalLength.denom != 0) { 586574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li bufLen = addKeyValueRational(&buf, bufLen, "FocalLength", ImageInfo.FocalLength); 58734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 58834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 58934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 59034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.DigitalZoomRatio > 1.0){ 59134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Digital zoom used. Shame on you! 59234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "DigitalZoomRatio", ImageInfo.DigitalZoomRatio, "%1.3f"); 59334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 59434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 59534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 59634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime){ 59734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* format; 59834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime < 0.010){ 59934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project format = "%6.4f"; 60034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 60134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project format = "%5.3f"; 60234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 60334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "ExposureTime", (double)ImageInfo.ExposureTime, format); 60534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 60634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 60734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ApertureFNumber){ 60934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "FNumber", (double)ImageInfo.ApertureFNumber, "%3.1f"); 61034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 61134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 61234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 61334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Distance){ 61434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "SubjectDistance", (double)ImageInfo.Distance, "%4.2f"); 61534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 61634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 61734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 61834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ISOequivalent){ 61934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ISOSpeedRatings", ImageInfo.ISOequivalent); 62034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 62134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 62234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 62334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureBias){ 62434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If exposure bias was specified, but set to zero, presumably its no bias at all, 62534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // so only show it if its nonzero. 62634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "ExposureBiasValue", (double)ImageInfo.ExposureBias, "%4.2f"); 62734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 62834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 62934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6302856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen if (ImageInfo.Whitebalance >= 0) { 6312856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen bufLen = addKeyValueInt(&buf, bufLen, "WhiteBalance", ImageInfo.Whitebalance); 6322856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen if (bufLen == 0) return NULL; 6332856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen } 63434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "LightSource", ImageInfo.LightSource); 63634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 63734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.MeteringMode) { 64034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "MeteringMode", ImageInfo.MeteringMode); 64134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 64234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 64334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 64434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureProgram) { 64534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ExposureProgram", ImageInfo.ExposureProgram); 64634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 64734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 64834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 64934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureMode) { 65034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ExposureMode", ImageInfo.ExposureMode); 65134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 65234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 65334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 65434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.GpsInfoPresent) { 6558d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLatRaw[0]) { 6568d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLatitude", ImageInfo.GpsLatRaw); 6578d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6588d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 6598d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLatRef[0]) { 6608d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLatitudeRef", ImageInfo.GpsLatRef); 6618d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6628d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 6638d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLongRaw[0]) { 6648d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLongitude", ImageInfo.GpsLongRaw); 6658d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6668d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 6678d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLongRef[0]) { 6688d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLongitudeRef", ImageInfo.GpsLongRef); 6698d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6708d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 67134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.GpsAlt[0]) { 6721ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li bufLen = addKeyValueRational(&buf, bufLen, "GPSAltitude", ImageInfo.GpsAltRaw); 6731ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li bufLen = addKeyValueInt(&buf, bufLen, "GPSAltitudeRef", ImageInfo.GpsAltRef); 67434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 67534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 676a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (ImageInfo.GpsDateStamp[0]) { 677a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen bufLen = addKeyValueString(&buf, bufLen, "GPSDateStamp", ImageInfo.GpsDateStamp); 678a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (bufLen == 0) return NULL; 679a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen } 680a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (ImageInfo.GpsTimeStamp[0]) { 681a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen bufLen = addKeyValueString(&buf, bufLen, "GPSTimeStamp", ImageInfo.GpsTimeStamp); 682a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (bufLen == 0) return NULL; 683a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen } 684434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen if (ImageInfo.GpsProcessingMethod[0]) { 685434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSProcessingMethod", ImageInfo.GpsProcessingMethod); 686434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen if (bufLen == 0) return NULL; 687434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen } 68834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 68934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 69034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Comments[0]) { 69134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "UserComment", ImageInfo.Comments); 69234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 69334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 69434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 69534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // put the attribute count at the beginnnig of the string 69634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int finalBufLen = strlen(buf) + 20; 69734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* finalResult = malloc(finalBufLen); 69834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (finalResult == NULL) { 69934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(buf); 70034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 70134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 70234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(finalResult, finalBufLen, "%d %s", attributeCount, buf); 70334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int k; 70434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (k = 0; k < finalBufLen; k++) 705189fc1d078bf9bb74fa74645b6d6c4e3b58da001Dongwon Kang if (!isascii(finalResult[k])) 70634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project finalResult[k] = '?'; 70734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(buf); 70834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 70934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 7107a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("*********Returning result \"%s\"", finalResult); 71134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 71234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jstring result = ((*env)->NewStringUTF(env, finalResult)); 71334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(finalResult); 71434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DiscardData(); 71534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return result; 71634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 71734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 718db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo syncstatic const char *classPathName = "android/media/ExifInterface"; 71934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 72034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic JNINativeMethod methods[] = { 72134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"saveAttributesNative", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)saveAttributes }, 72234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"getAttributesNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getAttributes }, 72334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"appendThumbnailNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)appendThumbnail }, 72434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"commitChangesNative", "(Ljava/lang/String;)V", (void*)commitChanges }, 72534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"getThumbnailNative", "(Ljava/lang/String;)[B", (void*)getThumbnail }, 72634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}; 72734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 72834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 72934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Register several native methods for one class. 73034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */ 73134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int registerNativeMethods(JNIEnv* env, const char* className, 73234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project JNINativeMethod* gMethods, int numMethods) 73334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 73434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jclass clazz; 73534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 73634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project clazz = (*env)->FindClass(env, className); 73734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (clazz == NULL) { 73834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, 73934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "Native registration unable to find class '%s'\n", className); 74034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 74134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 74234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) { 74334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, "RegisterNatives failed for '%s'\n", className); 74434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 74534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 74634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 74734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_TRUE; 74834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 74934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 75034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 75134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Register native methods for all classes we know about. 75234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */ 75334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int registerNatives(JNIEnv* env) 75434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 75534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return jniRegisterNativeMethods(env, classPathName, 75634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project methods, NELEM(methods)); 75734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 75834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 75934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 76034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Set some test stuff up. 76134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * 76234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Returns the JNI version on success, -1 on failure. 76334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */ 76434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project__attribute__ ((visibility("default"))) jint JNI_OnLoad(JavaVM* vm, void* reserved) 76534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 76634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project JNIEnv* env = NULL; 76734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jint result = -1; 76834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 76934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { 77034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, "ERROR: GetEnv failed\n"); 77134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto bail; 77234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 77334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project assert(env != NULL); 77434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 77534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("In mgmain JNI_OnLoad\n"); 77634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 77734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (registerNatives(env) < 0) { 77834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, "ERROR: Exif native registration failed\n"); 77934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto bail; 78034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 78134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 78234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project /* success -- return valid version number */ 78334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project result = JNI_VERSION_1_4; 78434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 78534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectbail: 78634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return result; 78734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 788