static jbyteArray getThumbnail(JNIEnv *env, jobject jobj, jstring jfilename) { LOGI("getThumbnail"); const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); if (filename) { loadExifInfo(filename, FALSE); Section_t* ExifSection = FindSection(M_EXIF); if (ExifSection == NULL || ImageInfo.ThumbnailSize == 0) { LOGE("no exif section or size == 0, so no thumbnail\n"); goto noThumbnail; } uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8; jbyteArray byteArray = (*env)->NewByteArray(env, ImageInfo.ThumbnailSize); if (byteArray == NULL) { LOGE("couldn't allocate thumbnail memory, so no thumbnail\n"); goto noThumbnail; } (*env)->SetByteArrayRegion(env, byteArray, 0, ImageInfo.ThumbnailSize, thumbnailPointer); LOGD("thumbnail size %d\n", ImageInfo.ThumbnailSize); (*env)->ReleaseStringUTFChars(env, jfilename, filename); DiscardData(); return byteArray; } noThumbnail: if (filename) { (*env)->ReleaseStringUTFChars(env, jfilename, filename); } DiscardData(); return NULL; }
static jlongArray getThumbnailRange(JNIEnv *env, jobject jobj, jstring jfilename) { jlongArray resultArray = NULL; const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); if (filename) { loadExifInfo(filename, FALSE); Section_t* ExifSection = FindSection(M_EXIF); if (ExifSection == NULL || ImageInfo.ThumbnailSize == 0) { goto done; } jlong result[2]; result[0] = ExifSection->Offset + ImageInfo.ThumbnailOffset + 8; result[1] = ImageInfo.ThumbnailSize; resultArray = (*env)->NewLongArray(env, 2); if (resultArray == NULL) { goto done; } (*env)->SetLongArrayRegion(env, resultArray, 0, 2, result); } done: if (filename) { (*env)->ReleaseStringUTFChars(env, jfilename, filename); } DiscardData(); return resultArray; }
static jstring getAttributes(JNIEnv *env, jobject jobj, jstring jfilename) { LOGI("******************************** getAttributes"); const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); LOGD("filename: %s", filename); loadExifInfo(filename, FALSE); // release the string (*env)->ReleaseStringUTFChars(env, jfilename, filename); attributeCount = 0; int bufLen = 1000; char* buf = malloc(bufLen); if (buf == NULL) { return NULL; } *buf = 0; // start the string out at zero length // ShowImageInfo(TRUE); // parse all attributes // thumbnail bufLen = addKeyValueString(&buf, bufLen, "hasThumbnail", ImageInfo.ThumbnailOffset == 0 || ImageInfo.ThumbnailAtEnd == FALSE || ImageInfo.ThumbnailSize == 0 ? "false" : "true"); if (bufLen == 0) return NULL; if( ImageInfo.Make[0] ) { bufLen = addKeyValueString( &buf, bufLen, "Make", ImageInfo.Make ); if( bufLen == 0 ) return NULL; } if( ImageInfo.Model[0] ) { bufLen = addKeyValueString( &buf, bufLen, "Model", ImageInfo.Model ); if( bufLen == 0 ) return NULL; } if( ImageInfo.DateTime[0] ) { bufLen = addKeyValueString( &buf, bufLen, "DateTime", ImageInfo.DateTime ); if( bufLen == 0 ) return NULL; } if( ImageInfo.DateTimeDigitized[0] ) { bufLen = addKeyValueString( &buf, bufLen, "DateTimeDigitized", ImageInfo.DateTimeDigitized ); if( bufLen == 0 ) return NULL; } if( ImageInfo.DateTimeOriginal[0] ) { bufLen = addKeyValueString( &buf, bufLen, "DateTimeOriginal", ImageInfo.DateTimeOriginal ); if( bufLen == 0 ) return NULL; } if( ImageInfo.Copyright[0] ) { bufLen = addKeyValueString( &buf, bufLen, "Copyright", ImageInfo.Copyright ); if( bufLen == 0 ) return NULL; } if( ImageInfo.Artist[0] ) { bufLen = addKeyValueString( &buf, bufLen, "Artist", ImageInfo.Artist ); if( bufLen == 0 ) return NULL; } if( ImageInfo.Software[0] ) { bufLen = addKeyValueString( &buf, bufLen, "Software", ImageInfo.Software ); if( bufLen == 0 ) return NULL; } if( ImageInfo.ImageWidth > 0 && ImageInfo.ImageLength > 0 ) { bufLen = addKeyValueInt(&buf, bufLen, "ImageWidth", ImageInfo.ImageWidth); if (bufLen == 0) return NULL; bufLen = addKeyValueInt(&buf, bufLen, "ImageLength", ImageInfo.ImageLength); if (bufLen == 0) return NULL; } if(ImageInfo.Orientation >= 0 ) { bufLen = addKeyValueInt(&buf, bufLen, "Orientation", ImageInfo.Orientation); if (bufLen == 0) return NULL; } if (ImageInfo.Flash >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "Flash", ImageInfo.Flash); if (bufLen == 0) return NULL; } if (ImageInfo.FocalLength) { bufLen = addKeyValueDouble(&buf, bufLen, "FocalLength", ImageInfo.FocalLength, "%4.2f"); 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.FNumber > 0) { bufLen = addKeyValueDouble(&buf, bufLen, "FNumber", (double)ImageInfo.FNumber, "%3.1f"); if (bufLen == 0) return NULL; } if( ImageInfo.ApertureValue ) { bufLen = addKeyValueDouble(&buf, bufLen, "ApertureValue", (double)ImageInfo.ApertureValue, "%4.2f"); if (bufLen == 0) return NULL; } if(ImageInfo.BrightnessValue ) { bufLen = addKeyValueDouble(&buf, bufLen, "BrightnessValue", (double)ImageInfo.BrightnessValue, "%4.2f"); if (bufLen == 0) return NULL; } if(ImageInfo.MaxApertureValue) { bufLen = addKeyValueDouble(&buf, bufLen, "MaxApertureValue", (double)ImageInfo.MaxApertureValue, "%4.2f"); if (bufLen == 0) return NULL; } if (ImageInfo.SubjectDistance) { bufLen = addKeyValueDouble(&buf, bufLen, "SubjectDistance", (double)ImageInfo.SubjectDistance, "%4.2f"); if (bufLen == 0) return NULL; } if (ImageInfo.ExposureBiasValue) { bufLen = addKeyValueDouble(&buf, bufLen, "ExposureBiasValue", (double)ImageInfo.ExposureBiasValue, "%4.2f"); if (bufLen == 0) return NULL; } if (ImageInfo.DigitalZoomRatio > 1.0) { // Digital zoom used. Shame on you! (LOL) bufLen = addKeyValueDouble(&buf, bufLen, "DigitalZoomRatio", ImageInfo.DigitalZoomRatio, "%2.3f"); if (bufLen == 0) return NULL; } if( ImageInfo.FocalLengthIn35mmFilm ) { bufLen = addKeyValueInt(&buf, bufLen, "FocalLengthIn35mmFilm", ImageInfo.FocalLengthIn35mmFilm); if (bufLen == 0) return NULL; } if( ImageInfo.SensingMethod > 0 ) { bufLen = addKeyValueInt(&buf, bufLen, "SensingMethod", ImageInfo.SensingMethod); if (bufLen == 0) return NULL; } if( ImageInfo.Whitebalance >= 0 && ImageInfo.Whitebalance <= 1 ) { bufLen = addKeyValueInt(&buf, bufLen, "Whitebalance", ImageInfo.Whitebalance); if (bufLen == 0) return NULL; } if( ImageInfo.MeteringMode > 0 && ImageInfo.MeteringMode <= 255) { bufLen = addKeyValueInt(&buf, bufLen, "MeteringMode", ImageInfo.MeteringMode); if (bufLen == 0) return NULL; } // if(ImageInfo.CompressedBitsPerPixel) // { // bufLen = addKeyValueDouble(&buf, bufLen, "CompressedBitsPerPixel", (double)ImageInfo.CompressedBitsPerPixel, "%4.2f"); // if (bufLen == 0) return NULL; // } if (ImageInfo.ExposureProgram > 0) { bufLen = addKeyValueInt(&buf, bufLen, "ExposureProgram", ImageInfo.ExposureProgram); if (bufLen == 0) return NULL; } if (ImageInfo.ExposureMode >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "ExposureMode", ImageInfo.ExposureMode); if (bufLen == 0) return NULL; } if (ImageInfo.ISOSpeedRatings) { bufLen = addKeyValueInt(&buf, bufLen, "ISOSpeedRatings", ImageInfo.ISOSpeedRatings); if (bufLen == 0) return NULL; } if(ImageInfo.LightSource >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "LightSource", ImageInfo.LightSource); if (bufLen == 0) return NULL; } if(ImageInfo.SubjectDistanceRange > 0) { bufLen = addKeyValueInt(&buf, bufLen, "SubjectDistanceRange", ImageInfo.SubjectDistanceRange); if (bufLen == 0) return NULL; } if(ImageInfo.XResolution) { bufLen = addKeyValueDouble(&buf, bufLen, "XResolution", ImageInfo.XResolution, "%.2f"); if (bufLen == 0) return NULL; } if(ImageInfo.YResolution) { bufLen = addKeyValueDouble(&buf, bufLen, "YResolution", ImageInfo.YResolution, "%.2f"); if (bufLen == 0) return NULL; } if(ImageInfo.ResolutionUnit) { bufLen = addKeyValueInt(&buf, bufLen, "ResolutionUnit", ImageInfo.ResolutionUnit); if (bufLen == 0) return NULL; } if(ImageInfo.FocalPlaneXResolution) { bufLen = addKeyValueDouble(&buf, bufLen, "FocalPlaneXResolution", ImageInfo.FocalPlaneXResolution, "%.4f"); if (bufLen == 0) return NULL; } if(ImageInfo.FocalPlaneYResolution) { bufLen = addKeyValueDouble(&buf, bufLen, "FocalPlaneYResolution", ImageInfo.FocalPlaneYResolution, "%.4f"); if (bufLen == 0) return NULL; } if(ImageInfo.FocalPlaneResolutionUnit) { bufLen = addKeyValueInt(&buf, bufLen, "FocalPlaneResolutionUnit", ImageInfo.FocalPlaneResolutionUnit); if (bufLen == 0) return NULL; } if(ImageInfo.PixelXDimension) { bufLen = addKeyValueInt(&buf, bufLen, "PixelXDimension", ImageInfo.PixelXDimension); if (bufLen == 0) return NULL; } if(ImageInfo.PixelYDimension) { bufLen = addKeyValueInt(&buf, bufLen, "PixelYDimension", ImageInfo.PixelYDimension); if (bufLen == 0) return NULL; } if (ImageInfo.QualityGuess) { bufLen = addKeyValueInt(&buf, bufLen, "QualityGuess", ImageInfo.QualityGuess); if (bufLen == 0) return NULL; } if( ImageInfo.SceneCaptureType >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "SceneCaptureType", ImageInfo.SceneCaptureType); if (bufLen == 0) return NULL; } if( ImageInfo.ShutterSpeedValue) { bufLen = addKeyValueDouble(&buf, bufLen, "ShutterSpeedValue", ImageInfo.ShutterSpeedValue, "%.4f"); if (bufLen == 0) return NULL; } if(ImageInfo.ExifVersion[0]) { bufLen = addKeyValueBytes(&buf, bufLen, "ExifVersion", ImageInfo.ExifVersion, 4); if (bufLen == 0) return NULL; } if(ImageInfo.ColorSpace > 0) { bufLen = addKeyValueInt(&buf, bufLen, "ColorSpace", ImageInfo.ColorSpace); if (bufLen == 0) return NULL; } if(ImageInfo.Compression > 0) { bufLen = addKeyValueInt(&buf, bufLen, "Compression", ImageInfo.Compression); if (bufLen == 0) return NULL; } if(ImageInfo.Process) { bufLen = addKeyValueInt(&buf, bufLen, "Process", ImageInfo.Process); if (bufLen == 0) return NULL; } if(ImageInfo.FileDateTime > 0) { char filedatetime[20]; FileTimeAsString( filedatetime ); bufLen = addKeyValueString( &buf, bufLen, "FileDateTime", filedatetime ); if( bufLen == 0 ) return NULL; } if(ImageInfo.FileSize) { bufLen = addKeyValueInt(&buf, bufLen, "FileSize", ImageInfo.FileSize); if (bufLen == 0) return NULL; } if( ImageInfo.Sharpness >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "Sharpness", ImageInfo.Sharpness); if (bufLen == 0) return NULL; } if( ImageInfo.Contrast >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "Contrast", ImageInfo.Contrast); if (bufLen == 0) return NULL; } if(ImageInfo.Saturation >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "Saturation", ImageInfo.Saturation); if (bufLen == 0) return NULL; } if(ImageInfo.GainControl >= 0) { bufLen = addKeyValueInt(&buf, bufLen, "GainControl", ImageInfo.GainControl); if (bufLen == 0) return NULL; } // GPS if (ImageInfo.GpsInfoPresent) { if (ImageInfo.GpsLatitudeRef[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsLatitudeRef", ImageInfo.GpsLatitudeRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsLongitudeRef[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsLongitudeRef", ImageInfo.GpsLongitudeRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsAltitudeRef == 0 || ImageInfo.GpsAltitudeRef == 1) { bufLen = addKeyValueInt(&buf, bufLen, "GpsAltitudeRef", ImageInfo.GpsAltitudeRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsLatitude[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsLatitude", ImageInfo.GpsLatitude); if (bufLen == 0) return NULL; } if (ImageInfo.GpsLongitude[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsLongitude", ImageInfo.GpsLongitude); if (bufLen == 0) return NULL; } if (ImageInfo.GpsAltitude[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsAltitude", ImageInfo.GpsAltitude); if (bufLen == 0) return NULL; } if( ImageInfo.GpsSpeedRef[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsSpeedRef", ImageInfo.GpsSpeedRef); if (bufLen == 0) return NULL; } if (ImageInfo.GpsSpeed[0]) { bufLen = addKeyValueString(&buf, bufLen, "GpsSpeed", ImageInfo.GpsSpeed); if (bufLen == 0) return NULL; } } // end parsing LOGD("final buffer: %s", buf); // 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 (!isascii(finalResult[k])) finalResult[k] = '?'; free(buf); LOGD("*********Returning result \"%s\"", finalResult); jstring result = ((*env)->NewStringUTF(env, finalResult)); free(finalResult); DiscardData(); return result; }
static void saveAttributes(JNIEnv *env, jobject jobj, jstring jfilename, jstring jattributes) { LOGI("******************************** saveAttributes"); // 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; } // Get the number of attributes - it's the first number in the string. attrCnt = atoi(attributes); char* attrPtr = strchr(attributes, ' ') + 1; LOGD("attribute count %d attrPtr %s\n", attrCnt, attrPtr); // Load all the hash exif elements into a more c-like structure exifElementTable = malloc(sizeof(ExifElement_t) * attrCnt); if (exifElementTable == NULL) { goto exit; } int i; char tag[100]; int hasDateTimeTag = FALSE; int gpsTagCount = 0; int exifTagCount = 0; int tagValue; int tagFound; ExifElement_t* item; 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 tagFound = 0; char* tagEnd = strchr(attrPtr, '='); if (tagEnd == 0) { LOGE("saveAttributes: couldn't find end of tag"); goto exit; } if (tagEnd - attrPtr > 99) { LOGE("saveAttributes: attribute tag way too long"); goto exit; } memcpy(tag, attrPtr, tagEnd - attrPtr); tag[tagEnd - attrPtr] = 0; exifElementTable[i].Format = 0; exifElementTable[i].Tag = 0; exifElementTable[i].GpsTag = FALSE; if (IsGpsTag(tag)) { tagValue = GpsTagNameToValue(tag); if( tagValue > -1 ) { LOGV("Tag '%s' with value: X%x", tag, tagValue); exifElementTable[i].GpsTag = TRUE; exifElementTable[i].Tag = GpsTagNameToValue(tag); ++gpsTagCount; tagFound = 1; } else { LOGE("(GPS) Skipping gps tag: %s = %i", tag, tagValue); } } else { tagValue = TagNameToValue(tag); if( tagValue > -1 ) { LOGV("Tag '%s' with value: X%x", tag, tagValue); exifElementTable[i].GpsTag = FALSE; exifElementTable[i].Tag = tagValue; ++exifTagCount; tagFound = 1; } else { LOGE("(EXIF) Skipping tag %s = %i", tag, tagValue); } } LOGV("tagFound: %i", tagFound); attrPtr = tagEnd + 1; // next get the length of the attribute value int valueLen = atoi(attrPtr); if (IsDateTimeTag(exifElementTable[i].Tag)) { hasDateTimeTag = TRUE; } attrPtr = strchr(attrPtr, ' ') + 1; if (attrPtr == 0) { LOGE("saveAttributes: couldn't find end of value len"); 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; LOGD("tag %s id %d value %s data length=%d isGps=%d", tag, exifElementTable[i].Tag, exifElementTable[i].Value, exifElementTable[i].DataLength, exifElementTable[i].GpsTag); } LOGD("Total tags: %i - %i ( total was: %i )", exifTagCount, gpsTagCount, attrCnt); filename = (*env)->GetStringUTFChars(env, jfilename, NULL); LOGD("Call loadAttributes() with filename is %s. Loading exif info\n", filename); loadExifInfo(filename, TRUE); // DEBUG ONLY ---------- // ShowTags = TRUE; // ShowImageInfo(TRUE); // LOGD("create exif 2"); // --------------------- // 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_Elements(exifElementTable, exifTagCount, gpsTagCount, attrCnt, hasDateTimeTag); if (thumbnailData) { copyThumbnailData(thumbnailData, thumbnailLength); } exit: LOGE("cleaning up now in saveAttributes"); // 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); } LOGD("returning from saveAttributes"); }
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"); }