Ejemplo n.º 1
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 (IsGrayColorspace(image->colorspace) != MagickFalse)
        (void) SetImageColorspace(combine_image,RGBColorspace);
    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,PixelIntensityToQuantum(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,PixelIntensityToQuantum(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,PixelIntensityToQuantum(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,PixelIntensityToQuantum(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,PixelIntensityToQuantum(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 (status == MagickFalse)
        combine_image=DestroyImage(combine_image);
    if (IsGrayColorspace(combine_image->colorspace) != MagickFalse)
        (void) TransformImageColorspace(combine_image,RGBColorspace);
    return(combine_image);
}
Ejemplo n.º 2
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d P A N G O I m a g e                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadPANGOImage() reads an image in the Pango Markup Language Format.
%
%  The format of the ReadPANGOImage method is:
%
%      Image *ReadPANGOImage(const ImageInfo *image_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadPANGOImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  cairo_font_options_t
    *font_options;

  cairo_surface_t
    *surface;

  char
    *caption,
    *property;

  cairo_t
    *cairo_image;

  const char
    *option;

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    status;

  PangoAlignment
    align;

  PangoContext
    *context;

  PangoFontMap
    *fontmap;

  PangoGravity
    gravity;

  PangoLayout
    *layout;

  PangoRectangle
    extent;

  PixelInfo
    fill_color;

  RectangleInfo
    page;

  register unsigned char
    *p;

  size_t
    stride;

  ssize_t
    y;

  unsigned char
    *pixels;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info,exception);
  (void) ResetImagePage(image,"0x0+0+0");
  /*
    Format caption.
  */
  option=GetImageArtifact(image,"filename");
  if (option == (const char *) NULL)
    property=InterpretImageProperties(image_info,image,image_info->filename,
      exception);
  else
    if (LocaleNCompare(option,"pango:",6) == 0)
      property=InterpretImageProperties(image_info,image,option+6,exception);
    else
      property=InterpretImageProperties(image_info,image,option,exception);
  (void) SetImageProperty(image,"caption",property,exception);
  property=DestroyString(property);
  caption=ConstantString(GetImageProperty(image,"caption",exception));
  /*
    Get context.
  */
  fontmap=pango_cairo_font_map_new();
  pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(fontmap),
    image->resolution.x == 0.0 ? 90.0 : image->resolution.x);
  font_options=cairo_font_options_create();
  option=GetImageArtifact(image,"pango:hinting");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"none") != 0)
        cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_NONE);
      if (LocaleCompare(option,"full") != 0)
        cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_FULL);
    }
  context=pango_font_map_create_context(fontmap);
  pango_cairo_context_set_font_options(context,font_options);
  cairo_font_options_destroy(font_options);
  option=GetImageArtifact(image,"pango:language");
  if (option != (const char *) NULL)
    pango_context_set_language(context,pango_language_from_string(option));
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  pango_context_set_base_dir(context,draw_info->direction ==
    RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
  switch (draw_info->gravity)
  {
    case NorthGravity:
    {
      gravity=PANGO_GRAVITY_NORTH;
      break;
    }
    case NorthWestGravity:
    case WestGravity:
    case SouthWestGravity:
    {
      gravity=PANGO_GRAVITY_WEST;
      break;
    }
    case NorthEastGravity:
    case EastGravity:
    case SouthEastGravity:
    {
      gravity=PANGO_GRAVITY_EAST;
      break;
    }
    case SouthGravity:
    {
      gravity=PANGO_GRAVITY_SOUTH;
      break;
    }
    default:
    {
      gravity=PANGO_GRAVITY_AUTO;
      break;
    }
  }
  pango_context_set_base_gravity(context,gravity);
  option=GetImageArtifact(image,"pango:gravity-hint");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"line") == 0)
        pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE);
      if (LocaleCompare(option,"natural") == 0)
        pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL);
      if (LocaleCompare(option,"strong") == 0)
        pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG);
    }
  /*
    Configure layout.
  */
  layout=pango_layout_new(context);
  option=GetImageArtifact(image,"pango:auto-dir");
  if (option != (const char *) NULL)
    pango_layout_set_auto_dir(layout,1);
  option=GetImageArtifact(image,"pango:ellipsize");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"end") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END);
      if (LocaleCompare(option,"middle") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE);
      if (LocaleCompare(option,"none") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE);
      if (LocaleCompare(option,"start") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START);
    }
  option=GetImageArtifact(image,"pango:justify");
  if (IfMagickTrue(IsStringTrue(option)))
    pango_layout_set_justify(layout,1);
  option=GetImageArtifact(image,"pango:single-paragraph");
  if (IfMagickTrue(IsStringTrue(option)))
    pango_layout_set_single_paragraph_mode(layout,1);
  option=GetImageArtifact(image,"pango:wrap");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"char") == 0)
        pango_layout_set_wrap(layout,PANGO_WRAP_CHAR);
      if (LocaleCompare(option,"word") == 0)
        pango_layout_set_wrap(layout,PANGO_WRAP_WORD);
      if (LocaleCompare(option,"word-char") == 0)
        pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR);
    }
  option=GetImageArtifact(image,"pango:indent");
  if (option != (const char *) NULL)
    pango_layout_set_indent(layout,(int) ((StringToLong(option)*
      (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)*PANGO_SCALE+36)/
      90.0+0.5));
  switch (draw_info->align)
  {
    case CenterAlign: align=PANGO_ALIGN_CENTER; break;
    case RightAlign: align=PANGO_ALIGN_RIGHT; break;
    case LeftAlign: align=PANGO_ALIGN_LEFT; break;
    default:
    {
      if (draw_info->gravity == CenterGravity)
        {
          align=PANGO_ALIGN_CENTER;
          break;
        }
      align=PANGO_ALIGN_LEFT;
      break;
    }
  }
  if ((align != PANGO_ALIGN_CENTER) &&
      (draw_info->direction == RightToLeftDirection))
    align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align);
  pango_layout_set_alignment(layout,align);
  if (draw_info->font != (char *) NULL)
    {
      PangoFontDescription
        *description;

      /*
        Set font.
      */
      description=pango_font_description_from_string(draw_info->font);
      pango_font_description_set_size(description,(int) (PANGO_SCALE*
        draw_info->pointsize+0.5));
      pango_layout_set_font_description(layout,description);
      pango_font_description_free(description);
    }
  option=GetImageArtifact(image,"pango:markup");
  if ((option != (const char *) NULL) && (IsStringTrue(option) == MagickFalse))
    pango_layout_set_text(layout,caption,-1);
  else
    {
      GError
        *error;

      error=(GError *) NULL;
      if (pango_parse_markup(caption,-1,0,NULL,NULL,NULL,&error) == 0)
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
          error->message,"`%s'",image_info->filename);
      pango_layout_set_markup(layout,caption,-1);
    }
  pango_layout_context_changed(layout);
  page.x=0;
  page.y=0;
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  if (image->columns == 0)
    {
      pango_layout_get_extents(layout,NULL,&extent);
      image->columns=(extent.x+extent.width+PANGO_SCALE/2)/PANGO_SCALE+2*page.x;
    }
  else
    {
      image->columns-=2*page.x;
      pango_layout_set_width(layout,(int) ((PANGO_SCALE*image->columns*
        (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)+45.0)/90.0+
        0.5));
    }
  if (image->rows == 0)
    {
      pango_layout_get_extents(layout,NULL,&extent);
      image->rows=(extent.y+extent.height+PANGO_SCALE/2)/PANGO_SCALE+2*page.y;
    }
  else
    {
      image->rows-=2*page.y;
      pango_layout_set_height(layout,(int) ((PANGO_SCALE*image->rows*
        (image->resolution.y == 0.0 ? 90.0 : image->resolution.y)+45.0)/90.0+
        0.5));
    }
  /*
    Render markup.
  */
  stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,
    image->columns);
  pixels=(unsigned char *) AcquireQuantumMemory(image->rows,stride*
    sizeof(*pixels));
  if (pixels == (unsigned char *) NULL)
    {
      draw_info=DestroyDrawInfo(draw_info);
      caption=DestroyString(caption);
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    }
  surface=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32,
    image->columns,image->rows,stride);
  cairo_image=cairo_create(surface);
  cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR);
  cairo_paint(cairo_image);
  cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER);
  cairo_translate(cairo_image,page.x,page.y);
  pango_cairo_show_layout(cairo_image,layout);
  cairo_destroy(cairo_image);
  cairo_surface_destroy(surface);
  g_object_unref(layout);
  g_object_unref(fontmap);
  /*
    Convert surface to image.
  */
  (void) SetImageBackgroundColor(image,exception);
  p=pixels;
  GetPixelInfo(image,&fill_color);
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register Quantum
      *q;

    register ssize_t
      x;

    q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    if (q == (Quantum *) NULL)
      break;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      double
        gamma;

      fill_color.blue=(double) ScaleCharToQuantum(*p++);
      fill_color.green=(double) ScaleCharToQuantum(*p++);
      fill_color.red=(double) ScaleCharToQuantum(*p++);
      fill_color.alpha=(double) ScaleCharToQuantum(*p++);
      /*
        Disassociate alpha.
      */
      gamma=1.0-QuantumScale*fill_color.alpha;
      gamma=PerceptibleReciprocal(gamma);
      fill_color.blue*=gamma;
      fill_color.green*=gamma;
      fill_color.red*=gamma;
      CompositePixelOver(image,&fill_color,fill_color.alpha,q,(double)
        GetPixelAlpha(image,q),q);
      q+=GetPixelChannels(image);
    }
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
      break;
    if (image->previous == (Image *) NULL)
      {
        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
        image->rows);
        if (status == MagickFalse)
          break;
      }
  }
  /*
    Relinquish resources.
  */
  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
  draw_info=DestroyDrawInfo(draw_info);
  caption=DestroyString(caption);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 3
0
MagickExport Image *MontageImageList(const ImageInfo *image_info,
  const MontageInfo *montage_info,const Image *images,ExceptionInfo *exception)
{
#define MontageImageTag  "Montage/Image"
#define TileImageTag  "Tile/Image"

  char
    tile_geometry[MagickPathExtent],
    *title;

  const char
    *value;

  DrawInfo
    *draw_info;

  FrameInfo
    frame_info;

  Image
    *image,
    **image_list,
    **master_list,
    *montage,
    *texture,
    *tile_image,
    *thumbnail;

  ImageInfo
    *clone_info;

  MagickBooleanType
    concatenate,
    proceed,
    status;

  MagickOffsetType
    tiles;

  MagickProgressMonitor
    progress_monitor;

  MagickStatusType
    flags;

  register ssize_t
    i;

  RectangleInfo
    bounds,
    geometry,
    extract_info;

  size_t
    bevel_width,
    border_width,
    extent,
    height,
    images_per_page,
    max_height,
    number_images,
    number_lines,
    sans,
    tiles_per_column,
    tiles_per_page,
    tiles_per_row,
    title_offset,
    total_tiles,
    width;

  ssize_t
    tile,
    x,
    x_offset,
    y,
    y_offset;

  TypeMetric
    metrics;

  /*
    Create image tiles.
  */
  assert(images != (Image *) NULL);
  assert(images->signature == MagickCoreSignature);
  if (images->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
  assert(montage_info != (MontageInfo *) NULL);
  assert(montage_info->signature == MagickCoreSignature);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  number_images=GetImageListLength(images);
  master_list=ImageListToArray(images,exception);
  image_list=master_list;
  image=image_list[0];
  if (master_list == (Image **) NULL)
    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
  thumbnail=NewImageList();
  for (i=0; i < (ssize_t) number_images; i++)
  {
    image=CloneImage(image_list[i],0,0,MagickTrue,exception);
    if (image == (Image *) NULL)
      break;
    (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
    progress_monitor=SetImageProgressMonitor(image,(MagickProgressMonitor) NULL,
      image->client_data);
    flags=ParseRegionGeometry(image,montage_info->geometry,&geometry,exception);
    thumbnail=ThumbnailImage(image,geometry.width,geometry.height,exception);
    if (thumbnail == (Image *) NULL)
      break;
    image_list[i]=thumbnail;
    (void) SetImageProgressMonitor(image,progress_monitor,image->client_data);
    proceed=SetImageProgress(image,TileImageTag,(MagickOffsetType) i,
      number_images);
    if (proceed == MagickFalse)
      break;
    image=DestroyImage(image);
  }
  if (i < (ssize_t) number_images)
    {
      if (thumbnail == (Image *) NULL)
        i--;
      for (tile=0; (ssize_t) tile <= i; tile++)
        if (image_list[tile] != (Image *) NULL)
          image_list[tile]=DestroyImage(image_list[tile]);
      master_list=(Image **) RelinquishMagickMemory(master_list);
      return((Image *) NULL);
    }
  /*
    Sort image list by increasing tile number.
  */
  for (i=0; i < (ssize_t) number_images; i++)
    if (image_list[i]->scene == 0)
      break;
  if (i == (ssize_t) number_images)
    qsort((void *) image_list,(size_t) number_images,sizeof(*image_list),
      SceneCompare);
  /*
    Determine tiles per row and column.
  */
  tiles_per_column=(size_t) sqrt((double) number_images);
  tiles_per_row=(size_t) ceil((double) number_images/tiles_per_column);
  x_offset=0;
  y_offset=0;
  if (montage_info->tile != (char *) NULL)
    GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
      &tiles_per_column,&tiles_per_row);
  /*
    Determine tile sizes.
  */
  concatenate=MagickFalse;
  SetGeometry(image_list[0],&extract_info);
  extract_info.x=(ssize_t) montage_info->border_width;
  extract_info.y=(ssize_t) montage_info->border_width;
  if (montage_info->geometry != (char *) NULL)
    {
      /*
        Initialize tile geometry.
      */
      flags=GetGeometry(montage_info->geometry,&extract_info.x,&extract_info.y,
        &extract_info.width,&extract_info.height);
      concatenate=((flags & RhoValue) == 0) && ((flags & SigmaValue) == 0) ?
        MagickTrue : MagickFalse;
    }
  border_width=montage_info->border_width;
  bevel_width=0;
  (void) ResetMagickMemory(&frame_info,0,sizeof(frame_info));
  if (montage_info->frame != (char *) NULL)
    {
      char
        absolute_geometry[MagickPathExtent];

      frame_info.width=extract_info.width;
      frame_info.height=extract_info.height;
      (void) FormatLocaleString(absolute_geometry,MagickPathExtent,"%s!",
        montage_info->frame);
      flags=ParseMetaGeometry(absolute_geometry,&frame_info.outer_bevel,
        &frame_info.inner_bevel,&frame_info.width,&frame_info.height);
      if ((flags & HeightValue) == 0)
        frame_info.height=frame_info.width;
      if ((flags & XiValue) == 0)
        frame_info.outer_bevel=(ssize_t) frame_info.width/2;
      if ((flags & PsiValue) == 0)
        frame_info.inner_bevel=frame_info.outer_bevel;
      frame_info.x=(ssize_t) frame_info.width;
      frame_info.y=(ssize_t) frame_info.height;
      bevel_width=(size_t) MagickMax(frame_info.inner_bevel,
        frame_info.outer_bevel);
      border_width=(size_t) MagickMax((ssize_t) frame_info.width,
        (ssize_t) frame_info.height);
    }
  for (i=0; i < (ssize_t) number_images; i++)
  {
    if (image_list[i]->columns > extract_info.width)
      extract_info.width=image_list[i]->columns;
    if (image_list[i]->rows > extract_info.height)
      extract_info.height=image_list[i]->rows;
  }
  /*
    Initialize draw attributes.
  */
  clone_info=CloneImageInfo(image_info);
  clone_info->background_color=montage_info->background_color;
  clone_info->border_color=montage_info->border_color;
  draw_info=CloneDrawInfo(clone_info,(DrawInfo *) NULL);
  if (montage_info->font != (char *) NULL)
    (void) CloneString(&draw_info->font,montage_info->font);
  if (montage_info->pointsize != 0.0)
    draw_info->pointsize=montage_info->pointsize;
  draw_info->gravity=CenterGravity;
  draw_info->stroke=montage_info->stroke;
  draw_info->fill=montage_info->fill;
  draw_info->text=AcquireString("");
  (void) GetTypeMetrics(image_list[0],draw_info,&metrics,exception);
  texture=NewImageList();
  if (montage_info->texture != (char *) NULL)
    {
      (void) CopyMagickString(clone_info->filename,montage_info->texture,
        MagickPathExtent);
      texture=ReadImage(clone_info,exception);
    }
  /*
    Determine the number of lines in an next label.
  */
  title=InterpretImageProperties(clone_info,image_list[0],montage_info->title,
    exception);
  title_offset=0;
  if (montage_info->title != (char *) NULL)
    title_offset=(size_t) (2*(metrics.ascent-metrics.descent)*
      MultilineCensus(title)+2*extract_info.y);
  number_lines=0;
  for (i=0; i < (ssize_t) number_images; i++)
  {
    value=GetImageProperty(image_list[i],"label",exception);
    if (value == (const char *) NULL)
      continue;
    if (MultilineCensus(value) > number_lines)
      number_lines=MultilineCensus(value);
  }
  /*
    Allocate next structure.
  */
  tile_image=AcquireImage((ImageInfo *) NULL,exception);
  montage=AcquireImage(clone_info,exception);
  montage->background_color=montage_info->background_color;
  montage->scene=0;
  images_per_page=(number_images-1)/(tiles_per_row*tiles_per_column)+1;
  tiles=0;
  total_tiles=(size_t) number_images;
  for (i=0; i < (ssize_t) images_per_page; i++)
  {
    /*
      Determine bounding box.
    */
    tiles_per_page=tiles_per_row*tiles_per_column;
    x_offset=0;
    y_offset=0;
    if (montage_info->tile != (char *) NULL)
      GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
        &sans,&sans);
    tiles_per_page=tiles_per_row*tiles_per_column;
    y_offset+=(ssize_t) title_offset;
    max_height=0;
    bounds.width=0;
    bounds.height=0;
    width=0;
    for (tile=0; tile < (ssize_t) tiles_per_page; tile++)
    {
      if (tile < (ssize_t) number_images)
        {
          width=concatenate != MagickFalse ? image_list[tile]->columns :
            extract_info.width;
          if (image_list[tile]->rows > max_height)
            max_height=image_list[tile]->rows;
        }
      x_offset+=(ssize_t) (width+2*(extract_info.x+border_width));
      if (x_offset > (ssize_t) bounds.width)
        bounds.width=(size_t) x_offset;
      if (((tile+1) == (ssize_t) tiles_per_page) ||
          (((tile+1) % tiles_per_row) == 0))
        {
          x_offset=0;
          if (montage_info->tile != (char *) NULL)
            GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y,
              &sans,&sans);
          height=concatenate != MagickFalse ? max_height : extract_info.height;
          y_offset+=(ssize_t) (height+(extract_info.y+(ssize_t) border_width)*2+
            (metrics.ascent-metrics.descent+4)*number_lines+
            (montage_info->shadow != MagickFalse ? 4 : 0));
          if (y_offset > (ssize_t) bounds.height)
            bounds.height=(size_t) y_offset;
          max_height=0;
        }
    }
    if (montage_info->shadow != MagickFalse)
      bounds.width+=4;
    /*
      Initialize montage image.
    */
    (void) CopyMagickString(montage->filename,montage_info->filename,
      MagickPathExtent);
    montage->columns=(size_t) MagickMax((ssize_t) bounds.width,1);
    montage->rows=(size_t) MagickMax((ssize_t) bounds.height,1);
    (void) SetImageBackgroundColor(montage,exception);
    /*
      Set montage geometry.
    */
    montage->montage=AcquireString((char *) NULL);
    tile=0;
    extent=1;
    while (tile < MagickMin((ssize_t) tiles_per_page,(ssize_t) number_images))
    {
      extent+=strlen(image_list[tile]->filename)+1;
      tile++;
    }
    montage->directory=(char *) AcquireQuantumMemory(extent,
      sizeof(*montage->directory));
    if ((montage->montage == (char *) NULL) ||
        (montage->directory == (char *) NULL))
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
    x_offset=0;
    y_offset=0;
    if (montage_info->tile != (char *) NULL)
      GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
        &sans,&sans);
    y_offset+=(ssize_t) title_offset;
    (void) FormatLocaleString(montage->montage,MagickPathExtent,
      "%.20gx%.20g%+.20g%+.20g",(double) (extract_info.width+
      (extract_info.x+border_width)*2),(double) (extract_info.height+
      (extract_info.y+border_width)*2+(double) ((metrics.ascent-
      metrics.descent+4)*number_lines+(montage_info->shadow != MagickFalse ? 4 :
      0))),(double) x_offset,(double) y_offset);
    *montage->directory='\0';
    tile=0;
    while (tile < MagickMin((ssize_t) tiles_per_page,(ssize_t) number_images))
    {
      (void) ConcatenateMagickString(montage->directory,
        image_list[tile]->filename,extent);
      (void) ConcatenateMagickString(montage->directory,"\n",extent);
      tile++;
    }
    progress_monitor=SetImageProgressMonitor(montage,(MagickProgressMonitor)
      NULL,montage->client_data);
    if (texture != (Image *) NULL)
      (void) TextureImage(montage,texture,exception);
    if (montage_info->title != (char *) NULL)
      {
        char
          geometry[MagickPathExtent];

        DrawInfo
          *clone_info;

        TypeMetric
          metrics;

        /*
          Annotate composite image with title.
        */
        clone_info=CloneDrawInfo(image_info,draw_info);
        clone_info->gravity=CenterGravity;
        clone_info->pointsize*=2.0;
        (void) GetTypeMetrics(image_list[0],clone_info,&metrics,exception);
        (void) FormatLocaleString(geometry,MagickPathExtent,
          "%.20gx%.20g%+.20g%+.20g",(double) montage->columns,(double)
          (metrics.ascent-metrics.descent),0.0,(double) extract_info.y+4);
        (void) CloneString(&clone_info->geometry,geometry);
        (void) CloneString(&clone_info->text,title);
        (void) AnnotateImage(montage,clone_info,exception);
        clone_info=DestroyDrawInfo(clone_info);
      }
    (void) SetImageProgressMonitor(montage,progress_monitor,
      montage->client_data);
    /*
      Copy tile to the composite.
    */
    x_offset=0;
    y_offset=0;
    if (montage_info->tile != (char *) NULL)
      GetMontageGeometry(montage_info->tile,number_images,&x_offset,&y_offset,
        &sans,&sans);
    x_offset+=extract_info.x;
    y_offset+=(ssize_t) title_offset+extract_info.y;
    max_height=0;
    status=MagickTrue;
    for (tile=0; tile < MagickMin((ssize_t) tiles_per_page,(ssize_t) number_images); tile++)
    {
      /*
        Copy this tile to the composite.
      */
      image=CloneImage(image_list[tile],0,0,MagickTrue,exception);
      progress_monitor=SetImageProgressMonitor(image,
        (MagickProgressMonitor) NULL,image->client_data);
      width=concatenate != MagickFalse ? image->columns : extract_info.width;
      if (image->rows > max_height)
        max_height=image->rows;
      height=concatenate != MagickFalse ? max_height : extract_info.height;
      if (border_width != 0)
        {
          Image
            *border_image;

          RectangleInfo
            border_info;

          /*
            Put a border around the image.
          */
          border_info.width=border_width;
          border_info.height=border_width;
          if (montage_info->frame != (char *) NULL)
            {
              border_info.width=(width-image->columns+1)/2;
              border_info.height=(height-image->rows+1)/2;
            }
          border_image=BorderImage(image,&border_info,image->compose,exception);
          if (border_image != (Image *) NULL)
            {
              image=DestroyImage(image);
              image=border_image;
            }
          if ((montage_info->frame != (char *) NULL) &&
              (image->compose == DstOutCompositeOp))
            {
              (void) SetPixelChannelMask(image,AlphaChannel);
              (void) NegateImage(image,MagickFalse,exception);
              (void) SetPixelChannelMask(image,DefaultChannels);
            }
        }
      /*
        Gravitate as specified by the tile gravity.
      */
      tile_image->columns=width;
      tile_image->rows=height;
      tile_image->gravity=montage_info->gravity;
      if (image->gravity != UndefinedGravity)
        tile_image->gravity=image->gravity;
      (void) FormatLocaleString(tile_geometry,MagickPathExtent,"%.20gx%.20g+0+0",
        (double) image->columns,(double) image->rows);
      flags=ParseGravityGeometry(tile_image,tile_geometry,&geometry,exception);
      x=(ssize_t) (geometry.x+border_width);
      y=(ssize_t) (geometry.y+border_width);
      if ((montage_info->frame != (char *) NULL) && (bevel_width != 0))
        {
          FrameInfo
            extract_info;

          Image
            *frame_image;

          /*
            Put an ornamental border around this tile.
          */
          extract_info=frame_info;
          extract_info.width=width+2*frame_info.width;
          extract_info.height=height+2*frame_info.height;
          value=GetImageProperty(image,"label",exception);
          if (value != (const char *) NULL)
            extract_info.height+=(size_t) ((metrics.ascent-metrics.descent+4)*
              MultilineCensus(value));
          frame_image=FrameImage(image,&extract_info,image->compose,exception);
          if (frame_image != (Image *) NULL)
            {
              image=DestroyImage(image);
              image=frame_image;
            }
          x=0;
          y=0;
        }
      if (LocaleCompare(image->magick,"NULL") != 0)
        {
          /*
            Composite background with tile.
          */
          if (montage_info->shadow != MagickFalse)
            {
              Image
                *shadow_image;

              /*
                Shadow image.
              */
              (void) QueryColorCompliance("#0000",AllCompliance,
                &image->background_color,exception);
              shadow_image=ShadowImage(image,80.0,2.0,5,5,exception);
              if (shadow_image != (Image *) NULL)
                {
                  (void) CompositeImage(shadow_image,image,OverCompositeOp,
                    MagickTrue,0,0,exception);
                  image=DestroyImage(image);
                  image=shadow_image;
                }
          }
          (void) CompositeImage(montage,image,image->compose,MagickTrue,
            x_offset+x,y_offset+y,exception);
          value=GetImageProperty(image,"label",exception);
          if (value != (const char *) NULL)
            {
              char
                geometry[MagickPathExtent];

              /*
                Annotate composite tile with label.
              */
              (void) FormatLocaleString(geometry,MagickPathExtent,
                "%.20gx%.20g%+.20g%+.20g",(double) ((montage_info->frame ?
                image->columns : width)-2*border_width),(double)
                (metrics.ascent-metrics.descent+4)*MultilineCensus(value),
                (double) (x_offset+border_width),(double)
                ((montage_info->frame ? y_offset+height+border_width+4 :
                y_offset+extract_info.height+border_width+
                (montage_info->shadow != MagickFalse ? 4 : 0))+bevel_width));
              (void) CloneString(&draw_info->geometry,geometry);
              (void) CloneString(&draw_info->text,value);
              (void) AnnotateImage(montage,draw_info,exception);
            }
        }
      x_offset+=(ssize_t) (width+2*(extract_info.x+border_width));
      if (((tile+1) == (ssize_t) tiles_per_page) ||
          (((tile+1) % tiles_per_row) == 0))
        {
          x_offset=extract_info.x;
          y_offset+=(ssize_t) (height+(extract_info.y+border_width)*2+
            (metrics.ascent-metrics.descent+4)*number_lines+
            (montage_info->shadow != MagickFalse ? 4 : 0));
          max_height=0;
        }
      if (images->progress_monitor != (MagickProgressMonitor) NULL)
        {
          MagickBooleanType
            proceed;

          proceed=SetImageProgress(image,MontageImageTag,tiles,total_tiles);
          if (proceed == MagickFalse)
            status=MagickFalse;
        }
      image_list[tile]=DestroyImage(image_list[tile]);
      image=DestroyImage(image);
      tiles++;
    }
    (void) status;
    if ((i+1) < (ssize_t) images_per_page)
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(clone_info,montage,exception);
        if (GetNextImageInList(montage) == (Image *) NULL)
          {
            montage=DestroyImageList(montage);
            return((Image *) NULL);
          }
        montage=GetNextImageInList(montage);
        montage->background_color=montage_info->background_color;
        image_list+=tiles_per_page;
        number_images-=tiles_per_page;
      }
  }
  tile_image=DestroyImage(tile_image);
  if (texture != (Image *) NULL)
    texture=DestroyImage(texture);
  title=DestroyString(title);
  master_list=(Image **) RelinquishMagickMemory(master_list);
  draw_info=DestroyDrawInfo(draw_info);
  clone_info=DestroyImageInfo(clone_info);
  return(GetFirstImageInList(montage));
}
Ejemplo n.º 4
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d L A B E L I m a g e                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadLABELImage() reads a LABEL image file and returns it.  It
%  allocates the memory necessary for the new Image structure and returns a
%  pointer to the new image.
%
%  The format of the ReadLABELImage method is:
%
%      Image *ReadLABELImage(const ImageInfo *image_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadLABELImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    geometry[MaxTextExtent],
    *property;

  const char
    *label;

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    status;

  TypeMetric
    metrics;

  unsigned long
    height,
    width;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  (void) ResetImagePage(image,"0x0+0+0");
  property=InterpretImageProperties(image_info,image,image_info->filename);
  (void) SetImageProperty(image,"label",property);
  property=DestroyString(property);
  label=GetImageProperty(image,"label");
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  draw_info->text=ConstantString(label);
  if (((image->columns != 0) || (image->rows != 0)) &&
      (image_info->pointsize == 0.0))
    {
      /*
        Fit label to canvas size.
      */
      status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      for ( ; status != MagickFalse; draw_info->pointsize*=2.0)
      {
        width=(unsigned long) (metrics.width+draw_info->stroke_width+0.5);
        height=(unsigned long) (metrics.height+draw_info->stroke_width+0.5);
        if (((image->columns != 0) && (width > (image->columns+1))) ||
            ((image->rows != 0) && (height > (image->rows+1))))
          break;
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      }
      for ( ; status != MagickFalse; draw_info->pointsize--)
      {
        width=(unsigned long) (metrics.width+draw_info->stroke_width+0.5);
        height=(unsigned long) (metrics.height+draw_info->stroke_width+0.5);
        if ((image->columns != 0) && (width <= (image->columns+1)) &&
           ((image->rows == 0) || (height <= (image->rows+1))))
          break;
        if ((image->rows != 0) && (height <= (image->rows+1)) &&
           ((image->columns == 0) || (width <= (image->columns+1))))
          break;
        if (draw_info->pointsize < 2.0)
          break;
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      }
    }
  status=GetMultilineTypeMetrics(image,draw_info,&metrics);
  if (status == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  if (image->columns == 0)
    image->columns=(unsigned long) (metrics.width+draw_info->stroke_width+1.5);
  if (image->columns == 0)
    image->columns=(unsigned long) (draw_info->pointsize+
      draw_info->stroke_width+1.5);
  if (draw_info->gravity == UndefinedGravity)
    {
      (void) FormatMagickString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+
        draw_info->stroke_width/2.0);
      draw_info->geometry=AcquireString(geometry);
    }
  if (image->rows == 0)
    image->rows=(unsigned long) (metrics.height+draw_info->stroke_width+0.5);
  if (image->rows == 0)
    image->rows=(unsigned long) (draw_info->pointsize+draw_info->stroke_width+
      0.5);
  if (SetImageBackgroundColor(image) == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  (void) AnnotateImage(image,draw_info);
  draw_info=DestroyDrawInfo(draw_info);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 5
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%     A f f i n e T r a n s f o r m I m a g e                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  AffineTransformImage() transforms an image as dictated by the affine matrix.
%  It allocates the memory necessary for the new Image structure and returns
%  a pointer to the new image.
%
%  The format of the AffineTransformImage method is:
%
%      Image *AffineTransformImage(const Image *image,AffineMatrix *affine,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image: The image.
%
%    o affine: The affine transform.
%
%    o exception: Return any errors or warnings in this structure.
%
%
*/
MagickExport Image *AffineTransformImage(const Image *image,
  const AffineMatrix *affine,ExceptionInfo *exception)
{
  AffineMatrix
    transform;

  Image
    *affine_image;

  PointInfo
    extent[4],
    min,
    max,
    point;

  register long
    i;

  /*
    Determine bounding box.
  */
  assert(image != (const Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(affine != (AffineMatrix *) NULL);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  extent[0].x=0.0;
  extent[0].y=0.0;
  extent[1].x=(double) image->columns;
  extent[1].y=0.0;
  extent[2].x=(double) image->columns;
  extent[2].y=(double) image->rows;
  extent[3].x=0.0;
  extent[3].y=(double) image->rows;
  for (i=0; i < 4; i++)
  {
    point=extent[i];
    extent[i].x=(double) (point.x*affine->sx+point.y*affine->ry+affine->tx);
    extent[i].y=(double) (point.x*affine->rx+point.y*affine->sy+affine->ty);
  }
  min=extent[0];
  max=extent[0];
  for (i=1; i < 4; i++)
  {
    if (min.x > extent[i].x)
      min.x=extent[i].x;
    if (min.y > extent[i].y)
      min.y=extent[i].y;
    if (max.x < extent[i].x)
      max.x=extent[i].x;
    if (max.y < extent[i].y)
      max.y=extent[i].y;
  }
  /*
    Affine transform image.
  */
  affine_image=CloneImage(image,(unsigned long) (max.x-min.x+0.5),
    (unsigned long) (max.y-min.y+0.5),MagickTrue,exception);
  if (affine_image == (Image *) NULL)
    return((Image *) NULL);
  affine_image->background_color.opacity=TransparentOpacity;
  SetImageBackgroundColor(affine_image);
  transform.sx=affine->sx;
  transform.rx=affine->rx;
  transform.ry=affine->ry;
  transform.sy=affine->sy;
  transform.tx=min.x;
  transform.ty=min.y;
  (void) DrawAffineImage(affine_image,image,&transform);
  return(affine_image);
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
static MagickBooleanType WriteHISTOGRAMImage(const ImageInfo *image_info,
  Image *image)
{
#define HistogramDensity  "256x200"

  ChannelType
    channel;

  char
    filename[MaxTextExtent];

  const char
    *option;

  ExceptionInfo
    *exception;

  Image
    *histogram_image;

  ImageInfo
    *write_info;

  MagickBooleanType
    status;

  MagickPixelPacket
    *histogram;

  MagickRealType
    maximum,
    scale;

  RectangleInfo
    geometry;

  register const PixelPacket
    *p;

  register PixelPacket
    *q,
    *r;

  register ssize_t
    x;

  size_t
    length;

  ssize_t
    y;

  /*
    Allocate histogram image.
  */
  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_info->filename);
  SetGeometry(image,&geometry);
  if (image_info->density == (char *) NULL)
    (void) ParseAbsoluteGeometry(HistogramDensity,&geometry);
  else
    (void) ParseAbsoluteGeometry(image_info->density,&geometry);
  histogram_image=CloneImage(image,geometry.width,geometry.height,MagickTrue,
    &image->exception);
  if (histogram_image == (Image *) NULL)
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
  (void) SetImageStorageClass(histogram_image,DirectClass);
  /*
    Allocate histogram count arrays.
  */
  length=MagickMax((size_t) ScaleQuantumToChar((Quantum) QuantumRange)+1UL,
    histogram_image->columns);
  histogram=(MagickPixelPacket *) AcquireQuantumMemory(length,
    sizeof(*histogram));
  if (histogram == (MagickPixelPacket *) NULL)
    {
      histogram_image=DestroyImage(histogram_image);
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    }
  /*
    Initialize histogram count arrays.
  */
  channel=image_info->channel;
  (void) ResetMagickMemory(histogram,0,length*sizeof(*histogram));
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
    if (p == (const PixelPacket *) NULL)
      break;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if ((channel & RedChannel) != 0)
        histogram[ScaleQuantumToChar(GetPixelRed(p))].red++;
      if ((channel & GreenChannel) != 0)
        histogram[ScaleQuantumToChar(GetPixelGreen(p))].green++;
      if ((channel & BlueChannel) != 0)
        histogram[ScaleQuantumToChar(GetPixelBlue(p))].blue++;
      p++;
    }
  }
  maximum=histogram[0].red;
  for (x=0; x < (ssize_t) histogram_image->columns; x++)
  {
    if (((channel & RedChannel) != 0) && (maximum < histogram[x].red))
      maximum=histogram[x].red;
    if (((channel & GreenChannel) != 0) && (maximum < histogram[x].green))
      maximum=histogram[x].green;
    if (((channel & BlueChannel) != 0) && (maximum < histogram[x].blue))
      maximum=histogram[x].blue;
  }
  scale=(MagickRealType) histogram_image->rows/maximum;
  /*
    Initialize histogram image.
  */
  exception=(&image->exception);
  (void) QueryColorDatabase("#000",&histogram_image->background_color,
    &image->exception);
  (void) SetImageBackgroundColor(histogram_image);
  for (x=0; x < (ssize_t) histogram_image->columns; x++)
  {
    q=GetAuthenticPixels(histogram_image,x,0,1,histogram_image->rows,exception);
    if (q == (PixelPacket *) NULL)
      break;
    if ((channel & RedChannel) != 0)
      {
        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].red-0.5);
        r=q+y;
        for ( ; y < (ssize_t) histogram_image->rows; y++)
        {
          SetPixelRed(r,QuantumRange);
          r++;
        }
      }
    if ((channel & GreenChannel) != 0)
      {
        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].green-0.5);
        r=q+y;
        for ( ; y < (ssize_t) histogram_image->rows; y++)
        {
          SetPixelGreen(r,QuantumRange);
          r++;
        }
      }
    if ((channel & BlueChannel) != 0)
      {
        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].blue-0.5);
        r=q+y;
        for ( ; y < (ssize_t) histogram_image->rows; y++)
        {
          SetPixelBlue(r,QuantumRange);
          r++;
        }
      }
    if (SyncAuthenticPixels(histogram_image,exception) == MagickFalse)
      break;
    status=SetImageProgress(image,SaveImageTag,y,histogram_image->rows);
    if (status == MagickFalse)
      break;
  }
  /*
    Relinquish resources.
  */
  histogram=(MagickPixelPacket *) RelinquishMagickMemory(histogram);
  option=GetImageOption(image_info,"histogram:unique-colors");
  if ((option == (const char *) NULL) || (IsMagickTrue(option) != MagickFalse))
    {
      FILE
        *file;

      int
        unique_file;

      /*
        Add a unique colors as an image comment.
      */
      file=(FILE *) NULL;
      unique_file=AcquireUniqueFileResource(filename);
      if (unique_file != -1)
        file=fdopen(unique_file,"wb");
      if ((unique_file != -1) && (file != (FILE *) NULL))
        {
          char
            *property;

          (void) GetNumberColors(image,file,&image->exception);
          (void) fclose(file);
          property=FileToString(filename,~0UL,&image->exception);
          if (property != (char *) NULL)
            {
              (void) SetImageProperty(histogram_image,"comment",property);
              property=DestroyString(property);
            }
        }
      (void) RelinquishUniqueFileResource(filename);
    }
  /*
    Write Histogram image.
  */
  (void) CopyMagickString(histogram_image->filename,image_info->filename,
    MaxTextExtent);
  write_info=CloneImageInfo(image_info);
  (void) SetImageInfo(write_info,1,&image->exception);
  if (LocaleCompare(write_info->magick,"HISTOGRAM") == 0)
    (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
      "miff:%s",write_info->filename);
  status=WriteImage(write_info,histogram_image);
  histogram_image=DestroyImage(histogram_image);
  write_info=DestroyImageInfo(write_info);
  return(status);
}
Ejemplo n.º 8
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d X C F I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadXCFImage() reads a GIMP (GNU Image Manipulation Program) image
%  file and returns it.  It allocates the memory necessary for the new Image
%  structure and returns a pointer to the new image.
%
%  The format of the ReadXCFImage method is:
%
%      image=ReadXCFImage(image_info)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
%
*/
static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
    char
    magick[14];

    Image
    *image;

    int
    foundPropEnd = 0;

    MagickBooleanType
    status;

    MagickOffsetType
    offset;

    register long
    i;

    size_t
    length;

    ssize_t
    count;

    unsigned long
    image_type;

    XCFDocInfo
    doc_info;

    /*
      Open image file.
    */
    assert(image_info != (const ImageInfo *) NULL);
    assert(image_info->signature == MagickSignature);
    if (image_info->debug != MagickFalse)
        (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
                              image_info->filename);
    assert(exception != (ExceptionInfo *) NULL);
    assert(exception->signature == MagickSignature);
    image=AcquireImage(image_info);
    status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    if (status == MagickFalse)
    {
        image=DestroyImageList(image);
        return((Image *) NULL);
    }
    count=ReadBlob(image,14,(unsigned char *) magick);
    if ((count == 0) ||
            (LocaleNCompare((char *) magick,"gimp xcf",8) != 0))
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    (void) ResetMagickMemory(&doc_info,0,sizeof(XCFDocInfo));
    doc_info.exception=exception;
    doc_info.width=ReadBlobMSBLong(image);
    doc_info.height=ReadBlobMSBLong(image);
    if ((doc_info.width > 262144) || (doc_info.height > 262144))
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    doc_info.image_type=ReadBlobMSBLong(image);
    /*
      Initialize image attributes.
    */
    image->columns=doc_info.width;
    image->rows=doc_info.height;
    image_type=doc_info.image_type;
    doc_info.file_size=GetBlobSize(image);
    image->compression=NoCompression;
    image->depth=8;
    if (image_type == GIMP_RGB)
        image->colorspace=RGBColorspace;
    else if (image_type == GIMP_GRAY)
        image->colorspace=GRAYColorspace;
    else if (image_type == GIMP_INDEXED)
        ThrowReaderException(CoderError,"ColormapTypeNotSupported");
    (void) SetImageBackgroundColor(image);
    image->matte=MagickTrue;
    /*
      Read properties.
    */
    while ((foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse))
    {
        PropType prop_type = (PropType) ReadBlobMSBLong(image);
        unsigned long prop_size = ReadBlobMSBLong(image);

        switch (prop_type)
        {
        case PROP_END:
            foundPropEnd=1;
            break;
        case PROP_COLORMAP:
        {
            /* Cannot rely on prop_size here--the value is set incorrectly
               by some Gimp versions.
            */
            unsigned long num_colours = ReadBlobMSBLong(image);
            for (i=0; i < (long) (3L*num_colours); i++ )
                (void) ReadBlobByte(image);
            /*
              if (info->file_version == 0)
              {
                gint i;

                g_message (_("XCF warning: version 0 of XCF file format\n"
                   "did not save indexed colormaps correctly.\n"
                   "Substituting grayscale map."));
                info->cp +=
                  xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1);
                gimage->cmap = g_new (guchar, gimage->num_cols*3);
                xcf_seek_pos (info, info->cp + gimage->num_cols);
                for (i = 0; i<gimage->num_cols; i++)
                  {
                    gimage->cmap[i*3+0] = i;
                    gimage->cmap[i*3+1] = i;
                    gimage->cmap[i*3+2] = i;
                  }
              }
              else
              {
                info->cp +=
                  xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1);
                gimage->cmap = g_new (guchar, gimage->num_cols*3);
                info->cp +=
                  xcf_read_int8 (info->fp,
                           (guint8*) gimage->cmap, gimage->num_cols*3);
              }
             */
            break;
        }
        case PROP_COMPRESSION:
        {
            doc_info.compression = ReadBlobByte(image);
            if ((doc_info.compression != COMPRESS_NONE) &&
                    (doc_info.compression != COMPRESS_RLE) &&
                    (doc_info.compression != COMPRESS_ZLIB) &&
                    (doc_info.compression != COMPRESS_FRACTAL))
                ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
        }
        break;

        case PROP_GUIDES:
        {
            /* just skip it - we don't care about guides */
            for (i=0; i < (long) prop_size; i++ )
                if (ReadBlobByte(image) == EOF)
                    ThrowFileException(exception,CorruptImageError,
                                       "UnexpectedEndOfFile",image->filename);
        }
        break;

        case PROP_RESOLUTION:
        {
            /* float xres = (float) */ (void) ReadBlobMSBLong(image);
            /* float yres = (float) */ (void) ReadBlobMSBLong(image);

            /*
            if (xres < GIMP_MIN_RESOLUTION || xres > GIMP_MAX_RESOLUTION ||
                yres < GIMP_MIN_RESOLUTION || yres > GIMP_MAX_RESOLUTION)
            {
            g_message ("Warning, resolution out of range in XCF file");
            xres = gimage->gimp->config->default_xresolution;
            yres = gimage->gimp->config->default_yresolution;
            }
            */


            /* BOGUS: we don't write these yet because we aren't
                  reading them properly yet :(
                  image->x_resolution = xres;
                  image->y_resolution = yres;
            */
        }
        break;

        case PROP_TATTOO:
        {
            /* we need to read it, even if we ignore it */
            /*unsigned long  tattoo_state = */ (void) ReadBlobMSBLong(image);
        }
        break;

        case PROP_PARASITES:
        {
            /* BOGUS: we may need these for IPTC stuff */
            for (i=0; i < (long) prop_size; i++ )
                if (ReadBlobByte(image) == EOF)
                    ThrowFileException(exception,CorruptImageError,
                                       "UnexpectedEndOfFile",image->filename);

            /*
            glong         base = info->cp;
            GimpParasite *p;

            while (info->cp - base < prop_size)
            {
              p = xcf_load_parasite (info);
              gimp_image_parasite_attach (gimage, p);
              gimp_parasite_free (p);
            }
            if (info->cp - base != prop_size)
            g_message ("Error detected while loading an image's parasites");
            */
        }
        break;

        case PROP_UNIT:
        {
            /* BOGUS: ignore for now... */
            /*unsigned long unit =  */ (void) ReadBlobMSBLong(image);
        }
        break;

        case PROP_PATHS:
        {
            /* BOGUS: just skip it for now */
            for (i=0; i< (long) prop_size; i++ )
                if (ReadBlobByte(image) == EOF)
                    ThrowFileException(exception,CorruptImageError,
                                       "UnexpectedEndOfFile",image->filename);

            /*
            PathList *paths = xcf_load_bzpaths (gimage, info);
            gimp_image_set_paths (gimage, paths);
            */
        }
        break;

        case PROP_USER_UNIT:
        {
            char  unit_string[1000];
            /*BOGUS: ignored for now */
            /*float  factor = (float) */ (void) ReadBlobMSBLong(image);
            /* unsigned long digits =  */ (void) ReadBlobMSBLong(image);
            for (i=0; i<5; i++)
                (void) ReadBlobStringWithLongSize(image, unit_string,
                                                  sizeof(unit_string));
        }
        break;

        default:
        {
            int buf[16];
            long amount;

            /* read over it... */
            while ((prop_size > 0) && (EOFBlob(image) == MagickFalse))
            {
                amount=(long) MagickMin(16, prop_size);
                amount=(long) ReadBlob(image,(size_t) amount,(unsigned char *) &buf);
                if (!amount)
                    ThrowReaderException(CorruptImageError,"CorruptImage");
                prop_size -= (unsigned long) MagickMin(16,(size_t) amount);
            }
        }
        break;
        }
    }
    if (foundPropEnd == MagickFalse)
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");

    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
    {
        ; /* do nothing, were just pinging! */
    }
    else
    {
        int
        current_layer = 0,
        foundAllLayers = MagickFalse,
        number_layers = 0;

        MagickOffsetType
        oldPos=TellBlob(image);

        XCFLayerInfo
        *layer_info;

        /*
          the read pointer
        */
        do
        {
            long offset = (long) ReadBlobMSBLong(image);
            if (offset == 0)
                foundAllLayers=MagickTrue;
            else
                number_layers++;
            if (EOFBlob(image) != MagickFalse)
            {
                ThrowFileException(exception,CorruptImageError,
                                   "UnexpectedEndOfFile",image->filename);
                break;
            }
        } while (foundAllLayers == MagickFalse);
        offset=SeekBlob(image,oldPos,SEEK_SET); /* restore the position! */
        if (offset < 0)
            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
        /* allocate our array of layer info blocks */
        length=(size_t) number_layers;
        layer_info=(XCFLayerInfo *) AcquireQuantumMemory(length,
                   sizeof(*layer_info));
        if (layer_info == (XCFLayerInfo *) NULL)
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        (void) ResetMagickMemory(layer_info,0,number_layers*sizeof(XCFLayerInfo));
        for ( ; ; )
        {
            MagickBooleanType
            layer_ok;

            MagickOffsetType
            offset,
            saved_pos;

            /* read in the offset of the next layer */
            offset=(MagickOffsetType) ReadBlobMSBLong(image);
            /* if the offset is 0 then we are at the end
            *  of the layer list.
            */
            if (offset == 0)
                break;
            /* save the current position as it is where the
            *  next layer offset is stored.
            */
            saved_pos=TellBlob(image);
            /* seek to the layer offset */
            offset=SeekBlob(image,offset,SEEK_SET);
            /* read in the layer */
            layer_ok=ReadOneLayer(image,&doc_info,&layer_info[current_layer]);
            if (layer_ok == MagickFalse)
            {
                int j;

                for (j=0; j < current_layer; j++)
                    layer_info[j].image=DestroyImage(layer_info[j].image);
                ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
            }
            /* restore the saved position so we'll be ready to
            *  read the next offset.
            */
            offset=SeekBlob(image, saved_pos, SEEK_SET);
            current_layer++;
        }
        if (number_layers == 1)
        {
            /*
              Composite the layer data onto the main image, dispose the layer.
            */
            (void) CompositeImage(image,OverCompositeOp,layer_info[0].image,
                                  layer_info[0].offset_x,layer_info[0].offset_y);
            layer_info[0].image =DestroyImage( layer_info[0].image);
        }
        else
        {
#if 0
            {
                /* NOTE: XCF layers are REVERSED from composite order! */
                signed int  j;
                for (j=number_layers-1; j>=0; j--) {
                    /* BOGUS: need to consider layer blending modes!! */

                    if ( layer_info[j].visible ) { /* only visible ones, please! */
                        CompositeImage(image, OverCompositeOp, layer_info[j].image,
                        layer_info[j].offset_x, layer_info[j].offset_y );
                        layer_info[j].image =DestroyImage( layer_info[j].image );

                        /* Bob says that if we do this, we'll get REAL gray images! */
                        if ( image_type == GIMP_GRAY ) {
                            QuantizeInfo  qi;
                            GetQuantizeInfo(&qi);
                            qi.colorspace = GRAYColorspace;
                            QuantizeImage( &qi, layer_info[j].image );
                        }
                    }
                }
            }
#else
            {
                /* NOTE: XCF layers are REVERSED from composite order! */
                signed int  j;

                /* first we copy the last layer on top of the main image */
                (void) CompositeImage(image,CopyCompositeOp,
                layer_info[number_layers-1].image,
                layer_info[number_layers-1].offset_x,
                layer_info[number_layers-1].offset_y);
                layer_info[number_layers-1].image=DestroyImage(
                    layer_info[number_layers-1].image);

                /* now reverse the order of the layers as they are put
                   into subimages
                */
                j=number_layers-2;
                image->next=layer_info[j].image;
                layer_info[j].image->previous=image;
                layer_info[j].image->page.x=layer_info[j].offset_x;
                layer_info[j].image->page.y=layer_info[j].offset_y;
                layer_info[j].image->page.width=layer_info[j].width;
                layer_info[j].image->page.height=layer_info[j].height;
                for (j=number_layers-3; j>=0; j--)
                {
                    if (j > 0)
                        layer_info[j].image->next=layer_info[j-1].image;
                    if (j < (number_layers-1))
                        layer_info[j].image->previous=layer_info[j+1].image;
                    layer_info[j].image->page.x=layer_info[j].offset_x;
                    layer_info[j].image->page.y=layer_info[j].offset_y;
                    layer_info[j].image->page.width=layer_info[j].width;
                    layer_info[j].image->page.height=layer_info[j].height;
                }
            }
#endif
        }

        layer_info=(XCFLayerInfo *) RelinquishMagickMemory(layer_info);

#if 0  /* BOGUS: do we need the channels?? */
        while (MagickTrue)
        {
            /* read in the offset of the next channel */
            info->cp += xcf_read_int32 (info->fp, &offset, 1);

            /* if the offset is 0 then we are at the end
            *  of the channel list.
            */
            if (offset == 0)
                break;

            /* save the current position as it is where the
            *  next channel offset is stored.
            */
            saved_pos = info->cp;

            /* seek to the channel offset */
            xcf_seek_pos (info, offset);

            /* read in the layer */
            channel = xcf_load_channel (info, gimage);
            if (channel == 0)
                goto error;

            num_successful_elements++;

            /* add the channel to the image if its not the selection */
            if (channel != gimage->selection_mask)
                gimp_image_add_channel (gimage, channel, -1);

            /* restore the saved position so we'll be ready to
            *  read the next offset.
            */
            xcf_seek_pos (info, saved_pos);
        }
#endif
    }

    (void) CloseBlob(image);
    if (image_type == GIMP_GRAY)
        image->type=GrayscaleType;
    return(GetFirstImageInList(image));
}
Ejemplo n.º 9
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d T X T I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadTXTImage() reads a text file and returns it as an image.  It allocates
%  the memory necessary for the new Image structure and returns a pointer to
%  the new image.
%
%  The format of the ReadTXTImage method is:
%
%      Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    colorspace[MaxTextExtent],
    text[MaxTextExtent];

  Image
    *image;

  IndexPacket
    *indexes;

  long
    type,
    x_offset,
    y,
    y_offset;

  MagickBooleanType
    status;

  MagickPixelPacket
    pixel;

  QuantumAny
    range;

  register ssize_t
    i,
    x;

  register PixelPacket
    *q;

  ssize_t
    count;

  unsigned long
    depth,
    height,
    max_value,
    width;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  (void) ResetMagickMemory(text,0,sizeof(text));
  (void) ReadBlobString(image,text);
  if (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) != 0)
    return(ReadTEXTImage(image_info,image,text,exception));
  do
  {
    width=0;
    height=0;
    max_value=0;
    *colorspace='\0';
    count=(ssize_t) sscanf(text+32,"%lu,%lu,%lu,%s",&width,&height,&max_value,
      colorspace);
    if ((count != 4) || (width == 0) || (height == 0) || (max_value == 0))
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    image->columns=width;
    image->rows=height;
    for (depth=1; (GetQuantumRange(depth)+1) < max_value; depth++) ;
    image->depth=depth;
    status=SetImageExtent(image,image->columns,image->rows);
    if (status == MagickFalse)
      {
        InheritException(exception,&image->exception);
        return(DestroyImageList(image));
      }
    LocaleLower(colorspace);
    i=(ssize_t) strlen(colorspace)-1;
    image->matte=MagickFalse;
    if ((i > 0) && (colorspace[i] == 'a'))
      {
        colorspace[i]='\0';
        image->matte=MagickTrue;
      }
    type=ParseCommandOption(MagickColorspaceOptions,MagickFalse,colorspace);
    if (type < 0)
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    image->colorspace=(ColorspaceType) type;
    (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
    (void) SetImageBackgroundColor(image);
    range=GetQuantumRange(image->depth);
    for (y=0; y < (ssize_t) image->rows; y++)
    {
      double
        blue,
        green,
        index,
        opacity,
        red;

      red=0.0;
      green=0.0;
      blue=0.0;
      index=0.0;
      opacity=0.0;
      for (x=0; x < (ssize_t) image->columns; x++)
      {
        if (ReadBlobString(image,text) == (char *) NULL)
          break;
        switch (image->colorspace)
        {
          case GRAYColorspace:
          {
            if (image->matte != MagickFalse)
              {
                (void) sscanf(text,"%ld,%ld: (%lf%*[%,]%lf%*[%,]",&x_offset,
                  &y_offset,&red,&opacity);
                green=red;
                blue=red;
                break;
              }
            (void) sscanf(text,"%ld,%ld: (%lf%*[%,]",&x_offset,&y_offset,&red);
            green=red;
            blue=red;
            break;
          }
          case CMYKColorspace:
          {
            if (image->matte != MagickFalse)
              {
                (void) sscanf(text,
                  "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]",
                  &x_offset,&y_offset,&red,&green,&blue,&index,&opacity);
                break;
              }
            (void) sscanf(text,
              "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]",&x_offset,
              &y_offset,&red,&green,&blue,&index);
            break;
          }
          default:
          {
            if (image->matte != MagickFalse)
              {
                (void) sscanf(text,
                  "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]",
                  &x_offset,&y_offset,&red,&green,&blue,&opacity);
                break;
              }
            (void) sscanf(text,"%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]",
              &x_offset,&y_offset,&red,&green,&blue);
            break;
          }
        }
        if (strchr(text,'%') != (char *) NULL)
          {
            red*=0.01*range;
            green*=0.01*range;
            blue*=0.01*range;
            index*=0.01*range;
            opacity*=0.01*range;
          }
        if (image->colorspace == LabColorspace)
          {
            green+=(range+1)/2.0;
            blue+=(range+1)/2.0;
          }
        pixel.red=ScaleAnyToQuantum((QuantumAny) (red+0.5),range);
        pixel.green=ScaleAnyToQuantum((QuantumAny) (green+0.5),range);
        pixel.blue=ScaleAnyToQuantum((QuantumAny) (blue+0.5),range);
        pixel.index=ScaleAnyToQuantum((QuantumAny) (index+0.5),range);
        pixel.opacity=ScaleAnyToQuantum((QuantumAny) (opacity+0.5),range);
        q=GetAuthenticPixels(image,x_offset,y_offset,1,1,exception);
        if (q == (PixelPacket *) NULL)
          continue;
        SetPixelRed(q,pixel.red);
        SetPixelGreen(q,pixel.green);
        SetPixelBlue(q,pixel.blue);
        if (image->colorspace == CMYKColorspace)
          {
            indexes=GetAuthenticIndexQueue(image);
            SetPixelIndex(indexes,pixel.index);
          }
        if (image->matte != MagickFalse)
          SetPixelAlpha(q,pixel.opacity);
        if (SyncAuthenticPixels(image,exception) == MagickFalse)
          break;
      }
    }
    (void) ReadBlobString(image,text);
    if (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) == 0)
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(image_info,image);
        if (GetNextImageInList(image) == (Image *) NULL)
          {
            image=DestroyImageList(image);
            return((Image *) NULL);
          }
        image=SyncNextImageInList(image);
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
          GetBlobSize(image));
        if (status == MagickFalse)
          break;
      }
  } while (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) == 0);
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 10
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d L A B E L I m a g e                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadLABELImage() reads a LABEL image file and returns it.  It
%  allocates the memory necessary for the new Image structure and returns a
%  pointer to the new image.
%
%  The format of the ReadLABELImage method is:
%
%      Image *ReadLABELImage(const ImageInfo *image_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadLABELImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    geometry[MagickPathExtent],
    *property;

  const char
    *label;

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    status;

  TypeMetric
    metrics;

  size_t
    height,
    width;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info,exception);
  (void) ResetImagePage(image,"0x0+0+0");
  property=InterpretImageProperties((ImageInfo *) image_info,image,
    image_info->filename,exception);
  (void) SetImageProperty(image,"label",property,exception);
  property=DestroyString(property);
  label=GetImageProperty(image,"label",exception);
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  draw_info->text=ConstantString(label);
  metrics.width=0;
  metrics.ascent=0.0;
  status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
  if ((image->columns == 0) && (image->rows == 0))
    {
      image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5);
      image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
    }
  else
    if (((image->columns == 0) || (image->rows == 0)) ||
        (fabs(image_info->pointsize) < MagickEpsilon))
      {
        double
          high,
          low;

        /*
          Auto fit text into bounding box.
        */
        for ( ; ; draw_info->pointsize*=2.0)
        {
          (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g",
            -metrics.bounds.x1,metrics.ascent);
          if (draw_info->gravity == UndefinedGravity)
            (void) CloneString(&draw_info->geometry,geometry);
          status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
          width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
          height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
          if ((image->columns != 0) && (image->rows != 0))
            {
              if ((width >= image->columns) && (height >= image->rows))
                break;
            }
          else
            if (((image->columns != 0) && (width >= image->columns)) ||
                ((image->rows != 0) && (height >= image->rows)))
              break;
        }
        high=draw_info->pointsize;
        for (low=1.0; (high-low) > 0.5; )
        {
          draw_info->pointsize=(low+high)/2.0;
          (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g",
            -metrics.bounds.x1,metrics.ascent);
          if (draw_info->gravity == UndefinedGravity)
            (void) CloneString(&draw_info->geometry,geometry);
          status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
          width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
          height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
          if ((image->columns != 0) && (image->rows != 0))
            {
              if ((width < image->columns) && (height < image->rows))
                low=draw_info->pointsize+0.5;
              else
                high=draw_info->pointsize-0.5;
            }
          else
            if (((image->columns != 0) && (width < image->columns)) ||
                ((image->rows != 0) && (height < image->rows)))
              low=draw_info->pointsize+0.5;
            else
              high=draw_info->pointsize-0.5;
        }
        draw_info->pointsize=(low+high)/2.0-0.5;
      }
   status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
   if (status == MagickFalse)
     {
      draw_info=DestroyDrawInfo(draw_info);
       image=DestroyImageList(image);
       return((Image *) NULL);
     }
  if (image->columns == 0)
    image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5);
  if (image->columns == 0)
    image->columns=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5);
  if (image->rows == 0)
    image->rows=(size_t) (metrics.ascent-metrics.descent+
      draw_info->stroke_width+0.5);
  if (image->rows == 0)
    image->rows=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5);
  status=SetImageExtent(image,image->columns,image->rows,exception);
  if (status == MagickFalse)
    {
      draw_info=DestroyDrawInfo(draw_info);
      return(DestroyImageList(image));
    }
  if (SetImageBackgroundColor(image,exception) == MagickFalse)
    {
      draw_info=DestroyDrawInfo(draw_info);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Draw label.
  */
  (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g",
    draw_info->direction == RightToLeftDirection ? image->columns-
    metrics.bounds.x2 : 0.0,draw_info->gravity == UndefinedGravity ?
    metrics.ascent : 0.0);
  draw_info->geometry=AcquireString(geometry);
  status=AnnotateImage(image,draw_info,exception);
  if (image_info->pointsize == 0.0)
    {
      char
        pointsize[MagickPathExtent];

      (void) FormatLocaleString(pointsize,MagickPathExtent,"%.20g",
        draw_info->pointsize);
      (void) SetImageProperty(image,"label:pointsize",pointsize,exception);
    }
  draw_info=DestroyDrawInfo(draw_info);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  return(GetFirstImageInList(image));
}
Ejemplo n.º 11
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d T E X T I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadTEXTImage() reads a text file and returns it as an image.  It
%  allocates the memory necessary for the new Image structure and returns a
%  pointer to the new image.
%
%  The format of the ReadTEXTImage method is:
%
%      Image *ReadTEXTImage(const ImageInfo *image_info,Image *image,
%        char *text,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o image: the image.
%
%    o text: the text storage buffer.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadTEXTImage(const ImageInfo *image_info,Image *image,
  char *text,ExceptionInfo *exception)
{
  char
    filename[MaxTextExtent],
    geometry[MaxTextExtent],
    *p;

  DrawInfo
    *draw_info;

  Image
    *texture;

  MagickBooleanType
    status;

  PointInfo
    delta;

  RectangleInfo
    page;

  ssize_t
    offset;

  TypeMetric
    metrics;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  /*
    Set the page geometry.
  */
  delta.x=DefaultResolution;
  delta.y=DefaultResolution;
  if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
    {
      GeometryInfo
        geometry_info;

      MagickStatusType
        flags;

      flags=ParseGeometry(PSDensityGeometry,&geometry_info);
      image->x_resolution=geometry_info.rho;
      image->y_resolution=geometry_info.sigma;
      if ((flags & SigmaValue) == 0)
        image->y_resolution=image->x_resolution;
    }
  page.width=612;
  page.height=792;
  page.x=43;
  page.y=43;
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  /*
    Initialize Image structure.
  */
  image->columns=(size_t) floor((((double) page.width*image->x_resolution)/
    delta.x)+0.5);
  image->rows=(size_t) floor((((double) page.height*image->y_resolution)/
    delta.y)+0.5);
  status=SetImageExtent(image,image->columns,image->rows);
  if (status == MagickFalse)
    {
      InheritException(exception,&image->exception);
      return(DestroyImageList(image));
    }
  image->page.x=0;
  image->page.y=0;
  texture=(Image *) NULL;
  if (image_info->texture != (char *) NULL)
    {
      ImageInfo
        *read_info;

      read_info=CloneImageInfo(image_info);
      SetImageInfoBlob(read_info,(void *) NULL,0);
      (void) CopyMagickString(read_info->filename,image_info->texture,
        MaxTextExtent);
      texture=ReadImage(read_info,exception);
      read_info=DestroyImageInfo(read_info);
    }
  /*
    Annotate the text image.
  */
  (void) SetImageBackgroundColor(image);
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  (void) CloneString(&draw_info->text,image_info->filename);
  (void) FormatLocaleString(geometry,MaxTextExtent,"0x0%+ld%+ld",(long) page.x,
    (long) page.y);
  (void) CloneString(&draw_info->geometry,geometry);
  status=GetTypeMetrics(image,draw_info,&metrics);
  if (status == MagickFalse)
    ThrowReaderException(TypeError,"UnableToGetTypeMetrics");
  page.y=(ssize_t) ceil((double) page.y+metrics.ascent-0.5);
  (void) FormatLocaleString(geometry,MaxTextExtent,"0x0%+ld%+ld",(long) page.x,
    (long) page.y);
  (void) CloneString(&draw_info->geometry,geometry);
  (void) CopyMagickString(filename,image_info->filename,MaxTextExtent);
  if (*draw_info->text != '\0')
    *draw_info->text='\0';
  p=text;
  for (offset=2*page.y; p != (char *) NULL; )
  {
    /*
      Annotate image with text.
    */
    (void) ConcatenateString(&draw_info->text,text);
    (void) ConcatenateString(&draw_info->text,"\n");
    offset+=(ssize_t) (metrics.ascent-metrics.descent);
    if (image->previous == (Image *) NULL)
      {
        status=SetImageProgress(image,LoadImageTag,offset,image->rows);
        if (status == MagickFalse)
          break;
      }
    p=ReadBlobString(image,text);
    if ((offset < (ssize_t) image->rows) && (p != (char *) NULL))
      continue;
    if (texture != (Image *) NULL)
      {
        MagickProgressMonitor
          progress_monitor;

        progress_monitor=SetImageProgressMonitor(image,
          (MagickProgressMonitor) NULL,image->client_data);
        (void) TextureImage(image,texture);
        (void) SetImageProgressMonitor(image,progress_monitor,
          image->client_data);
      }
    (void) AnnotateImage(image,draw_info);
    if (p == (char *) NULL)
      break;
    /*
      Page is full-- allocate next image structure.
    */
    *draw_info->text='\0';
    offset=2*page.y;
    AcquireNextImage(image_info,image);
    if (GetNextImageInList(image) == (Image *) NULL)
      {
        image=DestroyImageList(image);
        return((Image *) NULL);
      }
    image->next->columns=image->columns;
    image->next->rows=image->rows;
    image=SyncNextImageInList(image);
    (void) CopyMagickString(image->filename,filename,MaxTextExtent);
    (void) SetImageBackgroundColor(image);
    status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
      GetBlobSize(image));
    if (status == MagickFalse)
      break;
  }
  if (texture != (Image *) NULL)
    {
      MagickProgressMonitor
        progress_monitor;

      progress_monitor=SetImageProgressMonitor(image,
        (MagickProgressMonitor) NULL,image->client_data);
      (void) TextureImage(image,texture);
      (void) SetImageProgressMonitor(image,progress_monitor,image->client_data);
    }
  (void) AnnotateImage(image,draw_info);
  if (texture != (Image *) NULL)
    texture=DestroyImage(texture);
  draw_info=DestroyDrawInfo(draw_info);
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 12
0
static Image *ReadCAPTIONImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    *caption,
    geometry[MaxTextExtent],
    *property;

  const char
    *gravity;

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    status;

  register ssize_t
    i;

  size_t
    height,
    width;

  TypeMetric
    metrics;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  if (image->columns == 0)
    ThrowReaderException(OptionError,"MustSpecifyImageSize");
  (void) ResetImagePage(image,"0x0+0+0");
  /*
    Format caption.
  */
  property=InterpretImageProperties(image_info,image,image_info->filename);
  (void) SetImageProperty(image,"caption",property);
  property=DestroyString(property);
  caption=ConstantString(GetImageProperty(image,"caption"));
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  draw_info->text=ConstantString(caption);
  gravity=GetImageOption(image_info,"gravity");
  if (gravity != (char *) NULL)
    draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
      MagickFalse,gravity);
  if ((*caption != '\0') && (image->rows != 0) &&
      (image_info->pointsize == 0.0))
    {
      char
        *text;

      /*
        Scale text to fit bounding box.
      */
      for ( ; ; )
      {
        text=AcquireString(caption);
        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text);
        (void) CloneString(&draw_info->text,text);
        text=DestroyString(text);
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        (void) status;
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((width > (image->columns+1)) || (height > (image->rows+1)))
          break;
        draw_info->pointsize*=2.0;
      }
      draw_info->pointsize/=2.0;
      for ( ; ; )
      {
        text=AcquireString(caption);
        i=FormatMagickCaption(image,draw_info,MagickFalse,&metrics,&text);
        (void) CloneString(&draw_info->text,text);
        text=DestroyString(text);
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((width > (image->columns+1)) || (height > (image->rows+1)))
          break;
        draw_info->pointsize++;
      }
      draw_info->pointsize--;
    }
  i=FormatMagickCaption(image,draw_info,MagickTrue,&metrics,&caption);
  if (image->rows == 0)
    image->rows=(size_t) ((i+1)*(metrics.ascent-metrics.descent+
      draw_info->interline_spacing+draw_info->stroke_width)+0.5);
  if (image->rows == 0)
    image->rows=(size_t) ((i+1)*draw_info->pointsize+
      draw_info->interline_spacing+draw_info->stroke_width+0.5);
  if (SetImageBackgroundColor(image) == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Draw caption.
  */
  (void) CloneString(&draw_info->text,caption);
  status=GetMultilineTypeMetrics(image,draw_info,&metrics);
  if ((draw_info->gravity != UndefinedGravity) &&
      (draw_info->direction != RightToLeftDirection))
    image->page.x=(ssize_t) (metrics.bounds.x1-draw_info->stroke_width/2.0);
  else
    {
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+
        draw_info->stroke_width/2.0);
      if (draw_info->direction == RightToLeftDirection)
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          image->columns-(metrics.bounds.x2+draw_info->stroke_width/2.0),
          metrics.ascent+draw_info->stroke_width/2.0);
      draw_info->geometry=AcquireString(geometry);
    }
  (void) AnnotateImage(image,draw_info);
  draw_info=DestroyDrawInfo(draw_info);
  caption=DestroyString(caption);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 13
0
static Image *ReadCAPTIONImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    *caption,
    *property;

  const char
    *option;

  DrawInfo
    *draw_info;

  FT_Bitmap
    *canvas;

  Image
    *image;

  PangoAlignment
    align;

  PangoContext
    *context;

  PangoFontDescription
    *description;

  PangoFontMap
    *fontmap;

  PangoGravity
    gravity;

  PangoLayout
    *layout;

  PangoRectangle
    extent;

  PixelPacket
    fill_color;

  RectangleInfo
    page;

  register PixelPacket
    *q;

  register unsigned char
    *p;

  ssize_t
    y;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  (void) ResetImagePage(image,"0x0+0+0");
  /*
    Get context.
  */
  fontmap=(PangoFontMap *) pango_ft2_font_map_new();
  pango_ft2_font_map_set_resolution((PangoFT2FontMap *) fontmap,
    image->x_resolution,image->y_resolution);
  option=GetImageOption(image_info,"caption:hinting");
  pango_ft2_font_map_set_default_substitute((PangoFT2FontMap *) fontmap,
    PangoSubstitute,(char *) option,NULL);
  context=pango_font_map_create_context(fontmap);
  option=GetImageOption(image_info,"caption:language");
  if (option != (const char *) NULL)
    pango_context_set_language(context,pango_language_from_string(option));
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  pango_context_set_base_dir(context,draw_info->direction ==
    RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
  switch (draw_info->gravity)
  {
    case NorthGravity: gravity=PANGO_GRAVITY_NORTH; break;
    case WestGravity: gravity=PANGO_GRAVITY_WEST; break;
    case EastGravity: gravity=PANGO_GRAVITY_EAST; break;
    case SouthGravity: gravity=PANGO_GRAVITY_SOUTH; break;
    default: gravity=PANGO_GRAVITY_AUTO; break;
  }
  pango_context_set_base_gravity(context,gravity);
  option=GetImageOption(image_info,"caption:gravity-hint");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"line") == 0)
        pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE);
      if (LocaleCompare(option,"natural") == 0)
        pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL);
      if (LocaleCompare(option,"strong") == 0)
        pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG);
    }
  /*
    Configure layout.
  */
  layout=pango_layout_new(context);
  option=GetImageOption(image_info,"caption:auto-dir");
  if (option != (const char *) NULL)
    pango_layout_set_auto_dir(layout,1);
  option=GetImageOption(image_info,"caption:ellipsize");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"end") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END);
      if (LocaleCompare(option,"middle") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE);
      if (LocaleCompare(option,"none") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE);
      if (LocaleCompare(option,"start") == 0)
        pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START);
    }
  option=GetImageOption(image_info,"caption:justify");
  if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse))
    pango_layout_set_justify(layout,1);
  option=GetImageOption(image_info,"caption:single-paragraph");
  if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse))
    pango_layout_set_single_paragraph_mode(layout,1);
  option=GetImageOption(image_info,"caption:wrap");
  if (option != (const char *) NULL)
    {
      if (LocaleCompare(option,"char") == 0)
        pango_layout_set_wrap(layout,PANGO_WRAP_CHAR);
      if (LocaleCompare(option,"word") == 0)
        pango_layout_set_wrap(layout,PANGO_WRAP_WORD);
      if (LocaleCompare(option,"word-char") == 0)
        pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR);
    }
  option=GetImageOption(image_info,"caption:indent");
  if (option != (const char *) NULL)
    pango_layout_set_indent(layout,(StringToLong(option)*image->x_resolution*
      PANGO_SCALE+36)/72);
  switch (draw_info->align)
  {
    case CenterAlign: align=PANGO_ALIGN_CENTER; break;
    case RightAlign: align=PANGO_ALIGN_RIGHT; break;
    case LeftAlign:
    default: align=PANGO_ALIGN_LEFT; break;
  }
  if ((align != PANGO_ALIGN_CENTER) &&
      (draw_info->direction == RightToLeftDirection))
    align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align);
  pango_layout_set_alignment(layout,align);
  description=pango_font_description_from_string(draw_info->font ==
    (char *) NULL ? "helvetica" : draw_info->font);
  pango_font_description_set_size(description,PANGO_SCALE*draw_info->pointsize);
  pango_layout_set_font_description(layout,description);
  pango_font_description_free(description);
  property=InterpretImageProperties(image_info,image,image_info->filename);
  (void) SetImageProperty(image,"caption",property);
  property=DestroyString(property);
  caption=ConstantString(GetImageProperty(image,"caption"));
  /*
    Render caption.
  */
  option=GetImageOption(image_info,"caption:markup");
  if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse))
    pango_layout_set_markup(layout,caption,-1);
  else
    pango_layout_set_text(layout,caption,-1);
  pango_layout_context_changed(layout);
  page.x=0;
  page.y=0;
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  if (image->columns == 0)
    {
      pango_layout_get_pixel_extents(layout,NULL,&extent);
      image->columns=extent.x+extent.width;
    }
  else
    {
      image->columns-=2*page.x;
      pango_layout_set_width(layout,(PANGO_SCALE*image->columns*
        image->x_resolution+36.0)/72.0);
    }
  if (image->rows == 0)
    {
      pango_layout_get_pixel_extents(layout,NULL,&extent);
      image->rows=extent.y+extent.height;
    }
  else
    {
      image->rows-=2*page.y;
      pango_layout_set_height(layout,(PANGO_SCALE*image->rows*
        image->y_resolution+36.0)/72.0);
    }
  /*
    Create canvas.
  */
  canvas=(FT_Bitmap *) AcquireMagickMemory(sizeof(*canvas));
  if (canvas == (FT_Bitmap *) NULL)
    {
      draw_info=DestroyDrawInfo(draw_info);
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    }
  canvas->width=image->columns;
  canvas->pitch=(canvas->width+3) & ~3;
  canvas->rows=image->rows;
  canvas->buffer=(unsigned char *) AcquireQuantumMemory(canvas->pitch,
    canvas->rows*sizeof(*canvas->buffer));
  if (canvas->buffer == (unsigned char *) NULL)
    {
      draw_info=DestroyDrawInfo(draw_info);
      canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas);
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    }
  canvas->num_grays=256;
  canvas->pixel_mode=ft_pixel_mode_grays;
  ResetMagickMemory(canvas->buffer,0x00,canvas->pitch*canvas->rows);
  pango_ft2_render_layout(canvas,layout,0,0);
  /*
    Convert caption to image.
  */
  image->columns+=2*page.x;
  image->rows+=2*page.y;
  if (SetImageBackgroundColor(image) == MagickFalse)
    {
      draw_info=DestroyDrawInfo(draw_info);
      canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer);
      canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas);
      caption=DestroyString(caption);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  p=canvas->buffer;
  for (y=page.y; y < (ssize_t) (image->rows-page.y); y++)
  {
    register ssize_t
      x;

    q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    if (q == (PixelPacket *) NULL)
      break;
    q+=page.x;
    for (x=page.x; x < (ssize_t) (image->columns-page.x); x++)
    {
      MagickRealType
        fill_opacity;

      (void) GetFillColor(draw_info,x,y,&fill_color);
      fill_opacity=QuantumRange-(*p)/canvas->num_grays*(QuantumRange-
        fill_color.opacity);
      if (draw_info->text_antialias == MagickFalse)
        fill_opacity=fill_opacity >= 0.5 ? 1.0 : 0.0;
      MagickCompositeOver(&fill_color,fill_opacity,q,q->opacity,q);
      p++;
      q++;
    }
    for ( ; x < (ssize_t) ((canvas->width+3) & ~3); x++)
      p++;
  }
  /*
    Relinquish resources.
  */
  draw_info=DestroyDrawInfo(draw_info);
  canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer);
  canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas);
  caption=DestroyString(caption);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 14
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d M V G I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadMVGImage creates a gradient image and initializes it to
%  the X server color range as specified by the filename.  It allocates the
%  memory necessary for the new Image structure and returns a pointer to the
%  new image.
%
%  The format of the ReadMVGImage method is:
%
%      Image *ReadMVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadMVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
#define BoundingBox  "viewbox"

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    status;

  /*
    Open image.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  if ((image->columns == 0) || (image->rows == 0))
    {
      char
        primitive[MaxTextExtent];

      register char
        *p;

      SegmentInfo
        bounds;

      /*
        Determine size of image canvas.
      */
      while (ReadBlobString(image,primitive) != (char *) NULL)
      {
        for (p=primitive; (*p == ' ') || (*p == '\t'); p++) ;
        if (LocaleNCompare(BoundingBox,p,strlen(BoundingBox)) != 0)
          continue;
        (void) sscanf(p,"viewbox %lf %lf %lf %lf",&bounds.x1,&bounds.y1,
          &bounds.x2,&bounds.y2);
        image->columns=(size_t) floor((bounds.x2-bounds.x1)+0.5);
        image->rows=(size_t) floor((bounds.y2-bounds.y1)+0.5);
        break;
      }
    }
  if ((image->columns == 0) || (image->rows == 0))
    ThrowReaderException(OptionError,"MustSpecifyImageSize");
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  draw_info->affine.sx=image->x_resolution == 0.0 ? 1.0 : image->x_resolution/
    DefaultResolution;
  draw_info->affine.sy=image->y_resolution == 0.0 ? 1.0 : image->y_resolution/
    DefaultResolution;
  image->columns=(size_t) (draw_info->affine.sx*image->columns);
  image->rows=(size_t) (draw_info->affine.sy*image->rows);
  status=SetImageExtent(image,image->columns,image->rows);
  if (status == MagickFalse)
    {
      InheritException(exception,&image->exception);
      return(DestroyImageList(image));
    }
  if (SetImageBackgroundColor(image) == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Render drawing.
  */
  if (GetBlobStreamData(image) == (unsigned char *) NULL)
    draw_info->primitive=FileToString(image->filename,~0UL,exception);
  else
    {
      draw_info->primitive=(char *) AcquireMagickMemory(GetBlobSize(image)+1);
      if (draw_info->primitive != (char *) NULL)
        {
          CopyMagickMemory(draw_info->primitive,GetBlobStreamData(image),
            GetBlobSize(image));
          draw_info->primitive[GetBlobSize(image)]='\0';
        }
     }
  (void) DrawImage(image,draw_info);
  draw_info=DestroyDrawInfo(draw_info);
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 15
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d C A P T I O N I m a g e                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadCAPTIONImage() reads a CAPTION image file and returns it.  It
%  allocates the memory necessary for the new Image structure and returns a
%  pointer to the new image.
%
%  The format of the ReadCAPTIONImage method is:
%
%      Image *ReadCAPTIONImage(const ImageInfo *image_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadCAPTIONImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    *caption,
    geometry[MaxTextExtent],
    *property,
    *text;

  const char
    *gravity,
    *option;

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    split,
    status;

  register ssize_t
    i;

  size_t
    height,
    width;

  TypeMetric
    metrics;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  (void) ResetImagePage(image,"0x0+0+0");
  /*
    Format caption.
  */
  option=GetImageOption(image_info,"filename");
  if (option == (const char *) NULL)
    property=InterpretImageProperties(image_info,image,image_info->filename);
  else
    if (LocaleNCompare(option,"caption:",8) == 0)
      property=InterpretImageProperties(image_info,image,option+8);
    else
      property=InterpretImageProperties(image_info,image,option);
  (void) SetImageProperty(image,"caption",property);
  property=DestroyString(property);
  caption=ConstantString(GetImageProperty(image,"caption"));
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  (void) CloneString(&draw_info->text,caption);
  gravity=GetImageOption(image_info,"gravity");
  if (gravity != (char *) NULL)
    draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
      MagickFalse,gravity);
  split=MagickFalse;
  if (image->columns == 0)
    {
      text=AcquireString(caption);
      i=FormatMagickCaption(image,draw_info,split,&metrics,&text);
      (void) CloneString(&draw_info->text,text);
      text=DestroyString(text);
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1,metrics.ascent);
      if (draw_info->gravity == UndefinedGravity)
        (void) CloneString(&draw_info->geometry,geometry);
      status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
      image->columns=width;
    }
  if (image->rows == 0)
    {
      split=MagickTrue;
      text=AcquireString(caption);
      i=FormatMagickCaption(image,draw_info,split,&metrics,&text);
      (void) CloneString(&draw_info->text,text);
      text=DestroyString(text);
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1,metrics.ascent);
      if (draw_info->gravity == UndefinedGravity)
        (void) CloneString(&draw_info->geometry,geometry);
      status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      image->rows=(size_t) ((i+1)*(metrics.ascent-metrics.descent+
        draw_info->interline_spacing+draw_info->stroke_width)+0.5);
    }
  if (fabs(image_info->pointsize) < MagickEpsilon)
    {
      double
        high,
        low;

      /*
        Auto fit text into bounding box.
      */
      for ( ; ; draw_info->pointsize*=2.0)
      {
        text=AcquireString(caption);
        i=FormatMagickCaption(image,draw_info,split,&metrics,&text);
        (void) CloneString(&draw_info->text,text);
        text=DestroyString(text);
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        (void) status;
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((image->columns != 0) && (image->rows != 0))
          {
            if ((width >= image->columns) && (height >= image->rows))
              break;
          }
        else
          if (((image->columns != 0) && (width >= image->columns)) ||
              ((image->rows != 0) && (height >= image->rows)))
            break;
      }
      high=draw_info->pointsize;
      for (low=1.0; (high-low) > 0.5; )
      {
        draw_info->pointsize=(low+high)/2.0;
        text=AcquireString(caption);
        i=FormatMagickCaption(image,draw_info,split,&metrics,&text);
        (void) CloneString(&draw_info->text,text);
        text=DestroyString(text);
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((image->columns != 0) && (image->rows != 0))
          {
            if ((width < image->columns) && (height < image->rows))
              low=draw_info->pointsize+0.5;
            else
              high=draw_info->pointsize-0.5;
          }
        else
          if (((image->columns != 0) && (width < image->columns)) ||
              ((image->rows != 0) && (height < image->rows)))
            low=draw_info->pointsize+0.5;
          else
            high=draw_info->pointsize-0.5;
      }
      draw_info->pointsize=(low+high)/2.0-0.5;
    }
  (void) CloneString(&draw_info->text,caption);
  i=FormatMagickCaption(image,draw_info,split,&metrics,&caption);
  if (SetImageBackgroundColor(image) == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Draw caption.
  */
  (void) CloneString(&draw_info->text,caption);
  status=GetMultilineTypeMetrics(image,draw_info,&metrics);
  if ((draw_info->gravity != UndefinedGravity) &&
      (draw_info->direction != RightToLeftDirection))
    image->page.x=(ssize_t) (metrics.bounds.x1-draw_info->stroke_width/2.0);
  else
    {
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+
        draw_info->stroke_width/2.0);
      if (draw_info->direction == RightToLeftDirection)
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          image->columns-(metrics.bounds.x2+draw_info->stroke_width/2.0),
          metrics.ascent+draw_info->stroke_width/2.0);
      draw_info->geometry=AcquireString(geometry);
    }
  status=AnnotateImage(image,draw_info);
  draw_info=DestroyDrawInfo(draw_info);
  caption=DestroyString(caption);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  return(GetFirstImageInList(image));
}
Ejemplo n.º 16
0
static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
                                      XCFLayerInfo *outLayer )
{
    long
    i;

    MagickOffsetType
    offset;

    unsigned int
    foundPropEnd = 0;

    unsigned long
    hierarchy_offset,
    layer_mask_offset;

    /* clear the block! */
    (void) ResetMagickMemory( outLayer, 0, sizeof( XCFLayerInfo ) );
    /* read in the layer width, height, type and name */
    outLayer->width = ReadBlobMSBLong(image);
    outLayer->height = ReadBlobMSBLong(image);
    outLayer->type = ReadBlobMSBLong(image);
    (void) ReadBlobStringWithLongSize(image, outLayer->name,
                                      sizeof(outLayer->name));
    /* allocate the image for this layer */
    outLayer->image=CloneImage(image,outLayer->width, outLayer->height,MagickTrue,
                               &image->exception);
    if (outLayer->image == (Image *) NULL)
        return MagickFalse;
    /* read the layer properties! */
    foundPropEnd = 0;
    while ( (foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse) ) {
        PropType    prop_type = (PropType) ReadBlobMSBLong(image);
        unsigned long  prop_size = ReadBlobMSBLong(image);
        switch (prop_type)
        {
        case PROP_END:
            foundPropEnd = 1;
            break;
        case PROP_ACTIVE_LAYER:
            outLayer->active = 1;
            break;
        case PROP_FLOATING_SELECTION:
            outLayer->floating_offset = ReadBlobMSBLong(image);
            break;
        case PROP_OPACITY:
            outLayer->opacity = ReadBlobMSBLong(image);
            break;
        case PROP_VISIBLE:
            outLayer->visible = ReadBlobMSBLong(image);
            break;
        case PROP_LINKED:
            outLayer->linked = ReadBlobMSBLong(image);
            break;
        case PROP_PRESERVE_TRANSPARENCY:
            outLayer->preserve_trans = ReadBlobMSBLong(image);
            break;
        case PROP_APPLY_MASK:
            outLayer->apply_mask = ReadBlobMSBLong(image);
            break;
        case PROP_EDIT_MASK:
            outLayer->edit_mask = ReadBlobMSBLong(image);
            break;
        case PROP_SHOW_MASK:
            outLayer->show_mask = ReadBlobMSBLong(image);
            break;
        case PROP_OFFSETS:
            outLayer->offset_x = (long) ReadBlobMSBLong(image);
            outLayer->offset_y = (long) ReadBlobMSBLong(image);
            break;
        case PROP_MODE:
            outLayer->mode = ReadBlobMSBLong(image);
            break;
        case PROP_TATTOO:
            outLayer->preserve_trans = ReadBlobMSBLong(image);
            break;
        case PROP_PARASITES:
        {
            for (i=0; i < (long) prop_size; i++ )
                (void) ReadBlobByte(image);

            /*
            long base = info->cp;
            GimpParasite *p;
            while (info->cp - base < prop_size)
            {
            p = xcf_load_parasite(info);
            gimp_drawable_parasite_attach(GIMP_DRAWABLE(layer), p);
            gimp_parasite_free(p);
            }
            if (info->cp - base != prop_size)
            g_message ("Error detected while loading a layer's parasites");
            */
        }
        break;
        default:
            /* g_message ("unexpected/unknown layer property: %d (skipping)",
               prop_type); */

        {
            int buf[16];
            ssize_t amount;

            /* read over it... */
            while ((prop_size > 0) && (EOFBlob(image) == MagickFalse))
            {
                amount = (ssize_t) MagickMin(16, prop_size);
                amount = ReadBlob(image, (size_t) amount, (unsigned char *) &buf);
                if (!amount)
                    ThrowBinaryException(CorruptImageError,"CorruptImage",
                                         image->filename);
                prop_size -= (unsigned long) MagickMin(16, (size_t) amount);
            }
        }
        break;
        }
    }

    if (foundPropEnd == MagickFalse)
        return(MagickFalse);
    /* clear the image based on the layer opacity */
    outLayer->image->background_color.opacity=
        ScaleCharToQuantum((unsigned char) (255-outLayer->opacity));
    (void) SetImageBackgroundColor(outLayer->image);

    /* set the compositing mode */
    outLayer->image->compose = GIMPBlendModeToCompositeOperator( outLayer->mode );
    if ( outLayer->visible == MagickFalse )
    {
        /* BOGUS: should really be separate member var! */
        outLayer->image->compose = NoCompositeOp;
    }

    /* read the hierarchy and layer mask offsets */
    hierarchy_offset = ReadBlobMSBLong(image);
    layer_mask_offset = ReadBlobMSBLong(image);

    /* read in the hierarchy */
    offset=SeekBlob(image, (MagickOffsetType) hierarchy_offset, SEEK_SET);
    if (offset < 0)
        (void) ThrowMagickException(&image->exception,GetMagickModule(),
                                    CorruptImageError,"InvalidImageHeader","`%s'",image->filename);
    if (load_hierarchy (image, inDocInfo, outLayer) == 0)
        return(MagickFalse);

    /* read in the layer mask */
    if (layer_mask_offset != 0)
    {
        offset=SeekBlob(image, (MagickOffsetType) layer_mask_offset, SEEK_SET);

#if 0  /* BOGUS: support layer masks! */
        layer_mask = xcf_load_layer_mask (info, gimage);
        if (layer_mask == 0)
            goto error;

        /* set the offsets of the layer_mask */
        GIMP_DRAWABLE (layer_mask)->offset_x = GIMP_DRAWABLE (layer)->offset_x;
        GIMP_DRAWABLE (layer_mask)->offset_y = GIMP_DRAWABLE (layer)->offset_y;

        gimp_layer_add_mask (layer, layer_mask, MagickFalse);

        layer->mask->apply_mask = apply_mask;
        layer->mask->edit_mask  = edit_mask;
        layer->mask->show_mask  = show_mask;
#endif
    }

    /* attach the floating selection... */
#if 0  /* BOGUS: we may need to read this, even if we don't support it! */
    if (add_floating_sel)
    {
        GimpLayer *floating_sel;

        floating_sel = info->floating_sel;
        floating_sel_attach (floating_sel, GIMP_DRAWABLE (layer));
    }
#endif

    return MagickTrue;
}
Ejemplo n.º 17
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d L A B E L I m a g e                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadLABELImage() reads a LABEL image file and returns it.  It
%  allocates the memory necessary for the new Image structure and returns a
%  pointer to the new image.
%
%  The format of the ReadLABELImage method is:
%
%      Image *ReadLABELImage(const ImageInfo *image_info,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadLABELImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  char
    geometry[MaxTextExtent],
    *property;

  const char
    *label;

  DrawInfo
    *draw_info;

  Image
    *image;

  MagickBooleanType
    status;

  TypeMetric
    metrics;

  size_t
    height,
    width;

  /*
    Initialize Image structure.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  (void) ResetImagePage(image,"0x0+0+0");
  property=InterpretImageProperties(image_info,image,image_info->filename);
  (void) SetImageProperty(image,"label",property);
  property=DestroyString(property);
  label=GetImageProperty(image,"label");
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  draw_info->text=ConstantString(label);
  status=GetMultilineTypeMetrics(image,draw_info,&metrics);
  if (image->columns == 0)
    {
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1,metrics.ascent);
      if (draw_info->gravity == UndefinedGravity)
        (void) CloneString(&draw_info->geometry,geometry);
      status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      (void) status;
      image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
    }
  if (image->rows == 0)
    {
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1,metrics.ascent);
      if (draw_info->gravity == UndefinedGravity)
        (void) CloneString(&draw_info->geometry,geometry);
      status=GetMultilineTypeMetrics(image,draw_info,&metrics);
      image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
    }
  if (image_info->pointsize == 0.0)
    {
      double
        high,
        low;

      /*
        Auto fit text into bounding box.
      */
      for ( ; ; draw_info->pointsize*=2.0)
      {
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        (void) status;
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((width >= image->columns) && (height >= image->rows))
          break;
        if ((width >= (image->columns << 1)) || (height >= (image->rows << 1)))
          break;
      }
      high=draw_info->pointsize/2.0;
      for (low=high/2.0; (high-low) > 1.0; )
      {
        draw_info->pointsize=(low+high)/2.0;
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((width <= image->columns) && (height <= image->rows))
          low=draw_info->pointsize+1.0;
        else
          high=draw_info->pointsize-1.0;
      }
      for (draw_info->pointsize=(low+high)/2.0; (high-low) > 1.0; )
      {
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          -metrics.bounds.x1,metrics.ascent);
        if (draw_info->gravity == UndefinedGravity)
          (void) CloneString(&draw_info->geometry,geometry);
        status=GetMultilineTypeMetrics(image,draw_info,&metrics);
        width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
        height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
        if ((width <= image->columns) && (height <= image->rows))
          break;
        draw_info->pointsize--;
      }
      draw_info->pointsize=floor(draw_info->pointsize+0.5);
    }
  status=GetMultilineTypeMetrics(image,draw_info,&metrics);
  if (status == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  if (draw_info->gravity == UndefinedGravity)
    {
      (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
        -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+
        draw_info->stroke_width/2.0);
      (void) CloneString(&draw_info->geometry,geometry);
    }
  if (draw_info->direction == RightToLeftDirection)
    {
      if (draw_info->direction == RightToLeftDirection)
        (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",
          image->columns-(metrics.bounds.x2+draw_info->stroke_width/2.0),
          metrics.ascent+draw_info->stroke_width/2.0);
      (void) CloneString(&draw_info->geometry,geometry);
    }
  if (SetImageBackgroundColor(image) == MagickFalse)
    {
      InheritException(exception,&image->exception);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  (void) AnnotateImage(image,draw_info);
  if (image_info->pointsize == 0.0)
    {
      char
        pointsize[MaxTextExtent];

      (void) FormatLocaleString(pointsize,MaxTextExtent,"%.20g",
        draw_info->pointsize);
      (void) SetImageProperty(image,"label:pointsize",pointsize);
    }
  draw_info=DestroyDrawInfo(draw_info);
  return(GetFirstImageInList(image));
}
Ejemplo n.º 18
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   V a l i d a t e I m p o r t E x p o r t P i x e l s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ValidateImportExportPixels() validates the pixel import and export methods.
%  It returns the number of validation tests that passed and failed.
%
%  The format of the ValidateImportExportPixels method is:
%
%      unsigned long ValidateImportExportPixels(ImageInfo *image_info,
%        const char *reference_filename,const char *output_filename,
%        unsigned long *fail,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o reference_filename: the reference image filename.
%
%    o output_filename: the output image filename.
%
%    o fail: return the number of validation tests that pass.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static unsigned long ValidateImportExportPixels(ImageInfo *image_info,
  const char *reference_filename,const char *output_filename,
  unsigned long *fail,ExceptionInfo *exception)
{
  double
    distortion;

  Image
    *difference_image,
    *reference_image,
    *reconstruct_image;

  MagickBooleanType
    status;

  register long
    i,
    j;

  size_t
    length;

  unsigned char
    *pixels;

  unsigned long
    test;

  (void) output_filename;
  test=0;
  (void) fprintf(stdout,"validate the import and export of image pixels:\n");
  for (i=0; reference_map[i] != (char *) NULL; i++)
  {
    for (j=0; reference_storage[j].type != UndefinedPixel; j++)
    {
      /*
        Generate reference image.
      */
      CatchException(exception);
      (void) fprintf(stdout,"  test %lu: %s/%s",test++,
        reference_map[i],MagickOptionToMnemonic(MagickStorageOptions,
        reference_storage[j].type));
      (void) CopyMagickString(image_info->filename,reference_filename,
        MaxTextExtent);
      reference_image=ReadImage(image_info,exception);
      if (reference_image == (Image *) NULL)
        {
          (void) fprintf(stdout,"... fail @ %s/%s/%lu.\n",GetMagickModule());
          (*fail)++;
          continue;
        }
      if (LocaleNCompare(reference_map[i],"cmy",3) == 0)
        (void) TransformImageColorspace(reference_image,CMYKColorspace);
      length=strlen(reference_map[i])*reference_image->columns*
        reference_image->rows*reference_storage[j].quantum;
      pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
      if (pixels == (unsigned char *) NULL)
        {
          (void) fprintf(stdout,"... fail @ %s/%s/%lu.\n",GetMagickModule());
          (*fail)++;
          reference_image=DestroyImage(reference_image);
          continue;
        }
      (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
      status=ExportImagePixels(reference_image,0,0,reference_image->columns,
        reference_image->rows,reference_map[i],reference_storage[j].type,pixels,
        exception);
      if (status == MagickFalse)
        {
          (void) fprintf(stdout,"... fail @ %s/%s/%lu.\n",GetMagickModule());
          (*fail)++;
          pixels=(unsigned char *) RelinquishMagickMemory(pixels);
          reference_image=DestroyImage(reference_image);
          continue;
        }
      (void) SetImageBackgroundColor(reference_image);
      status=ImportImagePixels(reference_image,0,0,reference_image->columns,
        reference_image->rows,reference_map[i],reference_storage[j].type,
        pixels);
      InheritException(exception,&reference_image->exception);
      if (status == MagickFalse)
        {
          (void) fprintf(stdout,"... fail @ %s/%s/%lu.\n",GetMagickModule());
          (*fail)++;
           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
          reference_image=DestroyImage(reference_image);
          continue;
        }
      /*
        Read reconstruct image.
      */
      reconstruct_image=AcquireImage(image_info);
      (void) SetImageColorspace(reconstruct_image,reference_image->colorspace);
      (void) SetImageExtent(reconstruct_image,reference_image->columns,
        reference_image->rows);
      (void) SetImageBackgroundColor(reconstruct_image);
      status=ImportImagePixels(reconstruct_image,0,0,reconstruct_image->columns,
        reconstruct_image->rows,reference_map[i],reference_storage[j].type,
        pixels);
      InheritException(exception,&reconstruct_image->exception);
      pixels=(unsigned char *) RelinquishMagickMemory(pixels);
      if (status == MagickFalse)
        {
          (void) fprintf(stdout,"... fail @ %s/%s/%lu.\n",GetMagickModule());
          (*fail)++;
          reference_image=DestroyImage(reference_image);
          continue;
        }
      /*
        Compare reference to reconstruct image.
      */
      difference_image=CompareImageChannels(reference_image,reconstruct_image,
        AllChannels,MeanSquaredErrorMetric,&distortion,exception);
      reconstruct_image=DestroyImage(reconstruct_image);
      reference_image=DestroyImage(reference_image);
      if (difference_image == (Image *) NULL)
        {
          (void) fprintf(stdout,"... fail @ %s/%s/%lu.\n",GetMagickModule());
          (*fail)++;
          continue;
        }
      difference_image=DestroyImage(difference_image);
      if ((distortion/QuantumRange) > 0.0)
        {
          (void) fprintf(stdout,"... fail (with distortion %g).\n",distortion/
            QuantumRange);
          (*fail)++;
          continue;
        }
      (void) fprintf(stdout,"... pass.\n");
    }
  }
  (void) fprintf(stdout,"  summary: %lu subtests; %lu passed; %lu failed.\n",
    test,test-(*fail),*fail);
  return(test);
}
Ejemplo n.º 19
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d T X T I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadTXTImage() reads a text file and returns it as an image.  It allocates
%  the memory necessary for the new Image structure and returns a pointer to
%  the new image.
%
%  The format of the ReadTXTImage method is:
%
%      Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    colorspace[MaxTextExtent],
    text[MaxTextExtent];

  Image
    *image;

  IndexPacket
    *indexes;

  long
    type,
    x,
    y;

  LongPixelPacket
    pixel;

  MagickBooleanType
    status;

  QuantumAny
    range;

  register long
    i;

  register PixelPacket
    *q;

  ssize_t
    count;

  unsigned long
    depth,
    max_value;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  (void) ResetMagickMemory(text,0,sizeof(text));
  (void) ReadBlobString(image,text);
  if (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) != 0)
    return(ReadTEXTImage(image_info,image,text,exception));
  *colorspace='\0';
  count=(ssize_t) sscanf(text+32,"%lu,%lu,%lu,%s",&image->columns,
    &image->rows,&max_value,colorspace);
  if (count != 4)
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  for (depth=1; (GetQuantumRange(depth)+1) < max_value; depth++) ;
  image->depth=depth;
  LocaleLower(colorspace);
  i=(long) strlen(colorspace)-1;
  image->matte=MagickFalse;
  if ((i > 0) && (colorspace[i] == 'a'))
    {
      colorspace[i]='\0';
      image->matte=MagickTrue;
    }
  type=ParseMagickOption(MagickColorspaceOptions,MagickFalse,colorspace);
  if (type < 0)
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  image->colorspace=(ColorspaceType) type;
  (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
  (void) SetImageBackgroundColor(image);
  range=GetQuantumRange(image->depth);
  while (ReadBlobString(image,text) != (char *) NULL)
  {
    if (image->colorspace == CMYKColorspace)
      {
        if (image->matte != MagickFalse)
          count=(ssize_t) sscanf(text,"%ld,%ld: (%lu,%lu,%lu,%lu,%lu",&x,&y,
            &pixel.red,&pixel.green,&pixel.blue,&pixel.index,&pixel.opacity);
        else
          count=(ssize_t) sscanf(text,"%ld,%ld: (%lu,%lu,%lu,%lu",&x,&y,
            &pixel.red,&pixel.green,&pixel.blue,&pixel.index);
      }
    else
      if (image->matte != MagickFalse)
        count=(ssize_t) sscanf(text,"%ld,%ld: (%lu,%lu,%lu,%lu",&x,&y,
          &pixel.red,&pixel.green,&pixel.blue,&pixel.opacity);
      else
        count=(ssize_t) sscanf(text,"%ld,%ld: (%lu,%lu,%lu",&x,&y,
          &pixel.red,&pixel.green,&pixel.blue);
    if (count < 5)
      continue;
    q=GetAuthenticPixels(image,x,y,1,1,exception);
    if (q == (PixelPacket *) NULL)
      continue;
    q->red=ScaleAnyToQuantum(pixel.red,range);
    q->green=ScaleAnyToQuantum(pixel.green,range);
    q->blue=ScaleAnyToQuantum(pixel.blue,range);
    if (image->colorspace == CMYKColorspace)
      {
        indexes=GetAuthenticIndexQueue(image);
        *indexes=ScaleAnyToQuantum(pixel.index,range);
      }
    if (image->matte != MagickFalse)
      q->opacity=(Quantum) (QuantumRange-ScaleAnyToQuantum(pixel.opacity,
        range));
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
      break;
  }
  return(GetFirstImageInList(image));
}