static jboolean appendThumbnail(JNIEnv *env, jobject jobj, jstring jfilename, jstring jthumbnailfilename) { #ifdef SUPERDEBUG LOGE("******************************** appendThumbnail\n"); #endif const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); if (filename == NULL) { return JNI_FALSE; } const char* thumbnailfilename = (*env)->GetStringUTFChars(env, jthumbnailfilename, NULL); if (thumbnailfilename == NULL) { return JNI_FALSE; } #ifdef SUPERDEBUG LOGE("*******before actual call to ReplaceThumbnail\n"); ShowImageInfo(TRUE); #endif ReplaceThumbnail(thumbnailfilename); #ifdef SUPERDEBUG ShowImageInfo(TRUE); #endif (*env)->ReleaseStringUTFChars(env, jfilename, filename); (*env)->ReleaseStringUTFChars(env, jthumbnailfilename, thumbnailfilename); DiscardData(); return JNI_TRUE; }
static void print_exif_info(struct jpeg_marker_struct const marker) { /*---------------------------------------------------------------------------- Dump as informational messages the contents of the Jpeg miscellaneous marker 'marker', assuming it is an Exif header. -----------------------------------------------------------------------------*/ ImageInfo_t imageInfo; const char * error; assert(marker.data_length >= 6); process_EXIF(marker.data+6, marker.data_length-6, &imageInfo, FALSE, &error); if (error) { pm_message("EXIF header is invalid. %s", error); strfree(error); } else ShowImageInfo(&imageInfo); }
void show_exif_window(GtkWidget* widget, ExifWin * win) { GError* error = NULL; const char* current_image = image_list_get_current_file_path(win->mw->img_list); win->exif_window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable (win->exif_window, TRUE); gtk_window_set_default_size (win->exif_window, 400, 400); gtk_window_set_position(win->exif_window,GTK_WIN_POS_CENTER); gtk_window_set_title(win->exif_window, "Exif information"); win->box = (GtkVBox*)gtk_vbox_new (FALSE,0); win->hbox = (GtkHBox*)gtk_hbox_new (FALSE,0); win->exif_label = (GtkLabel*)gtk_label_new("Exif data"); gtk_label_set_justify(GTK_LABEL(win->exif_label), GTK_JUSTIFY_CENTER); gtk_box_pack_start(GTK_BOX(win->box), (GtkWidget*)win->exif_label, FALSE, FALSE, 5); win->exif_button = (GtkButton*)gtk_button_new_with_label("Close"); win->list = gtk_tree_view_new(); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(win->list), FALSE); win->align = gtk_alignment_new( 1,0 ,0,0); gtk_container_add( (GtkContainer*)win->align, (GtkWidget*)win->exif_button); win->scroll = (GtkScrolledWindow*)gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(win->scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_add_with_viewport(win->scroll, win->list); gtk_box_pack_start(GTK_BOX(win->box), GTK_WIDGET(win->scroll), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(win->box), GTK_WIDGET(gtk_hseparator_new()), FALSE, TRUE,0); gtk_box_pack_start(GTK_BOX(win->box), GTK_WIDGET(win->hbox), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(win->hbox),GTK_WIDGET(win->align), TRUE, TRUE, 0); int Modified = FALSE; ReadMode_t ReadMode; ReadMode = READ_METADATA; CurrentFile = current_image; FilesMatched = 1; ResetJpgfile(); memset(&ImageInfo, 0, sizeof(ImageInfo)); ImageInfo.FlashUsed = -1; ImageInfo.MeteringMode = -1; ImageInfo.Whitebalance = -1; { struct stat st; if (stat(current_image, &st) >= 0){ ImageInfo.FileDateTime = st.st_mtime; ImageInfo.FileSize = st.st_size; }else{ printf("No such file"); } } if (current_image == NULL) return; strncpy(ImageInfo.FileName, current_image, PATH_MAX); if (!ReadJpegFile(current_image, READ_METADATA)) return; DoModify = TRUE; Modified = TRUE; ReadMode = READ_IMAGE; if (!ReadJpegFile(current_image, ReadMode)) return; create_EXIF(); CheckFileSkip(); ShowTags = TRUE; ShowConciseImageInfo(); ShowImageInfo(TRUE); char buf[35]; char buf1[35]; char buf2[35]; char buf3[35]; char buf4[35]; char buf5[35]; char buf6[35]; char buf7[35]; char buf8[35]; char buf9[35]; char buf10[35]; char* size = itoa(ImageInfo.FileSize,buf); char* width = itoa(ImageInfo.Width, buf1); char* height = itoa(ImageInfo.Height, buf2); char Temp[20]; FileTimeAsString(Temp); const char* largest_offset = itoa(ImageInfo.LargestExifOffset, buf3); const char* thumbnail_size = itoa(ImageInfo.ThumbnailSize, buf4); const char* ThumbnailOffset = itoa(ImageInfo.ThumbnailOffset, buf5); const char* image_xdensity = itoa(ImageInfo.JfifHeader.XDensity, buf6); const char* image_ydensity = itoa(ImageInfo.JfifHeader.XDensity, buf7); const char* zoom = itoa(ImageInfo.DigitalZoomRatio, buf8); const char* iso = itoa(ImageInfo.ISOequivalent, buf9); const char* distance = itoa(ImageInfo.DistanceRange, buf10); float value = ImageInfo.ExposureTime; char *str = (char*)malloc(20); sprintf(str, "%f\n", value); float value2 = ImageInfo.ApertureFNumber; char *str2 = (char*)malloc(20); sprintf(str2, "f/%3.1f" , value2); float value3 = ImageInfo.FocalLength35mmEquiv; char *str3 = (char*)malloc(20); sprintf(str3, "f(35)=%dmm" , value3); init_list(win->list); add_to_list(win->list, "File name: ", ImageInfo.FileName); add_to_list(win->list, "File size (bytes) :", size); add_to_list(win->list, "File date: ", Temp); if (ImageInfo.CameraMake[0]){ add_to_list(win->list, "Camera make: ", ImageInfo.CameraMake); add_to_list(win->list, "Camer model: ", ImageInfo.CameraModel); } add_to_list(win->list, "Date time: ", ctime(&ImageInfo.FileDateTime)); if (ImageInfo.IsColor == 0) { add_to_list(win->list, "Color/bw: ", "Black and White"); } else { add_to_list(win->list, "Color/bw: ", "Non Black and White"); } add_to_list(win->list, "Image type :", "image/jpg"); add_to_list(win->list, "Image Width: ", width); add_to_list(win->list, "Image Height: ",height); add_to_list(win->list, "Largest Exif Offset: ", largest_offset); add_to_list(win->list, "Thumbnail size: ", thumbnail_size); add_to_list(win->list, "Thumbnail offset: ", ThumbnailOffset); add_to_list(win->list, "Image comments: ", ImageInfo.Comments); add_to_list(win->list, "Image X Density: ",image_xdensity); add_to_list(win->list, "Image Y Density: ", image_xdensity); add_to_list(win->list, "Digital zoom ratio: ", zoom); if (ImageInfo.FlashUsed > 0) add_to_list(win->list, "Flash used: ", "yes"); else add_to_list(win->list, "Flash used: ", "No"); add_to_list(win->list, "Exposure Time (s): ", str); add_to_list(win->list, "Aperture FNumber: ", str2); add_to_list(win->list, "Focal Length 35mm Equiv: ", str3); add_to_list(win->list, "ISOequivalent: ", iso); add_to_list(win->list, "Distance range: ", distance); switch(ImageInfo.ExposureProgram) { case 1: add_to_list(win->list, "Expusure: ", "manual"); break; case 2: add_to_list(win->list, "Expusure: ", "program (auto)"); break; case 3: add_to_list(win->list, "Expusure: ", "aperture priority (semi-auto)"); break; case 4: add_to_list(win->list, "Expusure: ", "shutter priority (semi-auto)"); break; case 5: add_to_list(win->list, "Expusure: ", "Creative Program (based towards depth of field)"); break; case 6: add_to_list(win->list, "Expusure: ", "Action program (based towards fast shutter speed)"); break; case 7: add_to_list(win->list, "Expusure: ", "Portrait Mode"); break; case 8: add_to_list(win->list, "Expusure: ", "LandscapeMode"); break; default: break; } if (ImageInfo.MeteringMode > 0)\ { switch(ImageInfo.MeteringMode) { case 1: add_to_list(win->list, "Metering Mode: ", "average"); break; case 2: add_to_list(win->list, "Metering Mode: ", "center weight"); break; case 3: add_to_list(win->list, "Metering Mode: ", "spot"); break; case 4: add_to_list(win->list, "Metering Mode: ", "multi spot"); break; case 5: add_to_list(win->list, "Metering Mode: ", "pattern"); break; case 6: printf("partial\n"); break; case 255: printf("other\n"); break; default: printf("unknown (%d)\n",ImageInfo.MeteringMode); break; } } g_signal_connect( win->exif_button, "clicked", G_CALLBACK(on_close), win ); gtk_container_add(GTK_CONTAINER(win->exif_window), GTK_WIDGET(win->box)); gtk_widget_show_all((GtkWidget*)win->exif_window); g_free(str); g_free(str2); g_free(str3); }
//-------------------------------------------------------------------------- // Do selected operations to one file at a time. //-------------------------------------------------------------------------- void ProcessFile(const char * FileName) { int Modified = FALSE; ReadMode_t ReadMode = READ_EXIF; CurrentFile = FileName; ResetJpgfile(); // Start with an empty image information structure. memset(&ImageInfo, 0, sizeof(ImageInfo)); ImageInfo.FlashUsed = -1; ImageInfo.MeteringMode = -1; // Store file date/time. { struct stat st; if (stat(FileName, &st) >= 0){ ImageInfo.FileDateTime = st.st_mtime; ImageInfo.FileSize = st.st_size; }else{ ErrFatal("No such file"); } } strncpy(ImageInfo.FileName, FileName, PATH_MAX); if (ApplyCommand){ // Applying a command is special - the headers from the file have to be // pre-read, then the command executed, and then the image part of the file read. if (!ReadJpegFile(FileName, READ_EXIF)) return; #ifdef MATTHIAS if (AutoResize){ // Automatic resize computation - to customize for each run... if (AutoResizeCmdStuff() == 0){ DiscardData(); return; } } #endif // MATTHIAS if (CheckFileSkip()){ DiscardData(); return; } DiscardAllButExif(); DoCommand(FileName); Modified = TRUE; ReadMode = READ_IMAGE; // Don't re-read exif section again on next read. }else if (ExifXferScrFile){ char RelativeExifName[PATH_MAX+1]; // Make a relative name. RelativeName(RelativeExifName, ExifXferScrFile, FileName); if(!ReadJpegFile(RelativeExifName, READ_EXIF)) return; DiscardAllButExif(); // Don't re-read exif section again on next read. Modified = TRUE; ReadMode = READ_IMAGE; } FilesMatched += 1; FilesMatched = TRUE; // Turns off complaining that nothing matched. if (DoModify){ ReadMode |= READ_IMAGE; } if (!ReadJpegFile(FileName, ReadMode)) return; if (CheckFileSkip()){ DiscardData(); return; } if (ShowConcise){ ShowConciseImageInfo(); }else{ if (!(DoModify || DoReadAction) || ShowTags){ if (DoN3) { ShowImageInfoInN3(); } else { ShowImageInfo(); } } } if (ThumbnailName){ if (ImageInfo.ThumbnailPointer){ FILE * ThumbnailFile; char OutFileName[PATH_MAX+1]; // Make a relative name. RelativeName(OutFileName, ThumbnailName, FileName); #ifndef _WIN32 if (strcmp(ThumbnailName, "-") == 0){ // A filename of '-' indicates thumbnail goes to stdout. // This doesn't make much sense under Windows, so this feature is unix only. ThumbnailFile = stdout; }else #endif { ThumbnailFile = fopen(OutFileName,"wb"); } if (ThumbnailFile){ fwrite(ImageInfo.ThumbnailPointer, ImageInfo.ThumbnailSize ,1, ThumbnailFile); fclose(ThumbnailFile); if (ThumbnailFile != stdout){ printf("Created: '%s'\n", OutFileName); }else{ // No point in printing to stdout when that is where the thumbnail goes! } }else{ ErrFatal("Could not write thumbnail file"); } }else{ printf("Image '%s' contains no thumbnail\n",FileName); } } #ifdef MATTHIAS if (EditComment || CommentInsertfileName || AddComment || RemComment){ #else if (EditComment || CommentInsertfileName){ #endif Section_t * CommentSec; char Comment[1000]; int CommentSize; CommentSec = FindSection(M_COM); if (CommentSec == NULL){ unsigned char * DummyData; DummyData = (uchar *) malloc(3); DummyData[0] = 0; DummyData[1] = 2; DummyData[2] = 0; CommentSec = CreateSection(M_COM, DummyData, 2); } CommentSize = CommentSec->Size-2; if (CommentInsertfileName){ // Read a new comment section from file. char CommentFileName[PATH_MAX+1]; FILE * CommentFile; // Make a relative name. RelativeName(CommentFileName, CommentInsertfileName, FileName); CommentFile = fopen(CommentFileName,"r"); if (CommentFile == NULL){ printf("Could not open '%s'\n",CommentFileName); }else{ // Read it in. // Replace the section. CommentSize = fread(Comment, 1, 999, CommentFile); fclose(CommentFile); if (CommentSize < 0) CommentSize = 0; } }else{ #ifdef MATTHIAS if (ModifyDescriptComment(Comment, (char *)CommentSec->Data+2)){ Modified = TRUE; CommentSize = strlen(Comment); } if (EditComment) #else memcpy(Comment, (char *)CommentSec->Data+2, CommentSize); #endif { char EditFileName[PATH_MAX+4]; strcpy(EditFileName, FileName); strcat(EditFileName, ".txt"); CommentSize = FileEditComment(EditFileName, Comment, CommentSize); } } if (strcmp(Comment, (char *)CommentSec->Data+2)){ // Discard old comment section and put a new one in. int size; size = CommentSize+2; free(CommentSec->Data); CommentSec->Size = size; CommentSec->Data = malloc(size); CommentSec->Data[0] = (uchar)(size >> 8); CommentSec->Data[1] = (uchar)(size); memcpy((CommentSec->Data)+2, Comment, size-2); Modified = TRUE; } if (!Modified){ printf("Comment not modified\n"); } }
static jstring getAttributes(JNIEnv *env, jobject jobj, jstring jfilename) { #ifdef SUPERDEBUG LOGE("******************************** getAttributes\n"); #endif const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); loadExifInfo(filename, FALSE); #ifdef SUPERDEBUG ShowImageInfo(TRUE); #endif (*env)->ReleaseStringUTFChars(env, jfilename, filename); attributeCount = 0; #ifdef REALLOCTEST int bufLen = 5; #else int bufLen = 1000; #endif char* buf = malloc(bufLen); if (buf == NULL) { return NULL; } *buf = 0; // start the string out at zero length // save a fake "hasThumbnail" tag to pass to the java ExifInterface bufLen = addKeyValueString(&buf, bufLen, "hasThumbnail", ImageInfo.ThumbnailOffset == 0 || ImageInfo.ThumbnailAtEnd == FALSE || ImageInfo.ThumbnailSize == 0 ? "false" : "true"); if (bufLen == 0) return NULL; if (ImageInfo.CameraMake[0]) { bufLen = addKeyValueString(&buf, bufLen, "Make", ImageInfo.CameraMake); if (bufLen == 0) return NULL; } if (ImageInfo.CameraModel[0]) { bufLen = addKeyValueString(&buf, bufLen, "Model", ImageInfo.CameraModel); if (bufLen == 0) return NULL; } if (ImageInfo.DateTime[0]) { bufLen = addKeyValueString(&buf, bufLen, "DateTime", ImageInfo.DateTime); if (bufLen == 0) return NULL; } bufLen = addKeyValueInt(&buf, bufLen, "ImageWidth", ImageInfo.Width); if (bufLen == 0) return NULL; bufLen = addKeyValueInt(&buf, bufLen, "ImageLength", ImageInfo.Height); if (bufLen == 0) return NULL; bufLen = addKeyValueInt(&buf, bufLen, "Orientation", ImageInfo.Orientation); if (bufLen == 0) return NULL; bufLen = addKeyValueInt(&buf, bufLen, "Flash", ImageInfo.FlashUsed); if (bufLen == 0) return NULL; if (ImageInfo.FocalLength.num != 0 && ImageInfo.FocalLength.denom != 0) { bufLen = addKeyValueRational(&buf, bufLen, "FocalLength", ImageInfo.FocalLength); if (bufLen == 0) return NULL; } if (ImageInfo.DigitalZoomRatio > 1.0){ // Digital zoom used. Shame on you! bufLen = addKeyValueDouble(&buf, bufLen, "DigitalZoomRatio", ImageInfo.DigitalZoomRatio, "%1.3f"); if (bufLen == 0) return NULL; } if (ImageInfo.ExposureTime){ const char* format; if (ImageInfo.ExposureTime < 0.010){ format = "%6.4f"; } else { format = "%5.3f"; } bufLen = addKeyValueDouble(&buf, bufLen, "ExposureTime", (double)ImageInfo.ExposureTime, format); if (bufLen == 0) return NULL; } if (ImageInfo.ApertureFNumber){ bufLen = addKeyValueDouble(&buf, bufLen, "FNumber", (double)ImageInfo.ApertureFNumber, "%3.1f"); if (bufLen == 0) return NULL; } if (ImageInfo.Distance){ bufLen = addKeyValueDouble(&buf, bufLen, "SubjectDistance", (double)ImageInfo.Distance, "%4.2f"); if (bufLen == 0) return NULL; } if (ImageInfo.ISOequivalent){ bufLen = addKeyValueInt(&buf, bufLen, "ISOSpeedRatings", ImageInfo.ISOequivalent); if (bufLen == 0) return NULL; } if (ImageInfo.ExposureBias){ // If exposure bias was specified, but set to zero, presumably its no bias at all, // so only show it if its nonzero. bufLen = addKeyValueDouble(&buf, bufLen, "ExposureBiasValue", (double)ImageInfo.ExposureBias, "%4.2f"); if (bufLen == 0) return NULL; } bufLen = addKeyValueInt(&buf, bufLen, "WhiteBalance", ImageInfo.Whitebalance); if (bufLen == 0) return NULL; bufLen = addKeyValueInt(&buf, bufLen, "LightSource", ImageInfo.LightSource); if (bufLen == 0) return NULL; if (ImageInfo.MeteringMode) { bufLen = addKeyValueInt(&buf, bufLen, "MeteringMode", ImageInfo.MeteringMode); if (bufLen == 0) return NULL; } if (ImageInfo.ExposureProgram) { bufLen = addKeyValueInt(&buf, bufLen, "ExposureProgram", ImageInfo.ExposureProgram); if (bufLen == 0) return NULL; } if (ImageInfo.ExposureMode) { bufLen = addKeyValueInt(&buf, bufLen, "ExposureMode", ImageInfo.ExposureMode); if (bufLen == 0) return NULL; } if (ImageInfo.GpsInfoPresent) { if (ImageInfo.GpsLatRaw[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSLatitude", ImageInfo.GpsLatRaw); if (bufLen == 0) return NULL; } if (ImageInfo.GpsLatRef[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSLatitudeRef", ImageInfo.GpsLatRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsLongRaw[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSLongitude", ImageInfo.GpsLongRaw); if (bufLen == 0) return NULL; } if (ImageInfo.GpsLongRef[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSLongitudeRef", ImageInfo.GpsLongRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsAlt[0]) { bufLen = addKeyValueRational(&buf, bufLen, "GPSAltitude", ImageInfo.GpsAltRaw); bufLen = addKeyValueInt(&buf, bufLen, "GPSAltitudeRef", ImageInfo.GpsAltRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsDateStamp[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSDateStamp", ImageInfo.GpsDateStamp); if (bufLen == 0) return NULL; } if (ImageInfo.GpsTimeStamp[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSTimeStamp", ImageInfo.GpsTimeStamp); if (bufLen == 0) return NULL; } if (ImageInfo.GpsProcessingMethod[0]) { bufLen = addKeyValueString(&buf, bufLen, "GPSProcessingMethod", ImageInfo.GpsProcessingMethod); if (bufLen == 0) return NULL; } } if (ImageInfo.Comments[0]) { bufLen = addKeyValueString(&buf, bufLen, "UserComment", ImageInfo.Comments); if (bufLen == 0) return NULL; } // put the attribute count at the beginnnig of the string int finalBufLen = strlen(buf) + 20; char* finalResult = malloc(finalBufLen); if (finalResult == NULL) { free(buf); return NULL; } snprintf(finalResult, finalBufLen, "%d %s", attributeCount, buf); int k; for (k = 0; k < finalBufLen; k++) if (finalResult[k] > 127) finalResult[k] = '?'; free(buf); #ifdef SUPERDEBUG LOGE("*********Returning result \"%s\"", finalResult); #endif jstring result = ((*env)->NewStringUTF(env, finalResult)); free(finalResult); DiscardData(); return result; }
static void saveAttributes(JNIEnv *env, jobject jobj, jstring jfilename, jstring jattributes) { #ifdef SUPERDEBUG LOGE("******************************** saveAttributes\n"); #endif // format of attributes string passed from java: // "attrCnt attr1=valueLen value1attr2=value2Len value2..." // example input: "4 ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO" ExifElement_t* exifElementTable = NULL; const char* filename = NULL; uchar* thumbnailData = NULL; int attrCnt = 0; const char* attributes = (*env)->GetStringUTFChars(env, jattributes, NULL); if (attributes == NULL) { goto exit; } #ifdef SUPERDEBUG LOGE("attributes %s\n", attributes); #endif // Get the number of attributes - it's the first number in the string. attrCnt = atoi(attributes); char* attrPtr = strchr(attributes, ' ') + 1; #ifdef SUPERDEBUG LOGE("attribute count %d attrPtr %s\n", attrCnt, attrPtr); #endif // Load all the hash exif elements into a more c-like structure exifElementTable = malloc(sizeof(ExifElement_t) * attrCnt); if (exifElementTable == NULL) { goto exit; } #ifdef OUTOFMEMORYTEST1 goto exit; #endif int i; char tag[100]; int gpsTagCount = 0; int exifTagCount = 0; for (i = 0; i < attrCnt; i++) { // get an element from the attribute string and add it to the c structure // first, extract the attribute name char* tagEnd = strchr(attrPtr, '='); if (tagEnd == 0) { #ifdef SUPERDEBUG LOGE("saveAttributes: couldn't find end of tag"); #endif goto exit; } if (tagEnd - attrPtr > 99) { #ifdef SUPERDEBUG LOGE("saveAttributes: attribute tag way too long"); #endif goto exit; } memcpy(tag, attrPtr, tagEnd - attrPtr); tag[tagEnd - attrPtr] = 0; if (IsGpsTag(tag)) { exifElementTable[i].GpsTag = TRUE; exifElementTable[i].Tag = GpsTagNameToValue(tag); ++gpsTagCount; } else { exifElementTable[i].GpsTag = FALSE; exifElementTable[i].Tag = TagNameToValue(tag); ++exifTagCount; } attrPtr = tagEnd + 1; // next get the length of the attribute value int valueLen = atoi(attrPtr); attrPtr = strchr(attrPtr, ' ') + 1; if (attrPtr == 0) { #ifdef SUPERDEBUG LOGE("saveAttributes: couldn't find end of value len"); #endif goto exit; } exifElementTable[i].Value = malloc(valueLen + 1); if (exifElementTable[i].Value == NULL) { goto exit; } memcpy(exifElementTable[i].Value, attrPtr, valueLen); exifElementTable[i].Value[valueLen] = 0; exifElementTable[i].DataLength = valueLen; attrPtr += valueLen; #ifdef SUPERDEBUG LOGE("tag %s id %d value %s data length=%d isGps=%d", tag, exifElementTable[i].Tag, exifElementTable[i].Value, exifElementTable[i].DataLength, exifElementTable[i].GpsTag); #endif } filename = (*env)->GetStringUTFChars(env, jfilename, NULL); #ifdef SUPERDEBUG LOGE("Call loadAttributes() with filename is %s. Loading exif info\n", filename); #endif loadExifInfo(filename, TRUE); #ifdef SUPERDEBUG // DumpExifMap = TRUE; ShowTags = TRUE; ShowImageInfo(TRUE); LOGE("create exif 2"); #endif // If the jpg file has a thumbnail, preserve it. int thumbnailLength = ImageInfo.ThumbnailSize; if (ImageInfo.ThumbnailOffset) { Section_t* ExifSection = FindSection(M_EXIF); if (ExifSection) { uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8; thumbnailData = (uchar*)malloc(ImageInfo.ThumbnailSize); // if the malloc fails, we just won't copy the thumbnail if (thumbnailData) { memcpy(thumbnailData, thumbnailPointer, thumbnailLength); } } } create_EXIF(exifElementTable, exifTagCount, gpsTagCount); if (thumbnailData) { copyThumbnailData(thumbnailData, thumbnailLength); } exit: #ifdef SUPERDEBUG LOGE("cleaning up now in saveAttributes"); #endif // try to clean up resources if (attributes) { (*env)->ReleaseStringUTFChars(env, jattributes, attributes); } if (filename) { (*env)->ReleaseStringUTFChars(env, jfilename, filename); } if (exifElementTable) { // free the table for (i = 0; i < attrCnt; i++) { free(exifElementTable[i].Value); } free(exifElementTable); } if (thumbnailData) { free(thumbnailData); } #ifdef SUPERDEBUG LOGE("returning from saveAttributes"); #endif // Temporarily saving these commented out lines because they represent a lot of figuring out // patterns for JNI. // // Get link to Method "entrySet" // jmethodID entrySetMethod = (*env)->GetMethodID(env, jclass_of_hashmap, "entrySet", "()Ljava/util/Set;"); // // // Invoke the "entrySet" method on the HashMap object // jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, entrySetMethod); // // // Get the Set Class // jclass jclass_of_set = (*env)->FindClass(env, "java/util/Set"); // // if (jclass_of_set == 0) { // printf("java/util/Set lookup failed\n"); // return; // } // // // Get link to Method "iterator" // jmethodID iteratorMethod = (*env)->GetMethodID(env, jclass_of_set, "iterator", "()Ljava/util/Iterator;"); // // // Invoke the "iterator" method on the jobject_of_entryset variable of type Set // jobject jobject_of_iterator = (*env)->CallObjectMethod(env, jobject_of_entryset, iteratorMethod); // // // Get the "Iterator" class // jclass jclass_of_iterator = (*env)->FindClass(env, "java/util/Iterator"); // // // Get link to Method "hasNext" // jmethodID hasNextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "hasNext", "()Z"); // // // Invoke - Get the value hasNextMethod // jboolean bHasNext = (*env)->CallBooleanMethod(env, jobject_of_iterator, hasNextMethod); // // Get link to Method "hasNext" // jmethodID nextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "next", "()Ljava/util/Map/Entry;"); // // jclass jclass_of_mapentry = (*env)->FindClass(env, "java/util/Map/Entry"); // // jmethodID getKeyMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getKey", "()Ljava/lang/Object"); // // jmethodID getValueMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getValue", "()Ljava/lang/Object"); }