main.c revision 8d61723fea0a5cdcd08e34325123fbd3e0bd41ae
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> 3834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <dlfcn.h> 3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <stdio.h> 4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <string.h> 4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <sys/stat.h> 4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <utils/Log.h> 4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h" 4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifndef NELEM 4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0]))) 4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Define the line below to turn on poor man's debugging output 5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef SUPERDEBUG 5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Various tests 5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef REALLOCTEST 5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef OUTOFMEMORYTEST1 5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void addExifAttibute(JNIEnv *env, jmethodID putMethod, jobject hashMap, char* key, char* value) { 5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jstring jkey = (*env)->NewStringUTF(env, key); 5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jstring jvalue = (*env)->NewStringUTF(env, value); 6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, putMethod, jkey, jvalue); 6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jkey, key); 6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jvalue, value); 6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectextern void ResetJpgfile(); 6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int loadExifInfo(const char* FileName, int readJPG) { 7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("loadExifInfo"); 7234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int Modified = FALSE; 7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ReadMode_t ReadMode = READ_METADATA; 7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (readJPG) { 7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Must add READ_IMAGE else we can't write the JPG back out. 7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ReadMode |= READ_IMAGE; 7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("ResetJpgfile"); 8234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ResetJpgfile(); 8434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Start with an empty image information structure. 8634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memset(&ImageInfo, 0, sizeof(ImageInfo)); 8734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FlashUsed = -1; 8834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.MeteringMode = -1; 8934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.Whitebalance = -1; 90db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 9134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Store file date/time. 9234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 9334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project struct stat st; 9434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (stat(FileName, &st) >= 0) { 9534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FileDateTime = st.st_mtime; 9634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FileSize = st.st_size; 9734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 9834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 9934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.FileName, FileName, PATH_MAX); 10134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 10234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("ReadJpegFile"); 10334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 10434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return ReadJpegFile(FileName, ReadMode); 10534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 10634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void saveJPGFile(const char* filename) { 10834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char backupName[400]; 10934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project struct stat buf; 11034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 11234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("Modified: %s\n", filename); 11334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 11434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(backupName, filename, 395); 11634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcat(backupName, ".t"); 11734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Remove any .old file name that may pre-exist 11934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 12034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("removing backup %s", backupName); 12134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 12234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unlink(backupName); 12334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 12434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Rename the old file. 12534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 12634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("rename %s to %s", filename, backupName); 12734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 12834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project rename(filename, backupName); 12934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 13034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Write the new file. 13134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 13234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("WriteJpegFile %s", filename); 13334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 13434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (WriteJpegFile(filename)) { 135db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 13634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Copy the access rights from original file 13734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 13834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("stating old file %s", backupName); 13934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 14034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (stat(backupName, &buf) == 0){ 14134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // set Unix access rights and time to new file 14234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project struct utimbuf mtime; 14334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project chmod(filename, buf.st_mode); 144db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 14534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project mtime.actime = buf.st_mtime; 14634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project mtime.modtime = buf.st_mtime; 147db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 14834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project utime(filename, &mtime); 14934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 150db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 15134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Now that we are done, remove original file. 15234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 15334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("unlinking old file %s", backupName); 15434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 15534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unlink(backupName); 15634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 15734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("returning from saveJPGFile"); 15834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 15934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 16034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 16134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("WriteJpegFile failed, restoring from backup file"); 16234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 16334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // move back the backup file 16434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project rename(backupName, filename); 16534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 16634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 16734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 16834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid copyThumbnailData(uchar* thumbnailData, int thumbnailLen) { 16934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 17034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("******************************** copyThumbnailData\n"); 17134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 17234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Section_t* ExifSection = FindSection(M_EXIF); 17334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection == NULL) { 17434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 17534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 17634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int NewExifSize = ImageInfo.ThumbnailOffset+8+thumbnailLen; 17734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Data = (uchar *)realloc(ExifSection->Data, NewExifSize); 17834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection->Data == NULL) { 17934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 18034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 18134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* ThumbnailPointer = ExifSection->Data+ImageInfo.ThumbnailOffset+8; 18234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(ThumbnailPointer, thumbnailData, thumbnailLen); 18434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailSize = thumbnailLen; 18634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(ExifSection->Data+ImageInfo.ThumbnailSizeOffset+8, thumbnailLen); 18834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 18934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Data[0] = (uchar)(NewExifSize >> 8); 19034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Data[1] = (uchar)NewExifSize; 19134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifSection->Size = NewExifSize; 19234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 19334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 19434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void saveAttributes(JNIEnv *env, jobject jobj, jstring jfilename, jstring jattributes) 19534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 19634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 19734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("******************************** saveAttributes\n"); 19834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 19934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // format of attributes string passed from java: 20034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // "attrCnt attr1=valueLen value1attr2=value2Len value2..." 20134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // example input: "4 ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO" 20234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifElement_t* exifElementTable = NULL; 20334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = NULL; 20434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* thumbnailData = NULL; 20534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int attrCnt = 0; 20634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* attributes = (*env)->GetStringUTFChars(env, jattributes, NULL); 20734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (attributes == NULL) { 20834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 20934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 21034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 21134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("attributes %s\n", attributes); 21234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 21334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 21434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Get the number of attributes - it's the first number in the string. 21534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrCnt = atoi(attributes); 21634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* attrPtr = strchr(attributes, ' ') + 1; 21734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 21834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("attribute count %d attrPtr %s\n", attrCnt, attrPtr); 21934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 22034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 22134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Load all the hash exif elements into a more c-like structure 22234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable = malloc(sizeof(ExifElement_t) * attrCnt); 22334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifElementTable == NULL) { 22434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 22534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 22634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef OUTOFMEMORYTEST1 22734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 22834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 22934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 23034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int i; 23134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char tag[100]; 23234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int gpsTagCount = 0; 23334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int exifTagCount = 0; 23434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 23534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < attrCnt; i++) { 23634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // get an element from the attribute string and add it to the c structure 23734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // first, extract the attribute name 23834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* tagEnd = strchr(attrPtr, '='); 23934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (tagEnd == 0) { 24034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 24134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("saveAttributes: couldn't find end of tag"); 24234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 24334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 24434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 24534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (tagEnd - attrPtr > 99) { 24634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 24734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("saveAttributes: attribute tag way too long"); 24834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 24934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 25034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 25134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(tag, attrPtr, tagEnd - attrPtr); 25234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project tag[tagEnd - attrPtr] = 0; 25334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 25434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (IsGpsTag(tag)) { 25534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].GpsTag = TRUE; 25634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Tag = GpsTagNameToValue(tag); 25734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++gpsTagCount; 25834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 25934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].GpsTag = FALSE; 26034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Tag = TagNameToValue(tag); 26134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++exifTagCount; 26234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 26334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrPtr = tagEnd + 1; 26434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 26534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // next get the length of the attribute value 26634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int valueLen = atoi(attrPtr); 26734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrPtr = strchr(attrPtr, ' ') + 1; 26834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (attrPtr == 0) { 26934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 27034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("saveAttributes: couldn't find end of value len"); 27134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 27234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 27334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 27434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Value = malloc(valueLen + 1); 27534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifElementTable[i].Value == NULL) { 27634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto exit; 27734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 27834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(exifElementTable[i].Value, attrPtr, valueLen); 27934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Value[valueLen] = 0; 28034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].DataLength = valueLen; 28134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 28234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attrPtr += valueLen; 28334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 28434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 28534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("tag %s id %d value %s data length=%d isGps=%d", tag, exifElementTable[i].Tag, 28634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifElementTable[i].Value, exifElementTable[i].DataLength, exifElementTable[i].GpsTag); 28734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 28834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 28934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 29034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 29134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 29234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("Call loadAttributes() with filename is %s. Loading exif info\n", filename); 29334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 29434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project loadExifInfo(filename, TRUE); 29534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 29634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 29734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// DumpExifMap = TRUE; 29834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowTags = TRUE; 29934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 30034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("create exif 2"); 30134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 30234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 30334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If the jpg file has a thumbnail, preserve it. 30434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int thumbnailLength = ImageInfo.ThumbnailSize; 30534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ThumbnailOffset) { 30634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Section_t* ExifSection = FindSection(M_EXIF); 30734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection) { 30834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8; 30934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project thumbnailData = (uchar*)malloc(ImageInfo.ThumbnailSize); 31034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // if the malloc fails, we just won't copy the thumbnail 31134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailData) { 31234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(thumbnailData, thumbnailPointer, thumbnailLength); 31334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 31734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project create_EXIF(exifElementTable, exifTagCount, gpsTagCount); 31834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 31934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailData) { 32034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project copyThumbnailData(thumbnailData, thumbnailLength); 32134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 32234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 32334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectexit: 32434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 32534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("cleaning up now in saveAttributes"); 32634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 32734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // try to clean up resources 32834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (attributes) { 32934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jattributes, attributes); 33034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 33234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 33334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifElementTable) { 33534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // free the table 33634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < attrCnt; i++) { 33734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(exifElementTable[i].Value); 33834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(exifElementTable); 34034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 34134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailData) { 34234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(thumbnailData); 34334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 34434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 34534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("returning from saveAttributes"); 34634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 34734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 34834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Temporarily saving these commented out lines because they represent a lot of figuring out 34934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// patterns for JNI. 35034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "entrySet" 35134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID entrySetMethod = (*env)->GetMethodID(env, jclass_of_hashmap, "entrySet", "()Ljava/util/Set;"); 35234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 35334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Invoke the "entrySet" method on the HashMap object 35434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, entrySetMethod); 35534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 35634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get the Set Class 35734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jclass jclass_of_set = (*env)->FindClass(env, "java/util/Set"); 35834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 35934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// if (jclass_of_set == 0) { 36034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// printf("java/util/Set lookup failed\n"); 36134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// return; 36234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// } 36334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 36434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "iterator" 36534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID iteratorMethod = (*env)->GetMethodID(env, jclass_of_set, "iterator", "()Ljava/util/Iterator;"); 36634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 36734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Invoke the "iterator" method on the jobject_of_entryset variable of type Set 36834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jobject jobject_of_iterator = (*env)->CallObjectMethod(env, jobject_of_entryset, iteratorMethod); 36934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 37034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get the "Iterator" class 37134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jclass jclass_of_iterator = (*env)->FindClass(env, "java/util/Iterator"); 37234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 37334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "hasNext" 37434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID hasNextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "hasNext", "()Z"); 37534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 37634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Invoke - Get the value hasNextMethod 37734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jboolean bHasNext = (*env)->CallBooleanMethod(env, jobject_of_iterator, hasNextMethod); 37834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 37934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Get link to Method "hasNext" 38034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID nextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "next", "()Ljava/util/Map/Entry;"); 38134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 38234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jclass jclass_of_mapentry = (*env)->FindClass(env, "java/util/Map/Entry"); 38334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 38434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID getKeyMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getKey", "()Ljava/lang/Object"); 38534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 38634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// jmethodID getValueMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getValue", "()Ljava/lang/Object"); 38734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 38834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 38934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jboolean appendThumbnail(JNIEnv *env, jobject jobj, jstring jfilename, jstring jthumbnailfilename) 39034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 39134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 39234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("******************************** appendThumbnail\n"); 39334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 39434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 39534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 39634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename == NULL) { 39734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 39834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 39934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* thumbnailfilename = (*env)->GetStringUTFChars(env, jthumbnailfilename, NULL); 40034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (thumbnailfilename == NULL) { 40134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 40234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 40334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #ifdef SUPERDEBUG 40434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("*******before actual call to ReplaceThumbnail\n"); 40534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 40634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #endif 40734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ReplaceThumbnail(thumbnailfilename); 40834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #ifdef SUPERDEBUG 40934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 41034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #endif 41134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 41234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jthumbnailfilename, thumbnailfilename); 413db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync 41434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DiscardData(); 41534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_TRUE; 41634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 41734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 41834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void commitChanges(JNIEnv *env, jobject jobj, jstring jfilename) 41934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 42034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 42134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("******************************** commitChanges\n"); 42234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 42334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 42434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 42534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project saveJPGFile(filename); 4266a3cf8f158c6f0f7e069f8aeb0825a3fefeabd02Chih-Chung Chang DiscardData(); 42734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 42834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 42934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 43034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jbyteArray getThumbnail(JNIEnv *env, jobject jobj, jstring jfilename) 43234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 43334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 43434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("******************************** getThumbnail\n"); 43534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 43634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 43834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 43934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project loadExifInfo(filename, FALSE); 44034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Section_t* ExifSection = FindSection(M_EXIF); 44134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifSection == NULL || ImageInfo.ThumbnailSize == 0) { 44234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 44334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("no exif section or size == 0, so no thumbnail\n"); 44434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 44534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto noThumbnail; 44634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 44734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8; 44834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 44934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jbyteArray byteArray = (*env)->NewByteArray(env, ImageInfo.ThumbnailSize); 45034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (byteArray == NULL) { 45134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 45234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("couldn't allocate thumbnail memory, so no thumbnail\n"); 45334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 45434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto noThumbnail; 45534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 45634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->SetByteArrayRegion(env, byteArray, 0, ImageInfo.ThumbnailSize, thumbnailPointer); 45734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 45834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("thumbnail size %d\n", ImageInfo.ThumbnailSize); 45934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 46034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 46134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return byteArray; 46234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 46334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectnoThumbnail: 46434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (filename) { 46534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 46634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 46734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DiscardData(); 46834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 46934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 47034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 47134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int attributeCount; // keep track of how many attributes we've added 47234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 47334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length 47434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueString(char** buf, int bufLen, const char* key, const char* value) { 47534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Appends to buf like this: "ImageLength=4 1024" 47634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 47734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char valueLen[15]; 47834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(valueLen, 15, "=%d ", (int)strlen(value)); 47934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 48034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // check to see if buf has enough room to append 48134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int len = strlen(key) + strlen(valueLen) + strlen(value); 48234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int newLen = strlen(*buf) + len; 48334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (newLen >= bufLen) { 48434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef REALLOCTEST 48534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = newLen + 5; 48634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("reallocing to %d", bufLen); 48734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#else 48834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = newLen + 500; 48934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 49034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project *buf = realloc(*buf, bufLen); 49134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (*buf == NULL) { 49234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return 0; 49334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 49434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 49534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // append the new attribute and value 49634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(*buf + strlen(*buf), bufLen, "%s%s%s", key, valueLen, value); 49734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 49834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("buf %s", *buf); 49934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 50034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++attributeCount; 50134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return bufLen; 50234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 50334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 50434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length 50534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueInt(char** buf, int bufLen, const char* key, int value) { 50634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char valueStr[20]; 50734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(valueStr, 20, "%d", value); 50834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 50934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return addKeyValueString(buf, bufLen, key, valueStr); 51034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 51134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 51234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length 51334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueDouble(char** buf, int bufLen, const char* key, double value, const char* format) { 51434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char valueStr[30]; 51534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(valueStr, 30, format, value); 51634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 51734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return addKeyValueString(buf, bufLen, key, valueStr); 51834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 51934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 520574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li// Returns new buffer length. Rational value will be appended as "numerator/denominator". 521574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Listatic int addKeyValueRational(char** buf, int bufLen, const char* key, rat_t value) { 522574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li char valueStr[25]; 523574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li snprintf(valueStr, sizeof(valueStr), "%u/%u", value.num, value.denom); 524574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li return addKeyValueString(buf, bufLen, key, valueStr); 525574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li} 526574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li 52734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jstring getAttributes(JNIEnv *env, jobject jobj, jstring jfilename) 52834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 52934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 53034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("******************************** getAttributes\n"); 53134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 53234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); 53334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project loadExifInfo(filename, FALSE); 53434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 53534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ShowImageInfo(TRUE); 53634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 53734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*env)->ReleaseStringUTFChars(env, jfilename, filename); 53834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 53934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project attributeCount = 0; 54034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef REALLOCTEST 54134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int bufLen = 5; 54234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#else 54334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int bufLen = 1000; 54434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 54534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* buf = malloc(bufLen); 54634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (buf == NULL) { 54734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 54834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 54934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project *buf = 0; // start the string out at zero length 55034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 55134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // save a fake "hasThumbnail" tag to pass to the java ExifInterface 55234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "hasThumbnail", 55334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailOffset == 0 || ImageInfo.ThumbnailAtEnd == FALSE || ImageInfo.ThumbnailSize == 0 ? 55434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "false" : "true"); 55534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 55634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 55734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.CameraMake[0]) { 55834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "Make", ImageInfo.CameraMake); 55934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 56034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 56134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.CameraModel[0]) { 56234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "Model", ImageInfo.CameraModel); 56334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 56434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 56534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.DateTime[0]) { 56634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "DateTime", ImageInfo.DateTime); 56734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 56834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 56934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ImageWidth", ImageInfo.Width); 57034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 57234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ImageLength", ImageInfo.Height); 57334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 57534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "Orientation", ImageInfo.Orientation); 57634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 57734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 57834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "Flash", ImageInfo.FlashUsed); 57934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 58034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 581574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li if (ImageInfo.FocalLength.num != 0 && ImageInfo.FocalLength.denom != 0) { 582574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li bufLen = addKeyValueRational(&buf, bufLen, "FocalLength", ImageInfo.FocalLength); 58334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 58434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 58534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 58634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.DigitalZoomRatio > 1.0){ 58734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Digital zoom used. Shame on you! 58834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "DigitalZoomRatio", ImageInfo.DigitalZoomRatio, "%1.3f"); 58934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 59034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 59134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 59234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime){ 59334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char* format; 59434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime < 0.010){ 59534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project format = "%6.4f"; 59634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 59734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project format = "%5.3f"; 59834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 59934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "ExposureTime", (double)ImageInfo.ExposureTime, format); 60134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 60234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 60334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ApertureFNumber){ 60534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "FNumber", (double)ImageInfo.ApertureFNumber, "%3.1f"); 60634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 60734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 60834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Distance){ 61034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "SubjectDistance", (double)ImageInfo.Distance, "%4.2f"); 61134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 61234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 61334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 61434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ISOequivalent){ 61534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ISOSpeedRatings", ImageInfo.ISOequivalent); 61634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 61734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 61834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 61934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureBias){ 62034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If exposure bias was specified, but set to zero, presumably its no bias at all, 62134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // so only show it if its nonzero. 62234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueDouble(&buf, bufLen, "ExposureBiasValue", (double)ImageInfo.ExposureBias, "%4.2f"); 62334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 62434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 62534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 62634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "WhiteBalance", ImageInfo.Whitebalance); 62734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 62834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 62934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "LightSource", ImageInfo.LightSource); 63034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 63134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.MeteringMode) { 63434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "MeteringMode", ImageInfo.MeteringMode); 63534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 63634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 63734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureProgram) { 63934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ExposureProgram", ImageInfo.ExposureProgram); 64034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 64134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 64234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 64334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureMode) { 64434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueInt(&buf, bufLen, "ExposureMode", ImageInfo.ExposureMode); 64534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 64634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 64734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 64834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.GpsInfoPresent) { 6498d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLatRaw[0]) { 6508d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLatitude", ImageInfo.GpsLatRaw); 6518d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6528d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 6538d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLatRef[0]) { 6548d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLatitudeRef", ImageInfo.GpsLatRef); 6558d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6568d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 6578d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLongRaw[0]) { 6588d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLongitude", ImageInfo.GpsLongRaw); 6598d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6608d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 6618d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (ImageInfo.GpsLongRef[0]) { 6628d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSLongitudeRef", ImageInfo.GpsLongRef); 6638d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen if (bufLen == 0) return NULL; 6648d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen } 66534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.GpsAlt[0]) { 66634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "GPSAltitude", ImageInfo.GpsAlt); 66734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 66834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 669a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (ImageInfo.GpsDateStamp[0]) { 670a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen bufLen = addKeyValueString(&buf, bufLen, "GPSDateStamp", ImageInfo.GpsDateStamp); 671a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (bufLen == 0) return NULL; 672a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen } 673a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (ImageInfo.GpsTimeStamp[0]) { 674a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen bufLen = addKeyValueString(&buf, bufLen, "GPSTimeStamp", ImageInfo.GpsTimeStamp); 675a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen if (bufLen == 0) return NULL; 676a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen } 677434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen if (ImageInfo.GpsProcessingMethod[0]) { 678434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen bufLen = addKeyValueString(&buf, bufLen, "GPSProcessingMethod", ImageInfo.GpsProcessingMethod); 679434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen if (bufLen == 0) return NULL; 680434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen } 68134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 68234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 68334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Comments[0]) { 68434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project bufLen = addKeyValueString(&buf, bufLen, "UserComment", ImageInfo.Comments); 68534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (bufLen == 0) return NULL; 68634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 68734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 68834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // put the attribute count at the beginnnig of the string 68934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int finalBufLen = strlen(buf) + 20; 69034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* finalResult = malloc(finalBufLen); 69134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (finalResult == NULL) { 69234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(buf); 69334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 69434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 69534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project snprintf(finalResult, finalBufLen, "%d %s", attributeCount, buf); 69634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int k; 69734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (k = 0; k < finalBufLen; k++) 69834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (finalResult[k] > 127) 69934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project finalResult[k] = '?'; 70034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(buf); 70134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 70234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 70334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project LOGE("*********Returning result \"%s\"", finalResult); 70434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 70534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jstring result = ((*env)->NewStringUTF(env, finalResult)); 70634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project free(finalResult); 70734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DiscardData(); 70834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return result; 70934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 71034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 711db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo syncstatic const char *classPathName = "android/media/ExifInterface"; 71234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 71334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic JNINativeMethod methods[] = { 71434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"saveAttributesNative", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)saveAttributes }, 71534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"getAttributesNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getAttributes }, 71634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"appendThumbnailNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)appendThumbnail }, 71734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"commitChangesNative", "(Ljava/lang/String;)V", (void*)commitChanges }, 71834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project {"getThumbnailNative", "(Ljava/lang/String;)[B", (void*)getThumbnail }, 71934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}; 72034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 72134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 72234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Register several native methods for one class. 72334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */ 72434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int registerNativeMethods(JNIEnv* env, const char* className, 72534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project JNINativeMethod* gMethods, int numMethods) 72634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 72734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jclass clazz; 72834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 72934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project clazz = (*env)->FindClass(env, className); 73034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (clazz == NULL) { 73134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, 73234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "Native registration unable to find class '%s'\n", className); 73334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 73434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 73534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) { 73634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, "RegisterNatives failed for '%s'\n", className); 73734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_FALSE; 73834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 73934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 74034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return JNI_TRUE; 74134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 74234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 74334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 74434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Register native methods for all classes we know about. 74534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */ 74634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int registerNatives(JNIEnv* env) 74734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 74834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return jniRegisterNativeMethods(env, classPathName, 74934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project methods, NELEM(methods)); 75034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 75134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 75234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/* 75334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Set some test stuff up. 75434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * 75534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Returns the JNI version on success, -1 on failure. 75634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */ 75734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project__attribute__ ((visibility("default"))) jint JNI_OnLoad(JavaVM* vm, void* reserved) 75834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 75934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project JNIEnv* env = NULL; 76034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project jint result = -1; 76134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 76234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { 76334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, "ERROR: GetEnv failed\n"); 76434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto bail; 76534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 76634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project assert(env != NULL); 76734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 76834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("In mgmain JNI_OnLoad\n"); 76934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 77034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (registerNatives(env) < 0) { 77134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project fprintf(stderr, "ERROR: Exif native registration failed\n"); 77234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project goto bail; 77334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 77434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 77534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project /* success -- return valid version number */ 77634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project result = JNI_VERSION_1_4; 77734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 77834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectbail: 77934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return result; 78034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 781