static void vips_exif_set_int( ExifData *ed, ExifEntry *entry, unsigned long component, void *data ) { int value = *((int *) data); ExifByteOrder bo; size_t sizeof_component; size_t offset = component; if( entry->components <= component ) { VIPS_DEBUG_MSG( "vips_exif_set_int: too few components\n" ); return; } /* Wait until after the component check to make sure we cant get /0. */ bo = exif_data_get_byte_order( ed ); sizeof_component = entry->size / entry->components; offset = component * sizeof_component; VIPS_DEBUG_MSG( "vips_exif_set_int: %s = %d\n", vips_exif_entry_get_name( entry ), value ); if( entry->format == EXIF_FORMAT_SHORT ) exif_set_short( entry->data + offset, bo, value ); else if( entry->format == EXIF_FORMAT_SSHORT ) exif_set_sshort( entry->data + offset, bo, value ); else if( entry->format == EXIF_FORMAT_LONG ) exif_set_long( entry->data + offset, bo, value ); else if( entry->format == EXIF_FORMAT_SLONG ) exif_set_slong( entry->data + offset, bo, value ); }
void exif_entry_set_slong (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, ExifSLong n) { ExifEntry *pE; ExifByteOrder eO; pE = exif_entry_new (); exif_content_add_entry (pEdata->ifd[eEifd], pE); exif_entry_initialize (pE, eEtag); eO = exif_data_get_byte_order (pE->parent->parent); if (pE->data) { exif_set_slong (pE->data, eO, n); } else { printf ("ERROR: unallocated e->data Tag %d\n", eEtag); } exif_entry_fix (pE); exif_entry_unref (pE); }
static void set_int(ExifData *ed, ExifEntry *ee, long value) { ExifByteOrder o = exif_data_get_byte_order(ed); switch (ee->format) { case EXIF_FORMAT_SHORT: exif_set_short (ee->data, o, value); break; case EXIF_FORMAT_LONG: exif_set_long (ee->data, o, value); break; case EXIF_FORMAT_SLONG: exif_set_slong (ee->data, o, value); break; default: fprintf(stderr,"set_int oops\n"); exit(1); } }
static int iExifWriteTag(ExifData* exif, int index, const char* name, int data_type, int attrib_count, const void* attrib_data) { int c; ExifTag tag = exif_tag_from_name(name); if (tag == 0) { if (!imStrEqual(name, "GPSVersionID")) // EXIF_TAG_GPS_VERSION_ID==0 return 1; } ExifEntry *entry = exif_entry_new(); ExifByteOrder byte_order = exif_data_get_byte_order(exif); ExifContent *content; if (name[0] == 'G' && name[1] == 'P' && name[2] == 'S') { content = exif->ifd[EXIF_IFD_GPS]; // GPS tags if (!iExifGetGPSTagInfo((int)tag, &(entry->format), &(entry->components))) { exif_entry_free(entry); return 1; } } else { if (tag > EXIF_TAG_COPYRIGHT) content = exif->ifd[EXIF_IFD_EXIF]; // EXIF tags else content = exif->ifd[EXIF_IFD_0]; // TIFF tags if (!iExifGetTagInfo(tag, &(entry->format), &(entry->components))) { exif_entry_free(entry); return 1; } } int format_size = exif_format_get_size(entry->format); if (entry->components == 0) entry->components = attrib_count; entry->tag = tag; entry->size = format_size * entry->components; entry->data = (imbyte*)malloc(entry->size); if (tag == EXIF_TAG_RESOLUTION_UNIT) { int res_unit; if (imStrEqual((char*)attrib_data, "DPI")) res_unit = 2; else res_unit = 3; exif_content_add_entry(content, entry); exif_set_short(entry->data, byte_order, (imushort)res_unit); return 1; } /* test if tag type is the same as the attribute type */ if (iExifGetDataType(entry->format) != data_type) { exif_entry_free(entry); return 1; } exif_content_add_entry(content, entry); switch (entry->format) { case EXIF_FORMAT_UNDEFINED: case EXIF_FORMAT_ASCII: case EXIF_FORMAT_SBYTE: case EXIF_FORMAT_BYTE: { imbyte *bvalue = (imbyte*)attrib_data; for (c = 0; c < (int)entry->components; c++) entry->data[c] = bvalue[c]; } break; case EXIF_FORMAT_SHORT: { imushort *usvalue = (imushort*)attrib_data; for (c = 0; c < (int)entry->components; c++) exif_set_short(entry->data + format_size * c, byte_order, usvalue[c]); } break; case EXIF_FORMAT_SSHORT: { short *svalue = (short*)attrib_data; for (c = 0; c < (int)entry->components; c++) exif_set_sshort(entry->data + format_size * c, byte_order, svalue[c]); } break; case EXIF_FORMAT_LONG: { int *ivalue = (int*)attrib_data; for (c = 0; c < (int)entry->components; c++) exif_set_long(entry->data + format_size * c, byte_order, (unsigned int)ivalue[c]); } break; case EXIF_FORMAT_SLONG: { int *ivalue = (int*)attrib_data; for (c = 0; c < (int)entry->components; c++) exif_set_slong(entry->data + format_size * c, byte_order, (int)ivalue[c]); } break; case EXIF_FORMAT_RATIONAL: { ExifRational v_rat; int num, den; float *fvalue = (float*)attrib_data; for (c = 0; c < (int)entry->components; c++) { iGetRational(fvalue[c], &num, &den, 1); v_rat.numerator = num; v_rat.denominator = den; exif_set_rational(entry->data + format_size * c, byte_order, v_rat); } } break; case EXIF_FORMAT_SRATIONAL: { ExifSRational v_srat; int num, den; float *fvalue = (float*)attrib_data; for (c = 0; c < (int)entry->components; c++) { iGetRational(fvalue[c], &num, &den, 1); v_srat.numerator = num; v_srat.denominator = den; exif_set_srational(entry->data + format_size * c, byte_order, v_srat); } } break; case EXIF_FORMAT_FLOAT: // defined but unsupported in libEXIF case EXIF_FORMAT_DOUBLE: // defined but unsupported in libEXIF break; } /* no need to release the entry here, it will be handled internally because we added the entry to the ExifContent */ (void)index; return 1; }
/** Heavily based on convert_arg_to_entry from exif command line tool. * But without ExifLog, exitting, use of g_* io functions * and can take a gdouble value instead of a string */ static void convert_to_entry (const char *set_value, gdouble gdvalue, ExifEntry *e, ExifByteOrder o) { unsigned int i, numcomponents; char *value_p = NULL; char *buf = NULL; /* * ASCII strings are handled separately, * since they don't require any conversion. */ if (e->format == EXIF_FORMAT_ASCII || e->tag == EXIF_TAG_USER_COMMENT) { if (e->data) g_free (e->data); e->components = strlen (set_value) + 1; if (e->tag == EXIF_TAG_USER_COMMENT) e->components += 8 - 1; e->size = sizeof (char) * e->components; e->data = g_malloc (e->size); if (!e->data) { g_warning (_("Not enough memory.")); return; } if (e->tag == EXIF_TAG_USER_COMMENT) { /* assume ASCII charset */ /* TODO: get this from the current locale */ memcpy ((char *) e->data, "ASCII\0\0\0", 8); memcpy ((char *) e->data + 8, set_value, strlen (set_value)); } else strcpy ((char *) e->data, set_value); return; } /* * Make sure we can handle this entry */ if ((e->components == 0) && *set_value) { g_warning (_("Setting a value for this tag is unsupported!")); return; } gboolean use_string = (set_value != NULL); if ( use_string ) { /* Copy the string so we can modify it */ buf = g_strdup (set_value); if (!buf) return; value_p = strtok (buf, " "); } numcomponents = e->components; for (i = 0; i < numcomponents; ++i) { unsigned char s; if ( use_string ) { if (!value_p) { g_warning (_("Too few components specified (need %d, found %d)\n"), numcomponents, i); return; } if (!isdigit(*value_p) && (*value_p != '+') && (*value_p != '-')) { g_warning (_("Numeric value expected\n")); return; } } s = exif_format_get_size (e->format); switch (e->format) { case EXIF_FORMAT_ASCII: g_warning (_("This shouldn't happen!")); return; break; case EXIF_FORMAT_SHORT: exif_set_short (e->data + (s * i), o, atoi (value_p)); break; case EXIF_FORMAT_SSHORT: exif_set_sshort (e->data + (s * i), o, atoi (value_p)); break; case EXIF_FORMAT_RATIONAL: { ExifRational er; double val = 0.0 ; if ( use_string && value_p ) val = fabs (atol (value_p)); else val = fabs (gdvalue); if ( i == 0 ) { // One (or first) part rational // Sneak peek into tag as location tags need rounding down to give just the degrees part if ( e->tag == EXIF_TAG_GPS_LATITUDE || e->tag == EXIF_TAG_GPS_LONGITUDE ) { er.numerator = (ExifLong) floor ( val ); er.denominator = 1.0; } else { // I don't see any point in doing anything too complicated here, // such as trying to work out the 'best' denominator // For the moment use KISS principle. // Fix a precision of 1/100 metre as that's more than enough for GPS accuracy especially altitudes! er.denominator = 100.0; er.numerator = (ExifLong) (val * er.denominator); } } // Now for Location 3 part rationals do Mins and Seconds format // Rounded down minutes if ( i == 1 ) { er.denominator = 1.0; er.numerator = (ExifLong) ( (int) floor ( ( val - floor (val) ) * 60.0 ) ); } // Finally seconds if ( i == 2 ) { er.denominator = 100.0; // Fractional minute. double FracPart = ((val - floor(val)) * 60) - (double)(int) floor ( ( val - floor (val) ) * 60.0 ); er.numerator = (ExifLong) ( (int)floor(FracPart * 6000) ); // Convert to seconds. } exif_set_rational (e->data + (s * i), o, er ); break; } case EXIF_FORMAT_LONG: exif_set_long (e->data + (s * i), o, atol (value_p)); break; case EXIF_FORMAT_SLONG: exif_set_slong (e->data + (s * i), o, atol (value_p)); break; case EXIF_FORMAT_BYTE: case EXIF_FORMAT_SBYTE: case EXIF_FORMAT_UNDEFINED: /* treat as byte array */ e->data[s * i] = atoi (value_p); break; case EXIF_FORMAT_FLOAT: case EXIF_FORMAT_DOUBLE: case EXIF_FORMAT_SRATIONAL: default: g_warning (_("Not yet implemented!")); return; } if ( use_string ) value_p = strtok (NULL, " "); } g_free (buf); if ( use_string ) if ( value_p ) g_warning (_("Warning; Too many components specified!")); }