Exemplo n.º 1
0
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_sshort (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
   ExifSShort 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_sshort (pE->data, eO, n);
  } else {
    printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  }
  exif_entry_fix (pE);
  exif_entry_unref (pE);
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
/** 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!"));
}