blob: f05818600c3c335f6fcf5765c4453bab2079af53 [file] [log] [blame] [edit]
// ==========================================================
// Tag to string conversion functions
//
// Design and implementation by
// - Hervé Drolon <drolon@infonie.fr>
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================
#ifdef _MSC_VER
#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
#endif
#include "FreeImage.h"
#include "Utilities.h"
#include "FreeImageTag.h"
#include "FIRational.h"
#define MAX_TEXT_EXTENT 512
/**
Convert a tag to a C string
*/
static const char*
ConvertAnyTag(FITAG *tag) {
char format[MAX_TEXT_EXTENT];
static std::string buffer;
DWORD i;
if(!tag)
return NULL;
buffer.erase();
// convert the tag value to a string buffer
FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
DWORD tag_count = FreeImage_GetTagCount(tag);
switch(tag_type) {
case FIDT_BYTE: // N x 8-bit unsigned integer
{
BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
sprintf(format, "%ld", (LONG) pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %ld", (LONG) pvalue[i]);
buffer += format;
}
break;
}
case FIDT_SHORT: // N x 16-bit unsigned integer
{
unsigned short *pvalue = (unsigned short *)FreeImage_GetTagValue(tag);
sprintf(format, "%hu", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %hu", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_LONG: // N x 32-bit unsigned integer
{
DWORD *pvalue = (DWORD *)FreeImage_GetTagValue(tag);
sprintf(format, "%lu", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %lu", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_RATIONAL: // N x 64-bit unsigned fraction
{
DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
sprintf(format, "%ld/%ld", pvalue[0], pvalue[1]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %ld/%ld", pvalue[2*i], pvalue[2*i+1]);
buffer += format;
}
break;
}
case FIDT_SBYTE: // N x 8-bit signed integer
{
char *pvalue = (char*)FreeImage_GetTagValue(tag);
sprintf(format, "%ld", (LONG) pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %ld", (LONG) pvalue[i]);
buffer += format;
}
break;
}
case FIDT_SSHORT: // N x 16-bit signed integer
{
short *pvalue = (short *)FreeImage_GetTagValue(tag);
sprintf(format, "%hd", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %hd", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_SLONG: // N x 32-bit signed integer
{
LONG *pvalue = (LONG *)FreeImage_GetTagValue(tag);
sprintf(format, "%ld", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %ld", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_SRATIONAL:// N x 64-bit signed fraction
{
LONG *pvalue = (LONG*)FreeImage_GetTagValue(tag);
sprintf(format, "%ld/%ld", pvalue[0], pvalue[1]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %ld/%ld", pvalue[2*i], pvalue[2*i+1]);
buffer += format;
}
break;
}
case FIDT_FLOAT: // N x 32-bit IEEE floating point
{
float *pvalue = (float *)FreeImage_GetTagValue(tag);
sprintf(format, "%f", (double) pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, "%f", (double) pvalue[i]);
buffer += format;
}
break;
}
case FIDT_DOUBLE: // N x 64-bit IEEE floating point
{
double *pvalue = (double *)FreeImage_GetTagValue(tag);
sprintf(format, "%f", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, "%f", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_IFD: // N x 32-bit unsigned integer (offset)
{
DWORD *pvalue = (DWORD *)FreeImage_GetTagValue(tag);
sprintf(format, "%X", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " %X", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_PALETTE: // N x 32-bit RGBQUAD
{
RGBQUAD *pvalue = (RGBQUAD *)FreeImage_GetTagValue(tag);
sprintf(format, "(%d,%d,%d,%d)", pvalue[0].rgbRed, pvalue[0].rgbGreen, pvalue[0].rgbBlue, pvalue[0].rgbReserved);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, " (%d,%d,%d,%d)", pvalue[i].rgbRed, pvalue[i].rgbGreen, pvalue[i].rgbBlue, pvalue[i].rgbReserved);
buffer += format;
}
break;
}
case FIDT_LONG8: // N x 64-bit unsigned integer
{
UINT64 *pvalue = (UINT64 *)FreeImage_GetTagValue(tag);
sprintf(format, "%ld", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, "%ld", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_IFD8: // N x 64-bit unsigned integer (offset)
{
UINT64 *pvalue = (UINT64 *)FreeImage_GetTagValue(tag);
sprintf(format, "%X", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, "%X", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_SLONG8: // N x 64-bit signed integer
{
INT64 *pvalue = (INT64 *)FreeImage_GetTagValue(tag);
sprintf(format, "%ld", pvalue[0]);
buffer += format;
for(i = 1; i < tag_count; i++) {
sprintf(format, "%ld", pvalue[i]);
buffer += format;
}
break;
}
case FIDT_ASCII: // 8-bit bytes w/ last byte null
case FIDT_UNDEFINED:// 8-bit untyped data
default:
{
int max_size = MIN((int)FreeImage_GetTagLength(tag), (int)MAX_TEXT_EXTENT);
if(max_size == MAX_TEXT_EXTENT)
max_size--;
memcpy(format, (char*)FreeImage_GetTagValue(tag), max_size);
format[max_size] = '\0';
buffer += format;
break;
}
}
return buffer.c_str();
}
/**
Convert a Exif tag to a C string
*/
static const char*
ConvertExifTag(FITAG *tag) {
char format[MAX_TEXT_EXTENT];
static std::string buffer;
if(!tag)
return NULL;
buffer.erase();
// convert the tag value to a string buffer
switch(FreeImage_GetTagID(tag)) {
case TAG_ORIENTATION:
{
unsigned short orientation = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (orientation) {
case 1:
return "top, left side";
case 2:
return "top, right side";
case 3:
return "bottom, right side";
case 4:
return "bottom, left side";
case 5:
return "left side, top";
case 6:
return "right side, top";
case 7:
return "right side, bottom";
case 8:
return "left side, bottom";
default:
break;
}
}
break;
case TAG_REFERENCE_BLACK_WHITE:
{
DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
if(FreeImage_GetTagLength(tag) == 48) {
// reference black point value and reference white point value (ReferenceBlackWhite)
int blackR = 0, whiteR = 0, blackG = 0, whiteG = 0, blackB = 0, whiteB = 0;
if(pvalue[1])
blackR = (int)(pvalue[0] / pvalue[1]);
if(pvalue[3])
whiteR = (int)(pvalue[2] / pvalue[3]);
if(pvalue[5])
blackG = (int)(pvalue[4] / pvalue[5]);
if(pvalue[7])
whiteG = (int)(pvalue[6] / pvalue[7]);
if(pvalue[9])
blackB = (int)(pvalue[8] / pvalue[9]);
if(pvalue[11])
whiteB = (int)(pvalue[10] / pvalue[11]);
sprintf(format, "[%d,%d,%d] [%d,%d,%d]", blackR, blackG, blackB, whiteR, whiteG, whiteB);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_COLOR_SPACE:
{
unsigned short colorSpace = *((unsigned short *)FreeImage_GetTagValue(tag));
if (colorSpace == 1) {
return "sRGB";
} else if (colorSpace == 65535) {
return "Undefined";
} else {
return "Unknown";
}
}
break;
case TAG_COMPONENTS_CONFIGURATION:
{
const char *componentStrings[7] = {"", "Y", "Cb", "Cr", "R", "G", "B"};
BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
for(DWORD i = 0; i < MIN((DWORD)4, FreeImage_GetTagCount(tag)); i++) {
int j = pvalue[i];
if(j > 0 && j < 7)
buffer += componentStrings[j];
}
return buffer.c_str();
}
break;
case TAG_COMPRESSED_BITS_PER_PIXEL:
{
FIRational r(tag);
buffer = r.toString();
if(buffer == "1")
buffer += " bit/pixel";
else
buffer += " bits/pixel";
return buffer.c_str();
}
break;
case TAG_X_RESOLUTION:
case TAG_Y_RESOLUTION:
case TAG_FOCAL_PLANE_X_RES:
case TAG_FOCAL_PLANE_Y_RES:
case TAG_BRIGHTNESS_VALUE:
case TAG_EXPOSURE_BIAS_VALUE:
{
FIRational r(tag);
buffer = r.toString();
return buffer.c_str();
}
break;
case TAG_RESOLUTION_UNIT:
case TAG_FOCAL_PLANE_UNIT:
{
unsigned short resolutionUnit = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (resolutionUnit) {
case 1:
return "(No unit)";
case 2:
return "inches";
case 3:
return "cm";
default:
break;
}
}
break;
case TAG_YCBCR_POSITIONING:
{
unsigned short yCbCrPosition = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (yCbCrPosition) {
case 1:
return "Center of pixel array";
case 2:
return "Datum point";
default:
break;
}
}
break;
case TAG_EXPOSURE_TIME:
{
FIRational r(tag);
buffer = r.toString();
buffer += " sec";
return buffer.c_str();
}
break;
case TAG_SHUTTER_SPEED_VALUE:
{
FIRational r(tag);
LONG apexValue = r.longValue();
LONG apexPower = 1 << apexValue;
sprintf(format, "1/%d sec", (int)apexPower);
buffer += format;
return buffer.c_str();
}
break;
case TAG_APERTURE_VALUE:
case TAG_MAX_APERTURE_VALUE:
{
FIRational r(tag);
double apertureApex = r.doubleValue();
double rootTwo = sqrt((double)2);
double fStop = pow(rootTwo, apertureApex);
sprintf(format, "F%.1f", fStop);
buffer += format;
return buffer.c_str();
}
break;
case TAG_FNUMBER:
{
FIRational r(tag);
double fnumber = r.doubleValue();
sprintf(format, "F%.1f", fnumber);
buffer += format;
return buffer.c_str();
}
break;
case TAG_FOCAL_LENGTH:
{
FIRational r(tag);
double focalLength = r.doubleValue();
sprintf(format, "%.1f mm", focalLength);
buffer += format;
return buffer.c_str();
}
break;
case TAG_FOCAL_LENGTH_IN_35MM_FILM:
{
unsigned short focalLength = *((unsigned short *)FreeImage_GetTagValue(tag));
sprintf(format, "%hu mm", focalLength);
buffer += format;
return buffer.c_str();
}
break;
case TAG_FLASH:
{
unsigned short flash = *((unsigned short *)FreeImage_GetTagValue(tag));
switch(flash) {
case 0x0000:
return "Flash did not fire";
case 0x0001:
return "Flash fired";
case 0x0005:
return "Strobe return light not detected";
case 0x0007:
return "Strobe return light detected";
case 0x0009:
return "Flash fired, compulsory flash mode";
case 0x000D:
return "Flash fired, compulsory flash mode, return light not detected";
case 0x000F:
return "Flash fired, compulsory flash mode, return light detected";
case 0x0010:
return "Flash did not fire, compulsory flash mode";
case 0x0018:
return "Flash did not fire, auto mode";
case 0x0019:
return "Flash fired, auto mode";
case 0x001D:
return "Flash fired, auto mode, return light not detected";
case 0x001F:
return "Flash fired, auto mode, return light detected";
case 0x0020:
return "No flash function";
case 0x0041:
return "Flash fired, red-eye reduction mode";
case 0x0045:
return "Flash fired, red-eye reduction mode, return light not detected";
case 0x0047:
return "Flash fired, red-eye reduction mode, return light detected";
case 0x0049:
return "Flash fired, compulsory flash mode, red-eye reduction mode";
case 0x004D:
return "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
case 0x004F:
return "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
case 0x0059:
return "Flash fired, auto mode, red-eye reduction mode";
case 0x005D:
return "Flash fired, auto mode, return light not detected, red-eye reduction mode";
case 0x005F:
return "Flash fired, auto mode, return light detected, red-eye reduction mode";
default:
sprintf(format, "Unknown (%d)", flash);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_SCENE_TYPE:
{
BYTE sceneType = *((BYTE*)FreeImage_GetTagValue(tag));
if (sceneType == 1) {
return "Directly photographed image";
} else {
sprintf(format, "Unknown (%d)", sceneType);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_SUBJECT_DISTANCE:
{
FIRational r(tag);
if(r.getNumerator() == 0xFFFFFFFF) {
return "Infinity";
} else if(r.getNumerator() == 0) {
return "Distance unknown";
} else {
double distance = r.doubleValue();
sprintf(format, "%.3f meters", distance);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_METERING_MODE:
{
unsigned short meteringMode = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (meteringMode) {
case 0:
return "Unknown";
case 1:
return "Average";
case 2:
return "Center weighted average";
case 3:
return "Spot";
case 4:
return "Multi-spot";
case 5:
return "Multi-segment";
case 6:
return "Partial";
case 255:
return "(Other)";
default:
return "";
}
}
break;
case TAG_LIGHT_SOURCE:
{
unsigned short lightSource = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (lightSource) {
case 0:
return "Unknown";
case 1:
return "Daylight";
case 2:
return "Fluorescent";
case 3:
return "Tungsten (incandescent light)";
case 4:
return "Flash";
case 9:
return "Fine weather";
case 10:
return "Cloudy weather";
case 11:
return "Shade";
case 12:
return "Daylight fluorescent (D 5700 - 7100K)";
case 13:
return "Day white fluorescent (N 4600 - 5400K)";
case 14:
return "Cool white fluorescent (W 3900 - 4500K)";
case 15:
return "White fluorescent (WW 3200 - 3700K)";
case 17:
return "Standard light A";
case 18:
return "Standard light B";
case 19:
return "Standard light C";
case 20:
return "D55";
case 21:
return "D65";
case 22:
return "D75";
case 23:
return "D50";
case 24:
return "ISO studio tungsten";
case 255:
return "(Other)";
default:
return "";
}
}
break;
case TAG_SENSING_METHOD:
{
unsigned short sensingMethod = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (sensingMethod) {
case 1:
return "(Not defined)";
case 2:
return "One-chip color area sensor";
case 3:
return "Two-chip color area sensor";
case 4:
return "Three-chip color area sensor";
case 5:
return "Color sequential area sensor";
case 7:
return "Trilinear sensor";
case 8:
return "Color sequential linear sensor";
default:
return "";
}
}
break;
case TAG_FILE_SOURCE:
{
BYTE fileSource = *((BYTE*)FreeImage_GetTagValue(tag));
if (fileSource == 3) {
return "Digital Still Camera (DSC)";
} else {
sprintf(format, "Unknown (%d)", fileSource);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_EXPOSURE_PROGRAM:
{
unsigned short exposureProgram = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (exposureProgram) {
case 1:
return "Manual control";
case 2:
return "Program normal";
case 3:
return "Aperture priority";
case 4:
return "Shutter priority";
case 5:
return "Program creative (slow program)";
case 6:
return "Program action (high-speed program)";
case 7:
return "Portrait mode";
case 8:
return "Landscape mode";
default:
sprintf(format, "Unknown program (%d)", exposureProgram);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_CUSTOM_RENDERED:
{
unsigned short customRendered = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (customRendered) {
case 0:
return "Normal process";
case 1:
return "Custom process";
default:
sprintf(format, "Unknown rendering (%d)", customRendered);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_EXPOSURE_MODE:
{
unsigned short exposureMode = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (exposureMode) {
case 0:
return "Auto exposure";
case 1:
return "Manual exposure";
case 2:
return "Auto bracket";
default:
sprintf(format, "Unknown mode (%d)", exposureMode);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_WHITE_BALANCE:
{
unsigned short whiteBalance = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (whiteBalance) {
case 0:
return "Auto white balance";
case 1:
return "Manual white balance";
default:
sprintf(format, "Unknown (%d)", whiteBalance);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_SCENE_CAPTURE_TYPE:
{
unsigned short sceneType = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (sceneType) {
case 0:
return "Standard";
case 1:
return "Landscape";
case 2:
return "Portrait";
case 3:
return "Night scene";
default:
sprintf(format, "Unknown (%d)", sceneType);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_GAIN_CONTROL:
{
unsigned short gainControl = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (gainControl) {
case 0:
return "None";
case 1:
return "Low gain up";
case 2:
return "High gain up";
case 3:
return "Low gain down";
case 4:
return "High gain down";
default:
sprintf(format, "Unknown (%d)", gainControl);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_CONTRAST:
{
unsigned short contrast = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (contrast) {
case 0:
return "Normal";
case 1:
return "Soft";
case 2:
return "Hard";
default:
sprintf(format, "Unknown (%d)", contrast);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_SATURATION:
{
unsigned short saturation = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (saturation) {
case 0:
return "Normal";
case 1:
return "Low saturation";
case 2:
return "High saturation";
default:
sprintf(format, "Unknown (%d)", saturation);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_SHARPNESS:
{
unsigned short sharpness = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (sharpness) {
case 0:
return "Normal";
case 1:
return "Soft";
case 2:
return "Hard";
default:
sprintf(format, "Unknown (%d)", sharpness);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_SUBJECT_DISTANCE_RANGE:
{
unsigned short distanceRange = *((unsigned short *)FreeImage_GetTagValue(tag));
switch (distanceRange) {
case 0:
return "unknown";
case 1:
return "Macro";
case 2:
return "Close view";
case 3:
return "Distant view";
default:
sprintf(format, "Unknown (%d)", distanceRange);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_ISO_SPEED_RATINGS:
{
unsigned short isoEquiv = *((unsigned short *)FreeImage_GetTagValue(tag));
if (isoEquiv < 50) {
isoEquiv *= 200;
}
sprintf(format, "%d", isoEquiv);
buffer += format;
return buffer.c_str();
}
break;
case TAG_USER_COMMENT:
{
// first 8 bytes are used to define an ID code
// we assume this is an ASCII string
const BYTE *userComment = (BYTE*)FreeImage_GetTagValue(tag);
for(DWORD i = 8; i < FreeImage_GetTagLength(tag); i++) {
buffer += userComment[i];
}
buffer += '\0';
return buffer.c_str();
}
break;
case TAG_COMPRESSION:
{
WORD compression = *((WORD*)FreeImage_GetTagValue(tag));
switch(compression) {
case TAG_COMPRESSION_NONE:
sprintf(format, "dump mode (%d)", compression);
break;
case TAG_COMPRESSION_CCITTRLE:
sprintf(format, "CCITT modified Huffman RLE (%d)", compression);
break;
case TAG_COMPRESSION_CCITTFAX3:
sprintf(format, "CCITT Group 3 fax encoding (%d)", compression);
break;
/*
case TAG_COMPRESSION_CCITT_T4:
sprintf(format, "CCITT T.4 (TIFF 6 name) (%d)", compression);
break;
*/
case TAG_COMPRESSION_CCITTFAX4:
sprintf(format, "CCITT Group 4 fax encoding (%d)", compression);
break;
/*
case TAG_COMPRESSION_CCITT_T6:
sprintf(format, "CCITT T.6 (TIFF 6 name) (%d)", compression);
break;
*/
case TAG_COMPRESSION_LZW:
sprintf(format, "LZW (%d)", compression);
break;
case TAG_COMPRESSION_OJPEG:
sprintf(format, "!6.0 JPEG (%d)", compression);
break;
case TAG_COMPRESSION_JPEG:
sprintf(format, "JPEG (%d)", compression);
break;
case TAG_COMPRESSION_NEXT:
sprintf(format, "NeXT 2-bit RLE (%d)", compression);
break;
case TAG_COMPRESSION_CCITTRLEW:
sprintf(format, "CCITTRLEW (%d)", compression);
break;
case TAG_COMPRESSION_PACKBITS:
sprintf(format, "PackBits Macintosh RLE (%d)", compression);
break;
case TAG_COMPRESSION_THUNDERSCAN:
sprintf(format, "ThunderScan RLE (%d)", compression);
break;
case TAG_COMPRESSION_PIXARFILM:
sprintf(format, "Pixar companded 10bit LZW (%d)", compression);
break;
case TAG_COMPRESSION_PIXARLOG:
sprintf(format, "Pixar companded 11bit ZIP (%d)", compression);
break;
case TAG_COMPRESSION_DEFLATE:
sprintf(format, "Deflate compression (%d)", compression);
break;
case TAG_COMPRESSION_ADOBE_DEFLATE:
sprintf(format, "Adobe Deflate compression (%d)", compression);
break;
case TAG_COMPRESSION_DCS:
sprintf(format, "Kodak DCS encoding (%d)", compression);
break;
case TAG_COMPRESSION_JBIG:
sprintf(format, "ISO JBIG (%d)", compression);
break;
case TAG_COMPRESSION_SGILOG:
sprintf(format, "SGI Log Luminance RLE (%d)", compression);
break;
case TAG_COMPRESSION_SGILOG24:
sprintf(format, "SGI Log 24-bit packed (%d)", compression);
break;
case TAG_COMPRESSION_JP2000:
sprintf(format, "Leadtools JPEG2000 (%d)", compression);
break;
case TAG_COMPRESSION_LZMA:
sprintf(format, "LZMA2 (%d)", compression);
break;
default:
sprintf(format, "Unknown type (%d)", compression);
break;
}
buffer += format;
return buffer.c_str();
}
break;
}
return ConvertAnyTag(tag);
}
/**
Convert a Exif GPS tag to a C string
*/
static const char*
ConvertExifGPSTag(FITAG *tag) {
char format[MAX_TEXT_EXTENT];
static std::string buffer;
if(!tag)
return NULL;
buffer.erase();
// convert the tag value to a string buffer
switch(FreeImage_GetTagID(tag)) {
case TAG_GPS_LATITUDE:
case TAG_GPS_LONGITUDE:
case TAG_GPS_TIME_STAMP:
{
DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
if(FreeImage_GetTagLength(tag) == 24) {
// dd:mm:ss or hh:mm:ss
int dd = 0, mm = 0;
double ss = 0;
// convert to seconds
if(pvalue[1])
ss += ((double)pvalue[0] / (double)pvalue[1]) * 3600;
if(pvalue[3])
ss += ((double)pvalue[2] / (double)pvalue[3]) * 60;
if(pvalue[5])
ss += ((double)pvalue[4] / (double)pvalue[5]);
// convert to dd:mm:ss.ss
dd = (int)(ss / 3600);
mm = (int)(ss / 60) - dd * 60;
ss = ss - dd * 3600 - mm * 60;
sprintf(format, "%d:%d:%.2f", dd, mm, ss);
buffer += format;
return buffer.c_str();
}
}
break;
case TAG_GPS_VERSION_ID:
case TAG_GPS_LATITUDE_REF:
case TAG_GPS_LONGITUDE_REF:
case TAG_GPS_ALTITUDE_REF:
case TAG_GPS_ALTITUDE:
case TAG_GPS_SATELLITES:
case TAG_GPS_STATUS:
case TAG_GPS_MEASURE_MODE:
case TAG_GPS_DOP:
case TAG_GPS_SPEED_REF:
case TAG_GPS_SPEED:
case TAG_GPS_TRACK_REF:
case TAG_GPS_TRACK:
case TAG_GPS_IMG_DIRECTION_REF:
case TAG_GPS_IMG_DIRECTION:
case TAG_GPS_MAP_DATUM:
case TAG_GPS_DEST_LATITUDE_REF:
case TAG_GPS_DEST_LATITUDE:
case TAG_GPS_DEST_LONGITUDE_REF:
case TAG_GPS_DEST_LONGITUDE:
case TAG_GPS_DEST_BEARING_REF:
case TAG_GPS_DEST_BEARING:
case TAG_GPS_DEST_DISTANCE_REF:
case TAG_GPS_DEST_DISTANCE:
case TAG_GPS_PROCESSING_METHOD:
case TAG_GPS_AREA_INFORMATION:
case TAG_GPS_DATE_STAMP:
case TAG_GPS_DIFFERENTIAL:
break;
}
return ConvertAnyTag(tag);
}
// ==========================================================
// Tag to string conversion function
//
const char* DLL_CALLCONV
FreeImage_TagToString(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make) {
switch(model) {
case FIMD_EXIF_MAIN:
case FIMD_EXIF_EXIF:
return ConvertExifTag(tag);
case FIMD_EXIF_GPS:
return ConvertExifGPSTag(tag);
case FIMD_EXIF_MAKERNOTE:
// We should use the Make string to select an appropriate conversion function
// TO DO ...
break;
case FIMD_EXIF_INTEROP:
default:
break;
}
return ConvertAnyTag(tag);
}