예제 #1
0
 public PNG_INFO png_get_bKGD(ref png_color_16 background)
 {
     if ((info_ptr_valid & PNG_INFO.bKGD) != PNG_INFO.bKGD)
     {
         return(PNG_INFO.None);
     }
     background = info_ptr_background;
     return(PNG_INFO.bKGD);
 }
예제 #2
0
 public PNG_INFO png_get_tRNS(ref byte[] trans_alpha, ref ushort num_trans, ref png_color_16 trans_color)
 {
     if ((info_ptr_valid & PNG_INFO.tRNS) != PNG_INFO.tRNS)
     {
         return(PNG_INFO.None);
     }
     trans_color = info_ptr_trans_color;
     trans_alpha = (info_ptr_color_type == PNG_COLOR_TYPE.PALETTE)?info_ptr_trans_alpha:null;
     num_trans   = info_ptr_num_trans;
     return(PNG_INFO.tRNS);
 }
예제 #3
0
        public void png_set_tRNS(png_color_16 trans_color)
        {
            int sample_max = (1 << info_ptr_bit_depth);

            if ((info_ptr_color_type == PNG_COLOR_TYPE.GRAY &&
                 (int)trans_color.gray > sample_max) ||
                (info_ptr_color_type == PNG_COLOR_TYPE.RGB &&
                 ((int)trans_color.red > sample_max ||
                  (int)trans_color.green > sample_max ||
                  (int)trans_color.blue > sample_max)))
            {
                Debug.WriteLine("tRNS chunk has out-of-range samples for bit_depth");
            }

            this.trans_color = info_ptr_trans_color = trans_color;
            num_trans        = info_ptr_num_trans = 1;
            info_ptr_valid  |= PNG_INFO.tRNS;
        }
예제 #4
0
		public PNG_INFO png_get_tRNS(ref byte[] trans_alpha, ref ushort num_trans, ref png_color_16 trans_color)
		{
			if((info_ptr_valid&PNG_INFO.tRNS)!=PNG_INFO.tRNS) return PNG_INFO.None;
			trans_color=info_ptr_trans_color;
			trans_alpha=(info_ptr_color_type==PNG_COLOR_TYPE.PALETTE)?info_ptr_trans_alpha:null;
			num_trans=info_ptr_num_trans;
			return PNG_INFO.tRNS;
		}
예제 #5
0
		public PNG_INFO png_get_bKGD(ref png_color_16 background)
		{
			if((info_ptr_valid&PNG_INFO.bKGD)!=PNG_INFO.bKGD) return PNG_INFO.None;
			background=info_ptr_background;
			return PNG_INFO.bKGD;
		}
예제 #6
0
		void png_handle_bKGD(uint length)
		{
			if((mode&PNG_MODE.HAVE_IHDR)!=PNG_MODE.HAVE_IHDR) throw new PNG_Exception("Missing IHDR before bKGD");
			else if((mode&PNG_MODE.HAVE_IDAT)==PNG_MODE.HAVE_IDAT)
			{
				Debug.WriteLine("Invalid bKGD after IDAT");
				png_crc_finish(length);
				return;
			}
			else if(color_type==PNG_COLOR_TYPE.PALETTE&&!((mode&PNG_MODE.HAVE_PLTE)==PNG_MODE.HAVE_PLTE))
			{
				Debug.WriteLine("Missing PLTE before bKGD");
				png_crc_finish(length);
				return;
			}
			else if((info_ptr_valid&PNG_INFO.bKGD)==PNG_INFO.bKGD)
			{
				Debug.WriteLine("Duplicate bKGD chunk");
				png_crc_finish(length);
				return;
			}

			uint truelen=2;
			if(color_type==PNG_COLOR_TYPE.PALETTE) truelen=1;
			else if((color_type&PNG_COLOR_TYPE.COLOR_MASK)==PNG_COLOR_TYPE.COLOR_MASK) truelen=6;

			if(length!=truelen)
			{
				Debug.WriteLine("Incorrect bKGD chunk length");
				png_crc_finish(length);
				return;
			}

			byte[] buf=new byte[truelen];
			png_crc_read(buf, truelen);
			if(png_crc_finish(0)) return;

			png_color_16 background=new png_color_16();

			// We convert the index value into RGB components so that we can allow
			// arbitrary RGB values for background when we have transparency, and
			// so it is easy to determine the RGB values of the background color
			// from the info_ptr struct.
			if(color_type==PNG_COLOR_TYPE.PALETTE)
			{
				background.index=buf[0];
				if(info_ptr_palette.Length!=0)
				{
					if(buf[0]>info_ptr_palette.Length)
					{
						Debug.WriteLine("Incorrect bKGD chunk index value");
						return;
					}
					background.red=(ushort)palette[buf[0]].red;
					background.green=(ushort)palette[buf[0]].green;
					background.blue=(ushort)palette[buf[0]].blue;
				}
			}
			else if((color_type&PNG_COLOR_TYPE.COLOR_MASK)!=PNG_COLOR_TYPE.COLOR_MASK)
			{
				background.red=background.green=background.blue=background.gray=png_get_uint_16(buf);
			}
			else
			{
				background.red=png_get_uint_16(buf);
				background.green=png_get_uint_16(buf, 2);
				background.blue=png_get_uint_16(buf, 4);
			}

			png_set_bKGD(background);
		}
예제 #7
0
		void png_handle_tRNS(uint length)
		{
			if((mode&PNG_MODE.HAVE_IHDR)!=PNG_MODE.HAVE_IHDR) throw new PNG_Exception("Missing IHDR before tRNS");
			else if((mode&PNG_MODE.HAVE_IDAT)==PNG_MODE.HAVE_IDAT)
			{
				Debug.WriteLine("Invalid tRNS after IDAT");
				png_crc_finish(length);
				return;
			}
			else if((info_ptr_valid&PNG_INFO.tRNS)==PNG_INFO.tRNS)
			{
				Debug.WriteLine("Duplicate tRNS chunk");
				png_crc_finish(length);
				return;
			}

			trans_color=new png_color_16();

			if(color_type==PNG_COLOR_TYPE.GRAY)
			{
				if(length!=2)
				{
					Debug.WriteLine("Incorrect tRNS chunk length");
					png_crc_finish(length);
					return;
				}

				png_crc_read(buf4, 2);
				if(png_crc_finish(0)) return;

				num_trans=1;
				trans_color.gray=png_get_uint_16(buf4);
				png_set_tRNS(trans_color);
			}
			else if(color_type==PNG_COLOR_TYPE.RGB)
			{
				if(length!=6)
				{
					Debug.WriteLine("Incorrect tRNS chunk length");
					png_crc_finish(length);
					return;
				}

				byte[] buf=new byte[6];
				png_crc_read(buf, 6);
				if(png_crc_finish(0)) return;

				num_trans=1;
				trans_color.red=png_get_uint_16(buf);
				trans_color.green=png_get_uint_16(buf, 2);
				trans_color.blue=png_get_uint_16(buf, 4);
				png_set_tRNS(trans_color);
			}
			else if(color_type==PNG_COLOR_TYPE.PALETTE)
			{
				if(!((mode&PNG_MODE.HAVE_PLTE)==PNG_MODE.HAVE_PLTE)) Debug.WriteLine("Missing PLTE before tRNS"); // Should be an error, but we can cope with it.

				if(length>palette.Length||length>PNG.MAX_PALETTE_LENGTH)
				{
					Debug.WriteLine("Incorrect tRNS chunk length");
					png_crc_finish(length);
					return;
				}
				if(length==0)
				{
					Debug.WriteLine("Zero length tRNS chunk");
					png_crc_finish(length);
					return;
				}

				byte[] readbuf=new byte[length];
				png_crc_read(readbuf, length);
				if(png_crc_finish(0)) return;

				num_trans=(ushort)length;
				png_set_tRNS(readbuf);
			}
			else
			{
				Debug.WriteLine("tRNS chunk not allowed with alpha channel");
				png_crc_finish(length);
				num_trans=0;
			}
		}
예제 #8
0
 public void png_set_bKGD(png_color_16 background)
 {
     info_ptr_background = background;
     info_ptr_valid     |= PNG_INFO.bKGD;
 }
예제 #9
0
		public void png_set_tRNS(png_color_16 trans_color)
		{
			int sample_max=(1<<info_ptr_bit_depth);
			if((info_ptr_color_type==PNG_COLOR_TYPE.GRAY&&
				(int)trans_color.gray>sample_max)||
				(info_ptr_color_type==PNG_COLOR_TYPE.RGB&&
				((int)trans_color.red>sample_max||
				(int)trans_color.green>sample_max||
				(int)trans_color.blue>sample_max)))
				Debug.WriteLine("tRNS chunk has out-of-range samples for bit_depth");

			this.trans_color=info_ptr_trans_color=trans_color;
			num_trans=info_ptr_num_trans=1;
			info_ptr_valid|=PNG_INFO.tRNS;
		}
예제 #10
0
		public void png_set_bKGD(png_color_16 background)
		{
			info_ptr_background=background;
			info_ptr_valid|=PNG_INFO.bKGD;
		}
예제 #11
0
		// write the background chunk
		void png_write_bKGD(png_color_16 back, PNG_COLOR_TYPE color_type)
		{
			byte[] buf=new byte[6];

			if(color_type==PNG_COLOR_TYPE.PALETTE)
			{
				uint num_palette=0;
				if(palette!=null) num_palette=(uint)palette.Length;
				if((num_palette!=0||(mng_features_permitted&PNG_FLAG_MNG.EMPTY_PLTE)!=PNG_FLAG_MNG.EMPTY_PLTE)&&back.index>=num_palette)
				{
					Debug.WriteLine("Invalid background palette index");
					return;
				}
				buf[0]=back.index;
				png_write_chunk(PNG.bKGD, buf, 1);
			}
			else if((color_type&PNG_COLOR_TYPE.COLOR_MASK)==PNG_COLOR_TYPE.COLOR_MASK)
			{
				png_save_uint_16(buf, back.red);
				png_save_uint_16(buf, 2, back.green);
				png_save_uint_16(buf, 4, back.blue);
				if(bit_depth==8&&(buf[0]|buf[2]|buf[4])!=0)
				{
					Debug.WriteLine("Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
					return;
				}
				png_write_chunk(PNG.bKGD, buf, 6);
			}
			else
			{
				if(back.gray>=(1<<bit_depth))
				{
					Debug.WriteLine("Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
					return;
				}
				png_save_uint_16(buf, back.gray);
				png_write_chunk(PNG.bKGD, buf, 2);
			}
		}
예제 #12
0
		// write the tRNS chunk
		void png_write_tRNS(byte[] trans_alpha, png_color_16 tran, int num_trans, PNG_COLOR_TYPE color_type)
		{
			byte[] buf=new byte[6];

			if(color_type==PNG_COLOR_TYPE.PALETTE)
			{
				if(num_trans<=0||num_trans>palette.Length)
				{
					Debug.WriteLine("Invalid number of transparent colors specified");
					return;
				}
				// write the chunk out as it is
				png_write_chunk(PNG.tRNS, trans_alpha, (uint)num_trans);
			}
			else if(color_type==PNG_COLOR_TYPE.GRAY)
			{
				// one 16 bit value
				if(tran.gray>=(1<<bit_depth))
				{
					Debug.WriteLine("Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
					return;
				}
				png_save_uint_16(buf, tran.gray);
				png_write_chunk(PNG.tRNS, buf, 2);
			}
			else if(color_type==PNG_COLOR_TYPE.RGB)
			{
				// three 16 bit values
				png_save_uint_16(buf, tran.red);
				png_save_uint_16(buf, 2, tran.green);
				png_save_uint_16(buf, 4, tran.blue);
				if(bit_depth==8&&(buf[0]|buf[2]|buf[4])!=0)
				{
					Debug.WriteLine("Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
					return;
				}
				png_write_chunk(PNG.tRNS, buf, 6);
			}
			else Debug.WriteLine("Can't write tRNS with an alpha channel");
		}
예제 #13
0
		// If the bit depth < 8, it is expanded to 8. Also, if the already
		// expanded transparency value is supplied, an alpha channel is built.
		static unsafe void png_do_expand_with_trans_values(ref png_row_info row_info, byte[] row, ref png_color_16 trans_value)
		{
			int shift, value;
			uint row_width=row_info.width;

			fixed(byte* row_=row)
			{
				byte* sp=row_+1; // skip filter value
				byte* dp=row_+1; // skip filter value

				if(row_info.color_type==PNG_COLOR_TYPE.GRAY)
				{
					ushort gray=trans_value.gray;

					if(row_info.bit_depth<8)
					{
						switch(row_info.bit_depth)
						{
							case 1:
								{
									gray=(ushort)((gray&0x01)*0xff);
									sp+=(row_width-1)>>3;
									dp+=row_width-1;
									shift=7-(int)((row_width+7)&0x07);
									for(uint i=0; i<row_width; i++)
									{
										if(((*sp>>shift)&0x01)==0x01) *dp=0xff;
										else *dp=0;
										if(shift==7)
										{
											shift=0;
											sp--;
										}
										else shift++;

										dp--;
									}
								}
								break;
							case 2:
								{
									gray=(ushort)((gray&0x03)*0x55);
									sp+=(row_width-1)>>2;
									dp+=row_width-1;
									shift=(int)((3-((row_width+3)&0x03))<<1);
									for(uint i=0; i<row_width; i++)
									{
										value=(*sp>>shift)&0x03;
										*dp=(byte)(value|(value<<2)|(value<<4)|(value<<6));
										if(shift==6)
										{
											shift=0;
											sp--;
										}
										else shift+=2;

										dp--;
									}
								}
								break;
							case 4:
								{
									gray=(ushort)((gray&0x0f)*0x11);
									sp+=(row_width-1)>>1;
									dp+=row_width-1;
									shift=(int)((1-((row_width+1)&0x01))<<2);
									for(uint i=0; i<row_width; i++)
									{
										value=(*sp>>shift)&0x0f;
										*dp=(byte)(value|(value<<4));
										if(shift==4)
										{
											shift=0;
											sp--;
										}
										else shift=4;

										dp--;
									}
								}
								break;
						}
						row_info.bit_depth=8;
						row_info.pixel_depth=8;
						row_info.rowbytes=row_width;

						// reset to start values
						sp=row_+1; // skip filter value
						dp=row_+1; // skip filter value
					} // if(row_info.bit_depth<8)

					if(row_info.bit_depth==8)
					{
						gray=(byte)(gray&0xff);
						sp+=row_width-1;
						dp+=(row_width<<1)-1;
						for(uint i=0; i<row_width; i++)
						{
							if(*sp==gray) *dp--=0;
							else *dp--=0xff;
							*dp--=*sp--;
						}
					}
					else if(row_info.bit_depth==16)
					{
						byte gray_high=(byte)((gray>>8)&0xff);
						byte gray_low=(byte)(gray&0xff);
						sp+=row_info.rowbytes-1;
						dp+=(row_info.rowbytes<<1)-1;
						for(uint i=0; i<row_width; i++)
						{
							if(*(sp-1)==gray_high&&*(sp)==gray_low)
							{
								*dp--=0;
								*dp--=0;
							}
							else
							{
								*dp--=0xff;
								*dp--=0xff;
							}
							*dp--=*sp--;
							*dp--=*sp--;
						}
					}
					row_info.color_type=PNG_COLOR_TYPE.GRAY_ALPHA;
					row_info.channels=2;
					row_info.pixel_depth=(byte)(row_info.bit_depth<<1);
					row_info.rowbytes=PNG_ROWBYTES(row_info.pixel_depth, row_width);
				}
				else if(row_info.color_type==PNG_COLOR_TYPE.RGB)
				{
					if(row_info.bit_depth==8)
					{
						byte red=(byte)(trans_value.red&0xff);
						byte green=(byte)(trans_value.green&0xff);
						byte blue=(byte)(trans_value.blue&0xff);
						sp+=row_info.rowbytes-1;
						dp+=(row_width<<2)-1;
						for(uint i=0; i<row_width; i++)
						{
							if(*(sp-2)==red&&*(sp-1)==green&&*(sp)==blue) *dp--=0;
							else *dp--=0xff;
							*dp--=*sp--;
							*dp--=*sp--;
							*dp--=*sp--;
						}
					}
					else if(row_info.bit_depth==16)
					{
						byte red_high=(byte)((trans_value.red>>8)&0xff);
						byte green_high=(byte)((trans_value.green>>8)&0xff);
						byte blue_high=(byte)((trans_value.blue>>8)&0xff);
						byte red_low=(byte)(trans_value.red&0xff);
						byte green_low=(byte)(trans_value.green&0xff);
						byte blue_low=(byte)(trans_value.blue&0xff);
						sp+=row_info.rowbytes-1;
						dp+=(row_width<<3)-1;
						for(uint i=0; i<row_width; i++)
						{
							if(*(sp-5)==red_high&&*(sp-4)==red_low&&*(sp-3)==green_high&&*(sp-2)==green_low&&*(sp-1)==blue_high&&*(sp)==blue_low)
							{
								*dp--=0;
								*dp--=0;
							}
							else
							{
								*dp--=0xff;
								*dp--=0xff;
							}
							*dp--=*sp--;
							*dp--=*sp--;
							*dp--=*sp--;
							*dp--=*sp--;
							*dp--=*sp--;
							*dp--=*sp--;
						}
					}
					row_info.color_type=PNG_COLOR_TYPE.RGB_ALPHA;
					row_info.channels=4;
					row_info.pixel_depth=(byte)(row_info.bit_depth<<2);
					row_info.rowbytes=PNG_ROWBYTES(row_info.pixel_depth, row_width);
				}
			}
		}
예제 #14
0
		// Replace any alpha or transparency with the supplied background color.
		// "background" is already in the screen gamma, while "background_1" is
		// at a gamma of 1.0. Paletted files have already been taken care of.
		static unsafe void png_do_background(ref png_row_info row_info, byte[] row, ref png_color_16 trans_color, ref png_color_16 background,
			ref png_color_16 background_1, byte[] gamma_table, byte[] gamma_from_1, byte[] gamma_to_1, ushort[][] gamma_16,
			ushort[][] gamma_16_from_1, ushort[][] gamma_16_to_1, int gamma_shift)
		{
			uint i;
			uint row_width=row_info.width;
			int shift;

			if(!((row_info.color_type&PNG_COLOR_TYPE.ALPHA_MASK)!=PNG_COLOR_TYPE.ALPHA_MASK||
				row_info.color_type!=PNG_COLOR_TYPE.PALETTE)) return;

			fixed(byte* row_=row)
			{
				byte* sp=row_+1; // skip filter value
				byte* dp=row_+1; // skip filter value

				switch(row_info.color_type)
				{
					case PNG_COLOR_TYPE.GRAY:
						{
							switch(row_info.bit_depth)
							{
								case 1:
									{
										shift=7;
										for(i=0; i<row_width; i++)
										{
											if((ushort)((*sp>>shift)&0x01)==trans_color.gray)
											{
												*sp&=(byte)((0x7f7f>>(7-shift))&0xff);
												*sp|=(byte)(background.gray<<shift);
											}
											if(shift==0)
											{
												shift=7;
												sp++;
											}
											else shift--;
										}
									}
									break;
								case 2:
									{
										shift=6;
										if(gamma_table!=null)
										{
											for(i=0; i<row_width; i++)
											{
												if((ushort)((*sp>>shift)&0x03)==trans_color.gray)
												{
													*sp&=(byte)((0x3f3f>>(6-shift))&0xff);
													*sp|=(byte)(background.gray<<shift);
												}
												else
												{
													byte p=(byte)((*sp>>shift)&0x03);
													byte g=(byte)((gamma_table[p|(p<<2)|(p<<4)|(p<<6)]>>6)&0x03);
													*sp&=(byte)((0x3f3f>>(6-shift))&0xff);
													*sp|=(byte)(g<<shift);
												}
												if(shift==0)
												{
													shift=6;
													sp++;
												}
												else shift-=2;
											}
										}
										else
										{
											for(i=0; i<row_width; i++)
											{
												if((ushort)((*sp>>shift)&0x03)==trans_color.gray)
												{
													*sp&=(byte)((0x3f3f>>(6-shift))&0xff);
													*sp|=(byte)(background.gray<<shift);
												}
												if(shift==0)
												{
													shift=6;
													sp++;
												}
												else shift-=2;
											}
										}
									}
									break;
								case 4:
									{
										shift=4;
										if(gamma_table!=null)
										{
											for(i=0; i<row_width; i++)
											{
												if((ushort)((*sp>>shift)&0x0f)==trans_color.gray)
												{
													*sp&=(byte)((0xf0f>>(4-shift))&0xff);
													*sp|=(byte)(background.gray<<shift);
												}
												else
												{
													byte p=(byte)((*sp>>shift)&0x0f);
													byte g=(byte)((gamma_table[p|(p<<4)]>>4)&0x0f);
													*sp&=(byte)((0xf0f>>(4-shift))&0xff);
													*sp|=(byte)(g<<shift);
												}
												if(shift==0)
												{
													shift=4;
													sp++;
												}
												else shift-=4;
											}
										}
										else
										{
											for(i=0; i<row_width; i++)
											{
												if((ushort)((*sp>>shift)&0x0f)==trans_color.gray)
												{
													*sp&=(byte)((0xf0f>>(4-shift))&0xff);
													*sp|=(byte)(background.gray<<shift);
												}
												if(shift==0)
												{
													shift=4;
													sp++;
												}
												else shift-=4;
											}
										}
									}
									break;
								case 8:
									{
										if(gamma_table!=null)
										{
											for(i=0; i<row_width; i++, sp++)
											{
												if(*sp==trans_color.gray) *sp=(byte)background.gray;
												else *sp=gamma_table[*sp];
											}
										}
										else
										{
											for(i=0; i<row_width; i++, sp++)
											{
												if(*sp==trans_color.gray) *sp=(byte)background.gray;
											}
										}
										break;
									}
								case 16:
									{
										if(gamma_16!=null)
										{
											for(i=0; i<row_width; i++, sp+=2)
											{
												ushort v=(ushort)(((*sp)<<8)+*(sp+1));
												if(v==trans_color.gray)
												{ // background is already in screen gamma
													*sp=(byte)((background.gray>>8)&0xff);
													*(sp+1)=(byte)(background.gray&0xff);
												}
												else
												{
													v=gamma_16[*(sp+1)>>gamma_shift][*sp];
													*sp=(byte)((v>>8)&0xff);
													*(sp+1)=(byte)(v&0xff);
												}
											}
										}
										else
										{
											for(i=0; i<row_width; i++, sp+=2)
											{
												ushort v=(ushort)(((*sp)<<8)+*(sp+1));
												if(v==trans_color.gray)
												{
													*sp=(byte)((background.gray>>8)&0xff);
													*(sp+1)=(byte)(background.gray&0xff);
												}
											}
										}
									}
									break;
							} // switch(row_info->bit_depth)
						}
						break;
					case PNG_COLOR_TYPE.RGB:
						{
							if(row_info.bit_depth==8)
							{
								if(gamma_table!=null)
								{
									for(i=0; i<row_width; i++, sp+=3)
									{
										if(*sp==trans_color.red&&*(sp+1)==trans_color.green&&*(sp+2)==trans_color.blue)
										{
											*sp=(byte)background.red;
											*(sp+1)=(byte)background.green;
											*(sp+2)=(byte)background.blue;
										}
										else
										{
											*sp=gamma_table[*sp];
											*(sp+1)=gamma_table[*(sp+1)];
											*(sp+2)=gamma_table[*(sp+2)];
										}
									}
								}
								else
								{
									for(i=0; i<row_width; i++, sp+=3)
									{
										if(*sp==trans_color.red&&*(sp+1)==trans_color.green&&*(sp+2)==trans_color.blue)
										{
											*sp=(byte)background.red;
											*(sp+1)=(byte)background.green;
											*(sp+2)=(byte)background.blue;
										}
									}
								}
							}
							else // if(row_info->bit_depth==16)
							{
								if(gamma_16!=null)
								{
									for(i=0; i<row_width; i++, sp+=6)
									{
										ushort r=(ushort)(((*sp)<<8)+*(sp+1));
										ushort g=(ushort)(((*(sp+2))<<8)+*(sp+3));
										ushort b=(ushort)(((*(sp+4))<<8)+*(sp+5));
										if(r==trans_color.red&&g==trans_color.green&&b==trans_color.blue)
										{ // background is already in screen gamma
											*sp=(byte)((background.red>>8)&0xff);
											*(sp+1)=(byte)(background.red&0xff);
											*(sp+2)=(byte)((background.green>>8)&0xff);
											*(sp+3)=(byte)(background.green&0xff);
											*(sp+4)=(byte)((background.blue>>8)&0xff);
											*(sp+5)=(byte)(background.blue&0xff);
										}
										else
										{
											ushort v=gamma_16[*(sp+1)>>gamma_shift][*sp];
											*sp=(byte)((v>>8)&0xff);
											*(sp+1)=(byte)(v&0xff);
											v=gamma_16[*(sp+3)>>gamma_shift][*(sp+2)];
											*(sp+2)=(byte)((v>>8)&0xff);
											*(sp+3)=(byte)(v&0xff);
											v=gamma_16[*(sp+5)>>gamma_shift][*(sp+4)];
											*(sp+4)=(byte)((v>>8)&0xff);
											*(sp+5)=(byte)(v&0xff);
										}
									}
								}
								else
								{
									for(i=0; i<row_width; i++, sp+=6)
									{
										ushort r=(ushort)(((*sp)<<8)+*(sp+1));
										ushort g=(ushort)(((*(sp+2))<<8)+*(sp+3));
										ushort b=(ushort)(((*(sp+4))<<8)+*(sp+5));

										if(r==trans_color.red&&g==trans_color.green&&b==trans_color.blue)
										{
											*sp=(byte)((background.red>>8)&0xff);
											*(sp+1)=(byte)(background.red&0xff);
											*(sp+2)=(byte)((background.green>>8)&0xff);
											*(sp+3)=(byte)(background.green&0xff);
											*(sp+4)=(byte)((background.blue>>8)&0xff);
											*(sp+5)=(byte)(background.blue&0xff);
										}
									}
								}
							}
						}
						break;
					case PNG_COLOR_TYPE.GRAY_ALPHA:
						{
							if(row_info.bit_depth==8)
							{
								if(gamma_to_1!=null&&gamma_from_1!=null&&gamma_table!=null)
								{
									for(i=0; i<row_width; i++, sp+=2, dp++)
									{
										ushort a=*(sp+1);
										if(a==0xff) *dp=gamma_table[*sp];
										else if(a==0) *dp=(byte)background.gray; // background is already in screen gamma
										else
										{
											byte w, v=gamma_to_1[*sp];
											//png_composite(w, v, a, background_1->gray);
											w=(byte)(((ushort)v*a+background_1.gray*(ushort)(255-a)+(ushort)127)/255);
											*dp=gamma_from_1[w];
										}
									}
								}
								else
								{
									for(i=0; i<row_width; i++, sp+=2, dp++)
									{
										byte a=*(sp+1);
										if(a==0xff) *dp=*sp;
										else if(a==0) *dp=(byte)background.gray;
										else //png_composite(*dp, *sp, a, background_1->gray);
											*dp=(byte)(((ushort)(*sp)*a+background_1.gray*(ushort)(255-a)+(ushort)127)/255);
									}
								}
							}
							else // if(png_ptr->bit_depth==16)
							{
								if(gamma_16!=null&&gamma_16_from_1!=null&&gamma_16_to_1!=null)
								{
									for(i=0; i<row_width; i++, sp+=4, dp+=2)
									{
										ushort a=(ushort)(((*(sp+2))<<8)+*(sp+3));
										if(a==(ushort)0xffff)
										{
											ushort v=gamma_16[*(sp+1)>>gamma_shift][*sp];
											*dp=(byte)((v>>8)&0xff);
											*(dp+1)=(byte)(v&0xff);
										}
										else if(a==0)
										{ // background is already in screen gamma
											*dp=(byte)((background.gray>>8)&0xff);
											*(dp+1)=(byte)(background.gray&0xff);
										}
										else
										{
											ushort v, w, g=gamma_16_to_1[*(sp+1)>>gamma_shift][*sp];
											//png_composite_16(v, g, a, background_1->gray);
											v=(ushort)(((uint)g*(uint)a+(uint)background_1.gray*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);
											w=gamma_16_from_1[(v&0xff)>>gamma_shift][v>>8];
											*dp=(byte)((w>>8)&0xff);
											*(dp+1)=(byte)(w&0xff);
										}
									}
								}
								else
								{
									for(i=0; i<row_width; i++, sp+=4, dp+=2)
									{
										ushort a=(ushort)(((*(sp+2))<<8)+*(sp+3));
										if(a==(ushort)0xffff)
										{
											//memcpy(dp, sp, 2);
											*dp=*sp;
											*(dp+1)=*(sp+1);
										}
										else if(a==0)
										{
											*dp=(byte)((background.gray>>8)&0xff);
											*(dp+1)=(byte)(background.gray&0xff);
										}
										else
										{
											ushort v, g=(ushort)(((*sp)<<8)+*(sp+1));
											//png_composite_16(v, g, a, background_1->gray);
											v=(ushort)(((uint)g*(uint)a+(uint)(background_1.gray)*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);
											*dp=(byte)((v>>8)&0xff);
											*(dp+1)=(byte)(v&0xff);
										}
									}
								}
							}
						}
						break;
					case PNG_COLOR_TYPE.RGB_ALPHA:
						{
							if(row_info.bit_depth==8)
							{
								if(gamma_to_1!=null&&gamma_from_1!=null&&gamma_table!=null)
								{
									for(i=0; i<row_width; i++, sp+=4, dp+=3)
									{
										byte a=*(sp+3);
										if(a==0xff)
										{
											*dp=gamma_table[*sp];
											*(dp+1)=gamma_table[*(sp+1)];
											*(dp+2)=gamma_table[*(sp+2)];
										}
										else if(a==0)
										{ // background is already in screen gamma
											*dp=(byte)background.red;
											*(dp+1)=(byte)background.green;
											*(dp+2)=(byte)background.blue;
										}
										else
										{
											byte w, v=gamma_to_1[*sp];
											// png_composite(w, v, a, background_1->red);
											w=(byte)(((ushort)v*(ushort)a+background_1.red*(ushort)(255-(ushort)a)+(ushort)127)/255);
											*dp=gamma_from_1[w];
											v=gamma_to_1[*(sp+1)];
											//png_composite(w, v, a, background_1->green);
											w=(byte)(((ushort)v*(ushort)a+background_1.green*(ushort)(255-(ushort)a)+(ushort)127)/255);
											*(dp+1)=gamma_from_1[w];
											v=gamma_to_1[*(sp+2)];
											//png_composite(w, v, a, background_1->blue);
											w=(byte)(((ushort)v*(ushort)a+background_1.blue*(ushort)(255-(ushort)a)+(ushort)127)/255);
											*(dp+2)=gamma_from_1[w];
										}
									}
								}
								else
								{
									for(i=0; i<row_width; i++, sp+=4, dp+=3)
									{
										byte a=*(sp+3);
										if(a==0xff)
										{
											*dp=*sp;
											*(dp+1)=*(sp+1);
											*(dp+2)=*(sp+2);
										}
										else if(a==0)
										{
											*dp=(byte)background.red;
											*(dp+1)=(byte)background.green;
											*(dp+2)=(byte)background.blue;
										}
										else
										{
											//png_composite(*dp, *sp, a, background->red);
											//png_composite(*(dp+1), *(sp+1), a, background->green);
											//png_composite(*(dp+2), *(sp+2), a, background->blue);
											*dp=(byte)(((ushort)(*sp)*(ushort)a+background.red*(ushort)(255-(ushort)a)+(ushort)127)/255);
											*(dp+1)=(byte)(((ushort)(*(sp+1))*(ushort)a+background.green*(ushort)(255-(ushort)a)+(ushort)127)/255);
											*(dp+2)=(byte)(((ushort)(*(sp+2))*(ushort)a+background.blue*(ushort)(255-(ushort)a)+(ushort)127)/255);
										}
									}
								}
							}
							else //if (row_info->bit_depth==16)
							{
								if(gamma_16!=null&&gamma_16_from_1!=null&&gamma_16_to_1!=null)
								{
									for(i=0; i<row_width; i++, sp+=8, dp+=6)
									{
										ushort a=(ushort)(((ushort)(*(sp+6))<<8)+(ushort)(*(sp+7)));
										if(a==(ushort)0xffff)
										{
											ushort v=gamma_16[*(sp+1)>>gamma_shift][*sp];
											*dp=(byte)((v>>8)&0xff);
											*(dp+1)=(byte)(v&0xff);
											v=gamma_16[*(sp+3)>>gamma_shift][*(sp+2)];
											*(dp+2)=(byte)((v>>8)&0xff);
											*(dp+3)=(byte)(v&0xff);
											v=gamma_16[*(sp+5)>>gamma_shift][*(sp+4)];
											*(dp+4)=(byte)((v>>8)&0xff);
											*(dp+5)=(byte)(v&0xff);
										}
										else if(a==0)
										{ // background is already in screen gamma
											*dp=(byte)((background.red>>8)&0xff);
											*(dp+1)=(byte)(background.red&0xff);
											*(dp+2)=(byte)((background.green>>8)&0xff);
											*(dp+3)=(byte)(background.green&0xff);
											*(dp+4)=(byte)((background.blue>>8)&0xff);
											*(dp+5)=(byte)(background.blue&0xff);
										}
										else
										{
											ushort w, x, v=gamma_16_to_1[*(sp+1)>>gamma_shift][*sp];

											//png_composite_16(w, v, a, background_1->red);
											w=(ushort)(((uint)v*(uint)a+(uint)background_1.red*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);

											x=gamma_16_from_1[((w&0xff)>>gamma_shift)][w>>8];
											*dp=(byte)((x>>8)&0xff);
											*(dp+1)=(byte)(x&0xff);
											v=gamma_16_to_1[*(sp+3)>>gamma_shift][*(sp+2)];

											//png_composite_16(w, v, a, background_1->green);
											w=(ushort)(((uint)v*(uint)a+(uint)background_1.green*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);

											x=gamma_16_from_1[((w&0xff)>>gamma_shift)][w>>8];
											*(dp+2)=(byte)((x>>8)&0xff);
											*(dp+3)=(byte)(x&0xff);
											v=gamma_16_to_1[*(sp+5)>>gamma_shift][*(sp+4)];

											//png_composite_16(w, v, a, background_1->blue);
											w=(ushort)(((uint)v*(uint)a+(uint)background_1.blue*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);

											x=gamma_16_from_1[(w&0xff)>>gamma_shift][w>>8];
											*(dp+4)=(byte)((x>>8)&0xff);
											*(dp+5)=(byte)(x&0xff);
										}
									}
								}
								else
								{
									for(i=0; i<row_width; i++, sp+=8, dp+=6)
									{
										ushort a=(ushort)(((ushort)(*(sp+6))<<8)+(ushort)(*(sp+7)));
										if(a==(ushort)0xffff)
										{
											//memcpy(dp, sp, 6);
											*dp=*sp;
											*(dp+1)=*(sp+1);
											*(dp+2)=*(sp+2);
											*(dp+3)=*(sp+3);
											*(dp+4)=*(sp+4);
											*(dp+5)=*(sp+5);
										}
										else if(a==0)
										{
											*dp=(byte)((background.red>>8)&0xff);
											*(dp+1)=(byte)(background.red&0xff);
											*(dp+2)=(byte)((background.green>>8)&0xff);
											*(dp+3)=(byte)(background.green&0xff);
											*(dp+4)=(byte)((background.blue>>8)&0xff);
											*(dp+5)=(byte)(background.blue&0xff);
										}
										else
										{
											ushort v;
											ushort r=(ushort)(((*sp)<<8)+*(sp+1));
											ushort g=(ushort)(((*(sp+2))<<8)+*(sp+3));
											ushort b=(ushort)(((*(sp+4))<<8)+*(sp+5));

											//png_composite_16(v, r, a, background->red);
											v=(ushort)(((uint)r*(uint)a+(uint)background.red*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);

											*dp=(byte)((v>>8)&0xff);
											*(dp+1)=(byte)(v&0xff);
											//png_composite_16(v, g, a, background->green);
											v=(ushort)(((uint)g*(uint)a+(uint)background.green*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);

											*(dp+2)=(byte)((v>>8)&0xff);
											*(dp+3)=(byte)(v&0xff);
											//png_composite_16(v, b, a, background->blue);
											v=(ushort)(((uint)b*(uint)a+(uint)background.blue*(uint)(65535-(uint)a)+(uint)32767)/(uint)65535);

											*(dp+4)=(byte)((v>>8)&0xff);
											*(dp+5)=(byte)(v&0xff);
										}
									}
								}
							}
						}
						break;
				} // switch(row_info->color_type)
			} // fixed

			if((row_info.color_type&PNG_COLOR_TYPE.ALPHA_MASK)==PNG_COLOR_TYPE.ALPHA_MASK)
			{
				row_info.color_type&=~PNG_COLOR_TYPE.ALPHA_MASK;
				row_info.channels--;
				row_info.pixel_depth=(byte)(row_info.channels*row_info.bit_depth);
				row_info.rowbytes=PNG_ROWBYTES(row_info.pixel_depth, row_width);
			}
		}
예제 #15
0
		// handle alpha and tRNS via a background color
		public void png_set_background(png_color_16 background_color, PNG_BACKGROUND_GAMMA background_gamma_code, bool need_expand, double background_gamma)
		{
			if(background_gamma_code==PNG_BACKGROUND_GAMMA.UNKNOWN)
			{
				Debug.WriteLine("Application must supply a known background gamma");
				return;
			}

			transformations|=PNG_TRANSFORMATION.BACKGROUND;
			background=background_color;
			this.background_gamma=background_gamma;
			background_gamma_type=background_gamma_code;
			transformations|=(need_expand?PNG_TRANSFORMATION.BACKGROUND_EXPAND:PNG_TRANSFORMATION.None);
		}