Пример #1
0
        // Save a PNG image to the specified stream.
        public static void Save(Stream stream, PortableImage image)
        {
            Frame frame = image.GetFrame(0);

            byte[]      buffer = new byte [1024];
            ChunkWriter writer = new ChunkWriter(stream);
            int         colorType, bitDepth;
            int         sigRed, sigGreen, sigBlue, sigAlpha;
            int         paletteSize, posn;

            int[]          palette;
            ZlibCompressor compressor;
            ScanlineWriter scanlineWriter;
            OutputFunc     func;
            int            y;

            // Determine the color type and bit depth for the image.
            sigRed      = -1;
            sigGreen    = -1;
            sigBlue     = -1;
            sigAlpha    = -1;
            paletteSize = 0;
            switch (frame.PixelFormat)
            {
            case PixelFormat.Format16bppRgb555:
            {
                sigRed    = 5;
                sigGreen  = 5;
                sigBlue   = 5;
                colorType = 2;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format16bppRgb565:
            {
                sigRed    = 5;
                sigGreen  = 6;
                sigBlue   = 5;
                colorType = 2;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format24bppRgb:
            case PixelFormat.Format32bppRgb:
            {
                colorType = 2;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format1bppIndexed:
            {
                colorType   = 3;
                bitDepth    = 1;
                paletteSize = 2;
            }
            break;

            case PixelFormat.Format4bppIndexed:
            {
                colorType   = 3;
                bitDepth    = 4;
                paletteSize = 16;
            }
            break;

            case PixelFormat.Format8bppIndexed:
            {
                colorType   = 3;
                bitDepth    = 8;
                paletteSize = 256;
            }
            break;

            case PixelFormat.Format16bppArgb1555:
            {
                sigRed    = 5;
                sigGreen  = 5;
                sigBlue   = 5;
                sigAlpha  = 1;
                colorType = 6;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format32bppPArgb:
            case PixelFormat.Format32bppArgb:
            {
                colorType = 6;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format16bppGrayScale:
            {
                colorType = 0;
                bitDepth  = 16;
            }
            break;

            case PixelFormat.Format48bppRgb:
            {
                colorType = 2;
                bitDepth  = 16;
            }
            break;

            case PixelFormat.Format64bppPArgb:
            case PixelFormat.Format64bppArgb:
            {
                colorType = 6;
                bitDepth  = 16;
            }
            break;

            default: throw new FormatException("unknown format");
            }

            // Write out the PNG magic number.
            stream.Write(magic, 0, magic.Length);

            // Write the header chunk.
            Utils.WriteInt32B(buffer, 0, frame.Width);
            Utils.WriteInt32B(buffer, 4, frame.Height);
            buffer[8]  = (byte)bitDepth;
            buffer[9]  = (byte)colorType;
            buffer[10] = (byte)0;                                       // Compression method.
            buffer[11] = (byte)0;                                       // Filter method.
            buffer[12] = (byte)0;                                       // Interlace method.
            writer.Write(PngReader.IHDR, buffer, 0, 13);

            // Write the significant bits chunk if necessary.
            if (sigAlpha != -1)
            {
                buffer[0] = (byte)sigRed;
                buffer[1] = (byte)sigGreen;
                buffer[2] = (byte)sigBlue;
                buffer[3] = (byte)sigAlpha;
                writer.Write(PngReader.sBIT, buffer, 0, 4);
            }
            else if (sigRed != -1)
            {
                buffer[0] = (byte)sigRed;
                buffer[1] = (byte)sigGreen;
                buffer[2] = (byte)sigBlue;
                writer.Write(PngReader.sBIT, buffer, 0, 3);
            }

            // Write the palette and transparency chunks.
            if (paletteSize > 0)
            {
                Array.Clear(buffer, 0, buffer.Length);
                palette = frame.Palette;
                if (palette != null)
                {
                    for (posn = 0; posn < palette.Length &&
                         posn < paletteSize; ++posn)
                    {
                        buffer[posn * 3]     = (byte)(palette[posn] >> 16);
                        buffer[posn * 2 + 1] = (byte)(palette[posn] >> 8);
                        buffer[posn * 2 + 2] = (byte)(palette[posn]);
                    }
                }
                writer.Write(PngReader.PLTE, buffer, 0, paletteSize * 3);
                if (frame.TransparentPixel >= 0 &&
                    frame.TransparentPixel < paletteSize)
                {
                    for (posn = 0; posn < paletteSize; ++posn)
                    {
                        buffer[posn] = (byte)0xFF;
                    }
                    buffer[frame.TransparentPixel] = (byte)0x00;
                    writer.Write(PngReader.tRNS, buffer, 0,
                                 frame.TransparentPixel + 1);
                }
            }

            // Compress and write the scanlines to the output stream.
            compressor     = new ZlibCompressor(writer);
            scanlineWriter = new ScanlineWriter
                                 (compressor, frame.Width, frame.PixelFormat);
            func = GetOutputFunc(frame.PixelFormat);
            for (y = 0; y < frame.Height; ++y)
            {
                func(frame, y, scanlineWriter.Buffer);
                scanlineWriter.FlushScanline();
            }
            compressor.Finish();

            // Write the end chunk.
            writer.Write(PngReader.IEND, buffer, 0, 0);
        }
Пример #2
0
	// Save a PNG image to the specified stream.
	public static void Save(Stream stream, Image image)
			{
				Frame frame = image.GetFrame(0);
				byte[] buffer = new byte [1024];
				ChunkWriter writer = new ChunkWriter(stream);
				int colorType, bitDepth;
				int sigRed, sigGreen, sigBlue, sigAlpha;
				int paletteSize, posn;
				int[] palette;
				ZlibCompressor compressor;
				ScanlineWriter scanlineWriter;
				OutputFunc func;
				int y;

				// Determine the color type and bit depth for the image.
				sigRed = -1;
				sigGreen = -1;
				sigBlue = -1;
				sigAlpha = -1;
				paletteSize = 0;
				switch(frame.PixelFormat)
				{
					case PixelFormat.Format16bppRgb555:
					{
						sigRed = 5;
						sigGreen = 5;
						sigBlue = 5;
						colorType = 2;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format16bppRgb565:
					{
						sigRed = 5;
						sigGreen = 6;
						sigBlue = 5;
						colorType = 2;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format24bppRgb:
					case PixelFormat.Format32bppRgb:
					{
						colorType = 2;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format1bppIndexed:
					{
						colorType = 3;
						bitDepth = 1;
						paletteSize = 2;
					}
					break;

					case PixelFormat.Format4bppIndexed:
					{
						colorType = 3;
						bitDepth = 4;
						paletteSize = 16;
					}
					break;

					case PixelFormat.Format8bppIndexed:
					{
						colorType = 3;
						bitDepth = 8;
						paletteSize = 256;
					}
					break;

					case PixelFormat.Format16bppArgb1555:
					{
						sigRed = 5;
						sigGreen = 5;
						sigBlue = 5;
						sigAlpha = 1;
						colorType = 6;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format32bppPArgb:
					case PixelFormat.Format32bppArgb:
					{
						colorType = 6;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format16bppGrayScale:
					{
						colorType = 0;
						bitDepth = 16;
					}
					break;

					case PixelFormat.Format48bppRgb:
					{
						colorType = 2;
						bitDepth = 16;
					}
					break;

					case PixelFormat.Format64bppPArgb:
					case PixelFormat.Format64bppArgb:
					{
						colorType = 6;
						bitDepth = 16;
					}
					break;

					default: throw new FormatException("unknown format");
				}

				// Write out the PNG magic number.
				stream.Write(magic, 0, magic.Length);

				// Write the header chunk.
				Utils.WriteInt32B(buffer, 0, frame.Width);
				Utils.WriteInt32B(buffer, 4, frame.Height);
				buffer[8] = (byte)bitDepth;
				buffer[9] = (byte)colorType;
				buffer[10] = (byte)0;			// Compression method.
				buffer[11] = (byte)0;			// Filter method.
				buffer[12] = (byte)0;			// Interlace method.
				writer.Write(PngReader.IHDR, buffer, 0, 13);

				// Write the significant bits chunk if necessary.
				if(sigAlpha != -1)
				{
					buffer[0] = (byte)sigRed;
					buffer[1] = (byte)sigGreen;
					buffer[2] = (byte)sigBlue;
					buffer[3] = (byte)sigAlpha;
					writer.Write(PngReader.sBIT, buffer, 0, 4);
				}
				else if(sigRed != -1)
				{
					buffer[0] = (byte)sigRed;
					buffer[1] = (byte)sigGreen;
					buffer[2] = (byte)sigBlue;
					writer.Write(PngReader.sBIT, buffer, 0, 3);
				}

				// Write the palette and transparency chunks.
				if(paletteSize > 0)
				{
					Array.Clear(buffer, 0, buffer.Length);
					palette = frame.Palette;
					if(palette != null)
					{
						for(posn = 0; posn < palette.Length &&
									  posn < paletteSize; ++posn)
						{
							buffer[posn * 3] = (byte)(palette[posn] >> 16);
							buffer[posn * 2 + 1] = (byte)(palette[posn] >> 8);
							buffer[posn * 2 + 2] = (byte)(palette[posn]);
						}
					}
					writer.Write(PngReader.PLTE, buffer, 0, paletteSize * 3);
					if(frame.TransparentPixel >= 0 &&
					   frame.TransparentPixel < paletteSize)
					{
						for(posn = 0; posn < paletteSize; ++posn)
						{
							buffer[posn] = (byte)0xFF;
						}
						buffer[frame.TransparentPixel] = (byte)0x00;
						writer.Write(PngReader.tRNS, buffer, 0,
									 frame.TransparentPixel + 1);
					}
				}

				// Compress and write the scanlines to the output stream.
				compressor = new ZlibCompressor(writer);
				scanlineWriter = new ScanlineWriter
					(compressor, frame.Width, frame.PixelFormat);
				func = GetOutputFunc(frame.PixelFormat);
				for(y = 0; y < frame.Height; ++y)
				{
					func(frame, y, scanlineWriter.Buffer);
					scanlineWriter.FlushScanline();
				}
				compressor.Finish();

				// Write the end chunk.
				writer.Write(PngReader.IEND, buffer, 0, 0);
			}