Back to index

tetex-bin  3.0
writepng.c
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
00003 
00004 This file is part of pdfTeX.
00005 
00006 pdfTeX is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 pdfTeX is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with pdfTeX; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writepng.c#5 $
00021 */
00022 
00023 #include "ptexlib.h"
00024 #include "image.h"
00025 
00026 static const char perforce_id[] = 
00027     "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writepng.c#5 $";
00028 
00029 void read_png_info(integer img)
00030 {
00031     FILE *png_file = xfopen(img_name(img), FOPEN_RBIN_MODE);
00032     if ((png_ptr(img) = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
00033         NULL, NULL, NULL)) == NULL)
00034         pdftex_fail("libpng: png_create_read_struct() failed");
00035     if ((png_info(img) = png_create_info_struct(png_ptr(img))) == NULL)
00036         pdftex_fail("libpng: png_create_info_struct() failed");
00037     if (setjmp(png_ptr(img)->jmpbuf))
00038         pdftex_fail("libpng: internal error");
00039     png_init_io(png_ptr(img), png_file);
00040     png_read_info(png_ptr(img), png_info(img));
00041     if (png_info(img)->color_type & PNG_COLOR_MASK_ALPHA)
00042         png_set_strip_alpha(png_ptr(img));
00043     if (png_info(img)->bit_depth == 16)
00044         png_set_strip_16(png_ptr(img));
00045     png_read_update_info(png_ptr(img), png_info(img));
00046     img_width(img) =  png_info(img)->width;
00047     img_height(img) =  png_info(img)->height;
00048     if (png_info(img)->valid & PNG_INFO_pHYs) {
00049         img_xres(img) = 
00050             round(0.0254*png_get_x_pixels_per_meter(png_ptr(img), png_info(img)));
00051         img_yres(img) =
00052             round(0.0254*png_get_y_pixels_per_meter(png_ptr(img), png_info(img)));
00053     }
00054     switch (png_info(img)->color_type) {
00055     case PNG_COLOR_TYPE_PALETTE:
00056         img_color(img) = IMAGE_COLOR_C | IMAGE_COLOR_I;
00057         break;
00058     case PNG_COLOR_TYPE_GRAY:
00059     case PNG_COLOR_TYPE_GRAY_ALPHA:
00060         img_color(img) = IMAGE_COLOR_B;
00061         break;
00062     case PNG_COLOR_TYPE_RGB:
00063     case PNG_COLOR_TYPE_RGB_ALPHA:
00064         img_color(img) = IMAGE_COLOR_C;
00065         break;
00066     default:
00067         pdftex_fail("unsupported type of color_type <%i>", png_info(img)->color_type);
00068     }
00069 }
00070 
00071 void write_png(integer img)
00072 {
00073     int i, j, k, l;
00074     integer palette_objnum = 0;
00075     png_bytep row, r, *rows;
00076     pdf_puts("/Type /XObject\n/Subtype /Image\n");
00077     pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
00078                (int)png_info(img)->width,
00079                (int)png_info(img)->height,
00080                (int)png_info(img)->bit_depth);
00081     pdf_puts("/ColorSpace ");
00082     if (img_colorspace_ref(img) != 0) {
00083         pdf_printf("%i 0 R\n", (int)img_colorspace_ref(img));
00084     }
00085     else {
00086         switch (png_info(img)->color_type) {
00087             case PNG_COLOR_TYPE_PALETTE:
00088                 pdfcreateobj(0, 0);
00089                 palette_objnum = objptr;
00090                 pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n",
00091                         (int)(png_info(img)->num_palette - 1),
00092                         (int)palette_objnum);
00093                 break;
00094             case PNG_COLOR_TYPE_GRAY:
00095             case PNG_COLOR_TYPE_GRAY_ALPHA:
00096                 pdf_puts("/DeviceGray\n");
00097                 break;
00098             case PNG_COLOR_TYPE_RGB:
00099             case PNG_COLOR_TYPE_RGB_ALPHA:
00100                 pdf_puts("/DeviceRGB\n");
00101                 break;
00102             default:
00103                 pdftex_fail("unsupported type of color_type <%i>", png_info(img)->color_type);
00104         }
00105     }
00106     pdfbeginstream();
00107     if (png_info(img)->interlace_type == PNG_INTERLACE_NONE) {
00108         row = xtalloc(png_info(img)->rowbytes, png_byte);
00109         for (i = 0; i < (int)png_info(img)->height; i++) {
00110             png_read_row(png_ptr(img), row, NULL);
00111            r = row;
00112            k = png_info(img)->rowbytes;
00113            while(k > 0) {
00114               l = (k > pdfbufsize)? pdfbufsize : k;
00115               pdfroom(l);
00116               for (j = 0; j < l; j++)
00117                   pdfbuf[pdfptr++] = *r++;
00118               k -= l;
00119            }
00120         }
00121         xfree(row);
00122     }
00123     else {
00124         if (png_info(img)->height*png_info(img)->rowbytes >= 10240000L)
00125             pdftex_warn("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
00126         rows = xtalloc(png_info(img)->height, png_bytep);
00127         for (i = 0; i < png_info(img)->height; i++)
00128             rows[i] = xtalloc(png_info(img)->rowbytes, png_byte);
00129         png_read_image(png_ptr(img), rows);
00130         for (i = 0; i < (int)png_info(img)->height; i++) {
00131             row = rows[i];
00132            k = png_info(img)->rowbytes;
00133            while(k > 0) {
00134               l = (k > pdfbufsize)? pdfbufsize : k;
00135               pdfroom(l);
00136               for (j = 0; j < l; j++)
00137                   pdfbuf[pdfptr++] = *row++;
00138               k -= l;
00139            }
00140             xfree(rows[i]);
00141         }
00142         xfree(rows);
00143     }
00144     pdfendstream();
00145     if (palette_objnum > 0) {
00146         pdfbegindict(palette_objnum);
00147         pdfbeginstream();
00148         for (i = 0; i < png_info(img)->num_palette; i++) {
00149             pdfroom(3);
00150             pdfbuf[pdfptr++] = png_info(img)->palette[i].red;
00151             pdfbuf[pdfptr++] = png_info(img)->palette[i].green;
00152             pdfbuf[pdfptr++] = png_info(img)->palette[i].blue;
00153         }
00154         pdfendstream();
00155     }
00156     pdfflush();
00157 }