public PNG_INFO png_get_sBIT(ref png_color_8 sig_bit) { if ((info_ptr_valid & PNG_INFO.sBIT) != PNG_INFO.sBIT) { return(PNG_INFO.None); } sig_bit = info_ptr_sig_bit; return(PNG_INFO.sBIT); }
public PNG_INFO png_get_sBIT(ref png_color_8 sig_bit) { if((info_ptr_valid&PNG_INFO.sBIT)!=PNG_INFO.sBIT) return PNG_INFO.None; sig_bit=info_ptr_sig_bit; return PNG_INFO.sBIT; }
public void png_set_sBIT(png_color_8 sig_bit) { info_ptr_sig_bit = sig_bit; info_ptr_valid |= PNG_INFO.sBIT; }
public void png_set_sBIT(png_color_8 sig_bit) { info_ptr_sig_bit=sig_bit; info_ptr_valid|=PNG_INFO.sBIT; }
// Shift pixel values to take advantage of whole range. Pass the // true number of bits in bit_depth. The row should be packed // according to row_info->bit_depth. Thus, if you had a row of // bit depth 4, but the pixels only had values from 0 to 7, you // would pass 3 as bit_depth, and this routine would translate the // data to 0 to 15. unsafe void png_do_shift(png_row_info row_info, byte[] row, png_color_8 bit_depth) { if(row_info.color_type==PNG_COLOR_TYPE.PALETTE) return; int[] shift_start=new int[4], shift_dec=new int[4]; uint channels=0; if((row_info.color_type&PNG_COLOR_TYPE.COLOR_MASK)==PNG_COLOR_TYPE.COLOR_MASK) { shift_start[channels]=row_info.bit_depth-bit_depth.red; shift_dec[channels]=bit_depth.red; channels++; shift_start[channels]=row_info.bit_depth-bit_depth.green; shift_dec[channels]=bit_depth.green; channels++; shift_start[channels]=row_info.bit_depth-bit_depth.blue; shift_dec[channels]=bit_depth.blue; channels++; } else { shift_start[channels]=row_info.bit_depth-bit_depth.gray; shift_dec[channels]=bit_depth.gray; channels++; } if((row_info.color_type&PNG_COLOR_TYPE.ALPHA_MASK)==PNG_COLOR_TYPE.ALPHA_MASK) { shift_start[channels]=row_info.bit_depth-bit_depth.alpha; shift_dec[channels]=bit_depth.alpha; channels++; } fixed(byte* row_=row) { // with low row depths, could only be grayscale, so one channel byte* bp=row_+1; // skip filter value if(row_info.bit_depth<8) { byte mask; uint row_bytes=row_info.rowbytes; if(bit_depth.gray==1&&row_info.bit_depth==2) mask=0x55; else if(row_info.bit_depth==4&&bit_depth.gray==3) mask=0x11; else mask=0xff; for(uint i=0; i<row_bytes; i++, bp++) { ushort v=*bp; *bp=0; for(int j=shift_start[0]; j>-shift_dec[0]; j-=shift_dec[0]) { if(j>0) *bp|=(byte)((v<<j)&0xff); else *bp|=(byte)((v>>(-j))&mask); } } } else if(row_info.bit_depth==8) { uint istop=channels*row_info.width; for(uint i=0; i<istop; i++, bp++) { int c=(int)(i%channels); ushort v=*bp; *bp=0; for(int j=shift_start[c]; j>-shift_dec[c]; j-=shift_dec[c]) { if(j>0) *bp|=(byte)((v<<j)&0xff); else *bp|=(byte)((v>>(-j))&0xff); } } } else { uint istop=channels*row_info.width; for(uint i=0; i<istop; i++) { int c=(int)(i%channels); ushort v=(ushort)(((ushort)(*bp)<<8)+*(bp+1)); ushort value=0; for(int j=shift_start[c]; j>-shift_dec[c]; j-=shift_dec[c]) { if(j>0) value|=(ushort)((v<<j)&(ushort)0xffff); else value|=(ushort)((v>>(-j))&(ushort)0xffff); } *bp++=(byte)(value>>8); *bp++=(byte)(value&0xff); } } } }
// write the sBIT chunk void png_write_sBIT(png_color_8 sbit, PNG_COLOR_TYPE color_type) { uint size; // make sure we don't depend upon the order of PNG_COLOR_8 if((color_type&PNG_COLOR_TYPE.COLOR_MASK)==PNG_COLOR_TYPE.COLOR_MASK) { byte maxbits=color_type==PNG_COLOR_TYPE.PALETTE?(byte)8:usr_bit_depth; if(sbit.red==0||sbit.red>maxbits||sbit.green==0||sbit.green>maxbits||sbit.blue==0||sbit.blue>maxbits) { Debug.WriteLine("Invalid sBIT depth specified"); return; } buf4[0]=sbit.red; buf4[1]=sbit.green; buf4[2]=sbit.blue; size=3; } else { if(sbit.gray==0||sbit.gray>usr_bit_depth) { Debug.WriteLine("Invalid sBIT depth specified"); return; } buf4[0]=sbit.gray; size=1; } if((color_type&PNG_COLOR_TYPE.ALPHA_MASK)==PNG_COLOR_TYPE.ALPHA_MASK) { if(sbit.alpha==0||sbit.alpha>usr_bit_depth) { Debug.WriteLine("Invalid sBIT depth specified"); return; } buf4[size++]=sbit.alpha; } png_write_chunk(PNG.sBIT, buf4, size); }
public void png_set_shift(png_color_8 true_bits) { transformations |= PNG_TRANSFORMATION.SHIFT; shift = true_bits; }
// Reverse the effects of png_do_shift. This routine merely shifts the // pixels back to their significant bits values. Thus, if you have // a row of bit depth 8, but only 5 are significant, this will shift // the values back to 0 through 31. static unsafe void png_do_unshift(ref png_row_info row_info, byte[] row, ref png_color_8 sig_bits) { if(row_info.color_type==PNG_COLOR_TYPE.PALETTE) return; int[] shift=new int[4]; uint channels=0; ushort value=0; uint row_width=row_info.width; if((row_info.color_type&PNG_COLOR_TYPE.COLOR_MASK)==PNG_COLOR_TYPE.COLOR_MASK) { shift[channels++]=row_info.bit_depth-sig_bits.red; shift[channels++]=row_info.bit_depth-sig_bits.green; shift[channels++]=row_info.bit_depth-sig_bits.blue; } else shift[channels++]=row_info.bit_depth-sig_bits.gray; if((row_info.color_type&PNG_COLOR_TYPE.ALPHA_MASK)==PNG_COLOR_TYPE.ALPHA_MASK) shift[channels++]=row_info.bit_depth-sig_bits.alpha; for(uint c=0; c<channels; c++) { if(shift[c]<=0) shift[c]=0; else value=1; } if(value==0) return; fixed(byte* row_=row) { byte* bp=row_+1; // skip filter value switch(row_info.bit_depth) { case 2: { uint istop=row_info.rowbytes; for(uint i=0; i<istop; i++) { *bp>>=1; *bp++&=0x55; } } break; case 4: { uint istop=row_info.rowbytes; byte mask=(byte)((((int)0xf0>>shift[0])&(int)0xf0)|(byte)((int)0xf>>shift[0])); for(uint i=0; i<istop; i++) { *bp>>=shift[0]; *bp++&=mask; } } break; case 8: { uint istop=row_width*channels; for(uint i=0; i<istop; i++) *bp++>>=shift[i%channels]; } break; case 16: { uint istop=row_width*channels; for(uint i=0; i<istop; i++) { value=(ushort)((*bp<<8)+*(bp+1)); value>>=shift[i%channels]; *bp++=(byte)(value>>8); *bp++=(byte)(value&0xff); } } break; } } }
public void png_set_shift(png_color_8 true_bits) { transformations|=PNG_TRANSFORMATION.SHIFT; shift=true_bits; }