Ejemplo n.º 1
0
static void OutputProperties(Image *image,ExceptionInfo *exception)
{
  const char
    *property,
    *value;

  (void) FormatLocaleFile(stdout,"  Image Properity:\n");
  ResetImagePropertyIterator(image);
  while ((property=GetNextImageProperty(image)) != (const char *) NULL ) {
    (void) FormatLocaleFile(stdout,"    %s: ",property);
    value=GetImageProperty(image,property,exception);
    if (value != (const char *) NULL)
      (void) FormatLocaleFile(stdout,"%s\n",value);
  }
  ResetImagePropertyIterator(image);
}
Ejemplo n.º 2
0
/*
    Function:   rm_exif_by_entry
    Purpose:    replicate old (< 6.3.2) EXIF:* functionality using GetImageProperty
                by returning the exif entries as a single string, separated by \n's.
                Do this so that RMagick.rb works no matter which version of
                ImageMagick is in use.
    Notes:      see magick/identify.c
*/
VALUE
rm_exif_by_entry(Image *image)
{
    const char *property, *value;
    char *str;
    size_t len = 0, property_l, value_l;
    volatile VALUE v;

    (void) GetImageProperty(image, "exif:*");
    ResetImagePropertyIterator(image);
    property = GetNextImageProperty(image);

    // Measure the exif properties and values
    while (property)
    {
        // ignore properties that don't start with "exif:"
        property_l = strlen(property);
        if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
        {
            if (len > 0)
            {
                len += 1;   // there will be a \n between property=value entries
            }
            len += property_l - 5;
            value = GetImageProperty(image,property);
            if (value)
            {
                // add 1 for the = between property and value
                len += 1 + strlen(value);
            }
        }
        property = GetNextImageProperty(image);
    }

    if (len == 0)
    {
        return Qnil;
    }
    str = xmalloc(len);
    len = 0;

    // Copy the exif properties and values into the string.
    ResetImagePropertyIterator(image);
    property = GetNextImageProperty(image);

    while (property)
    {
        property_l = strlen(property);
        if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0)
        {
            if (len > 0)
            {
                str[len++] = '\n';
            }
            memcpy(str+len, property+5, property_l-5);
            len += property_l - 5;
            value = GetImageProperty(image,property);
            if (value)
            {
                value_l = strlen(value);
                str[len++] = '=';
                memcpy(str+len, value, value_l);
                len += value_l;
            }
        }
        property = GetNextImageProperty(image);
    }

    v = rb_str_new(str, len);
    xfree(str);
    return v;
}
Ejemplo n.º 3
0
static int
parse_header( Read *read )
{
	VipsImage *im = read->im;
	Image *image = read->image;

	Image *p;
	int i;

#ifdef DEBUG
	printf( "parse_header: filename = %s\n", read->filename );
	printf( "GetImageChannelDepth(AllChannels) = %zd\n",
		GetImageChannelDepth( image, AllChannels, &image->exception ) );
	printf( "GetImageDepth() = %zd\n",
		GetImageDepth( image, &image->exception ) );
	printf( "image->depth = %zd\n", image->depth );
	printf( "GetImageType() = %d\n",
		GetImageType( image, &image->exception ) );
	printf( "IsGrayImage() = %d\n",
		IsGrayImage( image, &image->exception ) );
	printf( "IsMonochromeImage() = %d\n",
		IsMonochromeImage( image, &image->exception ) );
	printf( "IsOpaqueImage() = %d\n",
		IsOpaqueImage( image, &image->exception ) );
	printf( "image->columns = %zd\n", image->columns ); 
	printf( "image->rows = %zd\n", image->rows ); 
#endif /*DEBUG*/

	im->Xsize = image->columns;
	im->Ysize = image->rows;
	read->frame_height = image->rows;
	if( (im->Bands = get_bands( image )) < 0 )
		return( -1 );

	/* Depth can be 'fractional'. You'd think we should use
	 * GetImageDepth() but that seems unreliable. 16-bit mono DICOM images 
	 * are reported as depth 1, for example.
	 */
	im->BandFmt = -1;
	if( image->depth >= 1 && image->depth <= 8 ) 
		im->BandFmt = VIPS_FORMAT_UCHAR;
	if( image->depth >= 9 && image->depth <= 16 ) 
		im->BandFmt = VIPS_FORMAT_USHORT;
#ifdef UseHDRI
	if( image->depth == 32 )
		im->BandFmt = VIPS_FORMAT_FLOAT;
	if( image->depth == 64 )
		im->BandFmt = VIPS_FORMAT_DOUBLE;
#else /*!UseHDRI*/
	if( image->depth == 32 )
		im->BandFmt = VIPS_FORMAT_UINT;
#endif /*UseHDRI*/

	if( im->BandFmt == -1 ) {
		vips_error( "magick2vips", _( "unsupported bit depth %d" ),
			(int) image->depth );
		return( -1 );
	}

	switch( image->colorspace ) {
	case GRAYColorspace:
		if( im->BandFmt == VIPS_FORMAT_USHORT )
			im->Type = VIPS_INTERPRETATION_GREY16;
		else
			im->Type = VIPS_INTERPRETATION_B_W;
		break;

	case RGBColorspace:
		if( im->BandFmt == VIPS_FORMAT_USHORT )
			im->Type = VIPS_INTERPRETATION_RGB16;
		else
			im->Type = VIPS_INTERPRETATION_RGB;
		break;

	case sRGBColorspace:
		if( im->BandFmt == VIPS_FORMAT_USHORT )
			im->Type = VIPS_INTERPRETATION_RGB16;
		else
			im->Type = VIPS_INTERPRETATION_sRGB;
		break;

	case CMYKColorspace:
		im->Type = VIPS_INTERPRETATION_CMYK;
		break;

	default:
		vips_error( "magick2vips", _( "unsupported colorspace %d" ),
			(int) image->colorspace );
		return( -1 );
	}

	switch( image->units ) {
	case PixelsPerInchResolution:
		im->Xres = image->x_resolution / 25.4;
		im->Yres = image->y_resolution / 25.4;
		break;

	case PixelsPerCentimeterResolution:
		im->Xres = image->x_resolution / 10.0;
		im->Yres = image->y_resolution / 10.0;
		break;

	default:
		im->Xres = 1.0;
		im->Yres = 1.0;
		break;
	}

	/* Other fields.
	 */
	im->Coding = VIPS_CODING_NONE;

	vips_image_pipelinev( im, VIPS_DEMAND_STYLE_SMALLTILE, NULL );

	/* Three ways to loop over attributes / properties :-(
	 */

#ifdef HAVE_RESETIMAGEPROPERTYITERATOR
{
	char *key;

	/* This is the most recent imagemagick API, test for this first.
	 */
	ResetImagePropertyIterator( image );
	while( (key = GetNextImageProperty( image )) ) {
		char name_text[256];
		VipsBuf name = VIPS_BUF_STATIC( name_text );

		vips_buf_appendf( &name, "magick-%s", key );
		vips_image_set_string( im, 
			vips_buf_all( &name ), GetImageProperty( image, key ) );
	}
}
#elif defined(HAVE_RESETIMAGEATTRIBUTEITERATOR)
{
	const ImageAttribute *attr;

	/* magick6.1-ish and later, deprecated in 6.5ish.
	 */
	ResetImageAttributeIterator( image );
	while( (attr = GetNextImageAttribute( image )) ) {
		char name_text[256];
		VipsBuf name = VIPS_BUF_STATIC( name_text );

		vips_buf_appendf( &name, "magick-%s", attr->key );
		vips_image_set_string( im, vips_buf_all( &name ), attr->value );
	}
}
#else
{
	const ImageAttribute *attr;

	/* GraphicsMagick is missing the iterator: we have to loop ourselves.
	 * ->attributes is marked as private in the header, but there's no
	 * getter so we have to access it directly.
	 */
	for( attr = image->attributes; attr; attr = attr->next ) {
		char name_text[256];
		VipsBuf name = VIPS_BUF_STATIC( name_text );

		vips_buf_appendf( &name, "magick-%s", attr->key );
		vips_image_set_string( im, vips_buf_all( &name ), attr->value );
	}
}
#endif 

	/* Do we have a set of equal-sized frames? Append them.

	   	FIXME ... there must be an attribute somewhere from dicom read 
		which says this is a volumetric image

	 */
	read->n_frames = 0;
	for( p = image; p; (p = GetNextImageInList( p )) ) {
		if( p->columns != (unsigned int) im->Xsize ||
			p->rows != (unsigned int) im->Ysize ||
			get_bands( p ) != im->Bands )
			break;

		read->n_frames += 1;
	}
	if( p ) 
		/* Nope ... just do the first image in the list.
		 */
		read->n_frames = 1;

#ifdef DEBUG
	printf( "image has %d frames\n", read->n_frames );
#endif /*DEBUG*/

	/* If all_frames is off, just get the first one.
	 */
	if( !read->all_frames )
		read->n_frames = 1;

	/* Record frame pointers.
	 */
	im->Ysize *= read->n_frames;
	if( !(read->frames = VIPS_ARRAY( NULL, read->n_frames, Image * )) )
		return( -1 );
	p = image;
	for( i = 0; i < read->n_frames; i++ ) {
		read->frames[i] = p;
		p = GetNextImageInList( p );
	}

	return( 0 );
}
Ejemplo n.º 4
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e M P C I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WriteMPCImage() writes an Magick Persistent Cache image to a file.
%
%  The format of the WriteMPCImage method is:
%
%      MagickBooleanType WriteMPCImage(const ImageInfo *image_info,Image *image)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o image: the image.
%
*/
static MagickBooleanType WriteMPCImage(const ImageInfo *image_info,Image *image)
{
  char
    buffer[MaxTextExtent],
    cache_filename[MaxTextExtent];

  const char
    *property,
    *value;

  MagickBooleanType
    status;

  MagickOffsetType
    offset,
    scene;

  register long
    i;

  unsigned long
    depth;

  /*
    Open persistent cache.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
  if (status == MagickFalse)
    return(status);
  (void) CopyMagickString(cache_filename,image->filename,MaxTextExtent);
  AppendImageFormat("cache",cache_filename);
  scene=0;
  offset=0;
  do
  {
    /*
      Write persistent cache meta-information.
    */
    depth=GetImageQuantumDepth(image,MagickTrue);
    if ((image->storage_class == PseudoClass) &&
        (image->colors > (1UL << depth)))
      image->storage_class=DirectClass;
    (void) WriteBlobString(image,"id=MagickCache\n");
    (void) FormatMagickString(buffer,MaxTextExtent,"quantum-depth=%d\n",
      MAGICKCORE_QUANTUM_DEPTH);
    (void) WriteBlobString(image,buffer);
    (void) FormatMagickString(buffer,MaxTextExtent,
      "class=%s  colors=%lu  matte=%s\n",MagickOptionToMnemonic(
      MagickClassOptions,image->storage_class),image->colors,
      MagickOptionToMnemonic(MagickBooleanOptions,(long) image->matte));
    (void) WriteBlobString(image,buffer);
    (void) FormatMagickString(buffer,MaxTextExtent,
      "columns=%lu  rows=%lu  depth=%lu\n",image->columns,image->rows,
      image->depth);
    (void) WriteBlobString(image,buffer);
    if (image->type != UndefinedType)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"type=%s\n",
          MagickOptionToMnemonic(MagickTypeOptions,image->type));
        (void) WriteBlobString(image,buffer);
      }
    if (image->colorspace != UndefinedColorspace)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"colorspace=%s\n",
          MagickOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
        (void) WriteBlobString(image,buffer);
      }
    if (image->endian != UndefinedEndian)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"endian=%s\n",
          MagickOptionToMnemonic(MagickEndianOptions,image->endian));
        (void) WriteBlobString(image,buffer);
      }
    if (image->compression != UndefinedCompression)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,
          "compression=%s  quality=%lu\n",MagickOptionToMnemonic(
          MagickCompressOptions,image->compression),image->quality);
        (void) WriteBlobString(image,buffer);
      }
    if (image->units != UndefinedResolution)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"units=%s\n",
          MagickOptionToMnemonic(MagickResolutionOptions,image->units));
        (void) WriteBlobString(image,buffer);
      }
    if ((image->x_resolution != 0) || (image->y_resolution != 0))
      {
        (void) FormatMagickString(buffer,MaxTextExtent,
          "resolution=%gx%g\n",image->x_resolution,image->y_resolution);
        (void) WriteBlobString(image,buffer);
      }
    if ((image->page.width != 0) || (image->page.height != 0))
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"page=%lux%lu%+ld%+ld\n",
          image->page.width,image->page.height,image->page.x,image->page.y);
        (void) WriteBlobString(image,buffer);
      }
    else
      if ((image->page.x != 0) || (image->page.y != 0))
        {
          (void) FormatMagickString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
            image->page.x,image->page.y);
          (void) WriteBlobString(image,buffer);
        }
    if ((image->page.x != 0) || (image->page.y != 0))
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
          image->tile_offset.x,image->tile_offset.y);
        (void) WriteBlobString(image,buffer);
      }
    if ((GetNextImageInList(image) != (Image *) NULL) ||
        (GetPreviousImageInList(image) != (Image *) NULL))
      {
        if (image->scene == 0)
          (void) FormatMagickString(buffer,MaxTextExtent,
            "iterations=%lu  delay=%lu  ticks-per-second=%lu\n",
            image->iterations,image->delay,image->ticks_per_second);
        else
          (void) FormatMagickString(buffer,MaxTextExtent,
            "scene=%lu  iterations=%lu  delay=%lu  ticks-per-second=%lu\n",
            image->scene,image->iterations,image->delay,
            image->ticks_per_second);
        (void) WriteBlobString(image,buffer);
      }
    else
      {
        if (image->scene != 0)
          {
            (void) FormatMagickString(buffer,MaxTextExtent,"scene=%lu\n",
              image->scene);
            (void) WriteBlobString(image,buffer);
          }
        if (image->iterations != 0)
          {
            (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%lu\n",
              image->iterations);
            (void) WriteBlobString(image,buffer);
          }
        if (image->delay != 0)
          {
            (void) FormatMagickString(buffer,MaxTextExtent,"delay=%lu\n",
              image->delay);
            (void) WriteBlobString(image,buffer);
          }
        if (image->ticks_per_second != UndefinedTicksPerSecond)
          {
            (void) FormatMagickString(buffer,MaxTextExtent,
              "ticks-per-second=%lu\n",image->ticks_per_second);
            (void) WriteBlobString(image,buffer);
          }
      }
    if (image->gravity != UndefinedGravity)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"gravity=%s\n",
          MagickOptionToMnemonic(MagickGravityOptions,image->gravity));
        (void) WriteBlobString(image,buffer);
      }
    if (image->dispose != UndefinedDispose)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"dispose=%s\n",
          MagickOptionToMnemonic(MagickDisposeOptions,image->dispose));
        (void) WriteBlobString(image,buffer);
      }
    if (image->rendering_intent != UndefinedIntent)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,
          "rendering-intent=%s\n",
           MagickOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
        (void) WriteBlobString(image,buffer);
      }
    if (image->gamma != 0.0)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"gamma=%g\n",
          image->gamma);
        (void) WriteBlobString(image,buffer);
      }
    if (image->chromaticity.white_point.x != 0.0)
      {
        /*
          Note chomaticity points.
        */
        (void) FormatMagickString(buffer,MaxTextExtent,"red-primary="
          "%g,%g  green-primary=%g,%g  blue-primary=%g,%g\n",
          image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
          image->chromaticity.green_primary.x,
          image->chromaticity.green_primary.y,
          image->chromaticity.blue_primary.x,
          image->chromaticity.blue_primary.y);
        (void) WriteBlobString(image,buffer);
        (void) FormatMagickString(buffer,MaxTextExtent,
          "white-point=%g,%g\n",image->chromaticity.white_point.x,
          image->chromaticity.white_point.y);
        (void) WriteBlobString(image,buffer);
      }
    if (image->orientation != UndefinedOrientation)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,
          "orientation=%s\n",MagickOptionToMnemonic(MagickOrientationOptions,
          image->orientation));
        (void) WriteBlobString(image,buffer);
      }
    if (image->profiles != (void *) NULL)
      {
        const char
          *name;

        const StringInfo
          *profile;

        /*
          Generic profile.
        */
        ResetImageProfileIterator(image);
        for (name=GetNextImageProfile(image); name != (const char *) NULL; )
        {
          profile=GetImageProfile(image,name);
          if (profile != (StringInfo *) NULL)
            {
              (void) FormatMagickString(buffer,MaxTextExtent,"profile:%s=%lu\n",
                name,(unsigned long) GetStringInfoLength(profile));
              (void) WriteBlobString(image,buffer);
            }
          name=GetNextImageProfile(image);
        }
      }
    if (image->montage != (char *) NULL)
      {
        (void) FormatMagickString(buffer,MaxTextExtent,"montage=%s\n",
          image->montage);
        (void) WriteBlobString(image,buffer);
      }
    ResetImagePropertyIterator(image);
    property=GetNextImageProperty(image);
    while (property != (const char *) NULL)
    {
      (void) FormatMagickString(buffer,MaxTextExtent,"%s=",property);
      (void) WriteBlobString(image,buffer);
      value=GetImageProperty(image,property);
      if (value != (const char *) NULL)
        {
          for (i=0; i < (long) strlen(value); i++)
            if (isspace((int) ((unsigned char) value[i])) != 0)
              break;
          if (i <= (long) strlen(value))
            (void) WriteBlobByte(image,'{');
          (void) WriteBlob(image,strlen(value),(unsigned char *) value);
          if (i <= (long) strlen(value))
            (void) WriteBlobByte(image,'}');
        }
      (void) WriteBlobByte(image,'\n');
      property=GetNextImageProperty(image);
    }
    ResetImageArtifactIterator(image);
    (void) WriteBlobString(image,"\f\n:\032");
    if (image->montage != (char *) NULL)
      {
        /*
          Write montage tile directory.
        */
        if (image->directory != (char *) NULL)
          (void) WriteBlobString(image,image->directory);
        (void) WriteBlobByte(image,'\0');
      }
    if (image->profiles != 0)
      {
        const char
          *name;

        const StringInfo
          *profile;

        /*
          Write image profiles.
        */
        ResetImageProfileIterator(image);
        name=GetNextImageProfile(image);
        while (name != (const char *) NULL)
        {
          profile=GetImageProfile(image,name);
          (void) WriteBlob(image,GetStringInfoLength(profile),
            GetStringInfoDatum(profile));
          name=GetNextImageProfile(image);
        }
      }
    if (image->storage_class == PseudoClass)
      {
        size_t
          packet_size;

        unsigned char
          *colormap,
          *q;

        /*
          Allocate colormap.
        */
        packet_size=(size_t) (3UL*depth/8UL);
        colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
          packet_size*sizeof(*colormap));
        if (colormap == (unsigned char *) NULL)
          return(MagickFalse);
        /*
          Write colormap to file.
        */
        q=colormap;
        for (i=0; i < (long) image->colors; i++)
        {
          switch (depth)
          {
            default:
              ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
            case 32:
            {
              unsigned long
                pixel;

              pixel=ScaleQuantumToLong(image->colormap[i].red);
              q=PopLongPixel(MSBEndian,pixel,q);
              pixel=ScaleQuantumToLong(image->colormap[i].green);
              q=PopLongPixel(MSBEndian,pixel,q);
              pixel=ScaleQuantumToLong(image->colormap[i].blue);
              q=PopLongPixel(MSBEndian,pixel,q);
            }
            case 16:
            {
              unsigned short
                pixel;

              pixel=ScaleQuantumToShort(image->colormap[i].red);
              q=PopShortPixel(MSBEndian,pixel,q);
              pixel=ScaleQuantumToShort(image->colormap[i].green);
              q=PopShortPixel(MSBEndian,pixel,q);
              pixel=ScaleQuantumToShort(image->colormap[i].blue);
              q=PopShortPixel(MSBEndian,pixel,q);
              break;
            }
            case 8:
            {
              unsigned char
                pixel;

              pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
              q=PopCharPixel(pixel,q);
              pixel=(unsigned char) ScaleQuantumToChar(
                image->colormap[i].green);
              q=PopCharPixel(pixel,q);
              pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
              q=PopCharPixel(pixel,q);
              break;
            }
          }
        }
        (void) WriteBlob(image,packet_size*image->colors,colormap);
        colormap=(unsigned char *) RelinquishMagickMemory(colormap);
      }
    /*
      Initialize persistent pixel cache.
    */
    status=PersistPixelCache(image,cache_filename,MagickFalse,&offset,
      &image->exception);
    if (status == MagickFalse)
      ThrowWriterException(CacheError,"UnableToPersistPixelCache");
    if (GetNextImageInList(image) == (Image *) NULL)
      break;
    image=SyncNextImageInList(image);
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        status=image->progress_monitor(SaveImagesTag,scene,
          GetImageListLength(image),image->client_data);
        if (status == MagickFalse)
          break;
      }
    scene++;
  } while (image_info->adjoin != MagickFalse);
  (void) CloseBlob(image);
  return(status);
}