Пример #1
0
static void
exif_mnote_data_canon_save (ExifMnoteData *ne, 
	unsigned char **buf, unsigned int *buf_size)
{
	ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
	unsigned int i, o, s, doff;

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for all entries and the number
	 * of entries.
	 */
	*buf_size = 2 + n->count * 12 + 4;
	*buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
	if (!*buf) return;

	/* Save the number of entries */
	exif_set_short (*buf, n->order, (ExifShort) n->count);
	
	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		o = 2 + i * 12;
		exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
		exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order,
				n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 4) {
			*buf_size += s;

			/* Ensure even offsets. Set padding bytes to 0. */
			if (s & 1) *buf_size += 1;
			*buf = exif_mem_realloc (ne->mem, *buf,
						 sizeof (char) * *buf_size);
			if (!*buf) return;
			doff = *buf_size - s;
			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
			exif_set_long (*buf + o, n->order, n->offset + doff);
		} else
			doff = o;

		/*
		 * Write the data. Fill unneeded bytes with 0. Do not
		 * crash if data is NULL.
		 */
		if (!n->entries[i].data) memset (*buf + doff, 0, s);
		else memcpy (*buf + doff, n->entries[i].data, s);
		if (s < 4) memset (*buf + doff + s, 0, (4 - s));
	}
}
Пример #2
0
static void
write_short( ExifEntry *entry, ExifByteOrder bo, void *data )
{
	ExifShort *v = (ExifShort *) data;

	exif_set_short( entry->data, bo, *v );
}
Пример #3
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 );
}
Пример #4
0
void write_content_binary(unsigned char *data, ExifContent *content, ExifByteOrder order, unsigned int offset)
{
	unsigned int i = 0;
	unsigned int next_data = 0;
	ExifEntry *entry = NULL;
	unsigned int s = 0;
	unsigned char *d = data;

	exif_set_short(d, order, content->count);
	d += 2;
	next_data = 2 + offset + content->count * 12;// + 2;
	for (i = 0; i < content->count; i++)
	{
		entry = content->entries[i];
		if (entry != NULL)
		{
			exif_set_short(d + 0x00, order, entry->tag);
			exif_set_short(d + 0x02, order, entry->format);
			exif_set_long (d + 0x04, order, entry->components);
			s = exif_format_get_size(entry->format) * entry->components;
			if (s > 4)
			{
				exif_set_long (d + 0x08, order, next_data + 2*0);// начало смещения данных после APP2 (2 байта)
				memcpy(data + next_data - offset, entry->data, s);
				next_data += s;
			}
			else
			{
				if (entry->tag == SGEO_TAG_VERSIONID)
					write_sgeo_version(d + 0x08, order);
				else
					memcpy(d + 0x08, entry->data, s);
			}
			d = d + 0x0c;
		}
	}
}
void
exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
{
	if (ds)
		*ds = 0;	/* This means something went wrong */

	if (!data || !d || !ds)
		return;

	/* Header */
	*ds = 14;
	*d = exif_data_alloc (data, *ds);
	if (!*d)  {
		*ds = 0;
		return;
	}
	memcpy (*d, ExifHeader, 6);

	/* Order (offset 6) */
	if (data->priv->order == EXIF_BYTE_ORDER_INTEL) {
		memcpy (*d + 6, "II", 2);
	} else {
		memcpy (*d + 6, "MM", 2);
	}

	/* Fixed value (2 bytes, offset 8) */
	exif_set_short (*d + 8, data->priv->order, 0x002a);

	/*
	 * IFD 0 offset (4 bytes, offset 10).
	 * We will start 8 bytes after the
	 * EXIF header (2 bytes for order, another 2 for the test, and
	 * 4 bytes for the IFD 0 offset make 8 bytes together).
	 */
	exif_set_long (*d + 10, data->priv->order, 8);

	/* Now save IFD 0. IFD 1 will be saved automatically. */
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
		  "Saving IFDs...");
	exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds,
				     *ds - 6);
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
		  "Saved %i byte(s) EXIF data.", *ds);
}
void exif_entry_set_short (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
    ExifShort 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_short (pE->data, eO, n);
  } else {
    printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  }
  exif_entry_fix (pE);
  exif_entry_unref (pE);
}
Пример #7
0
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);
    }
}
Пример #8
0
void
jpeg_setup_exif_for_save (ExifData     *exif_data,
                          const gint32  image_ID)
{
  ExifRational  r;
  gdouble       xres, yres;
  ExifEntry    *entry;
  gint          byte_order = exif_data_get_byte_order (exif_data);

  /* set orientation to top - left */
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_0],
                                       EXIF_TAG_ORIENTATION)))
    {
      exif_set_short (entry->data, byte_order, (ExifShort) 1);
    }

  /* set x and y resolution */
  gimp_image_get_resolution (image_ID, &xres, &yres);
  r.numerator =   xres;
  r.denominator = 1;
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_0],
                                       EXIF_TAG_X_RESOLUTION)))
    {
      exif_set_rational (entry->data, byte_order, r);
    }
  r.numerator = yres;
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_0],
                                       EXIF_TAG_Y_RESOLUTION)))
    {
      exif_set_rational (entry->data, byte_order, r);
    }

  /* set resolution unit, always inches */
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_0],
                                       EXIF_TAG_RESOLUTION_UNIT)))
    {
      exif_set_short (entry->data, byte_order, (ExifShort) 2);
    }

  /* set software to "GIMP" and include the version number */
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_0],
                                       EXIF_TAG_SOFTWARE)))
    {
      const gchar *name = "GIMP " GIMP_VERSION;

      entry->data = (guchar *) g_strdup (name);
      entry->size = strlen (name) + 1;
      entry->components = entry->size;
    }

  /* set the width and height */
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_EXIF],
                                       EXIF_TAG_PIXEL_X_DIMENSION)))
    {
      exif_set_long (entry->data, byte_order,
                     (ExifLong) gimp_image_width (image_ID));
    }
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_EXIF],
                                       EXIF_TAG_PIXEL_Y_DIMENSION)))
    {
      exif_set_long (entry->data, byte_order,
                     (ExifLong) gimp_image_height (image_ID));
    }

  /*
   * set the date & time image was saved
   * note, date & time of original photo is stored elsewwhere, we
   * aren't losing it.
   */
  if ((entry = exif_content_get_entry (exif_data->ifd[EXIF_IFD_0],
                                       EXIF_TAG_DATE_TIME)))
    {
      /* small memory leak here */
      entry->data = NULL;
      exif_entry_initialize (entry, EXIF_TAG_DATE_TIME);
    }

  /* should set components configuration, don't know how */

  /*
   * remove entries that don't apply to jpeg
   * (may have come from tiff or raw)
   */
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_COMPRESSION);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_BITS_PER_SAMPLE);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_SAMPLES_PER_PIXEL);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_PHOTOMETRIC_INTERPRETATION);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_STRIP_OFFSETS);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_PLANAR_CONFIGURATION);
  gimp_exif_data_remove_entry (exif_data, EXIF_IFD_0, EXIF_TAG_YCBCR_SUB_SAMPLING);

  /* should set thumbnail attributes */
}
Пример #9
0
int createEXIF(dc1394featureset_t *xFeatures, ExifData ** pParentEd)
{
    ExifEntry *pE;
    ExifData * pEd;
    int i = !xFeatures->feature[DC1394_FEATURE_WHITE_BALANCE - DC1394_FEATURE_MIN].auto_active;

    ExifSRational xR = {xFeatures->feature[DC1394_FEATURE_BRIGHTNESS - DC1394_FEATURE_MIN].value, xFeatures->feature[DC1394_FEATURE_BRIGHTNESS - DC1394_FEATURE_MIN].max};;

    printf ("Creating EXIF data...\n");
    pEd = exif_data_new ();


    printf ("Adding a Make reference\n");
    pE = exif_entry_new ();
    exif_content_add_entry (pEd->ifd[EXIF_IFD_0], pE);
    exif_entry_initialize (pE, EXIF_TAG_MAKE);
    pE->data="AVT";
    exif_entry_unref (pE);

    printf ("Adding a Model reference\n");
    pE = exif_entry_new ();
    exif_content_add_entry (pEd->ifd[EXIF_IFD_0], pE);
    exif_entry_initialize (pE, EXIF_TAG_MODEL);
    pE->data="510c";
    exif_entry_unref (pE);

    printf ("Adding a Tag to reference # samples per pixel\n");
    pE = exif_entry_new ();
    exif_content_add_entry (pEd->ifd[EXIF_IFD_0], pE);
    exif_entry_initialize (pE, EXIF_TAG_SAMPLES_PER_PIXEL); 
    exif_entry_unref (pE);

    printf ("Adding a White Balance Reference\n");
    pE = exif_entry_new ();
    exif_content_add_entry (pEd->ifd[EXIF_IFD_0], pE);
    exif_entry_initialize (pE, EXIF_TAG_WHITE_BALANCE);
    exif_set_short(pE->data, exif_data_get_byte_order (pEd), i);  
    exif_entry_unref (pE);

    
    printf ("Adding a Sharpness Reference\n");
    pE = exif_entry_new ();
    exif_content_add_entry (pEd->ifd[EXIF_IFD_0], pE);
    exif_entry_initialize (pE, EXIF_TAG_SHARPNESS);
    exif_set_short(pE->data, exif_data_get_byte_order (pEd), 0);
    exif_entry_unref (pE);

    printf ("Adding a Brightness reference\n");

    
    

    pE = exif_entry_new ();
    exif_content_add_entry (pEd->ifd[EXIF_IFD_0], pE);
    exif_entry_initialize (pE, EXIF_TAG_BRIGHTNESS_VALUE);
    exif_set_srational (pE->data, exif_data_get_byte_order (pEd), xR);


    
    
    *pParentEd = pEd;
    printf("Done!\n");

    return 0;
}
/** 
 * @brief save the MnoteData from ne to buf
 * 
 * @param ne extract the data from this structure 
 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
 * @param buf_size the final size of the buffer
 */
static void
exif_mnote_data_pentax_save (ExifMnoteData *ne,
		unsigned char **buf, unsigned int *buf_size)
{
	ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) ne;
	size_t i,
	   base = 0,		/* internal MakerNote tag number offset */
	   o2 = 4 + 2;  	/* offset to first tag entry, past header */
        size_t datao = n->offset; /* this MakerNote style uses offsets
        			  based on main IFD, not makernote IFD */

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for header, the number of entries, entries,
	 * and next IFD pointer
	 */
	*buf_size = o2 + 2 + n->count * 12 + 4;
	switch (n->version) {
	case casioV2:
		base = MNOTE_PENTAX2_TAG_BASE;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}
		/* Write the magic header */
		strcpy ((char *)*buf, "QVC");
		exif_set_short (*buf + 4, n->order, (ExifShort) 0);

		break;

	case pentaxV3:
		base = MNOTE_PENTAX2_TAG_BASE;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}

		/* Write the magic header */
		strcpy ((char *)*buf, "AOC");
		exif_set_short (*buf + 4, n->order, (ExifShort) (
			(n->order == EXIF_BYTE_ORDER_INTEL) ?
			('I' << 8) | 'I' :
			('M' << 8) | 'M'));
		break;

	case pentaxV2:
		base = MNOTE_PENTAX2_TAG_BASE;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}

		/* Write the magic header */
		strcpy ((char *)*buf, "AOC");
		exif_set_short (*buf + 4, n->order, (ExifShort) 0);
		break;

	case pentaxV1:
		/* It looks like this format doesn't have a magic header as
		 * such, just has a fixed number of entries equal to 0x001b */
		*buf_size -= 6;
		o2 -= 6;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}
		break;

	default:
		/* internal error */
		return;
	}

	/* Write the number of entries. */
	exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
	o2 += 2;

	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		size_t doff;	/* offset to current data portion of tag */
		size_t s;
		unsigned char *t;
		size_t o = o2 + i * 12;   /* current offset into output buffer */
		exif_set_short (*buf + o + 0, n->order,
				(ExifShort) (n->entries[i].tag - base));
		exif_set_short (*buf + o + 2, n->order,
				(ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order,
				n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 65536) {
			/* Corrupt data: EXIF data size is limited to the
			 * maximum size of a JPEG segment (64 kb).
			 */
			continue;
		}
		if (s > 4) {
			size_t ts = *buf_size + s;
			doff = *buf_size;
			t = exif_mem_realloc (ne->mem, *buf,
						 sizeof (char) * ts);
			if (!t) {
				EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", ts);
				return;
			}
			*buf = t;
			*buf_size = ts;
			exif_set_long (*buf + o, n->order, datao + doff);
		} else
			doff = o;

		/* Write the data. */
		if (n->entries[i].data) {
			memcpy (*buf + doff, n->entries[i].data, s);
		} else {
			/* Most certainly damaged input file */
			memset (*buf + doff, 0, s);
		}
	}

	/* Sanity check the buffer size */
	if (*buf_size < (o2 + n->count * 12 + 4)) {
		exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataPentax",
			"Buffer overflow");
	}

	/* Reset next IFD pointer */
	exif_set_long (*buf + o2 + n->count * 12, n->order, 0);
}
Пример #11
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!"));
}
static void
exif_mnote_data_canon_save (ExifMnoteData *ne,
                            unsigned char **buf, unsigned int *buf_size)
{
    ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
    size_t i, o, s, doff;
    unsigned char *t;
    size_t ts;

    if (!n || !buf || !buf_size) return;

    /*
     * Allocate enough memory for all entries and the number
     * of entries.
     */
    *buf_size = 2 + n->count * 12 + 4;
    *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
    if (!*buf) {
        EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size);
        return;
    }

    /* Save the number of entries */
    exif_set_short (*buf, n->order, (ExifShort) n->count);

    /* Save each entry */
    for (i = 0; i < n->count; i++) {
        o = 2 + i * 12;
        exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
        exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
        exif_set_long  (*buf + o + 4, n->order,
                        n->entries[i].components);
        o += 8;
        s = exif_format_get_size (n->entries[i].format) *
            n->entries[i].components;
        if (s > 65536) {
            /* Corrupt data: EXIF data size is limited to the
             * maximum size of a JPEG segment (64 kb).
             */
            continue;
        }
        if (s > 4) {
            ts = *buf_size + s;

            /* Ensure even offsets. Set padding bytes to 0. */
            if (s & 1) ts += 1;
            t = exif_mem_realloc (ne->mem, *buf,
                                  sizeof (char) * ts);
            if (!t) {
                EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts);
                return;
            }
            *buf = t;
            *buf_size = ts;
            doff = *buf_size - s;
            if (s & 1) {
                doff--;
                *(*buf + *buf_size - 1) = '\0';
            }
            exif_set_long (*buf + o, n->order, n->offset + doff);
        } else
            doff = o;

        /*
         * Write the data. Fill unneeded bytes with 0. Do not
         * crash if data is NULL.
         */
        if (!n->entries[i].data) memset (*buf + doff, 0, s);
        else memcpy (*buf + doff, n->entries[i].data, s);
        if (s < 4) memset (*buf + doff + s, 0, (4 - s));
    }
}
Пример #13
0
void write_sgeo_version(unsigned char *data, ExifByteOrder order)
{
	memcpy(data + 0x00, "SG", 2);
	exif_set_short(data + 0x02, order, SGEO_VERSION);
}
Пример #14
0
static void
metadatamux_exif_for_each_tag_in_list (const GstTagList * list,
    const gchar * tag, gpointer user_data)
{
  ExifData *ed = (ExifData *) user_data;
  ExifTag exif_tag;
  GType type = G_TYPE_INVALID;
  ExifEntry *entry = NULL;
  ExifIfd ifd = EXIF_IFD_COUNT;
  const ExifByteOrder byte_order = exif_data_get_byte_order (ed);

  exif_tag = metadatamux_exif_get_exif_from_tag (tag, &type, &ifd);

  if (!exif_tag)
    goto done;

  entry = exif_data_get_entry (ed, exif_tag);

  if (entry)
    exif_entry_ref (entry);
  else {
    entry = exif_entry_new ();
    exif_content_add_entry (ed->ifd[ifd], entry);
    exif_entry_initialize (entry, exif_tag);
  }

  if (entry->data == NULL) {
    if (entry->tag == EXIF_TAG_GPS_ALTITUDE) {
      entry->format = EXIF_FORMAT_RATIONAL;
      entry->components = 1;
      entry->size = exif_format_get_size (entry->format) * entry->components;
      entry->data = g_malloc (entry->size);
    } else if (entry->tag == EXIF_TAG_GPS_LATITUDE
        || entry->tag == EXIF_TAG_GPS_LONGITUDE) {
      entry->format = EXIF_FORMAT_RATIONAL;
      entry->components = 3;
      entry->size = exif_format_get_size (entry->format) * entry->components;
      entry->data = g_malloc (entry->size);
    }
  }

  if (type == GST_TYPE_FRACTION) {
    const GValue *gvalue = gst_tag_list_get_value_index (list, tag, 0);
    gint numerator = gst_value_get_fraction_numerator (gvalue);
    gint denominator = gst_value_get_fraction_denominator (gvalue);

    switch (entry->format) {
      case EXIF_FORMAT_SRATIONAL:
      {
        ExifSRational sr = { numerator, denominator };

        exif_set_srational (entry->data, byte_order, sr);
      }
        break;
      case EXIF_FORMAT_RATIONAL:
      {
        ExifRational r;

        if (entry->tag == EXIF_TAG_X_RESOLUTION ||
            entry->tag == EXIF_TAG_Y_RESOLUTION) {
          ExifEntry *unit_entry = NULL;

          unit_entry = exif_data_get_entry (ed, EXIF_TAG_RESOLUTION_UNIT);

          if (unit_entry) {
            ExifShort vsh = exif_get_short (unit_entry->data, byte_order);

            if (vsh != 2)       /* inches */
              exif_set_short (unit_entry->data, byte_order, 2);
          }
        }
        r.numerator = numerator;
        r.denominator = denominator;
        if (numerator < 0)
          r.numerator = -numerator;
        if (denominator < 0)
          r.denominator = -denominator;
        exif_set_rational (entry->data, byte_order, r);
      }
        break;
      default:
        break;
    }
  } else if (type == GST_TYPE_BUFFER) {
    const GValue *val = NULL;
    GstBuffer *buf;

    val = gst_tag_list_get_value_index (list, tag, 0);
    buf = gst_value_get_buffer (val);
    entry->components = GST_BUFFER_SIZE (buf);
    entry->size = GST_BUFFER_SIZE (buf);
    entry->data = g_malloc (entry->size);
    memcpy (entry->data, GST_BUFFER_DATA (buf), entry->size);
  } else {
    switch (type) {
      case G_TYPE_STRING:
      {
        gchar *value = NULL;

        if (gst_tag_list_get_string (list, tag, &value)) {
          if (entry->tag == EXIF_TAG_DATE_TIME_DIGITIZED
              || entry->tag == EXIF_TAG_DATE_TIME
              || entry->tag == EXIF_TAG_DATE_TIME_ORIGINAL) {
            GString *datetime = g_string_new_len (value,
                20);            /* enough memory to hold "YYYY:MM:DD HH:MM:SS" */

            if (metadatamux_exif_convert_from_datetime (datetime)) {
            } else {
              GST_ERROR ("Unexpected date & time format for %s", tag);
            }
            g_free (value);
            value = datetime->str;
            g_string_free (datetime, FALSE);
          } else if (value) {
            entry->components = strlen (value) + 1;
            entry->size =
                exif_format_get_size (entry->format) * entry->components;
            entry->data = (guint8 *) value;
            value = NULL;
          }
        }
      }
        break;
      case G_TYPE_UINT:
      case G_TYPE_INT:
      {
        gint value;
        ExifShort v_short;

        if (G_TYPE_UINT == type) {
          gst_tag_list_get_uint (list, tag, (guint *) & value);
        } else {
          gst_tag_list_get_int (list, tag, &value);
        }

        switch (entry->format) {
          case EXIF_FORMAT_SHORT:
            if (entry->tag == EXIF_TAG_CONTRAST
                || entry->tag == EXIF_TAG_SATURATION) {
              if (value < -33)
                value = 1;      /* low */
              else if (value < 34)
                value = 0;      /* normal */
              else
                value = 2;      /* high */
            }
            v_short = value;
            exif_set_short (entry->data, byte_order, v_short);
            break;
          case EXIF_FORMAT_LONG:
            exif_set_long (entry->data, byte_order, value);
            break;
          default:
            break;
        }

      }
        break;
      case G_TYPE_DOUBLE:
      {
        gdouble value;

        gst_tag_list_get_double (list, tag, &value);
        if (entry->tag == EXIF_TAG_GPS_LATITUDE
            || entry->tag == EXIF_TAG_GPS_LONGITUDE) {
          ExifRational *rt = (ExifRational *) entry->data;
          gdouble v = fabs (value);
          ExifEntry *ref_entry = NULL;
          char ref;
          const ExifTag ref_tag = entry->tag == EXIF_TAG_GPS_LATITUDE ?
              EXIF_TAG_GPS_LATITUDE_REF : EXIF_TAG_GPS_LONGITUDE_REF;

          /* DDD - degrees */
          rt->numerator = (gulong) v;
          rt->denominator = 1;
          GST_DEBUG ("deg: %lf : %lu / %lu", v, (gulong) rt->numerator,
              (gulong) rt->denominator);
          v -= rt->numerator;
          rt++;

          /* MM - minutes */
          rt->numerator = (gulong) (v * 60.0);
          rt->denominator = 1;
          GST_DEBUG ("min: %lf : %lu / %lu", v, (gulong) rt->numerator,
              (gulong) rt->denominator);
          v -= ((gdouble) rt->numerator / 60.0);
          rt++;

          /* SS - seconds */
          rt->numerator = (gulong) (0.5 + v * 3600.0);
          rt->denominator = 1;
          GST_DEBUG ("sec: %lf : %lu / %lu", v, (gulong) rt->numerator,
              (gulong) rt->denominator);

          if (entry->tag == EXIF_TAG_GPS_LONGITUDE) {
            GST_DEBUG ("longitude : %lf", value);
            ref = (value < 0.0) ? 'W' : 'E';
          } else {
            GST_DEBUG ("latitude : %lf", value);
            ref = (value < 0.0) ? 'S' : 'N';
          }

          ref_entry = exif_data_get_entry (ed, ref_tag);
          if (ref_entry) {
            exif_entry_ref (ref_entry);
          } else {
            ref_entry = exif_entry_new ();
            exif_content_add_entry (ed->ifd[EXIF_IFD_GPS], ref_entry);
            exif_entry_initialize (ref_entry, ref_tag);
          }
          if (ref_entry->data == NULL) {
            ref_entry->format = EXIF_FORMAT_ASCII;
            ref_entry->components = 2;
            ref_entry->size = 2;
            ref_entry->data = g_malloc (2);
          }
          ref_entry->data[0] = ref;
          ref_entry->data[1] = 0;
          exif_entry_unref (ref_entry);
        } else if (entry->tag == EXIF_TAG_GPS_ALTITUDE) {
          ExifEntry *ref_entry = NULL;
          ExifRational *rt = (ExifRational *) entry->data;

          rt->numerator = (gulong) fabs (10.0 * value);
          rt->denominator = 10;

          GST_DEBUG ("altitude : %lf", value);

          ref_entry = exif_data_get_entry (ed, EXIF_TAG_GPS_ALTITUDE_REF);
          if (ref_entry) {
            exif_entry_ref (ref_entry);
          } else {
            ref_entry = exif_entry_new ();
            exif_content_add_entry (ed->ifd[EXIF_IFD_GPS], ref_entry);
            exif_entry_initialize (ref_entry, EXIF_TAG_GPS_ALTITUDE_REF);
          }
          if (ref_entry->data == NULL) {
            ref_entry->format = EXIF_FORMAT_BYTE;
            ref_entry->components = 1;
            ref_entry->size = 1;
            ref_entry->data = g_malloc (1);
          }
          if (value > 0.0) {
            ref_entry->data[0] = 0;
          } else {
            ref_entry->data[0] = 1;
          }
          exif_entry_unref (ref_entry);
        }
      }
        break;
      default:
        break;
    }
  }

done:

  if (entry)
    exif_entry_unref (entry);

}
static void
exif_data_save_data_entry (ExifData *data, ExifEntry *e,
			   unsigned char **d, unsigned int *ds,
			   unsigned int offset)
{
	unsigned int doff, s;
	unsigned int ts;

	if (!data || !data->priv) 
		return;

	/*
	 * Each entry is 12 bytes long. The memory for the entry has
	 * already been allocated.
	 */
	exif_set_short (*d + 6 + offset + 0,
			data->priv->order, (ExifShort) e->tag);
	exif_set_short (*d + 6 + offset + 2,
			data->priv->order, (ExifShort) e->format);

	if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) {
		/* If this is the maker note tag, update it. */
		if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) {
			/* TODO: this is using the wrong ExifMem to free e->data */
			exif_mem_free (data->priv->mem, e->data);
			e->data = NULL;
			e->size = 0;
			exif_mnote_data_set_offset (data->priv->md, *ds - 6);
			exif_mnote_data_save (data->priv->md, &e->data, &e->size);
			e->components = e->size;
		}
	}

	exif_set_long  (*d + 6 + offset + 4,
			data->priv->order, e->components);

	/*
	 * Size? If bigger than 4 bytes, the actual data is not in
	 * the entry but somewhere else.
	 */
	s = exif_format_get_size (e->format) * e->components;
	if (s > 4) {
		unsigned char *t;
		doff = *ds - 6;
		ts = *ds + s;

		/*
		 * According to the TIFF specification,
		 * the offset must be an even number. If we need to introduce
		 * a padding byte, we set it to 0.
		 */
		if (s & 1)
			ts++;
		t = exif_mem_realloc (data->priv->mem, *d, ts);
		if (!t) {
			EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
		  	return;
		}
		*d = t;
		*ds = ts;
		exif_set_long (*d + 6 + offset + 8, data->priv->order, doff);
		if (s & 1) 
			*(*d + *ds - 1) = '\0';

	} else
		doff = offset + 8;

	/* Write the data. Fill unneeded bytes with 0. Do not crash with
	 * e->data is NULL */
	if (e->data) {
		memcpy (*d + 6 + doff, e->data, s);
	} else {
		memset (*d + 6 + doff, 0, s);
	}
	if (s < 4) 
		memset (*d + 6 + doff + s, 0, (4 - s));
}
Пример #16
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;
}
static void
exif_data_save_data_content (ExifData *data, ExifContent *ifd,
			     unsigned char **d, unsigned int *ds,
			     unsigned int offset)
{
	unsigned int j, n_ptr = 0, n_thumb = 0;
	ExifIfd i;
	unsigned char *t;
	unsigned int ts;

	if (!data || !data->priv || !ifd || !d || !ds) 
		return;

	for (i = 0; i < EXIF_IFD_COUNT; i++)
		if (ifd == data->ifd[i])
			break;
	if (i == EXIF_IFD_COUNT)
		return;	/* error */

	/*
	 * Check if we need some extra entries for pointers or the thumbnail.
	 */
	switch (i) {
	case EXIF_IFD_0:

		/*
		 * The pointer to IFD_EXIF is in IFD_0. The pointer to
		 * IFD_INTEROPERABILITY is in IFD_EXIF.
		 */
		if (data->ifd[EXIF_IFD_EXIF]->count ||
		    data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
			n_ptr++;

		/* The pointer to IFD_GPS is in IFD_0. */
		if (data->ifd[EXIF_IFD_GPS]->count)
			n_ptr++;

		break;
	case EXIF_IFD_1:
		if (data->size)
			n_thumb = 2;
		break;
	case EXIF_IFD_EXIF:
		if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
			n_ptr++;
	default:
		break;
	}

	/*
	 * Allocate enough memory for all entries
	 * and the number of entries.
	 */
	ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4);
	t = exif_mem_realloc (data->priv->mem, *d, ts);
	if (!t) {
		EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
	  	return;
	}
	*d = t;
	*ds = ts;

	/* Save the number of entries */
	exif_set_short (*d + 6 + offset, data->priv->order,
			(ExifShort) (ifd->count + n_ptr + n_thumb));
	offset += 2;

	/*
	 * Save each entry. Make sure that no memcpys from NULL pointers are
	 * performed
	 */
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
		  "Saving %i entries (IFD '%s', offset: %i)...",
		  ifd->count, exif_ifd_get_name (i), offset);
	for (j = 0; j < ifd->count; j++) {
		if (ifd->entries[j]) {
			exif_data_save_data_entry (data, ifd->entries[j], d, ds,
				offset + 12 * j);
		}
	}

	offset += 12 * ifd->count;

	/* Now save special entries. */
	switch (i) {
	case EXIF_IFD_0:

		/*
		 * The pointer to IFD_EXIF is in IFD_0.
		 * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF,
		 * therefore, if IFD_INTEROPERABILITY is not empty, we need
		 * IFD_EXIF even if latter is empty.
		 */
		if (data->ifd[EXIF_IFD_EXIF]->count ||
		    data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
			exif_set_short (*d + 6 + offset + 0, data->priv->order,
					EXIF_TAG_EXIF_IFD_POINTER);
			exif_set_short (*d + 6 + offset + 2, data->priv->order,
					EXIF_FORMAT_LONG);
			exif_set_long  (*d + 6 + offset + 4, data->priv->order,
					1);
			exif_set_long  (*d + 6 + offset + 8, data->priv->order,
					*ds - 6);
			exif_data_save_data_content (data,
						     data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6);
			offset += 12;
		}

		/* The pointer to IFD_GPS is in IFD_0, too. */
		if (data->ifd[EXIF_IFD_GPS]->count) {
			exif_set_short (*d + 6 + offset + 0, data->priv->order,
					EXIF_TAG_GPS_INFO_IFD_POINTER);
			exif_set_short (*d + 6 + offset + 2, data->priv->order,
					EXIF_FORMAT_LONG);
			exif_set_long  (*d + 6 + offset + 4, data->priv->order,
					1);
			exif_set_long  (*d + 6 + offset + 8, data->priv->order,
					*ds - 6);
			exif_data_save_data_content (data,
						     data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6);
			offset += 12;
		}

		break;
	case EXIF_IFD_EXIF:

		/*
		 * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF.
		 * See note above.
		 */
		if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
			exif_set_short (*d + 6 + offset + 0, data->priv->order,
					EXIF_TAG_INTEROPERABILITY_IFD_POINTER);
			exif_set_short (*d + 6 + offset + 2, data->priv->order,
					EXIF_FORMAT_LONG);
			exif_set_long  (*d + 6 + offset + 4, data->priv->order,
					1);
			exif_set_long  (*d + 6 + offset + 8, data->priv->order,
					*ds - 6);
			exif_data_save_data_content (data,
						     data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds,
						     *ds - 6);
			offset += 12;
		}

		break;
	case EXIF_IFD_1:

		/*
		 * Information about the thumbnail (if any) is saved in
		 * IFD_1.
		 */
		if (data->size) {

			/* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */
			exif_set_short (*d + 6 + offset + 0, data->priv->order,
					EXIF_TAG_JPEG_INTERCHANGE_FORMAT);
			exif_set_short (*d + 6 + offset + 2, data->priv->order,
					EXIF_FORMAT_LONG);
			exif_set_long  (*d + 6 + offset + 4, data->priv->order,
					1);
			exif_set_long  (*d + 6 + offset + 8, data->priv->order,
					*ds - 6);
			ts = *ds + data->size;
			t = exif_mem_realloc (data->priv->mem, *d, ts);
			if (!t) {
				EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData",
						    ts);
			  	return;
			}
			*d = t;
			*ds = ts;
			memcpy (*d + *ds - data->size, data->data, data->size);
			offset += 12;

			/* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */
			exif_set_short (*d + 6 + offset + 0, data->priv->order,
					EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
			exif_set_short (*d + 6 + offset + 2, data->priv->order,
					EXIF_FORMAT_LONG);
			exif_set_long  (*d + 6 + offset + 4, data->priv->order,
					1);
			exif_set_long  (*d + 6 + offset + 8, data->priv->order,
					data->size);
			offset += 12;
		}

		break;
	default:
		break;
	}

	/* Sort the directory according to TIFF specification */
	qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12,
	       (ifd->count + n_ptr + n_thumb), 12,
	       (data->priv->order == EXIF_BYTE_ORDER_INTEL) ? cmp_func_intel : cmp_func_motorola);

	/* Correctly terminate the directory */
	if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count ||
				data->size)) {

		/*
		 * We are saving IFD 0. Tell where IFD 1 starts and save
		 * IFD 1.
		 */
		exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6);
		exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds,
					     *ds - 6);
	} else
		exif_set_long (*d + 6 + offset, data->priv->order, 0);
}
Пример #18
0
/** 
 * @brief save the MnoteData from ne to buf
 * 
 * @param ne extract the data from this structure 
 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
 * @param buf_size the size of the buffer
 */
static void
exif_mnote_data_olympus_save (ExifMnoteData *ne,
		unsigned char **buf, unsigned int *buf_size)
{
	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
	size_t i, o, s, doff, base = 0, o2 = 6 + 2;
	size_t datao = 0;
	unsigned char *t;
	size_t ts;

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for all entries and the number of entries.
	 */
	*buf_size = 6 + 2 + 2 + n->count * 12;
	switch (n->version) {
	case olympusV1:
	case sanyoV1:
	case epsonV1:
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
			return;
		}

		/* Write the header and the number of entries. */
		strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
					(n->version==epsonV1?"EPSON":"OLYMP"));
		exif_set_short (*buf + 6, n->order, (ExifShort) 1);
		datao = n->offset;
		break;
	case olympusV2:
		*buf_size += 8-6 + 4;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
			return;
		}

		/* Write the header and the number of entries. */
		strcpy ((char *)*buf, "OLYMPUS");
		exif_set_short (*buf + 8, n->order, (ExifShort) (
			(n->order == EXIF_BYTE_ORDER_INTEL) ?
			('I' << 8) | 'I' :
			('M' << 8) | 'M'));
		exif_set_short (*buf + 10, n->order, (ExifShort) 3);
		o2 += 4;
		break;
	case nikonV1: 
		base = MNOTE_NIKON1_TAG_BASE;

		/* v1 has offsets based to main IFD, not makernote IFD */
		datao += n->offset + 10;
		/* subtract the size here, so the increment in the next case will not harm us */
		*buf_size -= 8 + 2;
		/* Fall through */
	case nikonV2: 
		*buf_size += 8 + 2;
		*buf_size += 4; /* Next IFD pointer */
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
			return;
		}

		/* Write the header and the number of entries. */
		strcpy ((char *)*buf, "Nikon");
		(*buf)[6] = n->version;

		if (n->version == nikonV2) {
			exif_set_short (*buf + 10, n->order, (ExifShort) (
				(n->order == EXIF_BYTE_ORDER_INTEL) ?
				('I' << 8) | 'I' :
				('M' << 8) | 'M'));
			exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
			exif_set_long (*buf + 14, n->order, (ExifShort) 8);
			o2 += 2 + 8;
		}
		datao -= 10;
		/* Reset next IFD pointer */
		exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
		break;

	default:
		return;
	}

	exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
	o2 += 2;

	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		o = o2 + i * 12;
		exif_set_short (*buf + o + 0, n->order,
				(ExifShort) (n->entries[i].tag - base));
		exif_set_short (*buf + o + 2, n->order,
				(ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order,
				n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 65536) {
			/* Corrupt data: EXIF data size is limited to the
			 * maximum size of a JPEG segment (64 kb).
			 */
			continue;
		}
		if (s > 4) {
			doff = *buf_size;
			ts = *buf_size + s;
			t = exif_mem_realloc (ne->mem, *buf,
						 sizeof (char) * ts);
			if (!t) {
				EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
				return;
			}
			*buf = t;
			*buf_size = ts;
			exif_set_long (*buf + o, n->order, datao + doff);
		} else
			doff = o;

		/* Write the data. */
		if (n->entries[i].data) {
			memcpy (*buf + doff, n->entries[i].data, s);
		} else {
			/* Most certainly damaged input file */
			memset (*buf + doff, 0, s);
		}
	}
}
Пример #19
0
static void
exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
			   unsigned int *buf_size)
{
	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
	size_t i, o, s, doff;
	unsigned char *t;
	size_t ts;

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for all entries and the number
	 * of entries.
	 */
	*buf_size = 8 + 4 + 2 + n->count * 12 + 4;
	*buf = exif_mem_alloc (ne->mem, *buf_size);
	if (!*buf) {
		*buf_size = 0;
		return;
	}

	/*
	 * Header: "FUJIFILM" and 4 bytes offset to the first entry.
	 * As the first entry will start right thereafter, the offset is 12.
	 */
	memcpy (*buf, "FUJIFILM", 8);
	exif_set_long (*buf + 8, n->order, 12);

	/* Save the number of entries */
	exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
	
	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		o = 8 + 4 + 2 + i * 12;
		exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
		exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order, n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 65536) {
			/* Corrupt data: EXIF data size is limited to the
			 * maximum size of a JPEG segment (64 kb).
			 */
			continue;
		}
		if (s > 4) {
			ts = *buf_size + s;

			/* Ensure even offsets. Set padding bytes to 0. */
			if (s & 1) ts += 1;
			t = exif_mem_realloc (ne->mem, *buf, ts);
			if (!t) {
				return;
			}
			*buf = t;
			*buf_size = ts;
			doff = *buf_size - s;
			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
			exif_set_long (*buf + o, n->order, doff);
		} else
			doff = o;

		/*
		 * Write the data. Fill unneeded bytes with 0. Do not
		 * crash if data is NULL.
		 */
		if (!n->entries[i].data) memset (*buf + doff, 0, s);
		else memcpy (*buf + doff, n->entries[i].data, s);
	}
}