Esempio n. 1
0
static void
vips_exif_update( ExifData *ed, VipsImage *image )
{
	VipsExifRemove ve;

	VIPS_DEBUG_MSG( "vips_exif_update: \n" );

	/* If this exif came from the image (rather than being an exif block we
	 * have made afresh), then any fields which are in the block but not on
	 * the image must have been deliberately removed. Remove them from the
	 * block as well.
	 *
	 * If there are any string-valued fields (eg. comment etc.) which
	 * exist as libvips metadata tags, we must also remove those from the
	 * exif block.
	 *
	 * libexif does not allow you to change string lengths, you must make
	 * new tags, so we have to remove ready to re-add.
	 */
	if( vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) ) {
		ve.image = image;
		ve.ed = ed;
		exif_data_foreach_content( ed, 
			(ExifDataForeachContentFunc) vips_exif_exif_content, 
			&ve );
	}

	/* Walk the image and add any exif- that's set in image metadata.
	 */
	vips_image_map( image, vips_exif_image_field, ed );
}
Esempio n. 2
0
void
eog_exif_details_update (EogExifDetails *exif_details, ExifData *data)
{
	g_return_if_fail (EOG_IS_EXIF_DETAILS (exif_details));

	eog_exif_details_reset (exif_details);
	if (data) {
		exif_data_foreach_content (data, exif_content_cb, exif_details);
	}
}
Esempio n. 3
0
static void
show_values( ExifData *data )
{
        ExifByteOrder order;
	int ifd;

        order = exif_data_get_byte_order( data );
        printf( "EXIF tags in '%s' byte order\n", 
		exif_byte_order_get_name( order ) );

	printf( "Title|Value|Format|Size\n" ); 

	ifd = 0;
        exif_data_foreach_content( data, show_ifd, &ifd );

        if( data->size ) 
                printf( "contains thumbnail of %d bytes\n", data->size );
}
Esempio n. 4
0
void
show_values( ExifData *data )
{
        ExifByteOrder order;

        order = exif_data_get_byte_order( data );
        printf( "EXIF tags in '%s' byte order\n", 
		exif_byte_order_get_name( order ) );

	printf( "%-20.20s", "Tag" );
        printf( "|" );
	printf( "%-58.58s", "Value" );
        printf( "\n" );

        exif_data_foreach_content( data, show_ifd, NULL );

        if( data->size ) 
                printf( "contains thumbnail of %d bytes\n", data->size );
}
Esempio n. 5
0
static int
parse_exif( VipsImage *im, void *data, int data_length )
{
#ifdef HAVE_EXIF
    {
        ExifData *ed;
        VipsExif ve;

        if( !(ed = exif_data_new_from_data( data, data_length )) )
            return( -1 );

#ifdef DEBUG_VERBOSE
        show_tags( ed );
        show_values( ed );
#endif /*DEBUG_VERBOSE*/

        /* Attach informational fields for what we find.

        	FIXME ... better to have this in the UI layer?

        	Or we could attach non-human-readable tags here (int,
        	double etc) and then move the human stuff to the UI
        	layer?

         */
        ve.image = im;
        ve.ed = ed;
        exif_data_foreach_content( ed,
        (ExifDataForeachContentFunc) attach_exif_content, &ve );

        /* Look for resolution fields and use them to set the VIPS
         * xres/yres fields.
         */
        res_from_exif( im, ed );

        attach_thumbnail( im, ed );

        exif_data_free( ed );
    }
#endif /*HAVE_EXIF*/

    return( 0 );
}
static char *
exifdata_get_tag_value_utf8 (ExifData *data, ExifTag tag) 
{
	struct ExifAttribute attribute;
	char *utf8_value;

	attribute.tag = tag;
	attribute.value = NULL;
	attribute.found = FALSE;
	
	exif_data_foreach_content (data, exif_content_callback, &attribute);

	if (attribute.found) {
		utf8_value = exif_string_to_utf8 (attribute.value);
		g_free (attribute.value);
	} else {
		utf8_value = NULL;
	}

	return utf8_value;
}
Esempio n. 7
0
static void
vips_exif_update( ExifData *ed, VipsImage *image )
{
	VipsExif ve;

	VIPS_DEBUG_MSG( "vips_exif_update: \n" );

	/* Walk the image and update any stuff that's been changed in image
	 * metadata.
	 */
	vips_image_map( image, vips_exif_image_field, ed );

	/* Walk the exif and look for any fields which are NOT in image
	 * metadata. They must have been removed ... remove them from exif as
	 * well.
	 */
	ve.image = image;
	ve.ed = ed;
	exif_data_foreach_content( ed, 
		(ExifDataForeachContentFunc) vips_exif_exif_content, &ve );
}
Esempio n. 8
0
void
metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
    GstAdapter * adapter, MetadataTagMapping mapping)
{
  const guint8 *buf;
  guint32 size;
  ExifData *exif = NULL;
  MEUserData user_data = { taglist, mode, 2, -1, 'k', 'k' };

  if (adapter == NULL || (size = gst_adapter_available (adapter)) == 0) {
    goto done;
  }

  /* add chunk tag */
  if (mapping & METADATA_TAG_MAP_WHOLECHUNK)
    metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_EXIF,
        adapter);

  if (!(mapping & METADATA_TAG_MAP_INDIVIDUALS))
    goto done;

  buf = gst_adapter_peek (adapter, size);

  exif = exif_data_new_from_data (buf, size);
  if (exif == NULL) {
    goto done;
  }

  exif_data_foreach_content (exif,
      metadataparse_exif_data_foreach_content_func, (void *) &user_data);

done:

  if (exif)
    exif_data_unref (exif);

  return;

}
Esempio n. 9
0
/* Scan the exif block on the image, if any, and make a set of vips metadata 
 * tags for what we find.
 */
int
vips__exif_parse( VipsImage *image )
{
	void *data;
	size_t length;
	ExifData *ed;
	VipsExifParams params;
	const char *str;

	if( !vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) )
		return( 0 );
	if( vips_image_get_blob( image, VIPS_META_EXIF_NAME, &data, &length ) )
		return( -1 ); 
	if( !(ed = vips_exif_load_data_without_fix( data, length )) )
		return( -1 );

#ifdef DEBUG_VERBOSE
	show_tags( ed );
	show_values( ed );
#endif /*DEBUG_VERBOSE*/

	/* Look for resolution fields and use them to set the VIPS xres/yres 
	 * fields.
	 *
	 * If the fields are missing, set them from the image, which will have
	 * previously had them set from something like JFIF. 
	 */
	if( vips_image_resolution_from_exif( image, ed ) &&
		vips_exif_resolution_from_image( ed, image ) ) {
		exif_data_free( ed );
		return( -1 ); 
	}

	/* Make sure all required fields are there before we attach the vips
	 * metadata.
	 */
	exif_data_fix( ed );

	/* Attach informational fields for what we find.
	 */
	params.image = image;
	params.ed = ed;
	exif_data_foreach_content( ed, 
		(ExifDataForeachContentFunc) vips_exif_get_content, &params );

	vips_exif_get_thumbnail( image, ed );
	exif_data_free( ed );

	/* Orientation handling. ifd0 has the Orientation tag for the main
	 * image. 
	 */
	if( vips_image_get_typeof( image, "exif-ifd0-Orientation" ) != 0 &&
		!vips_image_get_string( image, 
			"exif-ifd0-Orientation", &str ) ) {
		int orientation;

		orientation = atoi( str );
		orientation = VIPS_CLIP( 1, orientation, 8 );
		vips_image_set_int( image, VIPS_META_ORIENTATION, orientation );
	}

	return( 0 );
}
Esempio n. 10
0
static int
read_exif( IMAGE *im, void *data, int data_length )
{
	char *data_copy;

	/* Horrifyingly, some JPEGs have several APP1 sections. We must only
	 * use the first one that starts "Exif.."
	 */
	if( ((char *) data)[0] != 'E' ||
		((char *) data)[1] != 'x' ||
		((char *) data)[2] != 'i' ||
		((char *) data)[3] != 'f' )
		return( 0 );
	if( im_header_get_typeof( im, IM_META_EXIF_NAME ) ) 
		return( 0 );

	/* Always attach a copy of the unparsed exif data.
	 */
	if( !(data_copy = im_malloc( NULL, data_length )) )
		return( -1 );
	memcpy( data_copy, data, data_length );
	if( im_meta_set_blob( im, IM_META_EXIF_NAME, 
		(im_callback_fn) im_free, data_copy, data_length ) ) {
		im_free( data_copy );
		return( -1 );
	}

#ifdef HAVE_EXIF
{
	ExifData *ed;

	if( !(ed = exif_data_new_from_data( data, data_length )) )
		return( -1 );

	if( ed->size > 0 ) {
#ifdef DEBUG_VERBOSE
		show_tags( ed );
		show_values( ed );
#endif /*DEBUG_VERBOSE*/

		/* Attach informational fields for what we find.

			FIXME ... better to have this in the UI layer?

			Or we could attach non-human-readable tags here (int, 
			double etc) and then move the human stuff to the UI 
			layer?

		 */
		exif_data_foreach_content( ed, 
			(ExifDataForeachContentFunc) attach_exif_content, im );

		/* Look for resolution fields and use them to set the VIPS 
		 * xres/yres fields.
		 */
		set_vips_resolution( im, ed );

		attach_thumbnail( im, ed );
	}

	exif_data_free( ed );
}
#endif /*HAVE_EXIF*/

	return( 0 );
}
Esempio n. 11
0
static int Difds (lua_State *L) { /** data:ifds() */
  ExifData *data = checkdata(L);
  lua_newtable(L);
  exif_data_foreach_content(data, contentfunc, (void *)L);
  return 1;
}
Esempio n. 12
0
int image_jpeg_read_header(MediaScanImage *i, MediaScanResult *r) {
  int ret = 1;
  int x;

  JPEGData *j = malloc(sizeof(JPEGData));
  i->_jpeg = (void *)j;
  LOG_MEM("new JPEGData @ %p\n", i->_jpeg);

  j->cinfo = malloc(sizeof(struct jpeg_decompress_struct));
  j->jpeg_error_pub = malloc(sizeof(struct jpeg_error_mgr));
  LOG_MEM("new JPEG cinfo @ %p\n", j->cinfo);
  LOG_MEM("new JPEG error_pub @ %p\n", j->jpeg_error_pub);

  j->cinfo->err = jpeg_std_error(j->jpeg_error_pub);
  j->jpeg_error_pub->error_exit = libjpeg_error_handler;
  j->jpeg_error_pub->output_message = libjpeg_output_message;

  if (setjmp(setjmp_buffer)) {
    image_jpeg_destroy(i);
    return 0;
  }

  // Save filename in case any warnings/errors occur
  strncpy(Filename, r->path, FILENAME_LEN);
  if (strlen(r->path) > FILENAME_LEN)
    Filename[FILENAME_LEN] = 0;

  jpeg_create_decompress(j->cinfo);

  // Init custom source manager to read from existing buffer
  image_jpeg_buf_src(i, r);

  // Save APP1 marker for EXIF
  jpeg_save_markers(j->cinfo, 0xE1, 1024 * 64);

  jpeg_read_header(j->cinfo, TRUE);

  i->width = j->cinfo->image_width;
  i->height = j->cinfo->image_height;
  i->channels = j->cinfo->num_components;
  r->mime_type = MIME_IMAGE_JPEG;

  // Match with DLNA profile
  for (x = 0; jpeg_profiles_mapping[x].profile; x++) {
    if (i->width <= jpeg_profiles_mapping[x].max_width && i->height <= jpeg_profiles_mapping[x].max_height) {
      r->dlna_profile = jpeg_profiles_mapping[x].profile->id;
      break;
    }
  }

  // Process Exif tag
  if (j->cinfo->marker_list != NULL) {
    jpeg_saved_marker_ptr marker = j->cinfo->marker_list;

    while (marker != NULL) {
      if (marker->marker == 0xE1
          && marker->data[0] == 'E' && marker->data[1] == 'x' && marker->data[2] == 'i' && marker->data[3] == 'f') {
        ExifData *exif;

        result_create_tag(r, "Exif");

        LOG_DEBUG("Parsing EXIF tag of size %d\n", marker->data_length);
        exif = exif_data_new_from_data(marker->data, marker->data_length);
        LOG_MEM("new EXIF data @ %p\n", exif);
        if (exif != NULL) {
          exif_data_foreach_content(exif, parse_exif_ifd, (void *)r);
          LOG_MEM("destroy EXIF data @ %p\n", exif);
          exif_data_free(exif);
        }

        break;
      }

      marker = marker->next;
    }
  }

  return ret;
}
Esempio n. 13
0
static int analyzer_jpeg_pload_analyze(struct analyzer *analyzer, struct analyzer_pload_buffer *pload, void *buffer, size_t buff_len) {


	struct analyzer_jpeg_pload_priv *priv = analyzer_pload_buffer_get_priv(pload);

	if (!priv) {
		priv = malloc(sizeof(struct analyzer_jpeg_pload_priv));
		if (!priv) {
			pom_oom(sizeof(struct analyzer_jpeg_pload_priv));
			return POM_ERR;
		}
		memset(priv, 0, sizeof(struct analyzer_jpeg_pload_priv));

		priv->pload_buff = buffer;
		priv->pload_buff_len = buff_len;
		
		// Setup error handler
		struct jpeg_error_mgr *jerr = malloc(sizeof(struct jpeg_error_mgr));
		if (!jerr) {
			free(priv);
			pom_oom(sizeof(struct jpeg_error_mgr));
			return POM_ERR;
		}
		memset(jerr, 0, sizeof(struct jpeg_error_mgr));
		priv->cinfo.err = jpeg_std_error(jerr);
		priv->cinfo.err->error_exit = analyzer_jpeg_lib_error_exit;

		// Allocate the decompressor
		jpeg_create_decompress(&priv->cinfo);

		priv->cinfo.client_data = priv;

#ifdef HAVE_LIBEXIF
		// Save APP1
		jpeg_save_markers(&priv->cinfo, JPEG_APP0 + 1, 0xFFFF);
#endif

		// Allocate the source
		
		struct jpeg_source_mgr *src = malloc(sizeof(struct jpeg_source_mgr));
		if (!src) {
			free(priv->cinfo.err);
			pom_oom(sizeof(struct jpeg_source_mgr));
			jpeg_destroy_decompress(&priv->cinfo);
			free(priv);
			return POM_ERR;
		}
		memset(src, 0, sizeof(struct jpeg_source_mgr));

		src->init_source = analyzer_jpeg_lib_init_source;
		src->fill_input_buffer = analyzer_jpeg_lib_fill_input_buffer;
		src->skip_input_data = analyzer_jpeg_lib_skip_input_data;
		src->resync_to_restart = jpeg_resync_to_restart;
		src->term_source = analyzer_jpeg_lib_term_source;
		priv->cinfo.src = src;


		analyzer_pload_buffer_set_priv(pload, priv);

	} else {
		priv->pload_buff = buffer;
		priv->pload_buff_len = buff_len;
	}


	if (priv->jpeg_lib_pos >= buff_len)
		// Nothing more to process
		return POM_OK;

	int res = POM_OK;
	if (!setjmp(priv->jmp_buff)) {

		if (priv->jpeg_lib_pos) {
			// It's not garanteed that buffer points to the
			// same memory area after each call, so we reset it here
			priv->cinfo.src->next_input_byte = buffer + priv->jpeg_lib_pos;
		}

		if (jpeg_read_header(&priv->cinfo, TRUE) == JPEG_SUSPENDED)
			return POM_OK; // Headers are incomplete

		struct data *data = analyzer_pload_buffer_get_data(pload);

		PTYPE_UINT16_SETVAL(data[analyzer_jpeg_pload_width].value, priv->cinfo.image_width);
		data_set(data[analyzer_jpeg_pload_width]);
		PTYPE_UINT16_SETVAL(data[analyzer_jpeg_pload_height].value, priv->cinfo.image_height);
		data_set(data[analyzer_jpeg_pload_height]);
		debug_jpeg("JPEG read header returned %u, image is %ux%u", res, priv->cinfo.image_width, priv->cinfo.image_height);

#ifdef HAVE_LIBEXIF		
		// Parse the exif data
		jpeg_saved_marker_ptr marker;
		for (marker = priv->cinfo.marker_list; marker && marker->marker != JPEG_APP0 + 1; marker = marker->next);

		if (marker) {
			ExifData *exif_data = exif_data_new_from_data(marker->data, marker->data_length);
			if (!exif_data) {
				pomlog(POMLOG_DEBUG "Unable to parse EXIF data");
			}

			exif_data_foreach_content(exif_data, analyzer_jpeg_exif_content_process, pload);

			exif_data_free(exif_data);
		}
#endif

		analyzer_pload_buffer_set_state(pload, analyzer_pload_buffer_state_analyzed);

	} else {
		pomlog(POMLOG_DEBUG "Error while parsing JPEG headers");
		res = POM_ERR;
	}

	free(priv->cinfo.err);
	free(priv->cinfo.src);
	jpeg_destroy_decompress(&priv->cinfo);
	free(priv);
	analyzer_pload_buffer_set_priv(pload, NULL);

	return res;
}