Пример #1
0
static void FormatLabel(ImageInfo *image_info,char *label,
  const unsigned int width,unsigned int *font_height)
{
  Image
    *image;

  MonitorHandler
    handler;

  register char
    *p,
    *q;

  if (label == (const char *) NULL)
    return;
  if (*label == '\0')
    return;
  if (strchr(label,'\n') != (char *) NULL)
    return;
  /*
    Format label to fit within a specified width.
  */
  handler=SetMonitorHandler((MonitorHandler) NULL);
  p=label;
  for (q=p+1; *q != '\0'; q++)
  {
    (void) strcpy(image_info->filename,"label:");
    (void) strncat(image_info->filename+6,p,(int) (q-p+1));
    image=ReadImage(image_info);
    if (image == (Image *) NULL)
      break;
    if (image->columns > width)
      {
        while (!isspace((int) (*q)) && (q > p))
          q--;
        if (q == p)
          break;
        *q='\n';
        p=q+1;
      }
    if (image->rows > *font_height)
      *font_height=image->rows;
    DestroyImage(image);
  }
  (void) SetMonitorHandler(handler);
}
Пример #2
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d P W P I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method ReadPWPImage reads a Seattle Film Works multi-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 ReadPWPImage method is:
%
%      Image *ReadPWPImage(const ImageInfo *image_info,ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image:  Method ReadPWPImage returns a pointer to the image after
%      reading.  A null image is returned if there is a memory shortage or
%      if the image cannot be read.
%
%    o image_info: Specifies a pointer to a ImageInfo structure.
%
%    o exception: return any errors or warnings in this structure.
%
%
*/
static Image *ReadPWPImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  FILE
    *file;

  Image
    *image,
    *next_image,
    *pwp_image;

  ImageInfo
    *clone_info;

  int
    c;

  MonitorHandler
    handler;

  register Image
    *p;

  register unsigned long
    i;

  size_t
    count;

  unsigned char
    magick[MaxTextExtent];

  unsigned int
    status;

  unsigned long
    filesize;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  image=(Image *) NULL;
  pwp_image=AllocateImage(image_info);
  status=OpenBlob(image_info,pwp_image,ReadBinaryBlobMode,exception);
  if (status == False)
    ThrowReaderException(FileOpenError,UnableToOpenFile,pwp_image);
  count=ReadBlob(pwp_image,5,(char *) magick);
  if ((count == 0) || (LocaleNCompare((char *) magick,"SFW95",5) != 0))
    ThrowReaderException(CorruptImageError,ImproperImageHeader,pwp_image);
  clone_info=CloneImageInfo(image_info);
  clone_info->blob=(void *) NULL;
  clone_info->length=0;
  for ( ; ; )
  {
    for (c=ReadBlobByte(pwp_image); c != EOF; c=ReadBlobByte(pwp_image))
    {
      for (i=0; i < 17; i++)
        magick[i]=magick[i+1];
      magick[17]=(unsigned char) c;
      if (LocaleNCompare((char *) (magick+12),"SFW94A",6) == 0)
        break;
    }
    if (c == EOF)
      break;
    if (LocaleNCompare((char *) (magick+12),"SFW94A",6) != 0)
      {
        ThrowReaderException(CorruptImageError,ImproperImageHeader,pwp_image);
      }
    /*
      Dump SFW image to a temporary file.
    */
    file=AcquireTemporaryFileStream(clone_info->filename,BinaryFileIOMode);
    if (file == (FILE *) NULL)
      {
        char
          filename[MaxTextExtent];

        (void) strcpy(filename,clone_info->filename);
        DestroyImageInfo(clone_info);
        ThrowReaderTemporaryFileException(filename);
      }
    (void) fwrite("SFW94A",1,6,file);
    filesize=(65535L*magick[2]+256L*magick[1]+magick[0]) & 0xFFFFFFFF;
    for (i=0; i < filesize; i++)
    {
      if ((c=ReadBlobByte(pwp_image)) == EOF)
        break;
      (void) fputc(c,file);
    }
    (void) fclose(file);
    if (c == EOF)
      break;
    handler=SetMonitorHandler((MonitorHandler) NULL);
    next_image=ReadImage(clone_info,exception);
    (void) LiberateTemporaryFile(clone_info->filename);
    (void) SetMonitorHandler(handler);
    if (next_image == (Image *) NULL)
      break;
    FormatString(next_image->filename,"slide_%02ld.sfw",next_image->scene);
    if (image == (Image *) NULL)
      image=next_image;
    else
      {
        /*
          Link image into image list.
        */
        for (p=image; p->next != (Image *) NULL; p=p->next);
        next_image->previous=p;
        next_image->scene=p->scene+1;
        p->next=next_image;
      }
    if (image_info->subrange != 0)
      if (next_image->scene >= (image_info->subimage+image_info->subrange-1))
        break;
    if (!MagickMonitorFormatted(TellBlob(pwp_image),GetBlobSize(image),
                                &image->exception,LoadImagesText,
                                image->filename))
      break;
  }
  DestroyImageInfo(clone_info);
  CloseBlob(pwp_image);
  DestroyImage(pwp_image);
  if (EOFBlob(image))
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
      image->filename);
  CloseBlob(image);
  return(image);
}
Пример #3
0
Export Image *MontageImages(const Image *images,const MontageInfo *montage_info)
{
#define MontageImageText  "  Creating visual image directory...  "
#define TileImageText  "  Creating image tiles...  "

  AnnotateInfo
    *annotate_info;

  char
    geometry[MaxTextExtent];

  FrameInfo
    frame_info;

  Image
    *image,
    **image_list,
    **master_list,
    *montage_image,
    *texture,
    *tiled_image;

  ImageInfo
    *local_info;

  int
    x,
    x_offset,
    y,
    y_offset;

  MonitorHandler
    handler;

  register int
    i;

  register PixelPacket
    *q;

  RectangleInfo
    bounding_box,
    tile_info;

  unsigned int
    border_width,
    bevel_width,
    concatenate,
    count,
    font_height,
    height,
    images_per_page,
    max_height,
    number_images,
    number_lines,
    tile,
    tiles,
    tiles_per_column,
    tiles_per_row,
    tiles_per_page,
    title_offset,
    total_tiles,
    width;

  assert(images != (Image *) NULL);
  assert(montage_info != (MontageInfo *) NULL);
  /*
    Convert image list to an image group.
  */
  image_list=ListToGroupImage(images,&number_images);
  if (image_list == (Image **) NULL)
    {
      MagickWarning(ResourceLimitWarning,"Unable to montage image_list",
        "Memory allocation failed");
      return((Image *) NULL);
    }
  master_list=image_list;
  /*
    Create image tiles.
  */
  for (tile=0; tile < number_images; tile++)
  {
    handler=SetMonitorHandler((MonitorHandler) NULL);
    width=image_list[tile]->columns;
    height=image_list[tile]->rows;
    x=0;
    y=0;
    (void) ParseImageGeometry(montage_info->geometry,&x,&y,&width,&height);
    image_list[tile]->orphan=True;
    tiled_image=ZoomImage(image_list[tile],width,height);
    if (tiled_image == (Image *) NULL)
      {
        for (i=0; i < (int) tile; i++)
          DestroyImage(image_list[i]);
        (void) SetMonitorHandler(handler);
        return((Image *) NULL);
      }
    image_list[tile]=tiled_image;
    (void) SetMonitorHandler(handler);
    ProgressMonitor(TileImageText,tile,number_images);
  }
  /*
    Sort image_list by increasing tile number.
  */
  for (tile=0; tile < number_images; tile++)
    if (image_list[tile]->scene == 0)
      break;
  if (tile == number_images)
    qsort((void *) image_list,number_images,sizeof(Image *),
      (int (*)(const void *, const void *)) SceneCompare);
  /*
    Determine tiles per row and column.
  */
  tiles_per_row=1;
  tiles_per_column=1;
  while ((tiles_per_row*tiles_per_column) < number_images)
  {
    tiles_per_row++;
    tiles_per_column++;
  }
  if (montage_info->tile != (char *) NULL)
    {
      tiles_per_column=number_images;
      x=0;
      y=0;
      (void) ParseGeometry(montage_info->tile,&x,&y,&tiles_per_row,
        &tiles_per_column);
    }
  /*
    Determine tile sizes.
  */
  border_width=montage_info->border_width;
  bevel_width=0;
  if (montage_info->frame != (char *) NULL)
    {
      int
        flags;

      frame_info.width=0;
      frame_info.height=0;
      frame_info.outer_bevel=0;
      frame_info.inner_bevel=0;
      flags=ParseGeometry(montage_info->frame,&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 & XValue) == 0)
        frame_info.outer_bevel=(frame_info.width >> 2)+1;
      if ((flags & YValue) == 0)
        frame_info.inner_bevel=frame_info.outer_bevel;
      frame_info.x=frame_info.width;
      frame_info.y=frame_info.height;
      bevel_width=Max(frame_info.inner_bevel,frame_info.outer_bevel);
      border_width=Max(frame_info.width,frame_info.height);
    }
Пример #4
0
Файл: txt.c Проект: airhuman/cwf
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d T X T I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method 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:  Method ReadTXTImage returns a pointer to the image after
%      reading. A null image is returned if there is a memory shortage or if
%      the image cannot be read.
%
%    o image_info: Specifies a pointer to a ImageInfo structure.
%
%    o exception: return any errors or warnings in this structure.
%
%
*/
static Image *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    filename[MaxTextExtent],
    geometry[MaxTextExtent],
    *p,
    text[MaxTextExtent];

  double
    dx_resolution,
    dy_resolution;

  DrawInfo
    *draw_info;

  Image
    *image,
    *texture;

  long
    count,
    offset;

  RectangleInfo
    page;

  TypeMetric
    metrics;

  unsigned int
    status;
  int logging;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);

  logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); 
  image=AllocateImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == False)
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);

  p = ReadBlobString(image,text);
  status = IsTXT((unsigned char *)p,strlen(p));
  if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
				    "File type: %d", status);

  if(status)
    {
      unsigned x,y;
      unsigned x_min,x_max,y_curr;
      int ch;
      unsigned long max,i;
      char NumOfPlanes;
      unsigned char *BImgBuff;
      magick_uint16_t *WImgBuff;
      magick_uint32_t *DImgBuff;
      magick_uint32_t R,G,B,A;
      const PixelPacket *q;
      ImportPixelAreaOptions import_options;

      (void) SeekBlob(image,0,SEEK_SET);    

      A=0;
      x=0;
      y=0;
      max=0;

      switch(status)
	{
	case TXT_GM8B_HEX:
	case TXT_GM8B_HEX_Q:  max=255; break;
	case TXT_GM16B_HEX:
	case TXT_GM16B_HEX_Q: max=65535; break;	
	case TXT_GM32B_HEX:	
	case TXT_GM32B_HEX_Q: max=65536; break;
	}

      if(!strncmp(p,"# ImageMagick pixel enumeration:",32))
	{
	  if(sscanf(p+32,"%u,%u,%u",&x_min,&y_curr,&x_max)==3)
	    {
	      if(strstr(p+32,",rgb")!=NULL)
		{
		  x = x_min-1;
		  y = y_curr-1;
		  max = x_max;
		}
	      if(strstr(p+32,",rgba")!=NULL)
		{
		  status = IMAGEMAGICK_TXT_Q;
		}
	    }
	}

      ch=0;
      if(x==0 && y==0) while(!EOFBlob(image))	/* auto detect sizes and num of planes */
	{
	  while(!(ch>='0' && ch<='9'))
	    {             /* go to the begin of number */
	      ch = ReadBlobByte(image);
	      if(ch==EOF) goto EndReading;
	      if(ch=='#') 
		{readln(image,&ch); continue;}
	      if(ch==0 || ch>128 || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))
		{
		TXT_FAIL:			/* not a text data */
		  ThrowReaderException(CoderError,ImageTypeNotSupported,image);
		}
	    }
	  /* x,y: (R,G,B) */
	  i = ReadInt(image,&ch);		/* x */
	  if(i>x) x=i;

	  while(ch!=',')
	    {  
	      ch = ReadBlobByte(image);
	      if(ch==EOF) break;
	      if(ch==10 || ch==13) goto TXT_FAIL;
	    }
	  ch=0;
	  i=ReadInt(image,&ch);		/* y */
	  if(i>y) y=i;

	  while(ch!=':')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==10 || ch==13) goto TXT_FAIL;
	      if(ch==EOF) break;
	    }
	  if(status!=TXT_GM8B_PLAIN2_Q)
	    while(ch!='(')
	      {
		ch = ReadBlobByte(image);
		if(ch==10 || ch==13) goto TXT_FAIL;
		if(ch==EOF) break;
	      }
	  ch=0;
	  R = ReadInt(image,&ch);		/* R */
	  if(R>max) max=R;

	  while(ch!=',')
	    { 
	      ch = ReadBlobByte(image);
	      if(ch==10 || ch==13) goto TXT_FAIL;
	      if(ch==EOF) break;
	    }
	  ch=0;
	  G = ReadInt(image,&ch);		/* G */
	  if(G>max) max=G;

	  while(ch!=',')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==10 || ch==13) goto TXT_FAIL;
	      if(ch==EOF) break;
	    }
	  ch=0;
	  B = ReadInt(image,&ch);		/* B */
	  if(B>max) max=B;

	  if(status>16)
	    {
	      while(ch!=',')
		{
		  ch = ReadBlobByte(image);
		  if(ch==10 || ch==13) goto TXT_FAIL;
		  if(ch==EOF) break;
		}
	      ch=0;
	      A = ReadInt(image,&ch);		/* A */
	      if(A>max) max=A;
	    }

	  if(status!=TXT_GM8B_PLAIN2_Q)
	    while(ch!=')')
	      {
		ch = ReadBlobByte(image);
		if(ch==10 || ch==13) goto TXT_FAIL;
		if(ch==EOF) break;
	      }

	  readln(image,&ch);
	}

    EndReading:
      x_min = 1; x_max = 0;
      y_curr = 0;

      NumOfPlanes=8;
      /*   if(max>=    2) i=2; */
      /*   if(max>=    4) i=4; */
      /*   if(max>=   16) i=8; */
      if(max>=  256) NumOfPlanes=16;
      if(max>=65536) NumOfPlanes=32;

      if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
					"Image detected [%u * %u]: %d", x, y, NumOfPlanes);

      image->depth = Min(QuantumDepth,NumOfPlanes);
      ImportPixelAreaOptionsInit(&import_options);
      import_options.endian = NativeEndian;
  
      BImgBuff = MagickAllocateMemory(unsigned char *,
				      (size_t)(x+1) * ( ((status>16)?4:3) * NumOfPlanes/8));  
      WImgBuff = (magick_uint16_t *)BImgBuff;
      DImgBuff = (magick_uint32_t *)BImgBuff;  
      if(BImgBuff==NULL) 
	ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
  
      image->columns = x+1;
      image->rows = y+1;

      (void) SeekBlob(image,0,SEEK_SET);

      while(!EOFBlob(image)) 	/* load picture data */
	{
	  x=0;
	  while(!(ch >= '0' && ch <= '9'))
	    {		/* move to the beginning of number */
	      if(EOFBlob(image)) goto FINISH;
	      ch = ReadBlobByte(image);
	      if(ch=='#') 
		{readln(image,&ch); continue;}
	    }
    
	  x = ReadInt(image,&ch);		/* x */

	  while(ch!=',')
	    {
	      ch = ReadBlobByte(image);       
	      if(ch==EOF) break;
	    }
	  ch = 0;
	  y = ReadInt(image,&ch);		/* y */

	  while(ch!=':')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==EOF) break;
	    }
	  while(ch!='(')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==EOF) break;
	    }
	  ch=0;
	  R = ReadInt(image,&ch);		/* R */

	  while(ch!=',')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==EOF) break;
	    }
	  ch=0;
	  G = ReadInt(image,&ch);		/* G */

	  while(ch!=',')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==EOF) break;
	    }
	  ch=0;
	  B = ReadInt(image,&ch);		/* B */

	  if(status>16)
	    {
	      while(ch!=',')
		{
		  ch = ReadBlobByte(image);       
		  if(ch==EOF) break;
		}
	      ch=0;
	      A = ReadInt(image,&ch);		/* A */
	      if(A>max) max=A;
	    }

	  while(ch!=')')
	    {
	      ch = ReadBlobByte(image);
	      if(ch==EOF) break;
	    }


	  /* a new line has been detected */
	  if(y!=y_curr)
	    {
	      q = SetImagePixels(image,x_min,y_curr,x_max-x_min+1,1);
	      if (q == (PixelPacket *)NULL) break;	
	      if(status>16)
		(void)ImportImagePixelArea(image,RGBAQuantum,NumOfPlanes,
					   BImgBuff + 4*x_min*(NumOfPlanes/8),&import_options,0);
	      else
		(void)ImportImagePixelArea(image,RGBQuantum,NumOfPlanes,
					   BImgBuff + 3*x_min*(NumOfPlanes/8),&import_options,0);
	      if (!SyncImagePixels(image)) break;

	      x_min = 1; x_max = 0;
	      y_curr=y;
	    }

	  if(x<image->columns)
	    {
	      if(status>16)
		{
		  switch(NumOfPlanes)
		    {
		    case 8: BImgBuff[0+4*x] = R;
		      BImgBuff[1+4*x] = G;
		      BImgBuff[2+4*x] = B;
		      BImgBuff[3+4*x] = A;
		      break;
		    case 16:WImgBuff[0+4*x] = R;
		      WImgBuff[1+4*x] = G;
		      WImgBuff[2+4*x] = B;
		      WImgBuff[3+4*x] = A;
		      break;
		    case 32:DImgBuff[0+4*x] = R;
		      DImgBuff[1+4*x] = G;
		      DImgBuff[2+4*x] = B;
		      DImgBuff[3+4*x] = A;
		      break;
		    }    
		}
	      else
		{
		  switch(NumOfPlanes)
		    {
		    case 8: BImgBuff[0+3*x] = R;
		      BImgBuff[1+3*x] = G;
		      BImgBuff[2+3*x] = B;
		      break;
		    case 16:WImgBuff[0+3*x] = R;
		      WImgBuff[1+3*x] = G;
		      WImgBuff[2+3*x] = B;
		      break;
		    case 32:DImgBuff[0+3*x] = R;
		      DImgBuff[1+3*x] = G;
		      DImgBuff[2+3*x] = B;
		      break;
		    }    
		}
	      if(x_min>x_max) 
		x_max=x_min=x;
	      else
		{
		  if(x<x_min) x_min=x;
		  if(x>x_max) x_max=x;
		}
	    }

	  readln(image,&ch);
	}

    FINISH:
      if(x_min<=x_max)
	{
	  q = SetImagePixels(image,x_min,y_curr,x_max-x_min+1,1);	  
	  if (q != (PixelPacket *)NULL)
	    {
	      if(status>16)        
		(void)ImportImagePixelArea(image, RGBAQuantum, NumOfPlanes,
					   BImgBuff + 4*x_min*(NumOfPlanes/8), &import_options, 0);
	      else
		(void)ImportImagePixelArea(image, RGBQuantum, NumOfPlanes,
					   BImgBuff + 3*x_min*(NumOfPlanes/8), &import_options, 0);
	      if(!SyncImagePixels(image))
		{
		  if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
						    "  TXT failed to sync image pixels for a row %u", y_curr);
		}

	    }
	}

      MagickFreeMemory(BImgBuff);
      goto TXT_FINISH;    
    }

  /*
    Set the page geometry.
  */
  dx_resolution=72.0;
  dy_resolution=72.0;
  if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
    {
      char
        density[MaxTextExtent];

      (void) strcpy(density,PSDensityGeometry);
      count=GetMagickDimension(density,&image->x_resolution,
			       &image->y_resolution,NULL,NULL);
      if (count != 2)
        image->y_resolution=image->x_resolution;
    }
  SetGeometry(image,&page);
  page.width=612;
  page.height=792;
  (void) GetGeometry("612x792+43+43",&page.x,&page.y,&page.width,&page.height);
  if (image_info->page != (char *) NULL)
    (void) GetGeometry(image_info->page,&page.x,&page.y,&page.width,
		       &page.height);
  /*
    Initialize Image structure.
  */
  image->columns=(unsigned long)
    ceil(((page.width*image->x_resolution)/dx_resolution)-0.5);
  image->rows=(unsigned long)
    ceil(((page.height*image->y_resolution)/dy_resolution)-0.5);
  texture=(Image *) NULL;
  if (image_info->texture != (char *) NULL)
    {
      ImageInfo
        *clone_info;

      clone_info=CloneImageInfo(image_info);
      clone_info->blob=(void *) NULL;
      clone_info->length=0;
      (void) strlcpy(clone_info->filename,image_info->texture,MaxTextExtent);
      texture=ReadImage(clone_info,exception);
      DestroyImageInfo(clone_info);
    }
  /*
    Annotate the text image.
  */
  (void) SetImage(image,OpaqueOpacity);
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
  draw_info->fill=image_info->pen;
  (void) CloneString(&draw_info->text,image_info->filename);
  FormatString(geometry,"0x0%+ld%+ld",page.x,page.y);
  (void) CloneString(&draw_info->geometry,geometry);
  status=GetTypeMetrics(image,draw_info,&metrics);
  if (status == False)
    ThrowReaderException(TypeError,UnableToGetTypeMetrics,image);
  (void) strlcpy(filename,image_info->filename,MaxTextExtent);
  if (draw_info->text != '\0')
    *draw_info->text='\0';  

  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+=(long) (metrics.ascent-metrics.descent);
      if (image->previous == (Image *) NULL)
	if (QuantumTick(offset,image->rows))
	  if (!MagickMonitorFormatted(offset,image->rows,&image->exception,
				      LoadImageText,image->filename,
				      image->columns,image->rows))
	    break;
      p=ReadBlobString(image,text);
      if ((offset < (long) image->rows) && (p != (char *) NULL))
	continue;
      if (texture != (Image *) NULL)
	{
	  MonitorHandler
	    handler;

	  handler=SetMonitorHandler((MonitorHandler) NULL);
	  (void) TextureImage(image,texture);
	  (void) SetMonitorHandler(handler);
	}
      (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;
      AllocateNextImage(image_info,image);
      if (image->next == (Image *) NULL)
	{
	  DestroyImageList(image);
	  return((Image *) NULL);
	}
      image->next->columns=image->columns;
      image->next->rows=image->rows;
      image=SyncNextImageInList(image);
      (void) strlcpy(image->filename,filename,MaxTextExtent);
      (void) SetImage(image,OpaqueOpacity);
      if (!MagickMonitorFormatted(TellBlob(image),GetBlobSize(image),exception,
				  LoadImagesText,image->filename))
	break;
    }

  if (texture != (Image *) NULL)
    {
      MonitorHandler
        handler;

      handler=SetMonitorHandler((MonitorHandler) NULL);
      (void) TextureImage(image,texture);
      (void) SetMonitorHandler(handler);
    }
  (void) AnnotateImage(image,draw_info);
  if (texture != (Image *) NULL)
    DestroyImage(texture);
  DestroyDrawInfo(draw_info);
  while (image->previous != (Image *) NULL)
    image=image->previous;
 TXT_FINISH:
  CloseBlob(image);
  return(image);
}