pngwtran.c
Go to the documentation of this file.
00001 
00002 /* pngwtran.c - transforms the data in a row for PNG writers
00003  *
00004  * Last changed in libpng 1.2.9 April 14, 2006
00005  * For conditions of distribution and use, see copyright notice in png.h
00006  * Copyright (c) 1998-2006 Glenn Randers-Pehrson
00007  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00008  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00009  */
00010 
00011 #define PNG_INTERNAL
00012 #include "png.h"
00013 #ifdef PNG_WRITE_SUPPORTED
00014 
00015 /* Transform the data according to the user's wishes.  The order of
00016  * transformations is significant.
00017  */
00018 void /* PRIVATE */
00019 png_do_write_transformations(png_structp png_ptr)
00020 {
00021    png_debug(1, "in png_do_write_transformations\n");
00022 
00023    if (png_ptr == NULL)
00024       return;
00025 
00026 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
00027    if (png_ptr->transformations & PNG_USER_TRANSFORM)
00028       if (png_ptr->write_user_transform_fn != NULL)
00029         (*(png_ptr->write_user_transform_fn)) /* user write transform function */
00030           (png_ptr,                    /* png_ptr */
00031            &(png_ptr->row_info),       /* row_info:     */
00032              /*  png_uint_32 width;          width of row */
00033              /*  png_uint_32 rowbytes;       number of bytes in row */
00034              /*  png_byte color_type;        color type of pixels */
00035              /*  png_byte bit_depth;         bit depth of samples */
00036              /*  png_byte channels;          number of channels (1-4) */
00037              /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
00038            png_ptr->row_buf + 1);      /* start of pixel data for row */
00039 #endif
00040 #if defined(PNG_WRITE_FILLER_SUPPORTED)
00041    if (png_ptr->transformations & PNG_FILLER)
00042       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
00043          png_ptr->flags);
00044 #endif
00045 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
00046    if (png_ptr->transformations & PNG_PACKSWAP)
00047       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
00048 #endif
00049 #if defined(PNG_WRITE_PACK_SUPPORTED)
00050    if (png_ptr->transformations & PNG_PACK)
00051       png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
00052          (png_uint_32)png_ptr->bit_depth);
00053 #endif
00054 #if defined(PNG_WRITE_SWAP_SUPPORTED)
00055    if (png_ptr->transformations & PNG_SWAP_BYTES)
00056       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
00057 #endif
00058 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
00059    if (png_ptr->transformations & PNG_SHIFT)
00060       png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
00061          &(png_ptr->shift));
00062 #endif
00063 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
00064    if (png_ptr->transformations & PNG_SWAP_ALPHA)
00065       png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
00066 #endif
00067 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
00068    if (png_ptr->transformations & PNG_INVERT_ALPHA)
00069       png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
00070 #endif
00071 #if defined(PNG_WRITE_BGR_SUPPORTED)
00072    if (png_ptr->transformations & PNG_BGR)
00073       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
00074 #endif
00075 #if defined(PNG_WRITE_INVERT_SUPPORTED)
00076    if (png_ptr->transformations & PNG_INVERT_MONO)
00077       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
00078 #endif
00079 }
00080 
00081 #if defined(PNG_WRITE_PACK_SUPPORTED)
00082 /* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
00083  * row_info bit depth should be 8 (one pixel per byte).  The channels
00084  * should be 1 (this only happens on grayscale and paletted images).
00085  */
00086 void /* PRIVATE */
00087 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
00088 {
00089    png_debug(1, "in png_do_pack\n");
00090    if (row_info->bit_depth == 8 &&
00091 #if defined(PNG_USELESS_TESTS_SUPPORTED)
00092        row != NULL && row_info != NULL &&
00093 #endif
00094       row_info->channels == 1)
00095    {
00096       switch ((int)bit_depth)
00097       {
00098          case 1:
00099          {
00100             png_bytep sp, dp;
00101             int mask, v;
00102             png_uint_32 i;
00103             png_uint_32 row_width = row_info->width;
00104 
00105             sp = row;
00106             dp = row;
00107             mask = 0x80;
00108             v = 0;
00109 
00110             for (i = 0; i < row_width; i++)
00111             {
00112                if (*sp != 0)
00113                   v |= mask;
00114                sp++;
00115                if (mask > 1)
00116                   mask >>= 1;
00117                else
00118                {
00119                   mask = 0x80;
00120                   *dp = (png_byte)v;
00121                   dp++;
00122                   v = 0;
00123                }
00124             }
00125             if (mask != 0x80)
00126                *dp = (png_byte)v;
00127             break;
00128          }
00129          case 2:
00130          {
00131             png_bytep sp, dp;
00132             int shift, v;
00133             png_uint_32 i;
00134             png_uint_32 row_width = row_info->width;
00135 
00136             sp = row;
00137             dp = row;
00138             shift = 6;
00139             v = 0;
00140             for (i = 0; i < row_width; i++)
00141             {
00142                png_byte value;
00143 
00144                value = (png_byte)(*sp & 0x03);
00145                v |= (value << shift);
00146                if (shift == 0)
00147                {
00148                   shift = 6;
00149                   *dp = (png_byte)v;
00150                   dp++;
00151                   v = 0;
00152                }
00153                else
00154                   shift -= 2;
00155                sp++;
00156             }
00157             if (shift != 6)
00158                *dp = (png_byte)v;
00159             break;
00160          }
00161          case 4:
00162          {
00163             png_bytep sp, dp;
00164             int shift, v;
00165             png_uint_32 i;
00166             png_uint_32 row_width = row_info->width;
00167 
00168             sp = row;
00169             dp = row;
00170             shift = 4;
00171             v = 0;
00172             for (i = 0; i < row_width; i++)
00173             {
00174                png_byte value;
00175 
00176                value = (png_byte)(*sp & 0x0f);
00177                v |= (value << shift);
00178 
00179                if (shift == 0)
00180                {
00181                   shift = 4;
00182                   *dp = (png_byte)v;
00183                   dp++;
00184                   v = 0;
00185                }
00186                else
00187                   shift -= 4;
00188 
00189                sp++;
00190             }
00191             if (shift != 4)
00192                *dp = (png_byte)v;
00193             break;
00194          }
00195       }
00196       row_info->bit_depth = (png_byte)bit_depth;
00197       row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
00198       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
00199          row_info->width);
00200    }
00201 }
00202 #endif
00203 
00204 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
00205 /* Shift pixel values to take advantage of whole range.  Pass the
00206  * true number of bits in bit_depth.  The row should be packed
00207  * according to row_info->bit_depth.  Thus, if you had a row of
00208  * bit depth 4, but the pixels only had values from 0 to 7, you
00209  * would pass 3 as bit_depth, and this routine would translate the
00210  * data to 0 to 15.
00211  */
00212 void /* PRIVATE */
00213 png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
00214 {
00215    png_debug(1, "in png_do_shift\n");
00216 #if defined(PNG_USELESS_TESTS_SUPPORTED)
00217    if (row != NULL && row_info != NULL &&
00218 #else
00219    if (
00220 #endif
00221       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
00222    {
00223       int shift_start[4], shift_dec[4];
00224       int channels = 0;
00225 
00226       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
00227       {
00228          shift_start[channels] = row_info->bit_depth - bit_depth->red;
00229          shift_dec[channels] = bit_depth->red;
00230          channels++;
00231          shift_start[channels] = row_info->bit_depth - bit_depth->green;
00232          shift_dec[channels] = bit_depth->green;
00233          channels++;
00234          shift_start[channels] = row_info->bit_depth - bit_depth->blue;
00235          shift_dec[channels] = bit_depth->blue;
00236          channels++;
00237       }
00238       else
00239       {
00240          shift_start[channels] = row_info->bit_depth - bit_depth->gray;
00241          shift_dec[channels] = bit_depth->gray;
00242          channels++;
00243       }
00244       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
00245       {
00246          shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
00247          shift_dec[channels] = bit_depth->alpha;
00248          channels++;
00249       }
00250 
00251       /* with low row depths, could only be grayscale, so one channel */
00252       if (row_info->bit_depth < 8)
00253       {
00254          png_bytep bp = row;
00255          png_uint_32 i;
00256          png_byte mask;
00257          png_uint_32 row_bytes = row_info->rowbytes;
00258 
00259          if (bit_depth->gray == 1 && row_info->bit_depth == 2)
00260             mask = 0x55;
00261          else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
00262             mask = 0x11;
00263          else
00264             mask = 0xff;
00265 
00266          for (i = 0; i < row_bytes; i++, bp++)
00267          {
00268             png_uint_16 v;
00269             int j;
00270 
00271             v = *bp;
00272             *bp = 0;
00273             for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
00274             {
00275                if (j > 0)
00276                   *bp |= (png_byte)((v << j) & 0xff);
00277                else
00278                   *bp |= (png_byte)((v >> (-j)) & mask);
00279             }
00280          }
00281       }
00282       else if (row_info->bit_depth == 8)
00283       {
00284          png_bytep bp = row;
00285          png_uint_32 i;
00286          png_uint_32 istop = channels * row_info->width;
00287 
00288          for (i = 0; i < istop; i++, bp++)
00289          {
00290 
00291             png_uint_16 v;
00292             int j;
00293             int c = (int)(i%channels);
00294 
00295             v = *bp;
00296             *bp = 0;
00297             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
00298             {
00299                if (j > 0)
00300                   *bp |= (png_byte)((v << j) & 0xff);
00301                else
00302                   *bp |= (png_byte)((v >> (-j)) & 0xff);
00303             }
00304          }
00305       }
00306       else
00307       {
00308          png_bytep bp;
00309          png_uint_32 i;
00310          png_uint_32 istop = channels * row_info->width;
00311 
00312          for (bp = row, i = 0; i < istop; i++)
00313          {
00314             int c = (int)(i%channels);
00315             png_uint_16 value, v;
00316             int j;
00317 
00318             v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
00319             value = 0;
00320             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
00321             {
00322                if (j > 0)
00323                   value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
00324                else
00325                   value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
00326             }
00327             *bp++ = (png_byte)(value >> 8);
00328             *bp++ = (png_byte)(value & 0xff);
00329          }
00330       }
00331    }
00332 }
00333 #endif
00334 
00335 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
00336 void /* PRIVATE */
00337 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
00338 {
00339    png_debug(1, "in png_do_write_swap_alpha\n");
00340 #if defined(PNG_USELESS_TESTS_SUPPORTED)
00341    if (row != NULL && row_info != NULL)
00342 #endif
00343    {
00344       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
00345       {
00346          /* This converts from ARGB to RGBA */
00347          if (row_info->bit_depth == 8)
00348          {
00349             png_bytep sp, dp;
00350             png_uint_32 i;
00351             png_uint_32 row_width = row_info->width;
00352             for (i = 0, sp = dp = row; i < row_width; i++)
00353             {
00354                png_byte save = *(sp++);
00355                *(dp++) = *(sp++);
00356                *(dp++) = *(sp++);
00357                *(dp++) = *(sp++);
00358                *(dp++) = save;
00359             }
00360          }
00361          /* This converts from AARRGGBB to RRGGBBAA */
00362          else
00363          {
00364             png_bytep sp, dp;
00365             png_uint_32 i;
00366             png_uint_32 row_width = row_info->width;
00367 
00368             for (i = 0, sp = dp = row; i < row_width; i++)
00369             {
00370                png_byte save[2];
00371                save[0] = *(sp++);
00372                save[1] = *(sp++);
00373                *(dp++) = *(sp++);
00374                *(dp++) = *(sp++);
00375                *(dp++) = *(sp++);
00376                *(dp++) = *(sp++);
00377                *(dp++) = *(sp++);
00378                *(dp++) = *(sp++);
00379                *(dp++) = save[0];
00380                *(dp++) = save[1];
00381             }
00382          }
00383       }
00384       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00385       {
00386          /* This converts from AG to GA */
00387          if (row_info->bit_depth == 8)
00388          {
00389             png_bytep sp, dp;
00390             png_uint_32 i;
00391             png_uint_32 row_width = row_info->width;
00392 
00393             for (i = 0, sp = dp = row; i < row_width; i++)
00394             {
00395                png_byte save = *(sp++);
00396                *(dp++) = *(sp++);
00397                *(dp++) = save;
00398             }
00399          }
00400          /* This converts from AAGG to GGAA */
00401          else
00402          {
00403             png_bytep sp, dp;
00404             png_uint_32 i;
00405             png_uint_32 row_width = row_info->width;
00406 
00407             for (i = 0, sp = dp = row; i < row_width; i++)
00408             {
00409                png_byte save[2];
00410                save[0] = *(sp++);
00411                save[1] = *(sp++);
00412                *(dp++) = *(sp++);
00413                *(dp++) = *(sp++);
00414                *(dp++) = save[0];
00415                *(dp++) = save[1];
00416             }
00417          }
00418       }
00419    }
00420 }
00421 #endif
00422 
00423 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
00424 void /* PRIVATE */
00425 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
00426 {
00427    png_debug(1, "in png_do_write_invert_alpha\n");
00428 #if defined(PNG_USELESS_TESTS_SUPPORTED)
00429    if (row != NULL && row_info != NULL)
00430 #endif
00431    {
00432       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
00433       {
00434          /* This inverts the alpha channel in RGBA */
00435          if (row_info->bit_depth == 8)
00436          {
00437             png_bytep sp, dp;
00438             png_uint_32 i;
00439             png_uint_32 row_width = row_info->width;
00440             for (i = 0, sp = dp = row; i < row_width; i++)
00441             {
00442                /* does nothing
00443                *(dp++) = *(sp++);
00444                *(dp++) = *(sp++);
00445                *(dp++) = *(sp++);
00446                */
00447                sp+=3; dp = sp;
00448                *(dp++) = (png_byte)(255 - *(sp++));
00449             }
00450          }
00451          /* This inverts the alpha channel in RRGGBBAA */
00452          else
00453          {
00454             png_bytep sp, dp;
00455             png_uint_32 i;
00456             png_uint_32 row_width = row_info->width;
00457 
00458             for (i = 0, sp = dp = row; i < row_width; i++)
00459             {
00460                /* does nothing
00461                *(dp++) = *(sp++);
00462                *(dp++) = *(sp++);
00463                *(dp++) = *(sp++);
00464                *(dp++) = *(sp++);
00465                *(dp++) = *(sp++);
00466                *(dp++) = *(sp++);
00467                */
00468                sp+=6; dp = sp;
00469                *(dp++) = (png_byte)(255 - *(sp++));
00470                *(dp++) = (png_byte)(255 - *(sp++));
00471             }
00472          }
00473       }
00474       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00475       {
00476          /* This inverts the alpha channel in GA */
00477          if (row_info->bit_depth == 8)
00478          {
00479             png_bytep sp, dp;
00480             png_uint_32 i;
00481             png_uint_32 row_width = row_info->width;
00482 
00483             for (i = 0, sp = dp = row; i < row_width; i++)
00484             {
00485                *(dp++) = *(sp++);
00486                *(dp++) = (png_byte)(255 - *(sp++));
00487             }
00488          }
00489          /* This inverts the alpha channel in GGAA */
00490          else
00491          {
00492             png_bytep sp, dp;
00493             png_uint_32 i;
00494             png_uint_32 row_width = row_info->width;
00495 
00496             for (i = 0, sp = dp = row; i < row_width; i++)
00497             {
00498                /* does nothing
00499                *(dp++) = *(sp++);
00500                *(dp++) = *(sp++);
00501                */
00502                sp+=2; dp = sp;
00503                *(dp++) = (png_byte)(255 - *(sp++));
00504                *(dp++) = (png_byte)(255 - *(sp++));
00505             }
00506          }
00507       }
00508    }
00509 }
00510 #endif
00511 
00512 #if defined(PNG_MNG_FEATURES_SUPPORTED)
00513 /* undoes intrapixel differencing  */
00514 void /* PRIVATE */
00515 png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
00516 {
00517    png_debug(1, "in png_do_write_intrapixel\n");
00518    if (
00519 #if defined(PNG_USELESS_TESTS_SUPPORTED)
00520        row != NULL && row_info != NULL &&
00521 #endif
00522        (row_info->color_type & PNG_COLOR_MASK_COLOR))
00523    {
00524       int bytes_per_pixel;
00525       png_uint_32 row_width = row_info->width;
00526       if (row_info->bit_depth == 8)
00527       {
00528          png_bytep rp;
00529          png_uint_32 i;
00530 
00531          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
00532             bytes_per_pixel = 3;
00533          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
00534             bytes_per_pixel = 4;
00535          else
00536             return;
00537 
00538          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
00539          {
00540             *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
00541             *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
00542          }
00543       }
00544       else if (row_info->bit_depth == 16)
00545       {
00546          png_bytep rp;
00547          png_uint_32 i;
00548 
00549          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
00550             bytes_per_pixel = 6;
00551          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
00552             bytes_per_pixel = 8;
00553          else
00554             return;
00555 
00556          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
00557          {
00558             png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
00559             png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
00560             png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
00561             png_uint_32 red  = (png_uint_32)((s0 - s1) & 0xffffL);
00562             png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
00563             *(rp  ) = (png_byte)((red >> 8) & 0xff);
00564             *(rp+1) = (png_byte)(red & 0xff);
00565             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
00566             *(rp+5) = (png_byte)(blue & 0xff);
00567          }
00568       }
00569    }
00570 }
00571 #endif /* PNG_MNG_FEATURES_SUPPORTED */
00572 #endif /* PNG_WRITE_SUPPORTED */


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Apr 11 2019 03:30:18