~ubuntu-branches/ubuntu/jaunty/luatex/jaunty

« back to all changes in this revision

Viewing changes to src/texk/web2c/luatexdir/image/writepng.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2007-09-24 12:56:11 UTC
  • Revision ID: james.westby@ubuntu.com-20070924125611-a8ge689azbptxvla
Tags: upstream-0.11.2
ImportĀ upstreamĀ versionĀ 0.11.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
 
3
 
 
4
This file is part of pdfTeX.
 
5
 
 
6
pdfTeX is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation; either version 2 of the License, or
 
9
(at your option) any later version.
 
10
 
 
11
pdfTeX is distributed in the hope that it will be useful,
 
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
GNU General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with pdfTeX; if not, write to the Free Software
 
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 
 
20
$Id: writepng.c,v 1.2 2006/01/06 22:35:43 hahe Exp hahe $
 
21
*/
 
22
 
 
23
#include "ptexlib.h"
 
24
#include "image.h"
 
25
 
 
26
/*@unused@*/
 
27
static const char perforce_id[] =
 
28
    "$Id: writepng.c,v 1.2 2006/01/06 22:35:43 hahe Exp hahe $";
 
29
 
 
30
void read_png_info (integer img)
 
31
{
 
32
    double gamma;
 
33
    FILE *png_file = xfopen (img_name (img), FOPEN_RBIN_MODE);
 
34
 
 
35
    if ((png_ptr (img) = png_create_read_struct (PNG_LIBPNG_VER_STRING,
 
36
                                                 NULL, NULL, NULL)) == NULL)
 
37
        pdftex_fail ("libpng: png_create_read_struct() failed");
 
38
    if ((png_info (img) = png_create_info_struct (png_ptr (img))) == NULL)
 
39
        pdftex_fail ("libpng: png_create_info_struct() failed");
 
40
    if (setjmp (png_ptr (img)->jmpbuf))
 
41
        pdftex_fail ("libpng: internal error");
 
42
    png_init_io (png_ptr (img), png_file);
 
43
    png_read_info (png_ptr (img), png_info (img));
 
44
    /* simple transparency support */
 
45
    if (png_get_valid (png_ptr (img), png_info (img), PNG_INFO_tRNS)) {
 
46
        png_set_tRNS_to_alpha (png_ptr (img));
 
47
    }
 
48
    /* alpha channel support  */
 
49
    if (fixed_pdf_minor_version < 4
 
50
        && png_ptr (img)->color_type | PNG_COLOR_MASK_ALPHA)
 
51
        png_set_strip_alpha (png_ptr (img));
 
52
    /* 16bit depth support */
 
53
    if (fixed_pdf_minor_version < 5)
 
54
        fixed_image_hicolor = 0;
 
55
    if (png_info (img)->bit_depth == 16 && !fixed_image_hicolor)
 
56
        png_set_strip_16 (png_ptr (img));
 
57
    /* gamma support */
 
58
    if (fixed_image_apply_gamma) {
 
59
        if (png_get_gAMA (png_ptr (img), png_info (img), &gamma))
 
60
            png_set_gamma (png_ptr (img), (fixed_gamma / 1000.0), gamma);
 
61
        else
 
62
            png_set_gamma (png_ptr (img), (fixed_gamma / 1000.0),
 
63
                           (1000.0 / fixed_image_gamma));
 
64
    }
 
65
    /* reset structure */
 
66
    png_read_update_info (png_ptr (img), png_info (img));
 
67
    /* resolution support */
 
68
    img_width (img) = png_info (img)->width;
 
69
    img_height (img) = png_info (img)->height;
 
70
    if (png_info (img)->valid & PNG_INFO_pHYs) {
 
71
        img_xres (img) =
 
72
            round (0.0254 *
 
73
                   png_get_x_pixels_per_meter (png_ptr (img), png_info (img)));
 
74
        img_yres (img) =
 
75
            round (0.0254 *
 
76
                   png_get_y_pixels_per_meter (png_ptr (img), png_info (img)));
 
77
    }
 
78
    switch (png_info (img)->color_type) {
 
79
    case PNG_COLOR_TYPE_PALETTE:
 
80
        img_color (img) = IMAGE_COLOR_C | IMAGE_COLOR_I;
 
81
        break;
 
82
    case PNG_COLOR_TYPE_GRAY:
 
83
    case PNG_COLOR_TYPE_GRAY_ALPHA:
 
84
        img_color (img) = IMAGE_COLOR_B;
 
85
        break;
 
86
    case PNG_COLOR_TYPE_RGB:
 
87
    case PNG_COLOR_TYPE_RGB_ALPHA:
 
88
        img_color (img) = IMAGE_COLOR_C;
 
89
        break;
 
90
    default:
 
91
        pdftex_fail ("unsupported type of color_type <%i>",
 
92
                     png_info (img)->color_type);
 
93
    }
 
94
}
 
95
 
 
96
 
 
97
#define write_gray_pixel_16(r)                           \
 
98
  if (j % 4 == 0||j % 4 == 1)  pdf_buf[pdf_ptr++]  = *r++; \
 
99
  else                        smask[smask_ptr++] = *r++
 
100
 
 
101
#define write_gray_pixel_8(r)                   \
 
102
    if (j % 2 == 0)  pdf_buf[pdf_ptr++]   = *r++; \
 
103
    else             smask[smask_ptr++] = *r++
 
104
 
 
105
 
 
106
#define write_rgb_pixel_16(r)                                 \
 
107
    if (!(j % 8 == 6||j % 8 == 7)) pdf_buf[pdf_ptr++]  = *r++;  \
 
108
    else                           smask[smask_ptr++] = *r++
 
109
 
 
110
#define write_rgb_pixel_8(r)                                 \
 
111
    if (j % 4 != 3)      pdf_buf[pdf_ptr++]  = *r++;           \
 
112
    else                 smask[smask_ptr++] = *r++
 
113
 
 
114
#define write_simple_pixel(r)    pdf_buf[pdf_ptr++] = *r++
 
115
 
 
116
 
 
117
#define write_noninterlaced(outmac)                    \
 
118
  for (i = 0; (unsigned) i < (int)png_info(img)->height; i++) {   \
 
119
    png_read_row(png_ptr(img), row, NULL);             \
 
120
    r = row;                                           \
 
121
    k = png_info(img)->rowbytes;                       \
 
122
    while(k > 0) {                                     \
 
123
        l = (k > pdf_buf_size)? pdf_buf_size : k;          \
 
124
                pdfroom(l);                            \
 
125
                for (j = 0; j < l; j++) {              \
 
126
                  outmac;                              \
 
127
                }                                      \
 
128
                k -= l;                                \
 
129
            }                                          \
 
130
        }
 
131
 
 
132
#define write_interlaced(outmac)                       \
 
133
  for (i = 0; (unsigned) i < (int)png_info(img)->height; i++) {   \
 
134
            row = rows[i];                             \
 
135
            k = png_info(img)->rowbytes;               \
 
136
            while(k > 0) {                             \
 
137
                l = (k > pdf_buf_size)? pdf_buf_size : k;  \
 
138
                pdfroom(l);                            \
 
139
                for (j = 0; j < l; j++) {              \
 
140
                  outmac;                              \
 
141
                }                                      \
 
142
                k -= l;                                \
 
143
            }                                          \
 
144
            xfree(rows[i]);                            \
 
145
        }
 
146
 
 
147
 
 
148
void write_png_palette (integer img)
 
149
{
 
150
    int i, j, k, l;
 
151
    png_bytep row, r, *rows;
 
152
    integer palette_objnum = 0;
 
153
    pdf_create_obj (0, 0);
 
154
    palette_objnum = obj_ptr;
 
155
    if (img_colorspace_ref (img) != 0) {
 
156
        pdf_printf ("%i 0 R\n", (int) img_colorspace_ref (img));
 
157
    } else {
 
158
        pdf_printf ("[/Indexed /DeviceRGB %i %i 0 R]\n",
 
159
                    (int) (png_info (img)->num_palette - 1),
 
160
                    (int) palette_objnum);
 
161
    }
 
162
    pdf_begin_stream ();
 
163
    if (png_info (img)->interlace_type == PNG_INTERLACE_NONE) {
 
164
        row = xtalloc (png_info (img)->rowbytes, png_byte);
 
165
        write_noninterlaced (write_simple_pixel (r));
 
166
        xfree (row);
 
167
    } else {
 
168
        if (png_info (img)->height * png_info (img)->rowbytes >= 10240000L)
 
169
            pdftex_warn
 
170
                ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
 
171
        rows = xtalloc (png_info (img)->height, png_bytep);
 
172
        for (i = 0; (unsigned) i < png_info (img)->height; i++)
 
173
            rows[i] = xtalloc (png_info (img)->rowbytes, png_byte);
 
174
        png_read_image (png_ptr (img), rows);
 
175
        write_interlaced (write_simple_pixel (row));
 
176
        xfree (rows);
 
177
    }
 
178
    pdf_end_stream ();
 
179
    if (palette_objnum > 0) {
 
180
        pdf_begin_dict (palette_objnum, 0);
 
181
        pdf_begin_stream ();
 
182
        for (i = 0; (unsigned) i < png_info (img)->num_palette; i++) {
 
183
            pdfroom (3);
 
184
            pdf_buf[pdf_ptr++] = png_info (img)->palette[i].red;
 
185
            pdf_buf[pdf_ptr++] = png_info (img)->palette[i].green;
 
186
            pdf_buf[pdf_ptr++] = png_info (img)->palette[i].blue;
 
187
        }
 
188
        pdf_end_stream ();
 
189
    }
 
190
}
 
191
 
 
192
void write_png_gray (integer img)
 
193
{
 
194
    int i, j, k, l;
 
195
    png_bytep row, r, *rows;
 
196
    if (img_colorspace_ref (img) != 0) {
 
197
        pdf_printf ("%i 0 R\n", (int) img_colorspace_ref (img));
 
198
    } else {
 
199
        pdf_puts ("/DeviceGray\n");
 
200
    }
 
201
    pdf_begin_stream ();
 
202
    if (png_info (img)->interlace_type == PNG_INTERLACE_NONE) {
 
203
        row = xtalloc (png_info (img)->rowbytes, png_byte);
 
204
        write_noninterlaced (write_simple_pixel (r));
 
205
        xfree (row);
 
206
    } else {
 
207
        if (png_info (img)->height * png_info (img)->rowbytes >= 10240000L)
 
208
            pdftex_warn
 
209
                ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
 
210
        rows = xtalloc (png_info (img)->height, png_bytep);
 
211
        for (i = 0; (unsigned) i < png_info (img)->height; i++)
 
212
            rows[i] = xtalloc (png_info (img)->rowbytes, png_byte);
 
213
        png_read_image (png_ptr (img), rows);
 
214
        write_interlaced (write_simple_pixel (row));
 
215
        xfree (rows);
 
216
    }
 
217
    pdf_end_stream ();
 
218
}
 
219
 
 
220
 
 
221
 
 
222
void write_png_gray_alpha (integer img)
 
223
{
 
224
    int i, j, k, l;
 
225
    png_bytep row, r, *rows;
 
226
    integer smask_objnum = 0;
 
227
    png_bytep smask;
 
228
    integer smask_ptr = 0;
 
229
    integer smask_size = 0;
 
230
    int bitdepth;
 
231
    if (img_colorspace_ref (img) != 0) {
 
232
        pdf_printf ("%i 0 R\n", (int) img_colorspace_ref (img));
 
233
    } else {
 
234
        pdf_puts ("/DeviceGray\n");
 
235
    }
 
236
    pdf_create_obj (0, 0);
 
237
    smask_objnum = obj_ptr;
 
238
    pdf_printf ("/SMask %i 0 R\n", (int) smask_objnum);
 
239
    smask_size = (png_info (img)->rowbytes / 2) * png_info (img)->height;
 
240
    smask = xtalloc (smask_size, png_byte);
 
241
    pdf_begin_stream ();
 
242
    if (png_info (img)->interlace_type == PNG_INTERLACE_NONE) {
 
243
        row = xtalloc (png_info (img)->rowbytes, png_byte);
 
244
        if ((png_info (img)->bit_depth == 16) && fixed_image_hicolor) {
 
245
            write_noninterlaced (write_gray_pixel_16 (r));
 
246
        } else {
 
247
            write_noninterlaced (write_gray_pixel_8 (r));
 
248
        }
 
249
        xfree (row);
 
250
    } else {
 
251
        if (png_info (img)->height * png_info (img)->rowbytes >= 10240000L)
 
252
            pdftex_warn
 
253
                ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
 
254
        rows = xtalloc (png_info (img)->height, png_bytep);
 
255
        for (i = 0; (unsigned) i < png_info (img)->height; i++)
 
256
            rows[i] = xtalloc (png_info (img)->rowbytes, png_byte);
 
257
        png_read_image (png_ptr (img), rows);
 
258
        if ((png_info (img)->bit_depth == 16) && fixed_image_hicolor) {
 
259
            write_interlaced (write_gray_pixel_16 (row));
 
260
        } else {
 
261
            write_interlaced (write_gray_pixel_8 (row));
 
262
        }
 
263
        xfree (rows);
 
264
    }
 
265
    pdf_end_stream ();
 
266
    pdf_flush ();
 
267
    /* now write the Smask object */
 
268
    if (smask_objnum > 0) {
 
269
        bitdepth = (int) png_info (img)->bit_depth;
 
270
        pdf_begin_dict (smask_objnum, 0);
 
271
        pdf_puts ("/Type /XObject\n/Subtype /Image\n");
 
272
        pdf_printf ("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
 
273
                    (int) png_info (img)->width,
 
274
                    (int) png_info (img)->height,
 
275
                    (bitdepth == 16 ? 8 : bitdepth));
 
276
        pdf_puts ("/ColorSpace /DeviceGray\n");
 
277
        pdf_begin_stream ();
 
278
        for (i = 0; i < smask_size; i++) {
 
279
            if (i % 8 == 0)
 
280
                pdfroom (8);
 
281
            pdf_buf[pdf_ptr++] = smask[i];
 
282
            if (bitdepth == 16)
 
283
                i++;
 
284
        }
 
285
        xfree (smask);
 
286
        pdf_end_stream ();
 
287
    }
 
288
}
 
289
 
 
290
void write_png_rgb (integer img)
 
291
{
 
292
    int i, j, k, l;
 
293
    png_bytep row, r, *rows;
 
294
    if (img_colorspace_ref (img) != 0) {
 
295
        pdf_printf ("%i 0 R\n", (int) img_colorspace_ref (img));
 
296
    } else {
 
297
        pdf_puts ("/DeviceRGB\n");
 
298
    }
 
299
    pdf_begin_stream ();
 
300
    if (png_info (img)->interlace_type == PNG_INTERLACE_NONE) {
 
301
        row = xtalloc (png_info (img)->rowbytes, png_byte);
 
302
        write_noninterlaced (write_simple_pixel (r));
 
303
        xfree (row);
 
304
    } else {
 
305
        if (png_info (img)->height * png_info (img)->rowbytes >= 10240000L)
 
306
            pdftex_warn
 
307
                ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
 
308
        rows = xtalloc (png_info (img)->height, png_bytep);
 
309
        for (i = 0; (unsigned) i < png_info (img)->height; i++)
 
310
            rows[i] = xtalloc (png_info (img)->rowbytes, png_byte);
 
311
        png_read_image (png_ptr (img), rows);
 
312
        write_interlaced (write_simple_pixel (row));
 
313
        xfree (rows);
 
314
    }
 
315
    pdf_end_stream ();
 
316
}
 
317
 
 
318
void write_png_rgb_alpha (integer img)
 
319
{
 
320
    int i, j, k, l;
 
321
    png_bytep row, r, *rows;
 
322
    integer smask_objnum = 0;
 
323
    png_bytep smask;
 
324
    integer smask_ptr = 0;
 
325
    integer smask_size = 0;
 
326
    int bitdepth;
 
327
    if (img_colorspace_ref (img) != 0) {
 
328
        pdf_printf ("%i 0 R\n", (int) img_colorspace_ref (img));
 
329
    } else {
 
330
        pdf_puts ("/DeviceRGB\n");
 
331
    }
 
332
    pdf_create_obj (0, 0);
 
333
    smask_objnum = obj_ptr;
 
334
    pdf_printf ("/SMask %i 0 R\n", (int) smask_objnum);
 
335
    smask_size = (png_info (img)->rowbytes / 2) * png_info (img)->height;
 
336
    smask = xtalloc (smask_size, png_byte);
 
337
    pdf_begin_stream ();
 
338
    if (png_info (img)->interlace_type == PNG_INTERLACE_NONE) {
 
339
        row = xtalloc (png_info (img)->rowbytes, png_byte);
 
340
        if ((png_info (img)->bit_depth == 16) && fixed_image_hicolor) {
 
341
            write_noninterlaced (write_rgb_pixel_16 (r));
 
342
        } else {
 
343
            write_noninterlaced (write_rgb_pixel_8 (r));
 
344
        }
 
345
        xfree (row);
 
346
    } else {
 
347
        if (png_info (img)->height * png_info (img)->rowbytes >= 10240000L)
 
348
            pdftex_warn
 
349
                ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
 
350
        rows = xtalloc (png_info (img)->height, png_bytep);
 
351
        for (i = 0; (unsigned) i < png_info (img)->height; i++)
 
352
            rows[i] = xtalloc (png_info (img)->rowbytes, png_byte);
 
353
        png_read_image (png_ptr (img), rows);
 
354
        if ((png_info (img)->bit_depth == 16) && fixed_image_hicolor) {
 
355
            write_interlaced (write_rgb_pixel_16 (row));
 
356
        } else {
 
357
            write_interlaced (write_rgb_pixel_8 (row));
 
358
        }
 
359
        xfree (rows);
 
360
    }
 
361
    pdf_end_stream ();
 
362
    pdf_flush ();
 
363
    /* now write the Smask object */
 
364
    if (smask_objnum > 0) {
 
365
        bitdepth = (int) png_info (img)->bit_depth;
 
366
        pdf_begin_dict (smask_objnum, 0);
 
367
        pdf_puts ("/Type /XObject\n/Subtype /Image\n");
 
368
        pdf_printf ("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
 
369
                    (int) png_info (img)->width,
 
370
                    (int) png_info (img)->height,
 
371
                    (bitdepth == 16 ? 8 : bitdepth));
 
372
        pdf_puts ("/ColorSpace /DeviceGray\n");
 
373
        pdf_begin_stream ();
 
374
        for (i = 0; i < smask_size; i++) {
 
375
            if (i % 8 == 0)
 
376
                pdfroom (8);
 
377
            pdf_buf[pdf_ptr++] = smask[i];
 
378
            if (bitdepth == 16)
 
379
                i++;
 
380
        }
 
381
        xfree (smask);
 
382
        pdf_end_stream ();
 
383
    }
 
384
}
 
385
 
 
386
 
 
387
/**********************************************************************/
 
388
/*
 
389
 *
 
390
 * The |copy_png| function is from Hartmut Henkel. The goal is to use 
 
391
 * pdf's native FlateDecode support if that is possible.
 
392
 *
 
393
 * Only a subset of the png files allows this, but when possible it
 
394
 * greatly improves inclusion speed. 
 
395
 *
 
396
 */
 
397
 
 
398
/* Code cheerfully gleaned from Thomas Merz' PDFlib, file p_png.c "SPNG - Simple PNG" */
 
399
 
 
400
static int spng_getint (FILE * fp)
 
401
{
 
402
    unsigned char buf[4];
 
403
    if (fread (buf, 1, 4, fp) != 4)
 
404
        pdftex_fail ("writepng: reading chunk type failed");
 
405
    return ((((((int) buf[0] << 8) + buf[1]) << 8) + buf[2]) << 8) + buf[3];
 
406
}
 
407
 
 
408
#define SPNG_CHUNK_IDAT 0x49444154
 
409
#define SPNG_CHUNK_IEND 0x49454E44
 
410
 
 
411
void copy_png (integer img)
 
412
{
 
413
    FILE *fp = (FILE *) png_ptr (img)->io_ptr;
 
414
    int i, len, type, streamlength = 0;
 
415
    boolean endflag = false;
 
416
    int idat = 0;               /* flag to check continuous IDAT chunks sequence */
 
417
    /* 1st pass to find overall stream /Length */
 
418
    if (fseek (fp, 8, SEEK_SET) != 0)
 
419
        pdftex_fail ("writepng: fseek in PNG file failed");
 
420
    do {
 
421
        len = spng_getint (fp);
 
422
        type = spng_getint (fp);
 
423
        switch (type) {
 
424
        case SPNG_CHUNK_IEND:
 
425
            endflag = true;
 
426
            break;
 
427
        case SPNG_CHUNK_IDAT:
 
428
            streamlength += len;
 
429
        default:
 
430
            if (fseek (fp, len + 4, SEEK_CUR) != 0)
 
431
                pdftex_fail ("writepng: fseek in PNG file failed");
 
432
        }
 
433
    } while (endflag == false);
 
434
    pdf_printf ("/Length %d\n", streamlength);
 
435
    pdf_printf ("/Filter /FlateDecode\n");
 
436
    pdf_printf ("/DecodeParms << ");
 
437
    pdf_printf ("/Colors %d ", png_info (img)->color_type == 2 ? 3 : 1);
 
438
    pdf_printf ("/Columns %d ", (int) png_info (img)->width);
 
439
    pdf_printf ("/BitsPerComponent %i ", (int) png_info (img)->bit_depth);
 
440
    pdf_printf ("/Predictor %d ", 10);  /* actual predictor defined on line basis */
 
441
    pdf_printf (">>\n>>\nstream\n");
 
442
    /* 2nd pass to copy data */
 
443
    endflag = false;
 
444
    if (fseek (fp, 8, SEEK_SET) != 0)
 
445
        pdftex_fail ("writepng: fseek in PNG file failed");
 
446
    do {
 
447
        len = spng_getint (fp);
 
448
        type = spng_getint (fp);
 
449
        switch (type) {
 
450
        case SPNG_CHUNK_IDAT:  /* do copy */
 
451
            if (idat == 2)
 
452
                pdftex_fail ("writepng: IDAT chunk sequence broken");
 
453
            idat = 1;
 
454
            while (len > 0) {
 
455
                i = (len > pdf_buf_size) ? pdf_buf_size : len;
 
456
                pdfroom (i);
 
457
                fread (&pdf_buf[pdf_ptr], 1, i, fp);
 
458
                pdf_ptr += i;
 
459
                len -= i;
 
460
            }
 
461
            if (fseek (fp, 4, SEEK_CUR) != 0)
 
462
                pdftex_fail ("writepng: fseek in PNG file failed");
 
463
            break;
 
464
        case SPNG_CHUNK_IEND:  /* done */
 
465
            pdf_end_stream ();
 
466
            endflag = true;
 
467
            break;
 
468
        default:
 
469
            if (idat == 1)
 
470
                idat = 2;
 
471
            if (fseek (fp, len + 4, SEEK_CUR) != 0)
 
472
                pdftex_fail ("writepng: fseek in PNG file failed");
 
473
        }
 
474
    } while (endflag == false);
 
475
}
 
476
 
 
477
void write_png (integer img)
 
478
{
 
479
 
 
480
    double gamma, checked_gamma;
 
481
    int i;
 
482
    integer palette_objnum = 0;
 
483
    if (fixed_pdf_minor_version < 5)
 
484
        fixed_image_hicolor = 0;
 
485
 
 
486
    pdf_puts ("/Type /XObject\n/Subtype /Image\n");
 
487
    pdf_printf ("/Width %i\n/Height %i\n/BitsPerComponent %i\n",
 
488
                (int) png_info (img)->width,
 
489
                (int) png_info (img)->height, (int) png_info (img)->bit_depth);
 
490
    pdf_puts ("/ColorSpace ");
 
491
    checked_gamma = 1.0;
 
492
    if (fixed_image_apply_gamma) {
 
493
        if (png_get_gAMA (png_ptr (img), png_info (img), &gamma)) {
 
494
            checked_gamma = (fixed_gamma / 1000.0) * gamma;
 
495
        } else {
 
496
            checked_gamma = (fixed_gamma / 1000.0) * (1000.0 / fixed_image_gamma);
 
497
        }
 
498
    }
 
499
    /* the switching between |png_info| and |png_ptr| queries has been trial and error. 
 
500
     */
 
501
    if (fixed_pdf_minor_version > 1 && png_info (img)->interlace_type == PNG_INTERLACE_NONE && (png_ptr (img)->transformations == 0 || png_ptr (img)->transformations == 0x2000)   /* gamma */
 
502
        &&!(png_ptr (img)->color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
 
503
            png_ptr (img)->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
 
504
        && (fixed_image_hicolor || (png_ptr (img)->bit_depth <= 8))
 
505
        && (checked_gamma <= 1.01 && checked_gamma > 0.99)
 
506
        ) {
 
507
        if (img_colorspace_ref (img) != 0) {
 
508
            pdf_printf ("%i 0 R\n", (int) img_colorspace_ref (img));
 
509
        } else {
 
510
            switch (png_info (img)->color_type) {
 
511
            case PNG_COLOR_TYPE_PALETTE:
 
512
                pdf_create_obj (0, 0);
 
513
                palette_objnum = obj_ptr;
 
514
                pdf_printf ("[/Indexed /DeviceRGB %i %i 0 R]\n",
 
515
                            (int) (png_info (img)->num_palette - 1),
 
516
                            (int) palette_objnum);
 
517
                break;
 
518
            case PNG_COLOR_TYPE_GRAY:
 
519
                pdf_puts ("/DeviceGray\n");
 
520
                break;
 
521
            default:           /* RGB */
 
522
                pdf_puts ("/DeviceRGB\n");
 
523
            };
 
524
        }
 
525
                if (tracefilenames)
 
526
                  tex_printf (" (PNG copy)");
 
527
        copy_png (img);
 
528
        if (palette_objnum > 0) {
 
529
            pdf_begin_dict (palette_objnum, 0);
 
530
            pdf_begin_stream ();
 
531
            for (i = 0; (unsigned) i < png_info (img)->num_palette; i++) {
 
532
                pdfroom (3);
 
533
                pdf_buf[pdf_ptr++] = png_info (img)->palette[i].red;
 
534
                pdf_buf[pdf_ptr++] = png_info (img)->palette[i].green;
 
535
                pdf_buf[pdf_ptr++] = png_info (img)->palette[i].blue;
 
536
            }
 
537
            pdf_end_stream ();
 
538
        }
 
539
    } else {
 
540
        if (0) {
 
541
            tex_printf (" PNG copy skipped because: ");
 
542
            if (fixed_image_apply_gamma &&
 
543
                (checked_gamma > 1.01 || checked_gamma < 0.99))
 
544
                tex_printf ("gamma delta=%lf ", checked_gamma);
 
545
            if (png_ptr (img)->transformations != PNG_TRANSFORM_IDENTITY)
 
546
                tex_printf ("transform=%lu", (long)png_ptr (img)->transformations);
 
547
            if ((png_info (img)->color_type != PNG_COLOR_TYPE_GRAY) &&
 
548
                (png_info (img)->color_type != PNG_COLOR_TYPE_RGB) &&
 
549
                (png_info (img)->color_type != PNG_COLOR_TYPE_PALETTE))
 
550
                tex_printf ("colortype ");
 
551
            if (fixed_pdf_minor_version <= 1)
 
552
                tex_printf ("version=%d ", (int)fixed_pdf_minor_version);
 
553
            if (png_info (img)->interlace_type != PNG_INTERLACE_NONE)
 
554
                tex_printf ("interlaced ");
 
555
            if (png_info (img)->bit_depth > 8)
 
556
                tex_printf ("bitdepth=%d ", png_info (img)->bit_depth);
 
557
            if (png_get_valid (png_ptr (img), png_info (img), PNG_INFO_tRNS))
 
558
                tex_printf ("simple transparancy ");
 
559
        }
 
560
        switch (png_info (img)->color_type) {
 
561
        case PNG_COLOR_TYPE_PALETTE:
 
562
            write_png_palette (img);
 
563
            break;
 
564
        case PNG_COLOR_TYPE_GRAY:
 
565
            write_png_gray (img);
 
566
            break;
 
567
        case PNG_COLOR_TYPE_GRAY_ALPHA:
 
568
            if (fixed_pdf_minor_version >= 4)
 
569
                write_png_gray_alpha (img);
 
570
            else
 
571
                write_png_gray (img);
 
572
            break;
 
573
        case PNG_COLOR_TYPE_RGB:
 
574
            write_png_rgb (img);
 
575
            break;
 
576
        case PNG_COLOR_TYPE_RGB_ALPHA:
 
577
            if (fixed_pdf_minor_version >= 4)
 
578
                write_png_rgb_alpha (img);
 
579
            else
 
580
                write_png_rgb (img);
 
581
            break;
 
582
        default:
 
583
            pdftex_fail ("unsupported type of color_type <%i>",
 
584
                         png_info (img)->color_type);
 
585
        }
 
586
    }
 
587
    pdf_flush ();
 
588
}