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