コード例 #1
0
ファイル: yuv.c プロジェクト: vgck/opendr2
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d Y U V I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method ReadYUVImage reads an image with digital YUV (CCIR 601 4:1:1) bytes
%  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 ReadYUVImage method is:
%
%      Image *ReadYUVImage(const ImageInfo *image_info)
%
%  A description of each parameter follows:
%
%    o image:  Method ReadYUVImage 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 an ImageInfo structure.
%
%
*/
Export Image *ReadYUVImage(const ImageInfo *image_info)
{
  Image
    *chroma_image,
    *image,
    *zoom_image;

  int
    count,
    y;

  register int
    i,
    x;

  register PixelPacket
    *q,
    *r;

  register unsigned char
    *p;

  unsigned char
    *scanline;

  unsigned int
    status;

  /*
    Allocate image structure.
  */
  image=AllocateImage(image_info);
  if (image == (Image *) NULL)
    return((Image *) NULL);
  if ((image->columns == 0) || (image->rows == 0))
    ReaderExit(OptionWarning,"Must specify image size",image);
  image->depth=8;
  if (image_info->interlace != PartitionInterlace)
    {
      /*
        Open image file.
      */
      status=OpenBlob(image_info,image,ReadBinaryType);
      if (status == False)
        ReaderExit(FileOpenWarning,"Unable to open file",image);
      for (i=0; i < image->offset; i++)
        (void) ReadByte(image);
    }
  /*
    Allocate memory for a scanline.
  */
  scanline=(unsigned char *)
    AllocateMemory(image->columns*sizeof(unsigned char));
  if (scanline == (unsigned char *) NULL)
    ReaderExit(ResourceLimitWarning,"Memory allocation failed",image);
  do
  {
    /*
      Convert raster image to pixel packets.
    */
    if (image_info->interlace == PartitionInterlace)
      {
        AppendImageFormat("Y",image->filename);
        status=OpenBlob(image_info,image,ReadBinaryType);
        if (status == False)
          ReaderExit(FileOpenWarning,"Unable to open file",image);
      }
    for (y=0; y < (int) image->rows; y++)
    {
      if ((y > 0) || (image->previous == (Image *) NULL))
        (void) ReadBlob(image,image->columns,scanline);
      p=scanline;
      q=SetPixelCache(image,0,y,image->columns,1);
      if (q == (PixelPacket *) NULL)
        break;
      for (x=0; x < (int) image->columns; x++)
      {
        q->red=UpScale(*p++);
        q->green=0;
        q->blue=0;
        q++;
      }
      if (!SyncPixelCache(image))
        break;
      if (image->previous == (Image *) NULL)
        ProgressMonitor(LoadImageText,y,image->rows);
    }
    if (image_info->interlace == PartitionInterlace)
      {
        CloseBlob(image);
        AppendImageFormat("U",image->filename);
        status=OpenBlob(image_info,image,ReadBinaryType);
        if (status == False)
          ReaderExit(FileOpenWarning,"Unable to open file",image);
      }
    chroma_image=CloneImage(image,image->columns/2,image->rows/2,True);
    if (chroma_image == (Image *) NULL)
      ReaderExit(ResourceLimitWarning,"Memory allocation failed",image);
    for (y=0; y < (int) chroma_image->rows; y++)
    {
      (void) ReadBlob(image,chroma_image->columns,scanline);
      p=scanline;
      q=SetPixelCache(chroma_image,0,y,chroma_image->columns,1);
      if (q == (PixelPacket *) NULL)
        break;
      for (x=0; x < (int) chroma_image->columns; x++)
      {
        q->red=0;
        q->green=UpScale(*p++);
        q->blue=0;
        q++;
      }
      if (!SyncPixelCache(chroma_image))
        break;
    }
    if (image_info->interlace == PartitionInterlace)
      {
        CloseBlob(image);
        AppendImageFormat("V",image->filename);
        status=OpenBlob(image_info,image,ReadBinaryType);
        if (status == False)
          ReaderExit(FileOpenWarning,"Unable to open file",image);
      }
    for (y=0; y < (int) chroma_image->rows; y++)
    {
      (void) ReadBlob(image,chroma_image->columns,scanline);
      p=scanline;
      q=GetPixelCache(chroma_image,0,y,chroma_image->columns,1);
      if (q == (PixelPacket *) NULL)
        break;
      for (x=0; x < (int) chroma_image->columns; x++)
      {
        q->blue=UpScale(*p++);
        q++;
      }
      if (!SyncPixelCache(chroma_image))
        break;
    }
    /*
      Scale image.
    */
    chroma_image->orphan=True;
    zoom_image=SampleImage(chroma_image,image->columns,image->rows);
    DestroyImage(chroma_image);
    if (zoom_image == (Image *) NULL)
      ReaderExit(ResourceLimitWarning,"Memory allocation failed",image);
    for (y=0; y < (int) image->rows; y++)
    {
      q=GetPixelCache(image,0,y,image->columns,1);
      r=GetPixelCache(zoom_image,0,y,zoom_image->columns,1);
      if ((q == (PixelPacket *) NULL) || (r == (PixelPacket *) NULL))
        break;
      for (x=0; x < (int) image->columns; x++)
      {
        q->green=r->green;
        q->blue=r->blue;
        r++;
        q++;
      }
      if (!SyncPixelCache(image))
        break;
    }
    DestroyImage(zoom_image);
    TransformRGBImage(image,YCbCrColorspace);
    if (image_info->interlace == PartitionInterlace)
      (void) strcpy(image->filename,image_info->filename);
    /*
      Proceed to next image.
    */
    if (image_info->subrange != 0)
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
        break;
    count=ReadBlob(image,image->columns,(char *) scanline);
    if (count > 0)
      {
        /*
          Allocate next image structure.
        */
        AllocateNextImage(image_info,image);
        if (image->next == (Image *) NULL)
          {
            DestroyImages(image);
            return((Image *) NULL);
          }
        image=image->next;
        ProgressMonitor(LoadImagesText,TellBlob(image),image->filesize);
      }
  } while (count > 0);
  FreeMemory(scanline);
  while (image->previous != (Image *) NULL)
    image=image->previous;
  CloseBlob(image);
  return(image);
}
コード例 #2
0
ファイル: sfw.c プロジェクト: SOLARIC/world-opponent-network
Export Image *ReadSFWImage(const ImageInfo *image_info)
{
  static unsigned char
    HuffmanTable[] =
    {
      0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
      0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
      0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
      0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,
      0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
      0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21,
      0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
      0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1,
      0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18,
      0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36,
      0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
      0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
      0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,
      0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A,
      0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3,
      0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5,
      0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
      0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
      0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
      0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x11,
      0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
      0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
      0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,
      0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09,
      0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24,
      0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28,
      0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45,
      0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
      0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73,
      0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,
      0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
      0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
      0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2,
      0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
      0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
      0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
      0xF9, 0xFA
    };

  FILE
    *file;

  Image
    *flipped_image,
    *image;

  ImageInfo
    *local_info;

  register unsigned char
    *header,
    *data;

  unsigned char
    *buffer,
    *offset;

  unsigned int
    status;

  /*
    Allocate image structure.
  */
  image=AllocateImage(image_info);
  if (image == (Image *) NULL)
    return((Image *) NULL);
  /*
    Open image file.
  */
  status=OpenBlob(image_info,image,ReadBinaryType);
  if (status == False)
    ReaderExit(FileOpenWarning,"Unable to open file",image);
  /*
    Read image into a buffer.
  */
  buffer=(unsigned char *)
    AllocateMemory(image->filesize*sizeof(unsigned char));
  if (buffer == (unsigned char *) NULL)
    ReaderExit(ResourceLimitWarning,"Memory allocation failed",image);
  status=ReadBlob(image,image->filesize,(char *) buffer);
  if ((status == False) || (strncmp((char *) buffer,"SFW",3) != 0))
    ReaderExit(CorruptImageWarning,"Not a SFW image file",image);
  CloseBlob(image);
  DestroyImage(image);
  /*
    Find the start of the JFIF data
  */
  header=SFWScan(buffer,buffer+image->filesize-1,(unsigned char *)
    "\377\310\377\320",4);
  if (header == (unsigned char *) NULL)
    {
      FreeMemory(buffer);
      ReaderExit(CorruptImageWarning,"Not a SFW image file",image);
    }
  TranslateSFWMarker(header);  /* translate soi and app tags */
  TranslateSFWMarker(header+2);
  (void) memcpy((char *) header+6,"JFIF\0\001\0",7);  /* JFIF magic */
  /*
    Translate remaining markers.
  */
  offset=header+2;
  offset+=(offset[2] << 8)+offset[3]+2;
  for ( ; ; )
  {
    TranslateSFWMarker(offset);
    if (offset[1] == 0xda)
      break;
    offset+=(offset[2] << 8)+offset[3]+2;
  }
  offset--;
  data=SFWScan(offset,buffer+image->filesize-1,(unsigned char *) "\377\311",2);
  if (data == (unsigned char *) NULL)
    {
      FreeMemory(buffer);
      ReaderExit(CorruptImageWarning,"Not a SFW image file",image);
    }
  TranslateSFWMarker(data++);  /* translate eoi marker */
  /*
    Write JFIF file.
  */
  local_info=CloneImageInfo(image_info);
  TemporaryFilename(local_info->filename);
  file=fopen(local_info->filename,WriteBinaryType);
  if (file == (FILE *) NULL)
    {
      FreeMemory(buffer);
      DestroyImageInfo(local_info);
      ReaderExit(FileOpenWarning,"Unable to write file",image);
    }
  (void) fwrite(header,offset-header+1,1,file);
  (void) fwrite(HuffmanTable,1,sizeof(HuffmanTable)/sizeof(*HuffmanTable),file);
  (void) fwrite(offset+1,data-offset,1,file);
  status=ferror(file);
  (void) fclose(file);
  FreeMemory(buffer);
  if (status)
    {
      (void) remove(local_info->filename);
      DestroyImageInfo(local_info);
      ReaderExit(FileOpenWarning,"Unable to write file",image);
    }
  /*
    Read JPEG image.
  */
  image=ReadImage(local_info);
  (void) remove(local_info->filename);
  DestroyImageInfo(local_info);
  if (image == (Image *) NULL)
    return(image);
  /*
    Correct image orientation.
  */
  flipped_image=FlipImage(image);
  if (flipped_image == (Image *) NULL)
    return(image);
  DestroyImage(image);
  return(flipped_image);
}
コード例 #3
0
ファイル: sct.c プロジェクト: vgck/opendr2
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d S C T I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method ReadSCTImage reads a Scitex 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 ReadSCTImage method is:
%
%      Image *ReadSCTImage(const ImageInfo *image_info)
%
%  A description of each parameter follows:
%
%    o image:  Method ReadSCTImage 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 an ImageInfo structure.
%
%
*/
Export Image *ReadSCTImage(const ImageInfo *image_info)
{
  char
    buffer[768],
    magick[2];

  Image
    *image;

  int
    y;

  register int
    x;

  register PixelPacket
    *q;

  unsigned int
    status;

  /*
    Allocate image structure.
  */
  image=AllocateImage(image_info);
  if (image == (Image *) NULL)
    return((Image *) NULL);
  /*
    Open image file.
  */
  status=OpenBlob(image_info,image,ReadBinaryType);
  if (status == False)
    ReaderExit(FileOpenWarning,"Unable to open file",image);
  /*
    Read control block.
  */
  (void) ReadBlob(image,80,(char *) buffer);
  (void) ReadBlob(image,2,(char *) magick);
  if ((strncmp((char *) magick,"CT",2) != 0) &&
      (strncmp((char *) magick,"LW",2) != 0) &&
      (strncmp((char *) magick,"BM",2) != 0) &&
      (strncmp((char *) magick,"PG",2) != 0) &&
      (strncmp((char *) magick,"TX",2) != 0))
    ReaderExit(CorruptImageWarning,"Not a SCT image file",image);
  if ((strncmp((char *) magick,"LW",2) == 0) ||
      (strncmp((char *) magick,"BM",2) == 0) ||
      (strncmp((char *) magick,"PG",2) == 0) ||
      (strncmp((char *) magick,"TX",2) == 0))
    ReaderExit(CorruptImageWarning,"only Continuous Tone Picture supported",
      image);
  (void) ReadBlob(image,174,(char *) buffer);
  (void) ReadBlob(image,768,(char *) buffer);
  /*
    Read paramter block.
  */
  (void) ReadBlob(image,32,(char *) buffer);
  (void) ReadBlob(image,14,(char *) buffer);
  image->rows=atoi(buffer);
  (void) ReadBlob(image,14,(char *) buffer);
  image->columns=atoi(buffer);
  (void) ReadBlob(image,196,(char *) buffer);
  (void) ReadBlob(image,768,(char *) buffer);
  if (image_info->ping)
    {
      CloseBlob(image);
      return(image);
    }
  /*
    Convert SCT raster image to pixel packets.
  */
  image->colorspace=CMYKColorspace;
  for (y=0; y < (int) image->rows; y++)
  {
    q=SetPixelCache(image,0,y,image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (int) image->columns; x++)
    {
      q->red=MaxRGB-UpScale(ReadByte(image));
      q++;
    }
    if ((image->columns % 2) != 0)
      (void) ReadByte(image);  /* pad */
    q=GetPixelCache(image,0,y,image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (int) image->columns; x++)
    {
      q->green=MaxRGB-UpScale(ReadByte(image));
      q++;
    }
    if ((image->columns % 2) != 0)
      (void) ReadByte(image);  /* pad */
    q=GetPixelCache(image,0,y,image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (int) image->columns; x++)
    {
      q->blue=MaxRGB-UpScale(ReadByte(image));
      q++;
    }
    if ((image->columns % 2) != 0)
      (void) ReadByte(image);  /* pad */
    q=GetPixelCache(image,0,y,image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (int) image->columns; x++)
    {
      q->opacity=MaxRGB-UpScale(ReadByte(image));
      q++;
    }
    if (!SyncPixelCache(image))
      break;
    if ((image->columns % 2) != 0)
      (void) ReadByte(image);  /* pad */
    if (QuantumTick(y,image->rows))
      ProgressMonitor(LoadImageText,y,image->rows);
  }
  return(image);
}
コード例 #4
0
ファイル: iptc.c プロジェクト: SOLARIC/world-opponent-network
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d I P T C I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method ReadIPTCImage reads an image file in the IPTC format and returns it.
%  It allocates the memory necessary for the new Image structure and returns a
%  pointer to the new image.  This method differs from the other decoder
%  methods in that only the iptc profile information is useful in the
%  returned image.
%
%  The format of the ReadIPTCImage method is:
%
%      Image *ReadIPTCImage(const ImageInfo *image_info)
%
%  A description of each parameter follows:
%
%    o image:  Method ReadIPTCImage 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 an ImageInfo structure.
%
%
*/
Export Image *ReadIPTCImage(const ImageInfo *image_info)
{
  Image
    *image;

  int
    c;

  register unsigned char
    *q;

  unsigned char
    *data;

  unsigned int
    tag_length,
    length,
    status;

  /*
    Allocate image structure.
  */
  image=AllocateImage(image_info);
  if (image == (Image *) NULL)
    return((Image *) NULL);
  /*
    Open image file.
  */
  status=OpenBlob(image_info,image,ReadBinaryType);
  if (status == False)
    ReaderExit(FileOpenWarning,"Unable to open file",image);
  /*
    Read IPTC image.
  */
  length=MaxTextExtent;
  tag_length=12;
  data=(unsigned char *)
    AllocateMemory((length+2)*sizeof(unsigned char));
  if (data == (unsigned char *) NULL)
    WriterExit(ResourceLimitWarning,"Memory allocation failed",image);
  (void) memcpy((char *) data,"8BIM\04\04\0\0\0\0\0\0",tag_length);
  q=data;
  q+=tag_length;
  while (1)
  {
    c=ReadByte(image);
    if (c == EOF)
      break;
    if ((q-data+1) >= (int) length)
      {
        image->iptc_profile.length=q-data;
        length<<=1;
        data=(unsigned char *) ReallocateMemory((char *)
          data,(length+2)*sizeof(unsigned char));
        if (data == (unsigned char *) NULL)
          break;
        q=data+image->iptc_profile.length;
      }
    *q++=(unsigned char) c;
  }
  image->iptc_profile.length=0;
  if (data != (unsigned char *) NULL)
    {
      image->iptc_profile.length=q-data;
      length=image->iptc_profile.length-tag_length;
      data[10]=length >> 8;
      data[11]=length & 0xff;
      image->iptc_profile.info=data;
    }
コード例 #5
0
ファイル: ttf.c プロジェクト: SOLARIC/world-opponent-network
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d T T F I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method ReadTTFImage reads a TrueType font 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 ReadTTFImage method is:
%
%      Image *ReadTTFImage(const ImageInfo *image_info)
%
%  A description of each parameter follows:
%
%    o image:  Method ReadTTFImage 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 an ImageInfo structure.
%
%
*/
Export Image *ReadTTFImage(const ImageInfo *image_info)
{
  AnnotateInfo
    *annotate_info;

  char
    font[MaxTextExtent],
    geometry[MaxTextExtent],
    text[MaxTextExtent];

  Image
    *image;

  int
    y;

  long
    magick;

  register int
    i;

  ImageInfo
    *local_info;

  unsigned int
    status;

  /*
    Allocate image structure.
  */
  image=AllocateImage(image_info);
  if (image == (Image *) NULL)
    return((Image *) NULL);
  /*
    Open image file.
  */
  status=OpenBlob(image_info,image,ReadBinaryType);
  if (status == False)
    ReaderExit(FileOpenWarning,"Unable to open file",image);
  magick=MSBFirstReadLong(image);
  if ((magick != 256) && (magick != 65536))
    ReaderExit(CorruptImageWarning,"Not a TTF font file",image);
  /*
    Start with a white canvas.
  */
  y=0;
  local_info=CloneImageInfo(image_info);
  if (local_info == (ImageInfo *) NULL)
    return((Image *) NULL);
  (void) CloneString(&local_info->size,"800x520");
  (void) CloneString(&local_info->pen,"black");
  *font='\0';
  (void) CloneString(&local_info->font,font);
  local_info->pointsize=18;
  FormatString(local_info->font,"@%.1024s",image_info->filename);
  annotate_info=CloneAnnotateInfo(local_info,(AnnotateInfo *) NULL);
  image->columns=annotate_info->bounds.width;
  image->rows=annotate_info->bounds.height;
  if (image_info->ping)
    {
      DestroyAnnotateInfo(annotate_info);
      DestroyImageInfo(local_info);
      CloseBlob(image);
      return(image);
    }
  DestroyImage(image);
  (void) strcpy(local_info->filename,"white");
  image=ReadXCImage(local_info);
  DestroyImageInfo(local_info);
  if (image == (Image *) NULL)
    {
      DestroyAnnotateInfo(annotate_info);
      return((Image *) NULL);
    }
  (void) strcpy(image->filename,image_info->filename);
  if (annotate_info->font_name != (char *) NULL)
    (void) CloneString(&image->label,annotate_info->font_name);
  /*
    Annotate canvas with text rendered with font at different point sizes.
  */
  y=10;
  if (annotate_info->font_name != (char *) NULL)
    {
      annotate_info->image_info->pointsize=30;
      FormatString(geometry,"+10%+d",y);
      (void) CloneString(&annotate_info->geometry,geometry);
      (void) CloneString(&annotate_info->text,annotate_info->font_name);
      AnnotateImage(image,annotate_info);
      y+=42;
    }
  annotate_info->image_info->pointsize=18;
  FormatString(geometry,"+10%+d",y);
  (void) CloneString(&annotate_info->geometry,geometry);
  (void) CloneString(&annotate_info->text,"abcdefghijklmnopqrstuvwxyz");
  AnnotateImage(image,annotate_info);
  y+=20;
  FormatString(geometry,"+10%+d",y);
  (void) CloneString(&annotate_info->geometry,geometry);
  (void) CloneString(&annotate_info->text,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  AnnotateImage(image,annotate_info);
  y+=20;
  FormatString(geometry,"+10%+d",y);
  (void) CloneString(&annotate_info->geometry,geometry);
  (void) CloneString(&annotate_info->text,"1234567890.:,;(:*!?')");
  AnnotateImage(image,annotate_info);
  y+=20;
  for (i=12; i <= 72; i+=6)
  {
    y+=i+6;
    annotate_info->image_info->pointsize=18;
    FormatString(geometry,"+10%+d",y);
    (void) CloneString(&annotate_info->geometry,geometry);
    FormatString(text,"%d",i);
    (void) CloneString(&annotate_info->text,text);
    AnnotateImage(image,annotate_info);
    annotate_info->image_info->pointsize=i;
    FormatString(geometry,"+50%+d",y);
    (void) CloneString(&annotate_info->geometry,geometry);
    (void) CloneString(&annotate_info->text,
      "That which does not destroy me, only makes me stronger");
    AnnotateImage(image,annotate_info);
    if (i >= 24)
      i+=6;
  }
  DestroyAnnotateInfo(annotate_info);
  return(image);
}