Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
96 giacomo 1
 
2
/* pngwtran.c - transforms the data in a row for PNG writers
3
 *
4
 * libpng 1.2.5 - October 3, 2002
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2002 Glenn Randers-Pehrson
7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9
 */
10
 
11
#define PNG_INTERNAL
12
#include "png.h"
13
#ifdef PNG_WRITE_SUPPORTED
14
 
15
/* Transform the data according to the user's wishes.  The order of
16
 * transformations is significant.
17
 */
18
void /* PRIVATE */
19
png_do_write_transformations(png_structp png_ptr)
20
{
21
   png_debug(1, "in png_do_write_transformations\n");
22
 
23
   if (png_ptr == NULL)
24
      return;
25
 
26
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
27
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
28
      if(png_ptr->write_user_transform_fn != NULL)
29
        (*(png_ptr->write_user_transform_fn)) /* user write transform function */
30
          (png_ptr,                    /* png_ptr */
31
           &(png_ptr->row_info),       /* row_info:     */
32
             /*  png_uint_32 width;          width of row */
33
             /*  png_uint_32 rowbytes;       number of bytes in row */
34
             /*  png_byte color_type;        color type of pixels */
35
             /*  png_byte bit_depth;         bit depth of samples */
36
             /*  png_byte channels;          number of channels (1-4) */
37
             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
38
           png_ptr->row_buf + 1);      /* start of pixel data for row */
39
#endif
40
#if defined(PNG_WRITE_FILLER_SUPPORTED)
41
   if (png_ptr->transformations & PNG_FILLER)
42
      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
43
         png_ptr->flags);
44
#endif
45
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
46
   if (png_ptr->transformations & PNG_PACKSWAP)
47
      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
48
#endif
49
#if defined(PNG_WRITE_PACK_SUPPORTED)
50
   if (png_ptr->transformations & PNG_PACK)
51
      png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
52
         (png_uint_32)png_ptr->bit_depth);
53
#endif
54
#if defined(PNG_WRITE_SWAP_SUPPORTED)
55
   if (png_ptr->transformations & PNG_SWAP_BYTES)
56
      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
57
#endif
58
#if defined(PNG_WRITE_SHIFT_SUPPORTED)
59
   if (png_ptr->transformations & PNG_SHIFT)
60
      png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
61
         &(png_ptr->shift));
62
#endif
63
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
64
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
65
      png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
66
#endif
67
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
68
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
69
      png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
70
#endif
71
#if defined(PNG_WRITE_BGR_SUPPORTED)
72
   if (png_ptr->transformations & PNG_BGR)
73
      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
74
#endif
75
#if defined(PNG_WRITE_INVERT_SUPPORTED)
76
   if (png_ptr->transformations & PNG_INVERT_MONO)
77
      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
78
#endif
79
}
80
 
81
#if defined(PNG_WRITE_PACK_SUPPORTED)
82
/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
83
 * row_info bit depth should be 8 (one pixel per byte).  The channels
84
 * should be 1 (this only happens on grayscale and paletted images).
85
 */
86
void /* PRIVATE */
87
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
88
{
89
   png_debug(1, "in png_do_pack\n");
90
   if (row_info->bit_depth == 8 &&
91
#if defined(PNG_USELESS_TESTS_SUPPORTED)
92
       row != NULL && row_info != NULL &&
93
#endif
94
      row_info->channels == 1)
95
   {
96
      switch ((int)bit_depth)
97
      {
98
         case 1:
99
         {
100
            png_bytep sp, dp;
101
            int mask, v;
102
            png_uint_32 i;
103
            png_uint_32 row_width = row_info->width;
104
 
105
            sp = row;
106
            dp = row;
107
            mask = 0x80;
108
            v = 0;
109
 
110
            for (i = 0; i < row_width; i++)
111
            {
112
               if (*sp != 0)
113
                  v |= mask;
114
               sp++;
115
               if (mask > 1)
116
                  mask >>= 1;
117
               else
118
               {
119
                  mask = 0x80;
120
                  *dp = (png_byte)v;
121
                  dp++;
122
                  v = 0;
123
               }
124
            }
125
            if (mask != 0x80)
126
               *dp = (png_byte)v;
127
            break;
128
         }
129
         case 2:
130
         {
131
            png_bytep sp, dp;
132
            int shift, v;
133
            png_uint_32 i;
134
            png_uint_32 row_width = row_info->width;
135
 
136
            sp = row;
137
            dp = row;
138
            shift = 6;
139
            v = 0;
140
            for (i = 0; i < row_width; i++)
141
            {
142
               png_byte value;
143
 
144
               value = (png_byte)(*sp & 0x03);
145
               v |= (value << shift);
146
               if (shift == 0)
147
               {
148
                  shift = 6;
149
                  *dp = (png_byte)v;
150
                  dp++;
151
                  v = 0;
152
               }
153
               else
154
                  shift -= 2;
155
               sp++;
156
            }
157
            if (shift != 6)
158
               *dp = (png_byte)v;
159
            break;
160
         }
161
         case 4:
162
         {
163
            png_bytep sp, dp;
164
            int shift, v;
165
            png_uint_32 i;
166
            png_uint_32 row_width = row_info->width;
167
 
168
            sp = row;
169
            dp = row;
170
            shift = 4;
171
            v = 0;
172
            for (i = 0; i < row_width; i++)
173
            {
174
               png_byte value;
175
 
176
               value = (png_byte)(*sp & 0x0f);
177
               v |= (value << shift);
178
 
179
               if (shift == 0)
180
               {
181
                  shift = 4;
182
                  *dp = (png_byte)v;
183
                  dp++;
184
                  v = 0;
185
               }
186
               else
187
                  shift -= 4;
188
 
189
               sp++;
190
            }
191
            if (shift != 4)
192
               *dp = (png_byte)v;
193
            break;
194
         }
195
      }
196
      row_info->bit_depth = (png_byte)bit_depth;
197
      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
198
      row_info->rowbytes =
199
         ((row_info->width * row_info->pixel_depth + 7) >> 3);
200
   }
201
}
202
#endif
203
 
204
#if defined(PNG_WRITE_SHIFT_SUPPORTED)
205
/* Shift pixel values to take advantage of whole range.  Pass the
206
 * true number of bits in bit_depth.  The row should be packed
207
 * according to row_info->bit_depth.  Thus, if you had a row of
208
 * bit depth 4, but the pixels only had values from 0 to 7, you
209
 * would pass 3 as bit_depth, and this routine would translate the
210
 * data to 0 to 15.
211
 */
212
void /* PRIVATE */
213
png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
214
{
215
   png_debug(1, "in png_do_shift\n");
216
#if defined(PNG_USELESS_TESTS_SUPPORTED)
217
   if (row != NULL && row_info != NULL &&
218
#else
219
   if (
220
#endif
221
      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
222
   {
223
      int shift_start[4], shift_dec[4];
224
      int channels = 0;
225
 
226
      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
227
      {
228
         shift_start[channels] = row_info->bit_depth - bit_depth->red;
229
         shift_dec[channels] = bit_depth->red;
230
         channels++;
231
         shift_start[channels] = row_info->bit_depth - bit_depth->green;
232
         shift_dec[channels] = bit_depth->green;
233
         channels++;
234
         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
235
         shift_dec[channels] = bit_depth->blue;
236
         channels++;
237
      }
238
      else
239
      {
240
         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
241
         shift_dec[channels] = bit_depth->gray;
242
         channels++;
243
      }
244
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
245
      {
246
         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
247
         shift_dec[channels] = bit_depth->alpha;
248
         channels++;
249
      }
250
 
251
      /* with low row depths, could only be grayscale, so one channel */
252
      if (row_info->bit_depth < 8)
253
      {
254
         png_bytep bp = row;
255
         png_uint_32 i;
256
         png_byte mask;
257
         png_uint_32 row_bytes = row_info->rowbytes;
258
 
259
         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
260
            mask = 0x55;
261
         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
262
            mask = 0x11;
263
         else
264
            mask = 0xff;
265
 
266
         for (i = 0; i < row_bytes; i++, bp++)
267
         {
268
            png_uint_16 v;
269
            int j;
270
 
271
            v = *bp;
272
            *bp = 0;
273
            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
274
            {
275
               if (j > 0)
276
                  *bp |= (png_byte)((v << j) & 0xff);
277
               else
278
                  *bp |= (png_byte)((v >> (-j)) & mask);
279
            }
280
         }
281
      }
282
      else if (row_info->bit_depth == 8)
283
      {
284
         png_bytep bp = row;
285
         png_uint_32 i;
286
         png_uint_32 istop = channels * row_info->width;
287
 
288
         for (i = 0; i < istop; i++, bp++)
289
         {
290
 
291
            png_uint_16 v;
292
            int j;
293
            int c = (int)(i%channels);
294
 
295
            v = *bp;
296
            *bp = 0;
297
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
298
            {
299
               if (j > 0)
300
                  *bp |= (png_byte)((v << j) & 0xff);
301
               else
302
                  *bp |= (png_byte)((v >> (-j)) & 0xff);
303
            }
304
         }
305
      }
306
      else
307
      {
308
         png_bytep bp;
309
         png_uint_32 i;
310
         png_uint_32 istop = channels * row_info->width;
311
 
312
         for (bp = row, i = 0; i < istop; i++)
313
         {
314
            int c = (int)(i%channels);
315
            png_uint_16 value, v;
316
            int j;
317
 
318
            v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
319
            value = 0;
320
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
321
            {
322
               if (j > 0)
323
                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
324
               else
325
                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
326
            }
327
            *bp++ = (png_byte)(value >> 8);
328
            *bp++ = (png_byte)(value & 0xff);
329
         }
330
      }
331
   }
332
}
333
#endif
334
 
335
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
336
void /* PRIVATE */
337
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
338
{
339
   png_debug(1, "in png_do_write_swap_alpha\n");
340
#if defined(PNG_USELESS_TESTS_SUPPORTED)
341
   if (row != NULL && row_info != NULL)
342
#endif
343
   {
344
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
345
      {
346
         /* This converts from ARGB to RGBA */
347
         if (row_info->bit_depth == 8)
348
         {
349
            png_bytep sp, dp;
350
            png_uint_32 i;
351
            png_uint_32 row_width = row_info->width;
352
            for (i = 0, sp = dp = row; i < row_width; i++)
353
            {
354
               png_byte save = *(sp++);
355
               *(dp++) = *(sp++);
356
               *(dp++) = *(sp++);
357
               *(dp++) = *(sp++);
358
               *(dp++) = save;
359
            }
360
         }
361
         /* This converts from AARRGGBB to RRGGBBAA */
362
         else
363
         {
364
            png_bytep sp, dp;
365
            png_uint_32 i;
366
            png_uint_32 row_width = row_info->width;
367
 
368
            for (i = 0, sp = dp = row; i < row_width; i++)
369
            {
370
               png_byte save[2];
371
               save[0] = *(sp++);
372
               save[1] = *(sp++);
373
               *(dp++) = *(sp++);
374
               *(dp++) = *(sp++);
375
               *(dp++) = *(sp++);
376
               *(dp++) = *(sp++);
377
               *(dp++) = *(sp++);
378
               *(dp++) = *(sp++);
379
               *(dp++) = save[0];
380
               *(dp++) = save[1];
381
            }
382
         }
383
      }
384
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
385
      {
386
         /* This converts from AG to GA */
387
         if (row_info->bit_depth == 8)
388
         {
389
            png_bytep sp, dp;
390
            png_uint_32 i;
391
            png_uint_32 row_width = row_info->width;
392
 
393
            for (i = 0, sp = dp = row; i < row_width; i++)
394
            {
395
               png_byte save = *(sp++);
396
               *(dp++) = *(sp++);
397
               *(dp++) = save;
398
            }
399
         }
400
         /* This converts from AAGG to GGAA */
401
         else
402
         {
403
            png_bytep sp, dp;
404
            png_uint_32 i;
405
            png_uint_32 row_width = row_info->width;
406
 
407
            for (i = 0, sp = dp = row; i < row_width; i++)
408
            {
409
               png_byte save[2];
410
               save[0] = *(sp++);
411
               save[1] = *(sp++);
412
               *(dp++) = *(sp++);
413
               *(dp++) = *(sp++);
414
               *(dp++) = save[0];
415
               *(dp++) = save[1];
416
            }
417
         }
418
      }
419
   }
420
}
421
#endif
422
 
423
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
424
void /* PRIVATE */
425
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
426
{
427
   png_debug(1, "in png_do_write_invert_alpha\n");
428
#if defined(PNG_USELESS_TESTS_SUPPORTED)
429
   if (row != NULL && row_info != NULL)
430
#endif
431
   {
432
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
433
      {
434
         /* This inverts the alpha channel in RGBA */
435
         if (row_info->bit_depth == 8)
436
         {
437
            png_bytep sp, dp;
438
            png_uint_32 i;
439
            png_uint_32 row_width = row_info->width;
440
            for (i = 0, sp = dp = row; i < row_width; i++)
441
            {
442
               *(dp++) = *(sp++);
443
               *(dp++) = *(sp++);
444
               *(dp++) = *(sp++);
445
               *(dp++) = (png_byte)(255 - *(sp++));
446
            }
447
         }
448
         /* This inverts the alpha channel in RRGGBBAA */
449
         else
450
         {
451
            png_bytep sp, dp;
452
            png_uint_32 i;
453
            png_uint_32 row_width = row_info->width;
454
 
455
            for (i = 0, sp = dp = row; i < row_width; i++)
456
            {
457
               *(dp++) = *(sp++);
458
               *(dp++) = *(sp++);
459
               *(dp++) = *(sp++);
460
               *(dp++) = *(sp++);
461
               *(dp++) = *(sp++);
462
               *(dp++) = *(sp++);
463
               *(dp++) = (png_byte)(255 - *(sp++));
464
               *(dp++) = (png_byte)(255 - *(sp++));
465
            }
466
         }
467
      }
468
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
469
      {
470
         /* This inverts the alpha channel in GA */
471
         if (row_info->bit_depth == 8)
472
         {
473
            png_bytep sp, dp;
474
            png_uint_32 i;
475
            png_uint_32 row_width = row_info->width;
476
 
477
            for (i = 0, sp = dp = row; i < row_width; i++)
478
            {
479
               *(dp++) = *(sp++);
480
               *(dp++) = (png_byte)(255 - *(sp++));
481
            }
482
         }
483
         /* This inverts the alpha channel in GGAA */
484
         else
485
         {
486
            png_bytep sp, dp;
487
            png_uint_32 i;
488
            png_uint_32 row_width = row_info->width;
489
 
490
            for (i = 0, sp = dp = row; i < row_width; i++)
491
            {
492
               *(dp++) = *(sp++);
493
               *(dp++) = *(sp++);
494
               *(dp++) = (png_byte)(255 - *(sp++));
495
               *(dp++) = (png_byte)(255 - *(sp++));
496
            }
497
         }
498
      }
499
   }
500
}
501
#endif
502
 
503
#if defined(PNG_MNG_FEATURES_SUPPORTED)
504
/* undoes intrapixel differencing  */
505
void /* PRIVATE */
506
png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
507
{
508
   png_debug(1, "in png_do_write_intrapixel\n");
509
   if (
510
#if defined(PNG_USELESS_TESTS_SUPPORTED)
511
       row != NULL && row_info != NULL &&
512
#endif
513
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
514
   {
515
      int bytes_per_pixel;
516
      png_uint_32 row_width = row_info->width;
517
      if (row_info->bit_depth == 8)
518
      {
519
         png_bytep rp;
520
         png_uint_32 i;
521
 
522
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
523
            bytes_per_pixel = 3;
524
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
525
            bytes_per_pixel = 4;
526
         else
527
            return;
528
 
529
         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
530
         {
531
            *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
532
            *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
533
         }
534
      }
535
      else if (row_info->bit_depth == 16)
536
      {
537
         png_bytep rp;
538
         png_uint_32 i;
539
 
540
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
541
            bytes_per_pixel = 6;
542
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
543
            bytes_per_pixel = 8;
544
         else
545
            return;
546
 
547
         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
548
         {
549
            png_uint_32 s0=*(rp  )<<8 | *(rp+1);
550
            png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
551
            png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
552
            png_uint_32 red=(s0-s1)&0xffff;
553
            png_uint_32 blue=(s2-s1)&0xffff;
554
            *(rp  ) = (png_byte)((red>>8)&0xff);
555
            *(rp+1) = (png_byte)(red&0xff);
556
            *(rp+4) = (png_byte)((blue>>8)&0xff);
557
            *(rp+5) = (png_byte)(blue&0xff);
558
         }
559
      }
560
   }
561
}
562
#endif /* PNG_MNG_FEATURES_SUPPORTED */
563
#endif /* PNG_WRITE_SUPPORTED */