Esempio n. 1
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   G e t Q u a n t u m T y p e                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  GetQuantumType() returns the quantum type of the image.
%
%  The format of the GetQuantumType method is:
%
%      QuantumType GetQuantumType(Image *image,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport QuantumType GetQuantumType(Image *image,ExceptionInfo *exception)
{
  QuantumType
    quantum_type;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  (void) exception;
  quantum_type=RGBQuantum;
  if (image->alpha_trait != UndefinedPixelTrait)
    quantum_type=RGBAQuantum;
  if (image->colorspace == CMYKColorspace)
    {
      quantum_type=CMYKQuantum;
      if (image->alpha_trait != UndefinedPixelTrait)
        quantum_type=CMYKAQuantum;
    }
  if (IsGrayColorspace(image->colorspace) != MagickFalse)
    {
      quantum_type=GrayQuantum;
      if (image->alpha_trait != UndefinedPixelTrait)
        quantum_type=GrayAlphaQuantum;
    }
  if (image->storage_class == PseudoClass)
    {
      quantum_type=IndexQuantum;
      if (image->alpha_trait != UndefinedPixelTrait)
        quantum_type=IndexAlphaQuantum;
    }
  return(quantum_type);
}
Esempio n. 2
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%     I s I m a g e G r a y                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  IsImageGray() returns MagickTrue if all the pixels in the image have the
%  same red, green, and blue intensities.
%
%  The format of the IsImageGray method is:
%
%      MagickBooleanType IsImageGray(const Image *image,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType IsImageGray(const Image *image,
  ExceptionInfo *exception)
{
  CacheView
    *image_view;

  ImageType
    type;

  register const Quantum
    *p;

  register ssize_t
    x;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
      (image->type == GrayscaleMatteType))
    return(MagickTrue);
  if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
      (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
    return(MagickFalse);
  type=BilevelType;
  image_view=AcquireVirtualCacheView(image,exception);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    if (p == (const Quantum *) NULL)
      break;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if (IsPixelGray(image,p) == MagickFalse)
        {
          type=UndefinedType;
          break;
        }
      if ((type == BilevelType) &&
          (IsPixelMonochrome(image,p) == MagickFalse))
        type=GrayscaleType;
      p+=GetPixelChannels(image);
    }
    if (type == UndefinedType)
      break;
  }
  image_view=DestroyCacheView(image_view);
  if (type == UndefinedType)
    return(MagickFalse);
  ((Image *) image)->type=type;
  if ((type == GrayscaleType) && (image->alpha_trait == BlendPixelTrait))
    ((Image *) image)->type=GrayscaleMatteType;
  return(SetImageColorspace((Image *) image,GRAYColorspace,exception));
}
Esempio n. 3
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%     C o m b i n e I m a g e s                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  CombineImages() combines one or more images into a single image.  The
%  grayscale value of the pixels of each image in the sequence is assigned in
%  order to the specified channels of the combined image.   The typical
%  ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
%
%  The format of the CombineImages method is:
%
%      Image *CombineImages(const Image *image,const ChannelType channel,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *CombineImages(const Image *image,const ChannelType channel,
  ExceptionInfo *exception)
{
#define CombineImageTag  "Combine/Image"

  CacheView
    *combine_view;

  const Image
    *next;

  Image
    *combine_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  ssize_t
    y;

  /*
    Ensure the image are the same size.
  */
  assert(image != (const Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
  {
    if ((next->columns != image->columns) || (next->rows != image->rows))
      ThrowImageException(OptionError,"ImagesAreNotTheSameSize");
  }
  combine_image=CloneImage(image,0,0,MagickTrue,exception);
  if (combine_image == (Image *) NULL)
    return((Image *) NULL);
  if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse)
    {
      InheritException(exception,&combine_image->exception);
      combine_image=DestroyImage(combine_image);
      return((Image *) NULL);
    }
  if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
    (void) SetImageColorspace(combine_image,sRGBColorspace);
  if ((channel & OpacityChannel) != 0)
    combine_image->matte=MagickTrue;
  (void) SetImageBackgroundColor(combine_image);
  /*
    Combine images.
  */
  status=MagickTrue;
  progress=0;
  combine_view=AcquireAuthenticCacheView(combine_image,exception);
  for (y=0; y < (ssize_t) combine_image->rows; y++)
  {
    CacheView
      *image_view;

    const Image
      *next;

    PixelPacket
      *pixels;

    register const PixelPacket
      *restrict p;

    register PixelPacket
      *restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
      1,exception);
    if (pixels == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    next=image;
    if (((channel & RedChannel) != 0) && (next != (Image *) NULL))
      {
        image_view=AcquireVirtualCacheView(next,exception);
        p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
        if (p == (const PixelPacket *) NULL)
          continue;
        q=pixels;
        for (x=0; x < (ssize_t) combine_image->columns; x++)
        {
          SetPixelRed(q,ClampToQuantum(GetPixelIntensity(image,p)));
          p++;
          q++;
        }
        image_view=DestroyCacheView(image_view);
        next=GetNextImageInList(next);
      }
    if (((channel & GreenChannel) != 0) && (next != (Image *) NULL))
      {
        image_view=AcquireVirtualCacheView(next,exception);
        p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
        if (p == (const PixelPacket *) NULL)
          continue;
        q=pixels;
        for (x=0; x < (ssize_t) combine_image->columns; x++)
        {
          SetPixelGreen(q,ClampToQuantum(GetPixelIntensity(image,p)));
          p++;
          q++;
        }
        image_view=DestroyCacheView(image_view);
        next=GetNextImageInList(next);
      }
    if (((channel & BlueChannel) != 0) && (next != (Image *) NULL))
      {
        image_view=AcquireVirtualCacheView(next,exception);
        p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
        if (p == (const PixelPacket *) NULL)
          continue;
        q=pixels;
        for (x=0; x < (ssize_t) combine_image->columns; x++)
        {
          SetPixelBlue(q,ClampToQuantum(GetPixelIntensity(image,p)));
          p++;
          q++;
        }
        image_view=DestroyCacheView(image_view);
        next=GetNextImageInList(next);
      }
    if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL))
      {
        image_view=AcquireVirtualCacheView(next,exception);
        p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
        if (p == (const PixelPacket *) NULL)
          continue;
        q=pixels;
        for (x=0; x < (ssize_t) combine_image->columns; x++)
        {
          SetPixelAlpha(q,ClampToQuantum(GetPixelIntensity(image,p)));
          p++;
          q++;
        }
        image_view=DestroyCacheView(image_view);
        next=GetNextImageInList(next);
      }
    if (((channel & IndexChannel) != 0) &&
        (image->colorspace == CMYKColorspace) && (next != (Image *) NULL))
      {
        IndexPacket
          *indexes;

        image_view=AcquireVirtualCacheView(next,exception);
        p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
        if (p == (const PixelPacket *) NULL)
          continue;
        indexes=GetCacheViewAuthenticIndexQueue(combine_view);
        for (x=0; x < (ssize_t) combine_image->columns; x++)
        {
          SetPixelIndex(indexes+x,ClampToQuantum(GetPixelIntensity(image,p)));
          p++;
        }
        image_view=DestroyCacheView(image_view);
        next=GetNextImageInList(next);
      }
    if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

        proceed=SetImageProgress(image,CombineImageTag,progress++,
          combine_image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  combine_view=DestroyCacheView(combine_view);
  if (IsGrayColorspace(combine_image->colorspace) != MagickFalse)
    (void) TransformImageColorspace(combine_image,sRGBColorspace);
  if (status == MagickFalse)
    combine_image=DestroyImage(combine_image);
  return(combine_image);
}
Esempio n. 4
0
MagickExport Image *ChannelFxImage(const Image *image,const char *expression,
  ExceptionInfo *exception)
{
#define ChannelFxImageTag  "ChannelFx/Image"

  ChannelFx
    channel_op;

  ChannelType
    channel_mask;

  char
    token[MaxTextExtent];

  const char
    *p;

  const Image
    *source_image;

  double
    pixel;

  Image
    *destination_image;

  MagickBooleanType
    status;

  PixelChannel
    source_channel,
    destination_channel;

  ssize_t
    channels;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  source_image=image;
  destination_image=CloneImage(source_image,0,0,MagickTrue,exception);
  if (destination_image == (Image *) NULL)
    return((Image *) NULL);
  if (expression == (const char *) NULL)
    return(destination_image);
  destination_channel=RedPixelChannel;
  channel_mask=UndefinedChannel;
  pixel=0.0;
  p=(char *) expression;
  GetMagickToken(p,&p,token);
  channel_op=ExtractChannelOp;
  for (channels=0; *token != '\0'; )
  {
    ssize_t
      i;

    /*
      Interpret channel expression.
    */
    switch (*token)
    {
      case ',':
      {
        GetMagickToken(p,&p,token);
        break;
      }
      case '|':
      {
        if (GetNextImageInList(source_image) != (Image *) NULL)
          source_image=GetNextImageInList(source_image);
        else
          source_image=GetFirstImageInList(source_image);
        GetMagickToken(p,&p,token);
        break;
      }
      case ';':
      {
        Image
          *canvas;

        SetPixelChannelMask(destination_image,channel_mask);
        if ((channel_op == ExtractChannelOp) && (channels == 1))
          (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
        status=SetImageStorageClass(destination_image,DirectClass,exception);
        if (status == MagickFalse)
          {
            destination_image=DestroyImageList(destination_image);
            return(destination_image);
          }
        canvas=CloneImage(source_image,0,0,MagickTrue,exception);
        if (canvas == (Image *) NULL)
          {
            destination_image=DestroyImageList(destination_image);
            return(destination_image);
          }
        AppendImageToList(&destination_image,canvas);
        destination_image=GetLastImageInList(destination_image);
        GetMagickToken(p,&p,token);
        channels=0;
        destination_channel=RedPixelChannel;
        channel_mask=UndefinedChannel;
        break;
      }
      default:
        break;
    }
    i=ParsePixelChannelOption(token);
    if (i < 0)
      {
        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
          "UnrecognizedChannelType","`%s'",token);
        destination_image=DestroyImageList(destination_image);
        return(destination_image);
      }
    source_channel=(PixelChannel) i;
    channel_op=ExtractChannelOp;
    GetMagickToken(p,&p,token);
    if (*token == '<')
      {
        channel_op=ExchangeChannelOp;
        GetMagickToken(p,&p,token);
      }
    if (*token == '=')
      {
        if (channel_op != ExchangeChannelOp)
          channel_op=AssignChannelOp;
        GetMagickToken(p,&p,token);
      }
    if (*token == '>')
      {
        if (channel_op != ExchangeChannelOp)
          channel_op=TransferChannelOp;
        GetMagickToken(p,&p,token);
      }
    switch (channel_op)
    {
      case AssignChannelOp:
      {
        pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0);
        GetMagickToken(p,&p,token);
        break;
      }
      case ExchangeChannelOp:
      case TransferChannelOp:
      {
        i=ParsePixelChannelOption(token);
        if (i < 0)
          {
            (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
              "UnrecognizedChannelType","`%s'",token);
            destination_image=DestroyImageList(destination_image);
            return(destination_image);
          }
        destination_channel=(PixelChannel) i;
        switch (destination_channel)
        {
          case RedPixelChannel:
          case GreenPixelChannel:
          case BluePixelChannel:
          case BlackPixelChannel:
          case IndexPixelChannel:
            break;
          case AlphaPixelChannel:
          {
            destination_image->alpha_trait=BlendPixelTrait;
            break;
          }
          case ReadMaskPixelChannel:
          {
            destination_image->read_mask=MagickTrue;
            break;
          }
          case WriteMaskPixelChannel:
          {
            destination_image->write_mask=MagickTrue;
            break;
          }
          case MetaPixelChannel:
          default:
          {
            (void) SetPixelMetaChannels(destination_image,(size_t) (i-
              GetPixelChannels(destination_image)+1),exception);
            break;
          }
        }
        channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token));
        if (((channels >= 1)  || (destination_channel >= 1)) &&
            (IsGrayColorspace(destination_image->colorspace) != MagickFalse))
          (void) SetImageColorspace(destination_image,sRGBColorspace,exception);
        GetMagickToken(p,&p,token);
        break;
      }
      default:
        break;
    }
    status=ChannelImage(destination_image,destination_channel,channel_op,
      source_image,source_channel,ClampToQuantum(pixel),exception);
    if (status == MagickFalse)
      {
        destination_image=DestroyImageList(destination_image);
        break;
      }
    channels++;
    if (channel_op == ExchangeChannelOp)
      {
        status=ChannelImage(destination_image,source_channel,channel_op,
          source_image,destination_channel,ClampToQuantum(pixel),exception);
        if (status == MagickFalse)
          {
            destination_image=DestroyImageList(destination_image);
            break;
          }
        channels++;
      }
    switch (channel_op)
    {
      case ExtractChannelOp:
      {
        channel_mask=(ChannelType) (channel_mask | (1 << destination_channel));
        destination_channel=(PixelChannel) (destination_channel+1);
        break;
      }
      default:
        break;
    }
    status=SetImageProgress(source_image,ChannelFxImageTag,p-expression,
      strlen(expression));
    if (status == MagickFalse)
      break;
  }
  SetPixelChannelMask(destination_image,channel_mask);
  if ((channel_op == ExtractChannelOp) && (channels == 1))
    (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
  status=SetImageStorageClass(destination_image,DirectClass,exception);
  if (status == MagickFalse)
    {
      destination_image=GetLastImageInList(destination_image);
      return((Image *) NULL);
    }
  return(GetFirstImageInList(destination_image));
}
Esempio n. 5
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   F r a m e I m a g e                                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  FrameImage() adds a simulated three-dimensional border around the image.
%  The color of the border is defined by the matte_color member of image.
%  Members width and height of frame_info specify the border width of the
%  vertical and horizontal sides of the frame.  Members inner and outer
%  indicate the width of the inner and outer shadows of the frame.
%
%  The format of the FrameImage method is:
%
%      Image *FrameImage(const Image *image,const FrameInfo *frame_info,
%        const CompositeOperator compose,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o frame_info: Define the width and height of the frame and its bevels.
%
%    o compose: the composite operator.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *FrameImage(const Image *image,const FrameInfo *frame_info,
  const CompositeOperator compose,ExceptionInfo *exception)
{
#define FrameImageTag  "Frame/Image"

  CacheView
    *image_view,
    *frame_view;

  Image
    *frame_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  PixelInfo
    accentuate,
    highlight,
    interior,
    matte,
    shadow,
    trough;

  register ssize_t
    x;

  size_t
    bevel_width,
    height,
    width;

  ssize_t
    y;

  /*
    Check frame geometry.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(frame_info != (FrameInfo *) NULL);
  if ((frame_info->outer_bevel < 0) || (frame_info->inner_bevel < 0))
    ThrowImageException(OptionError,"FrameIsLessThanImageSize");
  bevel_width=(size_t) (frame_info->outer_bevel+frame_info->inner_bevel);
  width=frame_info->width-frame_info->x-bevel_width;
  height=frame_info->height-frame_info->y-bevel_width;
  if ((width < image->columns) || (height < image->rows))
    ThrowImageException(OptionError,"FrameIsLessThanImageSize");
  /*
    Initialize framed image attributes.
  */
  frame_image=CloneImage(image,frame_info->width,frame_info->height,MagickTrue,
    exception);
  if (frame_image == (Image *) NULL)
    return((Image *) NULL);
  if (SetImageStorageClass(frame_image,DirectClass,exception) == MagickFalse)
    {
      frame_image=DestroyImage(frame_image);
      return((Image *) NULL);
    }
  if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
      (IsPixelInfoGray(&image->matte_color) == MagickFalse))
    SetImageColorspace(frame_image,sRGBColorspace,exception);
  if ((frame_image->border_color.matte != MagickFalse) &&
      (frame_image->matte == MagickFalse))
    (void) SetImageAlpha(frame_image,OpaqueAlpha,exception);
  frame_image->page=image->page;
  if ((image->page.width != 0) && (image->page.height != 0))
    {
      frame_image->page.width+=frame_image->columns-image->columns;
      frame_image->page.height+=frame_image->rows-image->rows;
    }
  /*
    Initialize 3D effects color.
  */
  interior=image->border_color;
  matte=image->matte_color;
  accentuate=matte;
  accentuate.red=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.red+(QuantumRange*AccentuateModulate)));
  accentuate.green=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.green+(QuantumRange*AccentuateModulate)));
  accentuate.blue=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.blue+(QuantumRange*AccentuateModulate)));
  accentuate.black=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.black+(QuantumRange*AccentuateModulate)));
  accentuate.alpha=matte.alpha;
  highlight=matte;
  highlight.red=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.red+(QuantumRange*HighlightModulate)));
  highlight.green=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.green+(QuantumRange*HighlightModulate)));
  highlight.blue=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.blue+(QuantumRange*HighlightModulate)));
  highlight.black=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.black+(QuantumRange*HighlightModulate)));
  highlight.alpha=matte.alpha;
  shadow=matte;
  shadow.red=QuantumScale*matte.red*ShadowModulate;
  shadow.green=QuantumScale*matte.green*ShadowModulate;
  shadow.blue=QuantumScale*matte.blue*ShadowModulate;
  shadow.black=QuantumScale*matte.black*ShadowModulate;
  shadow.alpha=matte.alpha;
  trough=matte;
  trough.red=QuantumScale*matte.red*TroughModulate;
  trough.green=QuantumScale*matte.green*TroughModulate;
  trough.blue=QuantumScale*matte.blue*TroughModulate;
  trough.black=QuantumScale*matte.black*TroughModulate;
  trough.alpha=matte.alpha;
  status=MagickTrue;
  progress=0;
  image_view=AcquireCacheView(image);
  frame_view=AcquireCacheView(frame_image);
  height=(size_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
    frame_info->inner_bevel);
  if (height != 0)
    {
      register ssize_t
        x;

      register Quantum
        *restrict q;

      /*
        Draw top of ornamental border.
      */
      q=QueueCacheViewAuthenticPixels(frame_view,0,0,frame_image->columns,
        height,exception);
      if (q != (Quantum *) NULL)
        {
          /*
            Draw top of ornamental border.
          */
          for (y=0; y < (ssize_t) frame_info->outer_bevel; y++)
          {
            for (x=0; x < (ssize_t) (frame_image->columns-y); x++)
            {
              if (x < y)
                SetPixelInfoPixel(frame_image,&highlight,q);
              else
                SetPixelInfoPixel(frame_image,&accentuate,q);
              q+=GetPixelChannels(frame_image);
            }
            for ( ; x < (ssize_t) frame_image->columns; x++)
            {
              SetPixelInfoPixel(frame_image,&shadow,q);
              q+=GetPixelChannels(frame_image);
            }
          }
          for (y=0; y < (ssize_t) (frame_info->y-bevel_width); y++)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&highlight,q);
              q+=GetPixelChannels(frame_image);
            }
            width=frame_image->columns-2*frame_info->outer_bevel;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelInfoPixel(frame_image,&matte,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&shadow,q);
              q+=GetPixelChannels(frame_image);
            }
          }
          for (y=0; y < (ssize_t) frame_info->inner_bevel; y++)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&highlight,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
            {
              SetPixelInfoPixel(frame_image,&matte,q);
              q+=GetPixelChannels(frame_image);
            }
            width=image->columns+((size_t) frame_info->inner_bevel << 1)-
              y;
            for (x=0; x < (ssize_t) width; x++)
            {
              if (x < y)
                SetPixelInfoPixel(frame_image,&shadow,q);
              else
                SetPixelInfoPixel(frame_image,&trough,q);
              q+=GetPixelChannels(frame_image);
            }
            for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
            {
              SetPixelInfoPixel(frame_image,&highlight,q);
              q+=GetPixelChannels(frame_image);
            }
            width=frame_info->width-frame_info->x-image->columns-bevel_width;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelInfoPixel(frame_image,&matte,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&shadow,q);
              q+=GetPixelChannels(frame_image);
            }
          }
          (void) SyncCacheViewAuthenticPixels(frame_view,exception);
        }
    }
  /*
    Draw sides of ornamental border.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT) 
  #pragma omp parallel for schedule(static) shared(progress,status)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register ssize_t
      x;

    register Quantum
      *restrict q;

    size_t
      width;

    /*
      Initialize scanline with matte color.
    */
    if (status == MagickFalse)
      continue;
    q=QueueCacheViewAuthenticPixels(frame_view,0,frame_info->y+y,
      frame_image->columns,1,exception);
    if (q == (Quantum *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
    {
      SetPixelInfoPixel(frame_image,&highlight,q);
      q+=GetPixelChannels(frame_image);
    }
    for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
    {
      SetPixelInfoPixel(frame_image,&matte,q);
      q+=GetPixelChannels(frame_image);
    }
    for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
    {
      SetPixelInfoPixel(frame_image,&shadow,q);
      q+=GetPixelChannels(frame_image);
    }
    /*
      Set frame interior to interior color.
    */
    if ((compose != CopyCompositeOp) && ((compose != OverCompositeOp) ||
        (image->matte != MagickFalse)))
      for (x=0; x < (ssize_t) image->columns; x++)
      {
        SetPixelInfoPixel(frame_image,&interior,q);
        q+=GetPixelChannels(frame_image);
      }
    else
      {
        register const Quantum
          *p;

        p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
        if (p == (const Quantum *) NULL)
          {
            status=MagickFalse;
            continue;
          }
        for (x=0; x < (ssize_t) image->columns; x++)
        {
          if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
            SetPixelRed(frame_image,GetPixelRed(image,p),q);
          if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
            SetPixelGreen(frame_image,GetPixelGreen(image,p),q);
          if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
            SetPixelBlue(frame_image,GetPixelBlue(image,p),q);
          if ((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0)
            SetPixelBlack(frame_image,GetPixelBlack(image,p),q);
          if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
            SetPixelAlpha(frame_image,GetPixelAlpha(image,p),q);
          p+=GetPixelChannels(image);
          q+=GetPixelChannels(frame_image);
        }
      }
    for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
    {
      SetPixelInfoPixel(frame_image,&highlight,q);
      q+=GetPixelChannels(frame_image);
    }
    width=frame_info->width-frame_info->x-image->columns-bevel_width;
    for (x=0; x < (ssize_t) width; x++)
    {
      SetPixelInfoPixel(frame_image,&matte,q);
      q+=GetPixelChannels(frame_image);
    }
    for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
    {
      SetPixelInfoPixel(frame_image,&shadow,q);
      q+=GetPixelChannels(frame_image);
    }
    if (SyncCacheViewAuthenticPixels(frame_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT) 
        #pragma omp critical (MagickCore_FrameImage)
#endif
        proceed=SetImageProgress(image,FrameImageTag,progress++,image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  height=(size_t) (frame_info->inner_bevel+frame_info->height-
    frame_info->y-image->rows-bevel_width+frame_info->outer_bevel);
  if (height != 0)
    {
      register ssize_t
        x;

      register Quantum
        *restrict q;

      /*
        Draw bottom of ornamental border.
      */
      q=QueueCacheViewAuthenticPixels(frame_view,0,(ssize_t) (frame_image->rows-
        height),frame_image->columns,height,exception);
      if (q != (Quantum *) NULL)
        {
          /*
            Draw bottom of ornamental border.
          */
          for (y=frame_info->inner_bevel-1; y >= 0; y--)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&highlight,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
            {
              SetPixelInfoPixel(frame_image,&matte,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < y; x++)
            {
              SetPixelInfoPixel(frame_image,&shadow,q);
              q+=GetPixelChannels(frame_image);
            }
            for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
            {
              if (x >= (ssize_t) (image->columns+2*frame_info->inner_bevel-y))
                SetPixelInfoPixel(frame_image,&highlight,q);
              else
                SetPixelInfoPixel(frame_image,&accentuate,q);
              q+=GetPixelChannels(frame_image);
            }
            width=frame_info->width-frame_info->x-image->columns-bevel_width;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelInfoPixel(frame_image,&matte,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&shadow,q);
              q+=GetPixelChannels(frame_image);
            }
          }
          height=frame_info->height-frame_info->y-image->rows-bevel_width;
          for (y=0; y < (ssize_t) height; y++)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&highlight,q);
              q+=GetPixelChannels(frame_image);
            }
            width=frame_image->columns-2*frame_info->outer_bevel;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelInfoPixel(frame_image,&matte,q);
              q+=GetPixelChannels(frame_image);
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelInfoPixel(frame_image,&shadow,q);
              q+=GetPixelChannels(frame_image);
            }
          }
          for (y=frame_info->outer_bevel-1; y >= 0; y--)
          {
            for (x=0; x < y; x++)
            {
              SetPixelInfoPixel(frame_image,&highlight,q);
              q+=GetPixelChannels(frame_image);
            }
            for ( ; x < (ssize_t) frame_image->columns; x++)
            {
              if (x >= (ssize_t) (frame_image->columns-y))
                SetPixelInfoPixel(frame_image,&shadow,q);
              else
                SetPixelInfoPixel(frame_image,&trough,q);
              q+=GetPixelChannels(frame_image);
            }
          }
          (void) SyncCacheViewAuthenticPixels(frame_view,exception);
        }
    }
  frame_view=DestroyCacheView(frame_view);
  image_view=DestroyCacheView(image_view);
  if ((compose != CopyCompositeOp) && ((compose != OverCompositeOp) ||
      (image->matte != MagickFalse)))
    {
      x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+
        frame_info->inner_bevel);
      y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
        frame_info->inner_bevel);
      (void) CompositeImage(frame_image,image,compose,MagickTrue,x,y,
        exception);
    }
  return(frame_image);
}
Esempio n. 6
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e J P 2 I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WriteJP2Image() writes an image in the JPEG 2000 image format.
%
%  JP2 support originally written by Nathan Brown, [email protected]
%
%  The format of the WriteJP2Image method is:
%
%      MagickBooleanType WriteJP2Image(const ImageInfo *image_info,
%        Image *image,ExceptionInfo *exception)
%
%  A description of each parameter follows.
%
%    o image_info: the image info.
%
%    o image:  The image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image,
  ExceptionInfo *exception)
{
  char
    *key,
    magick[MaxTextExtent],
    *options;

  const char
    *option;

  jas_image_cmptparm_t
    component_info[4];

  jas_image_t
    *jp2_image;

  jas_matrix_t
    *pixels[4];

  jas_stream_t
    *jp2_stream;

  MagickBooleanType
    status;

  QuantumAny
    range;

  register const Quantum
    *p;

  register ssize_t
    i,
    x;

  size_t
    number_components;

  ssize_t
    format,
    y;

  /*
    Open image file.
  */
  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);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(status);
  /*
    Initialize JPEG 2000 API.
  */
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
  jp2_stream=JP2StreamManager(image);
  if (jp2_stream == (jas_stream_t *) NULL)
    ThrowWriterException(DelegateError,"UnableToManageJP2Stream");
  number_components=image->alpha_trait ? 4UL : 3UL;
  if (IsGrayColorspace(image->colorspace) != MagickFalse)
    number_components=1;
  if ((image->columns != (unsigned int) image->columns) ||
      (image->rows != (unsigned int) image->rows))
    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
  (void) ResetMagickMemory(&component_info,0,sizeof(component_info));
  for (i=0; i < (ssize_t) number_components; i++)
  {
    component_info[i].tlx=0;
    component_info[i].tly=0;
    component_info[i].hstep=1;
    component_info[i].vstep=1;
    component_info[i].width=(unsigned int) image->columns;
    component_info[i].height=(unsigned int) image->rows;
    component_info[i].prec=(int) MagickMax(MagickMin(image->depth,16),2);
    component_info[i].sgnd=MagickFalse;
  }
  jp2_image=jas_image_create((int) number_components,component_info,
    JAS_CLRSPC_UNKNOWN);
  if (jp2_image == (jas_image_t *) NULL)
    ThrowWriterException(DelegateError,"UnableToCreateImage");
  switch (image->colorspace)
  {
    case RGBColorspace:
    case sRGBColorspace:
    {
      /*
        RGB colorspace.
      */
      jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB);
      jas_image_setcmpttype(jp2_image,0,
        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
      jas_image_setcmpttype(jp2_image,1,
        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
      jas_image_setcmpttype(jp2_image,2,
        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
      if (number_components == 4)
        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
      break;
    }
    case GRAYColorspace:
    {
      /*
        Grayscale colorspace.
      */
      jas_image_setclrspc(jp2_image,JAS_CLRSPC_SGRAY);
      jas_image_setcmpttype(jp2_image,0,
        JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
      break;
    }
    case YCbCrColorspace:
    {
      /*
        YCbCr colorspace.
      */
      jas_image_setclrspc(jp2_image,JAS_CLRSPC_SYCBCR);
      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(0));
      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(1));
      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(2));
      if (number_components == 4)
        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
      break;
    }
    case XYZColorspace:
    {
      /*
        XYZ colorspace.
      */
      jas_image_setclrspc(jp2_image,JAS_CLRSPC_CIEXYZ);
      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(0));
      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(1));
      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(2));
      if (number_components == 4)
        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
      break;
    }
    case LabColorspace:
    {
      /*
        Lab colorspace.
      */
      jas_image_setclrspc(jp2_image,JAS_CLRSPC_CIELAB);
      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(0));
      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(1));
      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(2));
      if (number_components == 4)
        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
      break;
    }
    default:
    {
      /*
        Unknow.
      */
      jas_image_setclrspc(jp2_image,JAS_CLRSPC_UNKNOWN);
      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(0));
      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(1));
      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
        JAS_IMAGE_CT_COLOR(2));
      if (number_components == 4)
        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
      break;
    }
  }
  /*
    Convert to JPEG 2000 pixels.
  */
  for (i=0; i < (ssize_t) number_components; i++)
  {
    pixels[i]=jas_matrix_create(1,(int) image->columns);
    if (pixels[i] == (jas_matrix_t *) NULL)
      {
        for (x=0; x < i; x++)
          jas_matrix_destroy(pixels[x]);
        jas_image_destroy(jp2_image);
        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
      }
  }
  range=GetQuantumRange((size_t) component_info[0].prec);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    if (p == (const Quantum *) NULL)
      break;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if (number_components == 1)
        jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
          GetPixelIntensity(image,p),range));
      else
        {
          jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
            GetPixelRed(image,p),range));
          jas_matrix_setv(pixels[1],x,(jas_seqent_t) ScaleQuantumToAny(
            GetPixelGreen(image,p),range));
          jas_matrix_setv(pixels[2],x,(jas_seqent_t) ScaleQuantumToAny(
            GetPixelBlue(image,p),range));
          if (number_components > 3)
            jas_matrix_setv(pixels[3],x,(jas_seqent_t) ScaleQuantumToAny(
              GetPixelAlpha(image,p),range));
        }
      p+=GetPixelChannels(image);
    }
    for (i=0; i < (ssize_t) number_components; i++)
      (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y,
        (unsigned int) image->columns,1,pixels[i]);
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
      image->rows);
    if (status == MagickFalse)
      break;
  }
  (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
  if (LocaleCompare(magick,"J2C") == 0)
    (void) CopyMagickString(magick,"JPC",MaxTextExtent);
  LocaleLower(magick);
  format=jas_image_strtofmt(magick);
  options=(char *) NULL;
  ResetImageOptionIterator(image_info);
  key=GetNextImageOption(image_info);
  for ( ; key != (char *) NULL; key=GetNextImageOption(image_info))
  {
    option=GetImageOption(image_info,key);
    if (option == (const char *) NULL)
      continue;
    if (LocaleNCompare(key,"jp2:",4) == 0)
      {
        (void) ConcatenateString(&options,key+4);
        if (*option != '\0')
          {
            (void) ConcatenateString(&options,"=");
            (void) ConcatenateString(&options,option);
          }
        (void) ConcatenateString(&options," ");
      }
  }
  option=GetImageOption(image_info,"jp2:rate");
  if ((option == (const char *) NULL) &&
      (image_info->compression != LosslessJPEGCompression) &&
      (image->quality != UndefinedCompressionQuality) &&
      ((double) image->quality <= 99.5) &&
      ((image->rows*image->columns) > 2500))
    {
      char
        option[MaxTextExtent];

      double
        alpha,
        header_size,
        number_pixels,
        rate,
        target_size;

      alpha=115.0-image->quality;
      rate=100.0/(alpha*alpha);
      header_size=550.0;
      header_size+=(number_components-1)*142;
      number_pixels=(double) image->rows*image->columns*number_components*
        (GetImageQuantumDepth(image,MagickTrue)/8);
      target_size=(number_pixels*rate)+header_size;
      rate=target_size/number_pixels;
      (void) FormatLocaleString(option,MaxTextExtent,"rate=%g",rate);
      (void) ConcatenateString(&options,option);
    }
  status=jas_image_encode(jp2_image,jp2_stream,format,options) != 0 ?
    MagickTrue : MagickFalse;
  if (options != (char *) NULL)
    options=DestroyString(options);
  (void) jas_stream_close(jp2_stream);
  for (i=0; i < (ssize_t) number_components; i++)
    jas_matrix_destroy(pixels[i]);
  jas_image_destroy(jp2_image);
  if (status != MagickFalse)
    ThrowWriterException(DelegateError,"UnableToEncodeImageFile");
  return(MagickTrue);
}
Esempio n. 7
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   F r a m e I m a g e                                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  FrameImage() adds a simulated three-dimensional border around the image.
%  The color of the border is defined by the matte_color member of image.
%  Members width and height of frame_info specify the border width of the
%  vertical and horizontal sides of the frame.  Members inner and outer
%  indicate the width of the inner and outer shadows of the frame.
%
%  The format of the FrameImage method is:
%
%      Image *FrameImage(const Image *image,const FrameInfo *frame_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o frame_info: Define the width and height of the frame and its bevels.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *FrameImage(const Image *image,const FrameInfo *frame_info,
  ExceptionInfo *exception)
{
#define FrameImageTag  "Frame/Image"

  CacheView
    *image_view,
    *frame_view;

  Image
    *frame_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  MagickPixelPacket
    accentuate,
    border,
    highlight,
    interior,
    matte,
    shadow,
    trough;

  register ssize_t
    x;

  size_t
    bevel_width,
    height,
    width;

  ssize_t
    y;

  /*
    Check frame geometry.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(frame_info != (FrameInfo *) NULL);
  if ((frame_info->outer_bevel < 0) || (frame_info->inner_bevel < 0))
    ThrowImageException(OptionError,"FrameIsLessThanImageSize");
  bevel_width=(size_t) (frame_info->outer_bevel+frame_info->inner_bevel);
  width=frame_info->width-frame_info->x-bevel_width;
  height=frame_info->height-frame_info->y-bevel_width;
  if ((width < image->columns) || (height < image->rows))
    ThrowImageException(OptionError,"FrameIsLessThanImageSize");
  /*
    Initialize framed image attributes.
  */
  frame_image=CloneImage(image,frame_info->width,frame_info->height,MagickTrue,
    exception);
  if (frame_image == (Image *) NULL)
    return((Image *) NULL);
  if (SetImageStorageClass(frame_image,DirectClass) == MagickFalse)
    {
      InheritException(exception,&frame_image->exception);
      frame_image=DestroyImage(frame_image);
      return((Image *) NULL);
    }
  if ((IsPixelGray(&frame_image->border_color) == MagickFalse) &&
      (IsGrayColorspace(frame_image->colorspace) != MagickFalse))
    (void) SetImageColorspace(frame_image,sRGBColorspace);
  if ((frame_image->border_color.opacity != OpaqueOpacity) &&
      (frame_image->matte == MagickFalse))
    (void) SetImageAlphaChannel(frame_image,OpaqueAlphaChannel);
  frame_image->page=image->page;
  if ((image->page.width != 0) && (image->page.height != 0))
    {
      frame_image->page.width+=frame_image->columns-image->columns;
      frame_image->page.height+=frame_image->rows-image->rows;
    }
  /*
    Initialize 3D effects color.
  */
  GetMagickPixelPacket(frame_image,&interior);
  SetMagickPixelPacket(frame_image,&image->border_color,(IndexPacket *) NULL,
    &interior);
  GetMagickPixelPacket(frame_image,&matte);
  matte.colorspace=sRGBColorspace;
  SetMagickPixelPacket(frame_image,&image->matte_color,(IndexPacket *) NULL,
    &matte);
  GetMagickPixelPacket(frame_image,&border);
  border.colorspace=sRGBColorspace;
  SetMagickPixelPacket(frame_image,&image->border_color,(IndexPacket *) NULL,
    &border);
  GetMagickPixelPacket(frame_image,&accentuate);
  accentuate.red=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.red+(QuantumRange*AccentuateModulate)));
  accentuate.green=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.green+(QuantumRange*AccentuateModulate)));
  accentuate.blue=(MagickRealType) (QuantumScale*((QuantumRange-
    AccentuateModulate)*matte.blue+(QuantumRange*AccentuateModulate)));
  accentuate.opacity=matte.opacity;
  GetMagickPixelPacket(frame_image,&highlight);
  highlight.red=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.red+(QuantumRange*HighlightModulate)));
  highlight.green=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.green+(QuantumRange*HighlightModulate)));
  highlight.blue=(MagickRealType) (QuantumScale*((QuantumRange-
    HighlightModulate)*matte.blue+(QuantumRange*HighlightModulate)));
  highlight.opacity=matte.opacity;
  GetMagickPixelPacket(frame_image,&shadow);
  shadow.red=QuantumScale*matte.red*ShadowModulate;
  shadow.green=QuantumScale*matte.green*ShadowModulate;
  shadow.blue=QuantumScale*matte.blue*ShadowModulate;
  shadow.opacity=matte.opacity;
  GetMagickPixelPacket(frame_image,&trough);
  trough.red=QuantumScale*matte.red*TroughModulate;
  trough.green=QuantumScale*matte.green*TroughModulate;
  trough.blue=QuantumScale*matte.blue*TroughModulate;
  trough.opacity=matte.opacity;
  if (image->colorspace == CMYKColorspace)
    {
      ConvertRGBToCMYK(&interior);
      ConvertRGBToCMYK(&matte);
      ConvertRGBToCMYK(&border);
      ConvertRGBToCMYK(&accentuate);
      ConvertRGBToCMYK(&highlight);
      ConvertRGBToCMYK(&shadow);
      ConvertRGBToCMYK(&trough);
    }
  status=MagickTrue;
  progress=0;
  image_view=AcquireVirtualCacheView(image,exception);
  frame_view=AcquireAuthenticCacheView(frame_image,exception);
  height=(size_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
    frame_info->inner_bevel);
  if (height != 0)
    {
      register IndexPacket
        *restrict frame_indexes;

      register ssize_t
        x;

      register PixelPacket
        *restrict q;

      /*
        Draw top of ornamental border.
      */
      q=QueueCacheViewAuthenticPixels(frame_view,0,0,frame_image->columns,
        height,exception);
      frame_indexes=GetCacheViewAuthenticIndexQueue(frame_view);
      if (q != (PixelPacket *) NULL)
        {
          /*
            Draw top of ornamental border.
          */
          for (y=0; y < (ssize_t) frame_info->outer_bevel; y++)
          {
            for (x=0; x < (ssize_t) (frame_image->columns-y); x++)
            {
              if (x < y)
                SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              else
                SetPixelPacket(frame_image,&accentuate,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for ( ; x < (ssize_t) frame_image->columns; x++)
            {
              SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              q++;
              frame_indexes++;
            }
          }
          for (y=0; y < (ssize_t) (frame_info->y-bevel_width); y++)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            width=frame_image->columns-2*frame_info->outer_bevel;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelPacket(frame_image,&matte,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              q++;
              frame_indexes++;
            }
          }
          for (y=0; y < (ssize_t) frame_info->inner_bevel; y++)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
            {
              SetPixelPacket(frame_image,&matte,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            width=image->columns+((size_t) frame_info->inner_bevel << 1)-
              y;
            for (x=0; x < (ssize_t) width; x++)
            {
              if (x < y)
                SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              else
                SetPixelPacket(frame_image,&trough,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
            {
              SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            width=frame_info->width-frame_info->x-image->columns-bevel_width;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelPacket(frame_image,&matte,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              q++;
              frame_indexes++;
            }
          }
          (void) SyncCacheViewAuthenticPixels(frame_view,exception);
        }
    }
  /*
    Draw sides of ornamental border.
  */
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status) \
    magick_threads(image,frame_image,1,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register IndexPacket
      *restrict frame_indexes;

    register ssize_t
      x;

    register PixelPacket
      *restrict q;

    /*
      Initialize scanline with matte color.
    */
    if (status == MagickFalse)
      continue;
    q=QueueCacheViewAuthenticPixels(frame_view,0,frame_info->y+y,
      frame_image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    frame_indexes=GetCacheViewAuthenticIndexQueue(frame_view);
    for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
    {
      SetPixelPacket(frame_image,&highlight,q,frame_indexes);
      q++;
      frame_indexes++;
    }
    for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
    {
      SetPixelPacket(frame_image,&matte,q,frame_indexes);
      q++;
      frame_indexes++;
    }
    for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
    {
      SetPixelPacket(frame_image,&shadow,q,frame_indexes);
      q++;
      frame_indexes++;
    }
    /*
      Set frame interior to interior color.
    */
    if ((image->compose != CopyCompositeOp) &&
        ((image->compose != OverCompositeOp) || (image->matte != MagickFalse)))
      for (x=0; x < (ssize_t) image->columns; x++)
      {
        SetPixelPacket(frame_image,&interior,q,frame_indexes);
        q++;
        frame_indexes++;
      }
    else
      {
        register const IndexPacket
          *indexes;

        register const PixelPacket
          *p;

        p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
        if (p == (const PixelPacket *) NULL)
          {
            status=MagickFalse;
            continue;
          }
        indexes=GetCacheViewVirtualIndexQueue(image_view);
        (void) CopyMagickMemory(q,p,image->columns*sizeof(*p));
        if ((image->colorspace == CMYKColorspace) &&
            (frame_image->colorspace == CMYKColorspace))
          {
            (void) CopyMagickMemory(frame_indexes,indexes,image->columns*
              sizeof(*indexes));
            frame_indexes+=image->columns;
          }
        q+=image->columns;
      }
    for (x=0; x < (ssize_t) frame_info->inner_bevel; x++)
    {
      SetPixelPacket(frame_image,&highlight,q,frame_indexes);
      q++;
      frame_indexes++;
    }
    width=frame_info->width-frame_info->x-image->columns-bevel_width;
    for (x=0; x < (ssize_t) width; x++)
    {
      SetPixelPacket(frame_image,&matte,q,frame_indexes);
      q++;
      frame_indexes++;
    }
    for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
    {
      SetPixelPacket(frame_image,&shadow,q,frame_indexes);
      q++;
      frame_indexes++;
    }
    if (SyncCacheViewAuthenticPixels(frame_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp critical (MagickCore_FrameImage)
#endif
        proceed=SetImageProgress(image,FrameImageTag,progress++,image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  height=(size_t) (frame_info->inner_bevel+frame_info->height-
    frame_info->y-image->rows-bevel_width+frame_info->outer_bevel);
  if (height != 0)
    {
      register IndexPacket
        *restrict frame_indexes;

      register ssize_t
        x;

      register PixelPacket
        *restrict q;

      /*
        Draw bottom of ornamental border.
      */
      q=QueueCacheViewAuthenticPixels(frame_view,0,(ssize_t) (frame_image->rows-
        height),frame_image->columns,height,exception);
      if (q != (PixelPacket *) NULL)
        {
          /*
            Draw bottom of ornamental border.
          */
          frame_indexes=GetCacheViewAuthenticIndexQueue(frame_view);
          for (y=frame_info->inner_bevel-1; y >= 0; y--)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < (ssize_t) (frame_info->x-bevel_width); x++)
            {
              SetPixelPacket(frame_image,&matte,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < y; x++)
            {
              SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for ( ; x < (ssize_t) (image->columns+2*frame_info->inner_bevel); x++)
            {
              if (x >= (ssize_t) (image->columns+2*frame_info->inner_bevel-y))
                SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              else
                SetPixelPacket(frame_image,&accentuate,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            width=frame_info->width-frame_info->x-image->columns-bevel_width;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelPacket(frame_image,&matte,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              q++;
              frame_indexes++;
            }
          }
          height=frame_info->height-frame_info->y-image->rows-bevel_width;
          for (y=0; y < (ssize_t) height; y++)
          {
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            width=frame_image->columns-2*frame_info->outer_bevel;
            for (x=0; x < (ssize_t) width; x++)
            {
              SetPixelPacket(frame_image,&matte,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for (x=0; x < (ssize_t) frame_info->outer_bevel; x++)
            {
              SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              q++;
              frame_indexes++;
            }
          }
          for (y=frame_info->outer_bevel-1; y >= 0; y--)
          {
            for (x=0; x < y; x++)
            {
              SetPixelPacket(frame_image,&highlight,q,frame_indexes);
              q++;
              frame_indexes++;
            }
            for ( ; x < (ssize_t) frame_image->columns; x++)
            {
              if (x >= (ssize_t) (frame_image->columns-y))
                SetPixelPacket(frame_image,&shadow,q,frame_indexes);
              else
                SetPixelPacket(frame_image,&trough,q,frame_indexes);
              q++;
              frame_indexes++;
            }
          }
          (void) SyncCacheViewAuthenticPixels(frame_view,exception);
        }
    }
  frame_view=DestroyCacheView(frame_view);
  image_view=DestroyCacheView(image_view);
  if ((image->compose != CopyCompositeOp) &&
      ((image->compose != OverCompositeOp) || (image->matte != MagickFalse)))
    {
      x=(ssize_t) (frame_info->outer_bevel+(frame_info->x-bevel_width)+
        frame_info->inner_bevel);
      y=(ssize_t) (frame_info->outer_bevel+(frame_info->y-bevel_width)+
        frame_info->inner_bevel);
      (void) CompositeImage(frame_image,image->compose,image,x,y);
    }
  if (status == MagickFalse)
    frame_image=DestroyImage(frame_image);
  return(frame_image);
}
Esempio n. 8
0
MagickExport MagickBooleanType OpaquePaintImageChannel(Image *image,
  const ChannelType channel,const MagickPixelPacket *target,
  const MagickPixelPacket *fill,const MagickBooleanType invert)
{
#define OpaquePaintImageTag  "Opaque/Image"

  CacheView
    *image_view;

  ExceptionInfo
    *exception;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  MagickPixelPacket
    zero;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  assert(target != (MagickPixelPacket *) NULL);
  assert(fill != (MagickPixelPacket *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
    return(MagickFalse);
  if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
      (IsMagickGray(fill) != MagickFalse))
    (void) TransformImageColorspace(image,sRGBColorspace);
  if ((fill->opacity != OpaqueOpacity) && (image->matte == MagickFalse))
    (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
  /*
    Make image color opaque.
  */
  status=MagickTrue;
  progress=0;
  exception=(&image->exception);
  GetMagickPixelPacket(image,&zero);
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(progress,status) \
    IsConcurrentDos(image->columns,image->rows,64)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    MagickPixelPacket
      pixel;

    register IndexPacket
      *restrict indexes;

    register ssize_t
      x;

    register PixelPacket
      *restrict q;

    if (status == MagickFalse)
      continue;
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    pixel=zero;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      SetMagickPixelPacket(image,q,indexes+x,&pixel);
      if (IsMagickColorSimilar(&pixel,target) != invert)
        {
          if ((channel & RedChannel) != 0)
            SetPixelRed(q,ClampToQuantum(fill->red));
          if ((channel & GreenChannel) != 0)
            SetPixelGreen(q,ClampToQuantum(fill->green));
          if ((channel & BlueChannel) != 0)
            SetPixelBlue(q,ClampToQuantum(fill->blue));
          if ((channel & OpacityChannel) != 0)
            SetPixelOpacity(q,ClampToQuantum(fill->opacity));
          if (((channel & IndexChannel) != 0) &&
              (image->colorspace == CMYKColorspace))
            SetPixelIndex(indexes+x,ClampToQuantum(fill->index));
        }
      q++;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp critical (MagickCore_OpaquePaintImageChannel)
#endif
        proceed=SetImageProgress(image,OpaquePaintImageTag,progress++,
          image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  image_view=DestroyCacheView(image_view);
  return(status);
}
Esempio n. 9
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   F l o o d f i l l P a i n t I m a g e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  FloodfillPaintImage() changes the color value of any pixel that matches
%  target and is an immediate neighbor.  If the method FillToBorderMethod is
%  specified, the color value is changed for any neighbor pixel that does not
%  match the bordercolor member of image.
%
%  By default target must match a particular pixel color exactly.
%  However, in many cases two colors may differ by a small amount.  The
%  fuzz member of image defines how much tolerance is acceptable to
%  consider two colors as the same.  For example, set fuzz to 10 and the
%  color red at intensities of 100 and 102 respectively are now
%  interpreted as the same color for the purposes of the floodfill.
%
%  The format of the FloodfillPaintImage method is:
%
%      MagickBooleanType FloodfillPaintImage(Image *image,
%        const ChannelType channel,const DrawInfo *draw_info,
%        const MagickPixelPacket target,const ssize_t x_offset,
%        const ssize_t y_offset,const MagickBooleanType invert)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o channel: the channel(s).
%
%    o draw_info: the draw info.
%
%    o target: the RGB value of the target color.
%
%    o x_offset,y_offset: the starting location of the operation.
%
%    o invert: paint any pixel that does not match the target color.
%
*/
MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
  const ChannelType channel,const DrawInfo *draw_info,
  const MagickPixelPacket *target,const ssize_t x_offset,const ssize_t y_offset,
  const MagickBooleanType invert)
{
#define MaxStacksize  (1UL << 15)
#define PushSegmentStack(up,left,right,delta) \
{ \
  if (s >= (segment_stack+MaxStacksize)) \
    ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \
  else \
    { \
      if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \
        { \
          s->x1=(double) (left); \
          s->y1=(double) (up); \
          s->x2=(double) (right); \
          s->y2=(double) (delta); \
          s++; \
        } \
    } \
}

  CacheView
    *floodplane_view,
    *image_view;

  ExceptionInfo
    *exception;

  Image
    *floodplane_image;

  MagickBooleanType
    skip;

  MagickPixelPacket
    fill,
    pixel;

  PixelPacket
    fill_color;

  register SegmentInfo
    *s;

  SegmentInfo
    *segment_stack;

  ssize_t
    offset,
    start,
    x,
    x1,
    x2,
    y;

  /*
    Check boundary conditions.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(draw_info != (DrawInfo *) NULL);
  assert(draw_info->signature == MagickSignature);
  if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
    return(MagickFalse);
  if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
    return(MagickFalse);
  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
    return(MagickFalse);
  if (IsGrayColorspace(image->colorspace) != MagickFalse)
    (void) TransformImageColorspace(image,sRGBColorspace);
  if ((image->matte == MagickFalse) &&
      (draw_info->fill.opacity != OpaqueOpacity))
    (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
  /*
    Set floodfill state.
  */
  floodplane_image=CloneImage(image,0,0,MagickTrue,&image->exception);
  if (floodplane_image == (Image *) NULL)
    return(MagickFalse);
  (void) SetImageAlphaChannel(floodplane_image,OpaqueAlphaChannel);
  segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize,
    sizeof(*segment_stack));
  if (segment_stack == (SegmentInfo *) NULL)
    {
      floodplane_image=DestroyImage(floodplane_image);
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
        image->filename);
    }
  /*
    Push initial segment on stack.
  */
  exception=(&image->exception);
  x=x_offset;
  y=y_offset;
  start=0;
  s=segment_stack;
  PushSegmentStack(y,x,x,1);
  PushSegmentStack(y+1,x,x,-1);
  GetMagickPixelPacket(image,&fill);
  GetMagickPixelPacket(image,&pixel);
  image_view=AcquireVirtualCacheView(image,exception);
  floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
  while (s > segment_stack)
  {
    register const IndexPacket
      *restrict indexes;

    register const PixelPacket
      *restrict p;

    register ssize_t
      x;

    register PixelPacket
      *restrict q;

    /*
      Pop segment off stack.
    */
    s--;
    x1=(ssize_t) s->x1;
    x2=(ssize_t) s->x2;
    offset=(ssize_t) s->y2;
    y=(ssize_t) s->y1+offset;
    /*
      Recolor neighboring pixels.
    */
    p=GetCacheViewVirtualPixels(image_view,0,y,(size_t) (x1+1),1,exception);
    q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(size_t) (x1+1),1,
      exception);
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
      break;
    indexes=GetCacheViewVirtualIndexQueue(image_view);
    p+=x1;
    q+=x1;
    for (x=x1; x >= 0; x--)
    {
      if (q->opacity == (Quantum) TransparentOpacity)
        break;
      SetMagickPixelPacket(image,p,indexes+x,&pixel);
      if (IsMagickColorSimilar(&pixel,target) == invert)
        break;
      q->opacity=(Quantum) TransparentOpacity;
      p--;
      q--;
    }
    if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
      break;
    skip=x >= x1 ? MagickTrue : MagickFalse;
    if (skip == MagickFalse)
      {
        start=x+1;
        if (start < x1)
          PushSegmentStack(y,start,x1-1,-offset);
        x=x1+1;
      }
    do
    {
      if (skip == MagickFalse)
        {
          if (x < (ssize_t) image->columns)
            {
              p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1,
                exception);
              q=GetCacheViewAuthenticPixels(floodplane_view,x,y,
                image->columns-x,1,exception);
              if ((p == (const PixelPacket *) NULL) ||
                  (q == (PixelPacket *) NULL))
                break;
              indexes=GetCacheViewVirtualIndexQueue(image_view);
              for ( ; x < (ssize_t) image->columns; x++)
              {
                if (q->opacity == (Quantum) TransparentOpacity)
                  break;
                SetMagickPixelPacket(image,p,indexes+x,&pixel);
                if (IsMagickColorSimilar(&pixel,target) == invert)
                  break;
                q->opacity=(Quantum) TransparentOpacity;
                p++;
                q++;
              }
              if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
                break;
            }
          PushSegmentStack(y,start,x-1,offset);
          if (x > (x2+1))
            PushSegmentStack(y,x2+1,x-1,-offset);
        }
      skip=MagickFalse;
      x++;
      if (x <= x2)
        {
          p=GetCacheViewVirtualPixels(image_view,x,y,(size_t) (x2-x+1),1,
            exception);
          q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(size_t) (x2-x+1),1,
            exception);
          if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
            break;
          indexes=GetCacheViewVirtualIndexQueue(image_view);
          for ( ; x <= x2; x++)
          {
            if (q->opacity == (Quantum) TransparentOpacity)
              break;
            SetMagickPixelPacket(image,p,indexes+x,&pixel);
            if (IsMagickColorSimilar(&pixel,target) != invert)
              break;
            p++;
            q++;
          }
        }
      start=x;
    } while (x <= x2);
  }
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register const PixelPacket
      *restrict p;

    register IndexPacket
      *restrict indexes;

    register ssize_t
      x;

    register PixelPacket
      *restrict q;

    /*
      Tile fill color onto floodplane.
    */
    p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,
      exception);
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
      break;
    indexes=GetCacheViewAuthenticIndexQueue(image_view);
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if (GetPixelOpacity(p) != OpaqueOpacity)
        {
          (void) GetFillColor(draw_info,x,y,&fill_color);
          SetMagickPixelPacket(image,&fill_color,(IndexPacket *) NULL,&fill);
          if (image->colorspace == CMYKColorspace)
            ConvertRGBToCMYK(&fill);
          if ((channel & RedChannel) != 0)
            SetPixelRed(q,ClampToQuantum(fill.red));
          if ((channel & GreenChannel) != 0)
            SetPixelGreen(q,ClampToQuantum(fill.green));
          if ((channel & BlueChannel) != 0)
            SetPixelBlue(q,ClampToQuantum(fill.blue));
          if ((channel & OpacityChannel) != 0)
            SetPixelOpacity(q,ClampToQuantum(fill.opacity));
          if (((channel & IndexChannel) != 0) &&
              (image->colorspace == CMYKColorspace))
            SetPixelIndex(indexes+x,ClampToQuantum(fill.index));
        }
      p++;
      q++;
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      break;
  }
  floodplane_view=DestroyCacheView(floodplane_view);
  image_view=DestroyCacheView(image_view);
  segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack);
  floodplane_image=DestroyImage(floodplane_image);
  return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
}
Esempio n. 10
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   F l o o d f i l l P a i n t I m a g e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  FloodfillPaintImage() changes the color value of any pixel that matches
%  target and is an immediate neighbor.  If the method FillToBorderMethod is
%  specified, the color value is changed for any neighbor pixel that does not
%  match the bordercolor member of image.
%
%  By default target must match a particular pixel color exactly.  However,
%  in many cases two colors may differ by a small amount.  The fuzz member of
%  image defines how much tolerance is acceptable to consider two colors as
%  the same.  For example, set fuzz to 10 and the color red at intensities of
%  100 and 102 respectively are now interpreted as the same color for the
%  purposes of the floodfill.
%
%  The format of the FloodfillPaintImage method is:
%
%      MagickBooleanType FloodfillPaintImage(Image *image,
%        const DrawInfo *draw_info,const PixelInfo target,
%        const ssize_t x_offset,const ssize_t y_offset,
%        const MagickBooleanType invert,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o draw_info: the draw info.
%
%    o target: the RGB value of the target color.
%
%    o x_offset,y_offset: the starting location of the operation.
%
%    o invert: paint any pixel that does not match the target color.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
  const DrawInfo *draw_info,const PixelInfo *target,const ssize_t x_offset,
  const ssize_t y_offset,const MagickBooleanType invert,
  ExceptionInfo *exception)
{
#define MaxStacksize  262144UL
#define PushSegmentStack(up,left,right,delta) \
{ \
  if (s >= (segment_stack+MaxStacksize)) \
    ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \
  else \
    { \
      if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \
        { \
          s->x1=(double) (left); \
          s->y1=(double) (up); \
          s->x2=(double) (right); \
          s->y2=(double) (delta); \
          s++; \
        } \
    } \
}

  CacheView
    *floodplane_view,
    *image_view;

  Image
    *floodplane_image;

  MagickBooleanType
    skip,
    status;

  MemoryInfo
    *segment_info;

  PixelInfo
    fill_color,
    pixel;

  register SegmentInfo
    *s;

  SegmentInfo
    *segment_stack;

  ssize_t
    offset,
    start,
    x,
    x1,
    x2,
    y;

  /*
    Check boundary conditions.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(draw_info != (DrawInfo *) NULL);
  assert(draw_info->signature == MagickCoreSignature);
  if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
    return(MagickFalse);
  if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
    return(MagickFalse);
  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
    return(MagickFalse);
  if (IsGrayColorspace(image->colorspace) != MagickFalse)
    (void) SetImageColorspace(image,sRGBColorspace,exception);
  if ((image->alpha_trait == UndefinedPixelTrait) &&
      (draw_info->fill.alpha_trait != UndefinedPixelTrait))
    (void) SetImageAlpha(image,OpaqueAlpha,exception);
  /*
    Set floodfill state.
  */
  floodplane_image=CloneImage(image,image->columns,image->rows,MagickTrue,
    exception);
  if (floodplane_image == (Image *) NULL)
    return(MagickFalse);
  floodplane_image->alpha_trait=UndefinedPixelTrait;
  floodplane_image->colorspace=GRAYColorspace;
  (void) QueryColorCompliance("#000",AllCompliance,
    &floodplane_image->background_color,exception);
  (void) SetImageBackgroundColor(floodplane_image,exception);
  segment_info=AcquireVirtualMemory(MaxStacksize,sizeof(*segment_stack));
  if (segment_info == (MemoryInfo *) NULL)
    {
      floodplane_image=DestroyImage(floodplane_image);
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
        image->filename);
    }
  segment_stack=(SegmentInfo *) GetVirtualMemoryBlob(segment_info);
  /*
    Push initial segment on stack.
  */
  status=MagickTrue;
  x=x_offset;
  y=y_offset;
  start=0;
  s=segment_stack;
  PushSegmentStack(y,x,x,1);
  PushSegmentStack(y+1,x,x,-1);
  GetPixelInfo(image,&pixel);
  image_view=AcquireVirtualCacheView(image,exception);
  floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
  while (s > segment_stack)
  {
    register const Quantum
      *restrict p;

    register Quantum
      *restrict q;

    register ssize_t
      x;

    /*
      Pop segment off stack.
    */
    s--;
    x1=(ssize_t) s->x1;
    x2=(ssize_t) s->x2;
    offset=(ssize_t) s->y2;
    y=(ssize_t) s->y1+offset;
    /*
      Recolor neighboring pixels.
    */
    p=GetCacheViewVirtualPixels(image_view,0,y,(size_t) (x1+1),1,exception);
    q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(size_t) (x1+1),1,
      exception);
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
      break;
    p+=x1*GetPixelChannels(image);
    q+=x1*GetPixelChannels(floodplane_image);
    for (x=x1; x >= 0; x--)
    {
      if (GetPixelGray(floodplane_image,q) != 0)
        break;
      GetPixelInfoPixel(image,p,&pixel);
      if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert)
        break;
      SetPixelGray(floodplane_image,QuantumRange,q);
      p-=GetPixelChannels(image);
      q-=GetPixelChannels(floodplane_image);
    }
    if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
      break;
    skip=x >= x1 ? MagickTrue : MagickFalse;
    if (skip == MagickFalse)
      {
        start=x+1;
        if (start < x1)
          PushSegmentStack(y,start,x1-1,-offset);
        x=x1+1;
      }
    do
    {
      if (skip == MagickFalse)
        {
          if (x < (ssize_t) image->columns)
            {
              p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1,
                exception);
              q=GetCacheViewAuthenticPixels(floodplane_view,x,y,image->columns-
                x,1,exception);
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
                break;
              for ( ; x < (ssize_t) image->columns; x++)
              {
                if (GetPixelGray(floodplane_image,q) != 0)
                  break;
                GetPixelInfoPixel(image,p,&pixel);
                if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert)
                  break;
                SetPixelGray(floodplane_image,QuantumRange,q);
                p+=GetPixelChannels(image);
                q+=GetPixelChannels(floodplane_image);
              }
              status=SyncCacheViewAuthenticPixels(floodplane_view,exception);
              if (status == MagickFalse)
                break;
            }
          PushSegmentStack(y,start,x-1,offset);
          if (x > (x2+1))
            PushSegmentStack(y,x2+1,x-1,-offset);
        }
      skip=MagickFalse;
      x++;
      if (x <= x2)
        {
          p=GetCacheViewVirtualPixels(image_view,x,y,(size_t) (x2-x+1),1,
            exception);
          q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(size_t) (x2-x+1),1,
            exception);
          if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
            break;
          for ( ; x <= x2; x++)
          {
            if (GetPixelGray(floodplane_image,q) != 0)
              break;
            GetPixelInfoPixel(image,p,&pixel);
            if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert)
              break;
            p+=GetPixelChannels(image);
            q+=GetPixelChannels(floodplane_image);
          }
        }
      start=x;
    } while (x <= x2);
  }
  status=MagickTrue;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(status) \
    magick_threads(floodplane_image,image,floodplane_image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register const Quantum
      *restrict p;

    register Quantum
      *restrict q;

    register ssize_t
      x;

    /*
      Tile fill color onto floodplane.
    */
    if (status == MagickFalse)
      continue;
    p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,exception);
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if (GetPixelGray(floodplane_image,p) != 0)
        {
          (void) GetFillColor(draw_info,x,y,&fill_color,exception);
          SetPixelViaPixelInfo(image,&fill_color,q);
        }
      p+=GetPixelChannels(floodplane_image);
      q+=GetPixelChannels(image);
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
  }
  floodplane_view=DestroyCacheView(floodplane_view);
  image_view=DestroyCacheView(image_view);
  segment_info=RelinquishVirtualMemory(segment_info);
  floodplane_image=DestroyImage(floodplane_image);
  return(status);
}
Esempio n. 11
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%     O p a q u e P a i n t I m a g e                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  OpaquePaintImage() changes any pixel that matches color with the color
%  defined by fill.
%
%  By default color must match a particular pixel color exactly.  However, in
%  many cases two colors may differ by a small amount.  Fuzz defines how much
%  tolerance is acceptable to consider two colors as the same.  For example,
%  set fuzz to 10 and the color red at intensities of 100 and 102 respectively
%  are now interpreted as the same color.
%
%  The format of the OpaquePaintImage method is:
%
%      MagickBooleanType OpaquePaintImage(Image *image,
%        const PixelInfo *target,const PixelInfo *fill,
%        const MagickBooleanType invert,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: the image.
%
%    o target: the RGB value of the target color.
%
%    o fill: the replacement color.
%
%    o invert: paint any pixel that does not match the target color.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType OpaquePaintImage(Image *image,
  const PixelInfo *target,const PixelInfo *fill,const MagickBooleanType invert,
  ExceptionInfo *exception)
{
#define OpaquePaintImageTag  "Opaque/Image"

  CacheView
    *image_view;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  PixelInfo
    zero;

  ssize_t
    y;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  assert(target != (PixelInfo *) NULL);
  assert(fill != (PixelInfo *) NULL);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
    return(MagickFalse);
  if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
      (IsPixelInfoGray(fill) == MagickFalse))
    (void) SetImageColorspace(image,sRGBColorspace,exception);
  if ((fill->alpha_trait == BlendPixelTrait) &&
      (image->alpha_trait != BlendPixelTrait))
    (void) SetImageAlpha(image,OpaqueAlpha,exception);
  /*
    Make image color opaque.
  */
  status=MagickTrue;
  progress=0;
  GetPixelInfo(image,&zero);
  image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static,4) shared(progress,status) \
    magick_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    PixelInfo
      pixel;

    register Quantum
      *restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    if (q == (Quantum *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    pixel=zero;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      GetPixelInfoPixel(image,q,&pixel);
      if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert)
        SetPixelInfoPixel(image,fill,q);
      q+=GetPixelChannels(image);
    }
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp critical (MagickCore_OpaquePaintImage)
#endif
        proceed=SetImageProgress(image,OpaquePaintImageTag,progress++,
          image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  image_view=DestroyCacheView(image_view);
  return(status);
}
Esempio n. 12
0
File: describe.c Progetto: pedia/cwf
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   D e s c r i b e I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  DescribeImage() describes an image by printing its attributes to the file.
%  Attributes include the image width, height, size, and others.
%
%  The format of the DescribeImage method is:
%
%      void DescribeImage(Image *image,FILE *file,const MagickBool verbose)
%
%  A description of each parameter follows:
%
%    o image: The image.
%
%    o file: The file, typically stdout.
%
%    o verbose: A value other than zero prints more detailed information
%      about the image. Values greater than one enable counting the number of
%      colors in the image.
%
%
*/
MagickExport MagickPassFail DescribeImage(Image *image,FILE *file,
        const MagickBool verbose)
{
    char
    color[MaxTextExtent],
          format[MaxTextExtent];

    const unsigned char
    *profile;

    size_t
    profile_length;

    const ImageAttribute
    *attribute;

    const MagickInfo
    *magick_info;

    double
    elapsed_time,
    user_time;

    unsigned long
    columns,
    rows;

    magick_int64_t
    pixels_per_second;

    Image
    *p;

    long
    y;

    register long
    i,
    x;

    unsigned long
    count;

    assert(image != (Image *) NULL);
    assert(image->signature == MagickSignature);
    assert(file != (FILE *) NULL);
    elapsed_time=GetElapsedTime(&image->timer);
    user_time=GetUserTime(&image->timer);
    GetTimerInfo(&image->timer);
    if (!verbose)
    {
        /*
          Display summary info about the image.
        */
        if (*image->magick_filename != '\0')
            if (LocaleCompare(image->magick_filename,image->filename) != 0)
                (void) fprintf(file,"%.1024s=>",image->magick_filename);
        if ((image->previous == (Image *) NULL) &&
                (image->next == (Image *) NULL) && (image->scene == 0))
            (void) fprintf(file,"%.1024s ",image->filename);
        else
            (void) fprintf(file,"%.1024s[%lu] ",image->filename,image->scene);
        (void) fprintf(file,"%.1024s ",image->magick);
        columns=image->columns;
        rows=image->rows;
        if ((image->magick_columns != 0) || (image->magick_rows != 0))
            if ((image->magick_columns != image->columns) ||
                    (image->magick_rows != image->rows))
            {
                columns=image->magick_columns;
                rows=image->magick_rows;
                (void) fprintf(file,"%lux%lu=>",image->magick_columns,
                               image->magick_rows);
            }
        (void) fprintf(file,"%lux%lu%+ld%+ld ",image->columns,image->rows,
                       image->page.x,image->page.y);
        if (image->storage_class == DirectClass)
        {
            (void) fprintf(file,"DirectClass ");
            if (image->total_colors != 0)
            {
                FormatSize(image->total_colors,format);
                (void) fprintf(file,"%.1024s ",format);
            }
        }
        else if (image->total_colors <= image->colors)
            (void) fprintf(file,"PseudoClass %uc ",image->colors);
        else
        {
            (void) fprintf(file,"PseudoClass %lu=>%uc ",image->total_colors,
                           image->colors);
            (void) fprintf(file,"%ld/%.6f/%.6fe ",
                           (long) image->error.mean_error_per_pixel,
                           image->error.normalized_mean_error,
                           image->error.normalized_maximum_error);
        }
        (void) fprintf(file,"%u-bit ",image->depth);
        if (GetBlobSize(image) != 0)
        {
            FormatSize(GetBlobSize(image),format);
            (void) fprintf(file,"%.1024s ",format);
        }
        (void) fprintf(file,"%0.3fu %ld:%02ld",user_time,
                       (long) (elapsed_time/60.0),
                       (long) ceil(fmod(elapsed_time,60.0)));
        /*
          Only display pixel read rate if the time accumulated is at
          least six times the timer's resolution (typically 0.01 on
          Unix).
        */
        if (elapsed_time >= GetTimerResolution()*6)
        {
            pixels_per_second=(magick_int64_t) ((double) rows*columns/ elapsed_time);
            FormatSize(pixels_per_second,format);
            (void) fprintf(file," (%s pixels/s)",format);
        }
        (void) fprintf(file,"\n");

        return (ferror(file) ? MagickFail : MagickPass);
    }
    /*
      Display verbose info about the image.
    */
    (void) SignatureImage(image);
    if (verbose > 1)
        image->total_colors=GetNumberColors(image,(FILE *) NULL,&image->exception);
    (void) fprintf(file,"Image: %.1024s\n",image->filename);
    magick_info=GetMagickInfo(image->magick,&image->exception);
    if ((magick_info == (const MagickInfo *) NULL) ||
            (*magick_info->description == '\0'))
        (void) fprintf(file,"  Format: %.1024s\n",image->magick);
    else
        (void) fprintf(file,"  Format: %.1024s (%.1024s)\n",image->magick,
                       magick_info->description);
    (void) fprintf(file,"  Geometry: %lux%lu\n",image->columns,image->rows);
    if (image->storage_class == DirectClass)
        (void) fprintf(file,"  Class: DirectClass\n");
    else
        (void) fprintf(file,"  Class: PseudoClass\n");
    if ((image->magick_columns != 0) || (image->magick_rows != 0))
        if ((image->magick_columns != image->columns) ||
                (image->magick_rows != image->rows))
            (void) fprintf(file,"  Base geometry: %lux%lu\n",image->magick_columns,
                           image->magick_rows);
    (void) fprintf(file,"  Type: ");
    switch (GetImageType(image,&image->exception))
    {
    case BilevelType:
        (void) fprintf(file,"bilevel");
        break;
    case GrayscaleType:
        (void) fprintf(file,"grayscale");
        break;
    case GrayscaleMatteType:
        (void) fprintf(file,"grayscale with transparency");
        break;
    case PaletteType:
        (void) fprintf(file,"palette");
        break;
    case PaletteMatteType:
        (void) fprintf(file,"palette with transparency");
        break;
    case TrueColorType:
        (void) fprintf(file,"true color");
        break;
    case TrueColorMatteType:
        (void) fprintf(file,"true color with transparency");
        break;
    case ColorSeparationType:
        (void) fprintf(file,"color separated");
        break;
    case ColorSeparationMatteType:
        (void) fprintf(file,"color separated with transparency");
        break;
    default:
        (void) fprintf(file,"undefined");
        break;
    }
    (void) fprintf(file,"\n");
    (void) fprintf(file,"  Depth: %lu bits-per-pixel component\n",
                   GetImageDepth(image,&image->exception));
    (void) fprintf(file,"  Channel Depths:\n");
    if (image->colorspace == CMYKColorspace)
    {
        (void) fprintf(file,"    Cyan:     %u bits\n",
                       GetImageChannelDepth(image,CyanChannel,&image->exception));
        (void) fprintf(file,"    Magenta:  %u bits\n",
                       GetImageChannelDepth(image,MagentaChannel,&image->exception));
        (void) fprintf(file,"    Yellow:   %u bits\n",
                       GetImageChannelDepth(image,YellowChannel,&image->exception));
        (void) fprintf(file,"    Black:    %u bits\n",
                       GetImageChannelDepth(image,BlackChannel,&image->exception));
    }
    else if ((IsGrayColorspace(image->colorspace)) ||
             (image->is_grayscale == True))
    {
        (void) fprintf(file,"    Gray:     %u bits\n",
                       GetImageChannelDepth(image,RedChannel,&image->exception));
    }
    else
    {
        (void) fprintf(file,"    Red:      %u bits\n",
                       GetImageChannelDepth(image,RedChannel,&image->exception));
        (void) fprintf(file,"    Green:    %u bits\n",
                       GetImageChannelDepth(image,GreenChannel,&image->exception));
        (void) fprintf(file,"    Blue:     %u bits\n",
                       GetImageChannelDepth(image,BlueChannel,&image->exception));
    }
    if (image->matte)
        (void) fprintf(file,"    Opacity:  %u bits\n",
                       GetImageChannelDepth(image,OpacityChannel,&image->exception));
    (void) fprintf(file,"  Channel Statistics:\n");
    {
        ImageStatistics
        statistics;

        (void) GetImageStatistics(image,&statistics,&image->exception);

        if (image->colorspace == CMYKColorspace)
        {
            (void) fprintf(file,"    Cyan:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.minimum,
                           statistics.red.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.maximum,
                           statistics.red.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.mean,
                           statistics.red.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.standard_deviation,
                           statistics.red.standard_deviation);
            (void) fprintf(file,"    Magenta:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.minimum,
                           statistics.green.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.maximum,
                           statistics.green.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.mean,
                           statistics.green.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.standard_deviation,
                           statistics.green.standard_deviation);
            (void) fprintf(file,"    Yellow:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.minimum,
                           statistics.blue.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.maximum,
                           statistics.blue.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.mean,
                           statistics.blue.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.standard_deviation,
                           statistics.blue.standard_deviation);
            (void) fprintf(file,"    Black:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.minimum,
                           statistics.opacity.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.maximum,
                           statistics.opacity.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.mean,
                           statistics.opacity.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.standard_deviation,
                           statistics.opacity.standard_deviation);
            /*
            if (image->matte)
              (void) fprintf(file,"    Opacity:\n");
            */
        }
        else if ((IsGrayColorspace(image->colorspace)) ||
                 (image->is_grayscale == True))
        {
            (void) fprintf(file,"    Gray:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.minimum,
                           statistics.red.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.maximum,
                           statistics.red.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.mean,
                           statistics.red.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.standard_deviation,
                           statistics.red.standard_deviation);
            if (image->matte)
            {
                (void) fprintf(file,"    Opacity:\n");
                (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.minimum,
                               statistics.opacity.minimum);
                (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.maximum,
                               statistics.opacity.maximum);
                (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.mean,
                               statistics.opacity.mean);
                (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.standard_deviation,
                               statistics.opacity.standard_deviation);
            }
        }
        else
        {
            (void) fprintf(file,"    Red:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.minimum,
                           statistics.red.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.maximum,
                           statistics.red.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.mean,
                           statistics.red.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.standard_deviation,
                           statistics.red.standard_deviation);
            (void) fprintf(file,"    Green:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.minimum,
                           statistics.green.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.maximum,
                           statistics.green.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.mean,
                           statistics.green.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.standard_deviation,
                           statistics.green.standard_deviation);
            (void) fprintf(file,"    Blue:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.minimum,
                           statistics.blue.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.maximum,
                           statistics.blue.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.mean,
                           statistics.blue.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.standard_deviation,
                           statistics.blue.standard_deviation);
            if (image->matte)
            {
                (void) fprintf(file,"    Opacity:\n");
                (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.minimum,
                               statistics.opacity.minimum);
                (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.maximum,
                               statistics.opacity.maximum);
                (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.mean,
                               statistics.opacity.mean);
                (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.standard_deviation,
                               statistics.opacity.standard_deviation);
            }
        }
    }
    x=0;
    p=(Image *) NULL;
    if ((image->matte && (strcmp(image->magick,"GIF") != 0)) || image->taint)
    {
        char
        tuple[MaxTextExtent];

        register const PixelPacket
        *p;

        p=(PixelPacket *) NULL;
        for (y=0; y < (long) image->rows; y++)
        {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
                break;
            for (x=0; x < (long) image->columns; x++)
            {
                if (p->opacity == TransparentOpacity)
                    break;
                p++;
            }
            if (x < (long) image->columns)
                break;
        }
        if ((x < (long) image->columns) || (y < (long) image->rows))
        {
            GetColorTuple(p,image->depth,image->matte,False,tuple);
            (void) fprintf(file,"  Opacity: %.1024s\t",tuple);
            GetColorTuple(p,image->depth,image->matte,True,tuple);
            (void) fprintf(file,"  %.1024s\n",tuple);
        }
    }
    if (image->storage_class == DirectClass)
    {
        if (image->total_colors != 0)
            (void) fprintf(file,"  Colors: %lu\n",image->total_colors);
    }
    else
    {
        if (image->total_colors <= image->colors)
            (void) fprintf(file,"  Colors: %u\n",image->colors);
        else
            (void) fprintf(file,"  Colors: %lu=>%u\n",image->total_colors,
                           image->colors);
    }
    if (image->storage_class == DirectClass)
    {
        if (image->total_colors < 1024)
            if (verbose > 1)
                (void) GetNumberColors(image,file,&image->exception);
    }
    else
    {
        char
        name[MaxTextExtent];

        register PixelPacket
        *p;

        /*
          Display image colormap.
        */
        p=image->colormap;
        for (i=0; i < (long) image->colors; i++)
        {
            char
            tuple[MaxTextExtent];

            GetColorTuple(p,image->depth,image->matte,False,tuple);
            (void) fprintf(file,"    %lu: %.1024s",i,tuple);
            (void) fprintf(file,"\t");
            (void) QueryColorname(image,p,SVGCompliance,name,&image->exception);
            (void) fprintf(file,"  %.1024s",name);
            (void) fprintf(file,"\n");
            p++;
        }
    }
    if (image->error.mean_error_per_pixel != 0.0)
        (void) fprintf(file,"  Mean Exception Per Pixel: %ld\n",
                       (long) image->error.mean_error_per_pixel);
    if (image->error.normalized_mean_error != 0.0)
        (void) fprintf(file,"  Normalized Mean Exception: %g\n",
                       image->error.normalized_mean_error);
    if (image->error.normalized_maximum_error != 0.0)
        (void) fprintf(file,"  Normalized Maximum Exception: %gn",
                       image->error.normalized_maximum_error);
    if (image->rendering_intent == SaturationIntent)
        (void) fprintf(file,"  Rendering-Intent: saturation\n");
    else if (image->rendering_intent == PerceptualIntent)
        (void) fprintf(file,"  Rendering-Intent: perceptual\n");
    else if (image->rendering_intent == AbsoluteIntent)
        (void) fprintf(file,"  Rendering-Intent: absolute\n");
    else if (image->rendering_intent == RelativeIntent)
        (void) fprintf(file,"  Rendering-Intent: relative\n");
    if (image->gamma != 0.0)
        (void) fprintf(file,"  Gamma: %g\n",image->gamma);
    if ((image->chromaticity.red_primary.x != 0.0) ||
            (image->chromaticity.green_primary.x != 0.0) ||
            (image->chromaticity.blue_primary.x != 0.0) ||
            (image->chromaticity.white_point.x != 0.0))
    {
        /*
          Display image chromaticity.
        */
        (void) fprintf(file,"  Chromaticity:\n");
        (void) fprintf(file,"    red primary: (%g,%g)\n",
                       image->chromaticity.red_primary.x,image->chromaticity.red_primary.y);
        (void) fprintf(file,"    green primary: (%g,%g)\n",
                       image->chromaticity.green_primary.x,
                       image->chromaticity.green_primary.y);
        (void) fprintf(file,"    blue primary: (%g,%g)\n",
                       image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y);
        (void) fprintf(file,"    white point: (%g,%g)\n",
                       image->chromaticity.white_point.x,image->chromaticity.white_point.y);
    }
    if ((image->tile_info.width*image->tile_info.height) != 0)
        (void) fprintf(file,"  Tile geometry: %lux%lu%+ld%+ld\n",
                       image->tile_info.width,image->tile_info.height,image->tile_info.x,
                       image->tile_info.y);
    if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
    {
        /*
          Display image resolution.
        */
        (void) fprintf(file,"  Resolution: %gx%g",image->x_resolution,
                       image->y_resolution);
        if (image->units == UndefinedResolution)
            (void) fprintf(file," pixels\n");
        else if (image->units == PixelsPerInchResolution)
            (void) fprintf(file," pixels/inch\n");
        else if (image->units == PixelsPerCentimeterResolution)
            (void) fprintf(file," pixels/centimeter\n");
        else
            (void) fprintf(file,"\n");
    }
    FormatSize(GetBlobSize(image),format);
    (void) fprintf(file,"  Filesize: %.1024s\n",format);
    fprintf(file,"  Interlace: %s\n",
            InterlaceTypeToString(image->interlace == UndefinedInterlace ?
                                  NoInterlace : image->interlace));
    (void) fprintf(file,"  Orientation: %s\n", OrientationTypeToString(image->orientation));
    (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
                          &image->exception);
    (void) fprintf(file,"  Background Color: %.1024s\n",color);
    (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
                          &image->exception);
    (void) fprintf(file,"  Border Color: %.1024s\n",color);
    (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
                          &image->exception);
    (void) fprintf(file,"  Matte Color: %.1024s\n",color);
    if ((image->page.width != 0) && (image->page.height != 0))
        (void) fprintf(file,"  Page geometry: %lux%lu%+ld%+ld\n",image->page.width,
                       image->page.height,image->page.x,image->page.y);
    (void) fprintf(file,"  Compose: %s\n",
                   CompositeOperatorToString(image->compose));
    (void) fprintf(file,"  Dispose: ");
    switch (image->dispose)
    {
    case UndefinedDispose:
        (void) fprintf(file,"Undefined\n");
        break;
    case NoneDispose:
        (void) fprintf(file,"None\n");
        break;
    case BackgroundDispose:
        (void) fprintf(file,"Background\n");
        break;
    case PreviousDispose:
        (void) fprintf(file,"Previous\n");
        break;
    default:
        (void) fprintf(file,"\n");
        break;
    }
    if (image->delay != 0)
        (void) fprintf(file,"  Delay: %lu\n",image->delay);
    if (image->iterations != 1)
        (void) fprintf(file,"  Iterations: %lu\n",image->iterations);
    p=image;
    while (p->previous != (Image *) NULL)
        p=p->previous;
    for (count=1; p->next != (Image *) NULL; count++)
        p=p->next;
    if (count > 1)
        (void) fprintf(file,"  Scene: %lu of %lu\n",image->scene,count);
    else if (image->scene != 0)
        (void) fprintf(file,"  Scene: %lu\n",image->scene);
    (void) fprintf(file,"  Compression: %s\n",
                   CompressionTypeToString(image->compression));
    /*
      Display formatted image attributes. This must happen before we access
      any pseudo attributes like EXIF since doing so causes real attributes
      to be created and we would get duplicates in the output.
    */
    attribute=GetImageAttribute(image,(char *) NULL);
    {
        for ( ; attribute != (const ImageAttribute *) NULL; attribute=attribute->next)
        {
            if (LocaleNCompare("EXIF",attribute->key,4) != 0)
            {
                (void) fprintf(file,"  %c", toupper((int)attribute->key[0]));
                if (strlen(attribute->key) > 1)
                    (void) fprintf(file,"%.1024s",attribute->key+1);

                (void) fprintf(file,": ");
                (void) fprintf(file,"%s\n",attribute->value);
            }
        }
    }
    if((profile=GetImageProfile(image,"ICM",&profile_length)) != 0)
        (void) fprintf(file,"  Profile-color: %lu bytes\n",(unsigned long)
                       profile_length);
    if((profile=GetImageProfile(image,"IPTC",&profile_length)) != 0)
    {
        char
        *tag,
        *text;

        size_t
        length;

        /*
          Describe IPTC data.
        */
        (void) fprintf(file,"  Profile-iptc: %lu bytes\n",(unsigned long)
                       profile_length);
        for (i=0; i < (long) profile_length; )
        {
            if (profile[i] != 0x1c)
            {
                i++;
                continue;
            }
            i++;  /* skip file separator */
            i++;  /* skip record number */
            switch (profile[i])
            {
            case 5:
                tag=(char *) "Image Name";
                break;
            case 7:
                tag=(char *) "Edit Status";
                break;
            case 10:
                tag=(char *) "Priority";
                break;
            case 15:
                tag=(char *) "Category";
                break;
            case 20:
                tag=(char *) "Supplemental Category";
                break;
            case 22:
                tag=(char *) "Fixture Identifier";
                break;
            case 25:
                tag=(char *) "Keyword";
                break;
            case 30:
                tag=(char *) "Release Date";
                break;
            case 35:
                tag=(char *) "Release Time";
                break;
            case 40:
                tag=(char *) "Special Instructions";
                break;
            case 45:
                tag=(char *) "Reference Service";
                break;
            case 47:
                tag=(char *) "Reference Date";
                break;
            case 50:
                tag=(char *) "Reference Number";
                break;
            case 55:
                tag=(char *) "Created Date";
                break;
            case 60:
                tag=(char *) "Created Time";
                break;
            case 65:
                tag=(char *) "Originating Program";
                break;
            case 70:
                tag=(char *) "Program Version";
                break;
            case 75:
                tag=(char *) "Object Cycle";
                break;
            case 80:
                tag=(char *) "Byline";
                break;
            case 85:
                tag=(char *) "Byline Title";
                break;
            case 90:
                tag=(char *) "City";
                break;
            case 95:
                tag=(char *) "Province State";
                break;
            case 100:
                tag=(char *) "Country Code";
                break;
            case 101:
                tag=(char *) "Country";
                break;
            case 103:
                tag=(char *) "Original Transmission Reference";
                break;
            case 105:
                tag=(char *) "Headline";
                break;
            case 110:
                tag=(char *) "Credit";
                break;
            case 115:
                tag=(char *) "Source";
                break;
            case 116:
                tag=(char *) "Copyright String";
                break;
            case 120:
                tag=(char *) "Caption";
                break;
            case 121:
                tag=(char *) "Local Caption";
                break;
            case 122:
                tag=(char *) "Caption Writer";
                break;
            case 200:
                tag=(char *) "Custom Field 1";
                break;
            case 201:
                tag=(char *) "Custom Field 2";
                break;
            case 202:
                tag=(char *) "Custom Field 3";
                break;
            case 203:
                tag=(char *) "Custom Field 4";
                break;
            case 204:
                tag=(char *) "Custom Field 5";
                break;
            case 205:
                tag=(char *) "Custom Field 6";
                break;
            case 206:
                tag=(char *) "Custom Field 7";
                break;
            case 207:
                tag=(char *) "Custom Field 8";
                break;
            case 208:
                tag=(char *) "Custom Field 9";
                break;
            case 209:
                tag=(char *) "Custom Field 10";
                break;
            case 210:
                tag=(char *) "Custom Field 11";
                break;
            case 211:
                tag=(char *) "Custom Field 12";
                break;
            case 212:
                tag=(char *) "Custom Field 13";
                break;
            case 213:
                tag=(char *) "Custom Field 14";
                break;
            case 214:
                tag=(char *) "Custom Field 15";
                break;
            case 215:
                tag=(char *) "Custom Field 16";
                break;
            case 216:
                tag=(char *) "Custom Field 17";
                break;
            case 217:
                tag=(char *) "Custom Field 18";
                break;
            case 218:
                tag=(char *) "Custom Field 19";
                break;
            case 219:
                tag=(char *) "Custom Field 20";
                break;
            default:
                tag=(char *) "unknown";
                break;
            }
            i++;
            (void) fprintf(file,"    %.1024s:\n",tag);
            length=profile[i++] << 8;
            length|=profile[i++];
            text=MagickAllocateMemory(char *,length+1);
            if (text != (char *) NULL)
            {
                char
                **textlist;

                register long
                j;

                (void) strncpy(text,(char *) profile+i,length);
                text[length]='\0';
                textlist=StringToList(text);
                if (textlist != (char **) NULL)
                {
                    for (j=0; textlist[j] != (char *) NULL; j++)
                    {
                        (void) fprintf(file,"  %s\n",textlist[j]);
                        MagickFreeMemory(textlist[j]);
                    }
                    MagickFreeMemory(textlist);
                }
                MagickFreeMemory(text);
            }
            i+=length;
        }
    }