// Add filler channel if we have RGB color static unsafe void png_do_read_filler(ref png_row_info row_info, byte[] row, uint filler, PNG_FLAG flags) { uint i; uint row_width=row_info.width; byte hi_filler=(byte)((filler>>8)&0xff); byte lo_filler=(byte)(filler&0xff); fixed(byte* row_=row) { byte* sp=row_+1; // skip filter value if(row_info.color_type==PNG_COLOR_TYPE.GRAY) { if(row_info.bit_depth==8) { // This changes the data from G to GX if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { sp+=row_width; byte* dp=sp+row_width; for(i=1; i<row_width; i++) { *(--dp)=lo_filler; *(--dp)=*(--sp); } *(--dp)=lo_filler; row_info.channels=2; row_info.pixel_depth=16; row_info.rowbytes=row_width*2; } else // This changes the data from G to XG { sp+=row_width; byte* dp=sp+row_width; for(i=0; i<row_width; i++) { *(--dp)=*(--sp); *(--dp)=lo_filler; } row_info.channels=2; row_info.pixel_depth=16; row_info.rowbytes=row_width*2; } } else if(row_info.bit_depth==16) { // This changes the data from GG to GGXX if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { sp+=row_width*2; byte* dp=sp+row_width*2; for(i=1; i<row_width; i++) { *(--dp)=hi_filler; *(--dp)=lo_filler; *(--dp)=*(--sp); *(--dp)=*(--sp); } *(--dp)=hi_filler; *(--dp)=lo_filler; row_info.channels=2; row_info.pixel_depth=32; row_info.rowbytes=row_width*4; } else // This changes the data from GG to XXGG { sp+=row_width*2; byte* dp=sp+row_width*2; for(i=0; i<row_width; i++) { *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=hi_filler; *(--dp)=lo_filler; } row_info.channels=2; row_info.pixel_depth=32; row_info.rowbytes=row_width*4; } } } // COLOR_TYPE==GRAY else if(row_info.color_type==PNG_COLOR_TYPE.RGB) { if(row_info.bit_depth==8) { // This changes the data from RGB to RGBX if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { sp+=row_width*3; byte* dp=sp+row_width; for(i=1; i<row_width; i++) { *(--dp)=lo_filler; *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); } *(--dp)=lo_filler; row_info.channels=4; row_info.pixel_depth=32; row_info.rowbytes=row_width*4; } else // This changes the data from RGB to XRGB { sp+=row_width*3; byte* dp=sp+row_width; for(i=0; i<row_width; i++) { *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=lo_filler; } row_info.channels=4; row_info.pixel_depth=32; row_info.rowbytes=row_width*4; } } else if(row_info.bit_depth==16) { // This changes the data from RRGGBB to RRGGBBXX if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { sp+=row_width*6; byte* dp=sp+row_width*2; for(i=1; i<row_width; i++) { *(--dp)=hi_filler; *(--dp)=lo_filler; *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); } *(--dp)=hi_filler; *(--dp)=lo_filler; row_info.channels=4; row_info.pixel_depth=64; row_info.rowbytes=row_width*8; } else // This changes the data from RRGGBB to XXRRGGBB { sp+=row_width*6; byte* dp=sp+row_width*2; for(i=0; i<row_width; i++) { *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=*(--sp); *(--dp)=hi_filler; *(--dp)=lo_filler; } row_info.channels=4; row_info.pixel_depth=64; row_info.rowbytes=row_width*8; } } } // COLOR_TYPE==RGB } }
// remove filler or alpha byte(s) static unsafe void png_do_strip_filler(ref png_row_info row_info, byte[] row, PNG_FLAG flags) { fixed(byte *row_ = row) { byte *sp = row_ + 1; // skip filter value byte *dp = row_ + 1; // skip filter value uint row_width = row_info.width; uint i; if (row_info.channels == 4 && (row_info.color_type == PNG_COLOR_TYPE.RGB || (row_info.color_type == PNG_COLOR_TYPE.RGB_ALPHA && (flags & PNG_FLAG.STRIP_ALPHA) == PNG_FLAG.STRIP_ALPHA))) { if (row_info.bit_depth == 8) { // This converts from RGBX or RGBA to RGB if ((flags & PNG_FLAG.FILLER_AFTER) == PNG_FLAG.FILLER_AFTER) { dp += 3; sp += 4; for (i = 1; i < row_width; i++) { *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; sp++; } } // This converts from XRGB or ARGB to RGB else { for (i = 0; i < row_width; i++) { sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; } } row_info.pixel_depth = 24; row_info.rowbytes = row_width * 3; } else // if(row_info->bit_depth==16) { if ((flags & PNG_FLAG.FILLER_AFTER) == PNG_FLAG.FILLER_AFTER) { // This converts from RRGGBBXX or RRGGBBAA to RRGGBB sp += 8; dp += 6; for (i = 1; i < row_width; i++) { *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; sp += 2; } } else { // This converts from XXRRGGBB or AARRGGBB to RRGGBB for (i = 0; i < row_width; i++) { sp += 2; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++; } } row_info.pixel_depth = 48; row_info.rowbytes = row_width * 6; } row_info.channels = 3; } else if (row_info.channels == 2 && (row_info.color_type == PNG_COLOR_TYPE.GRAY || (row_info.color_type == PNG_COLOR_TYPE.GRAY_ALPHA && (flags & PNG_FLAG.STRIP_ALPHA) == PNG_FLAG.STRIP_ALPHA))) { if (row_info.bit_depth == 8) { // This converts from GX or GA to G if ((flags & PNG_FLAG.FILLER_AFTER) == PNG_FLAG.FILLER_AFTER) { for (i = 0; i < row_width; i++) { *dp++ = *sp++; sp++; } } // This converts from XG or AG to G else { for (i = 0; i < row_width; i++) { sp++; *dp++ = *sp++; } } row_info.pixel_depth = 8; row_info.rowbytes = row_width; } else // if(row_info->bit_depth==16) { if ((flags & PNG_FLAG.FILLER_AFTER) == PNG_FLAG.FILLER_AFTER) { // This converts from GGXX or GGAA to GG sp += 4; dp += 2; for (i = 1; i < row_width; i++) { *dp++ = *sp++; *dp++ = *sp++; sp += 2; } } else { // This converts from XXGG or AAGG to GG for (i = 0; i < row_width; i++) { sp += 2; *dp++ = *sp++; *dp++ = *sp++; } } row_info.pixel_depth = 16; row_info.rowbytes = row_width * 2; } row_info.channels = 1; } } if ((flags & PNG_FLAG.STRIP_ALPHA) == PNG_FLAG.STRIP_ALPHA) { row_info.color_type &= ~PNG_COLOR_TYPE.ALPHA_MASK; } }
// remove filler or alpha byte(s) static unsafe void png_do_strip_filler(ref png_row_info row_info, byte[] row, PNG_FLAG flags) { fixed(byte* row_=row) { byte* sp=row_+1;// skip filter value byte* dp=row_+1;// skip filter value uint row_width=row_info.width; uint i; if(row_info.channels==4&&(row_info.color_type==PNG_COLOR_TYPE.RGB|| (row_info.color_type==PNG_COLOR_TYPE.RGB_ALPHA&&(flags&PNG_FLAG.STRIP_ALPHA)==PNG_FLAG.STRIP_ALPHA))) { if(row_info.bit_depth==8) { // This converts from RGBX or RGBA to RGB if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { dp+=3; sp+=4; for(i=1; i<row_width; i++) { *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; sp++; } } // This converts from XRGB or ARGB to RGB else { for(i=0; i<row_width; i++) { sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; } } row_info.pixel_depth=24; row_info.rowbytes=row_width*3; } else // if(row_info->bit_depth==16) { if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { // This converts from RRGGBBXX or RRGGBBAA to RRGGBB sp+=8; dp+=6; for(i=1; i<row_width; i++) { *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; sp+=2; } } else { // This converts from XXRRGGBB or AARRGGBB to RRGGBB for(i=0; i<row_width; i++) { sp+=2; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; *dp++=*sp++; } } row_info.pixel_depth=48; row_info.rowbytes=row_width*6; } row_info.channels=3; } else if(row_info.channels==2&&(row_info.color_type==PNG_COLOR_TYPE.GRAY|| (row_info.color_type==PNG_COLOR_TYPE.GRAY_ALPHA&&(flags&PNG_FLAG.STRIP_ALPHA)==PNG_FLAG.STRIP_ALPHA))) { if(row_info.bit_depth==8) { // This converts from GX or GA to G if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { for(i=0; i<row_width; i++) { *dp++=*sp++; sp++; } } // This converts from XG or AG to G else { for(i=0; i<row_width; i++) { sp++; *dp++=*sp++; } } row_info.pixel_depth=8; row_info.rowbytes=row_width; } else // if(row_info->bit_depth==16) { if((flags&PNG_FLAG.FILLER_AFTER)==PNG_FLAG.FILLER_AFTER) { // This converts from GGXX or GGAA to GG sp+=4; dp+=2; for(i=1; i<row_width; i++) { *dp++=*sp++; *dp++=*sp++; sp+=2; } } else { // This converts from XXGG or AAGG to GG for(i=0; i<row_width; i++) { sp+=2; *dp++=*sp++; *dp++=*sp++; } } row_info.pixel_depth=16; row_info.rowbytes=row_width*2; } row_info.channels=1; } } if((flags&PNG_FLAG.STRIP_ALPHA)==PNG_FLAG.STRIP_ALPHA) row_info.color_type&=~PNG_COLOR_TYPE.ALPHA_MASK; }