Beispiel #1
0
int /* PRIVATE */
pngx_read_tiff(png_structp png_ptr, png_infop info_ptr, FILE *stream)
{
    struct minitiff_info tiff_info;
    unsigned int width, height, pixel_size, sample_depth, sample_max;
    int color_type;
    int sample_overflow;
    png_bytepp row_pointers;
    png_bytep row;
    unsigned int i, j, k;

    pngx_err_ptr = png_ptr;
    num_extra_images = 0;
    minitiff_init_info(&tiff_info);
    tiff_info.error_handler   = pngx_tiff_error;
    tiff_info.warning_handler = pngx_tiff_warning;
    minitiff_read_info(&tiff_info, stream);
    minitiff_validate_info(&tiff_info);

    width  = (unsigned int)tiff_info.width;
    height = (unsigned int)tiff_info.height;
    pixel_size   = tiff_info.samples_per_pixel;
    sample_depth = tiff_info.bits_per_sample;
    switch (pixel_size)
    {
    case 1:
        color_type = PNG_COLOR_TYPE_GRAY;
        break;
    case 2:
        color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
        break;
    case 3:
        color_type = PNG_COLOR_TYPE_RGB;
        break;
    case 4:
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
        break;
    default:
        png_error(png_ptr, "Unsupported TIFF color space");
        return 0;  /* avoid "uninitialized color_type" warning */
    }
    if (sample_depth > 16)
        png_error(png_ptr, "Unsupported TIFF sample depth");
    sample_max = (1 << sample_depth) - 1;
    sample_overflow = 0;

    png_set_IHDR(png_ptr, info_ptr, width, height,
                 (sample_depth <= 8) ? 8 : 16,
                 color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    row_pointers = pngx_malloc_rows(png_ptr, info_ptr, 0);

    if (sample_depth <= 8)
    {
        for (i = 0; i < height; ++i)
        {
            row = row_pointers[i];
            minitiff_read_row(&tiff_info, row, i, stream);
            if (sample_depth < 8)
            {
                for (j = 0; j < pixel_size * width; ++j)
                {
                    unsigned int b = row[j];
                    if (b > sample_max)
                    {
                        b = sample_max;
                        sample_overflow = 1;
                    }
                    row[j] = (png_byte)((b * 255 + sample_max / 2) / sample_max);
                }
            }
            if (tiff_info.photometric == 0)
            {
                for (j = 0; j < pixel_size * width; ++j)
                    row[j] = (png_byte)(255 - row[j]);
            }
        }
    }
    else
    {
        for (i = 0; i < height; ++i)
        {
            row = row_pointers[i];
            minitiff_read_row(&tiff_info, row, i, stream);
            if (tiff_info.byte_order == 'I')
            {
                /* "Intel" byte order => swap row bytes */
                for (j = k = 0; j < pixel_size * width; ++j, k+=2)
                {
                    png_byte b = row[k];
                    row[k] = row[k + 1];
                    row[k + 1] = b;
                }
            }
            if (sample_depth < 16)
            {
                for (j = k = 0; k < pixel_size * width; ++j, k+=2)
                {
                    unsigned int b = (row[k] << 8) + row[k + 1];
                    if (b > sample_max)
                    {
                        b = sample_max;
                        sample_overflow = 1;
                    }
                    b = (b * 65535U + sample_max / 2) / sample_max;
                    row[k] = (png_byte)(b >> 8);
                    row[k + 1] = (png_byte)(b & 255);
                }
            }
        }
    }

    if (sample_overflow)
        png_warning(png_ptr, "Overflow in TIFF samples");

    minitiff_destroy_info(&tiff_info);
    return 1 + num_extra_images;
}
Beispiel #2
0
int /* PRIVATE */
pngx_read_gif(png_structp png_ptr, png_infop info_ptr, FILE *stream)
{
   /* GIF-specific data */
   struct GIFScreen screen;
   struct GIFImage image;
   struct GIFExtension ext;
   struct GIFGraphicCtlExt graphicExt;
   int code;
   unsigned char *colorTable;
   unsigned int numColors;
   unsigned int transparent;
   unsigned int numImages;
   /* PNG-specific data */
   png_uint_32 width, height;
   png_bytepp row_pointers;

   /* Set up the custom error handling. */
   pngx_err_ptr = png_ptr;
   GIFError     = pngx_gif_error;
   GIFWarning   = pngx_gif_warning;

   /* Read the GIF screen. */
   GIFReadScreen(&screen, stream);
   width  = screen.Width;
   height = screen.Height;

   /* Set the PNG image type. */
   png_set_IHDR(png_ptr, info_ptr,
      width, height, 8, PNG_COLOR_TYPE_PALETTE,
      PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

   /* Allocate memory. */
   row_pointers = pngx_malloc_rows(png_ptr, info_ptr, (int)screen.Background);

   /* Complete the initialization of the GIF reader. */
   GIFInitImage(&image, &screen, row_pointers);
   GIFInitExtension(&ext, &screen, NULL, 0);
   transparent = (unsigned int)(-1);
   numImages = 0;

   /* Iterate over the GIF file. */
   for ( ; ; )
   {
      code = GIFReadNextBlock(&image, &ext, stream);
      if (code == GIF_IMAGE)  /* ',' */
      {
         if (image.Rows != NULL)
         {
            /* Complete the PNG info. */
            if (image.InterlaceFlag)
               pngx_set_interlace_type(png_ptr, info_ptr,
                  PNG_INTERLACE_ADAM7);
            colorTable = GIFGetColorTable(&image, &numColors);
            pngx_set_GIF_palette(png_ptr, info_ptr, colorTable, numColors);
            if (transparent < 256)
               pngx_set_GIF_transparent(png_ptr, info_ptr, transparent);

            /* Inform the GIF routines not to read the upcoming images. */
            image.Rows = NULL;
         }
         ++numImages;
      }
      else if (code == GIF_EXTENSION && ext.Label == GIF_GRAPHICCTL)  /* '!' */
      {
         GIFGetGraphicCtl(&ext, &graphicExt);
         if (image.Rows != NULL && graphicExt.TransparentFlag)
            if (transparent >= 256)
               transparent = graphicExt.Transparent;
      }
      else if (code == GIF_TERMINATOR)  /* ';' */
         break;
   }

   /* Deallocate the GIF reader's extension buffer.
    * Use free() in conjunction with the reader's realloc().
    */
   if (ext.Buffer != NULL)
      free(ext.Buffer);
   /* FIXME:
    * Deallocate ext.Buffer on error, to prevent memory leaks.
    */

   if (image.Rows != NULL)
      png_error(png_ptr, "No image in GIF file");

   return numImages;
}
Beispiel #3
0
int /* PRIVATE */
pngx_read_pnm(png_structp png_ptr, png_infop info_ptr, FILE *stream)
{
   pnm_struct pnminfo;
   unsigned int format, depth, width, height, maxval;
   unsigned int max_width, num_samples, sample_size;
   unsigned int *pnmrow;
   size_t row_size;
   png_bytepp row_pointers;
   png_color_8 sig_bit;
   unsigned int i, j;
   int failed, overflow;

   /* Read the PNM header. */
   if (pnm_fget_header(&pnminfo, stream) != 1)
      return 0;  /* not PNM */
   format = pnminfo.format;
   depth = pnminfo.depth;
   width = pnminfo.width;
   height = pnminfo.height;
   maxval = pnminfo.maxval;
   if (format > PNM_P6)
      png_error(png_ptr, "Can't handle PNM formats newer than PPM (\"P6\")");
   max_width =
      (sizeof(size_t) <= sizeof(unsigned int)) ?
         UINT_MAX / sizeof(unsigned int) / depth : UINT_MAX;
#if UINT_MAX > PNGX_PNM_LENGTH_MAX
   if (max_width > PNGX_PNM_LENGTH_MAX)
      max_width = PNGX_PNM_LENGTH_MAX;
#endif
   if (width > max_width)
      png_error(png_ptr, "Can't handle exceedingly large PNM dimensions");
   sample_size = 1;
   row_size = num_samples = depth * width;
   if (maxval > 65535)
      png_error(png_ptr, "Can't handle PNM samples larger than 16 bits");
   else if (maxval > 255)
   {
      sample_size = 2;
      row_size *= 2;
   }

   /* Set the PNG image type. */
   png_set_IHDR(png_ptr, info_ptr,
      width, height,
      (maxval <= 255) ? 8 : 16,
      (depth == 1) ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_RGB,
      PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
   for (i = 1, j = 2; j - 1 < maxval; ++i, j <<= 1) { }
   if (j - 1 != maxval)
      png_warning(png_ptr,
         "Possibly inexact sample conversion from PNM to PNG");
   else if (i % 8 != 0 && (depth > 1 || 8 % i != 0))
   {
      sig_bit.red = sig_bit.green = sig_bit.blue = sig_bit.gray = (png_byte)i;
      sig_bit.alpha = 0;
      png_set_sBIT(png_ptr, info_ptr, &sig_bit);
   }

   /* Allocate memory. */
   row_pointers = pngx_malloc_rows(png_ptr, info_ptr, -1);
   if ((format >= PNM_P4) && (maxval == 255 || maxval == 65535))
      pnmrow = NULL;  /* can read raw data directly into row_pointers */
   else
      pnmrow = (unsigned int *)
         png_malloc(png_ptr, num_samples * sizeof(unsigned int));

   /* Read the image data. */
   failed = 0;
   overflow = 0;
   if (pnmrow != NULL)
   {
      for (i = 0; i < height; ++i)
      {
         if (pnm_fget_values(&pnminfo, pnmrow, 1, stream) <= 0)
            failed = 1;
         /* Transfer the samples, even on partial (unsuccessful) reads. */
         if (maxval <= 255)
         {
            for (j = 0; j < num_samples; ++j)
            {
               unsigned int val = pnmrow[j];
               if (val > maxval)
               {
                  val = 255;
                  overflow = 1;
               }
               else if (maxval != 255)
                  val = (val * 255 + maxval/2) / maxval;
               row_pointers[i][j] = (png_byte)val;
            }
         }
         else  /* maxval > 255 */
         {
            for (j = 0; j < num_samples; ++j)
            {
               png_uint_32 val = pnmrow[j];
               if (val > maxval)
               {
                  val = 65535;
                  overflow = 1;
               }
               else if (maxval != 65535)
                  val = (val * 65535 + maxval/2) / maxval;
               row_pointers[i][2 * j] = (png_byte)(val >> 8);
               row_pointers[i][2 * j + 1] = (png_byte)(val & 0xff);
            }
         }
         if (failed)
            break;
      }
   }
   else  /* read the raw data directly */
   {
      for (i = 0; i < height; ++i)