Example #1
0
        private void ReadMipMapsContent(Stream stream, IList <TgvMipMap> mipMaps, bool compressed)
        {
            for (int i = 0; i < mipMaps.Count; i++)
            {
                var buffer = new byte[4];

                stream.Seek(mipMaps[i].Offset, SeekOrigin.Begin);

                if (compressed)
                {
                    stream.Read(buffer, 0, buffer.Length);
                    if (!MiscUtilities.ComparerByteArrays(buffer, ZIPO))
                    {
                        throw new InvalidDataException("Mipmap has to start with \"ZIPO\"!");
                    }

                    stream.Read(buffer, 0, buffer.Length);
                    mipMaps[i].MipSize = (uint)BitConverter.ToInt32(buffer, 0); //Tu nie by³o rzutowania
                }

                // odejmujemy 8 bo rozmiar zawiera 8 bajtów dodatkowych, 4 magii i 4 rozmiaru mipampy
                buffer = new byte[mipMaps[i].Length - 8];
                stream.Read(buffer, 0, buffer.Length);

                if (compressed)
                {
                    ICompressor comp = new ZlibCompressor();
                    buffer = comp.Decompress(buffer);
                }

                mipMaps[i].Content = buffer;
            }
        }
Example #2
0
            // Constructor.
            public ScanlineWriter(ZlibCompressor compressor,
                                  int width, PixelFormat format)
            {
                // Initialize the object.
                this.compressor = compressor;
                usePaeth        = true;
                filter          = new byte [1];
                y = 0;

                // Get the scanline size parameters.
                switch (format)
                {
                case PixelFormat.Format16bppRgb555:
                case PixelFormat.Format16bppRgb565:
                case PixelFormat.Format24bppRgb:
                case PixelFormat.Format32bppRgb:
                {
                    bytesPerLine  = width * 3;
                    bytesPerPixel = 3;
                }
                break;

                case PixelFormat.Format1bppIndexed:
                case PixelFormat.Format4bppIndexed:
                case PixelFormat.Format8bppIndexed:
                {
                    bytesPerLine  = width;
                    bytesPerPixel = 1;
                    usePaeth      = false;
                }
                break;

                case PixelFormat.Format16bppArgb1555:
                case PixelFormat.Format32bppPArgb:
                case PixelFormat.Format32bppArgb:
                {
                    bytesPerLine  = width * 4;
                    bytesPerPixel = 4;
                }
                break;

                case PixelFormat.Format16bppGrayScale:
                {
                    bytesPerLine  = width * 2;
                    bytesPerPixel = 2;
                }
                break;

                case PixelFormat.Format48bppRgb:
                {
                    bytesPerLine  = width * 6;
                    bytesPerPixel = 6;
                }
                break;

                case PixelFormat.Format64bppPArgb:
                case PixelFormat.Format64bppArgb:
                {
                    bytesPerLine  = width * 8;
                    bytesPerPixel = 8;
                }
                break;
                }

                // Allocate space for the scanline buffers.
                Buffer       = new byte [bytesPerLine];
                prevScanline = new byte [bytesPerLine];
                paeth        = (usePaeth ? new byte [bytesPerLine] : null);
            }
Example #3
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);
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        /// <remarks>
        /// Credits to enohka for this code.
        /// See more at: http://github.com/enohka/moddingSuite
        /// </remarks>
        public virtual byte[] Write(TgvImage file)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                file.PixelFormatString = TgvUtilities.GetTgvFromPixelFormat(file.Format); //"DXT5_SRGB"

                var buffer = BitConverter.GetBytes(VersionMagic);
                stream.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(file.IsCompressed ? 1 : 0);
                stream.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(file.Width);
                stream.Write(buffer, 0, buffer.Length);
                buffer = BitConverter.GetBytes(file.Height);
                stream.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes(file.Width);
                stream.Write(buffer, 0, buffer.Length);
                buffer = BitConverter.GetBytes(file.Height);
                stream.Write(buffer, 0, buffer.Length);

                buffer = BitConverter.GetBytes((short)file.MipMapCount);
                stream.Write(buffer, 0, buffer.Length);

                var fmtLen = (short)file.PixelFormatString.Length;
                buffer = BitConverter.GetBytes(fmtLen);
                stream.Write(buffer, 0, buffer.Length);

                buffer = Encoding.ASCII.GetBytes(file.PixelFormatString);
                stream.Write(buffer, 0, buffer.Length);
                stream.Seek(MathUtilities.RoundToNextDivBy4(fmtLen) - fmtLen, SeekOrigin.Current);

                stream.Write(file.SourceChecksum, 0, file.SourceChecksum.Length);

                var mipOffset = (uint)(stream.Position);

                stream.Seek(8 * file.MipMapCount, SeekOrigin.Current);

                var sortedMipMaps = file.MipMaps.OrderBy(x => x.MipSize).ToList();

                // Create the content and write all MipMaps,
                // since we compress on this part its the first part where we know the size of a MipMap
                foreach (var sortedMipMap in sortedMipMaps)
                {
                    sortedMipMap.Offset = (uint)stream.Position;
                    if (file.IsCompressed)
                    {
                        var zipoMagic = Encoding.ASCII.GetBytes("ZIPO");
                        stream.Write(zipoMagic, 0, zipoMagic.Length);

                        //buffer = BitConverter.GetBytes(mipImgsizes[sortedMipMaps.IndexOf(sortedMipMap)]);
                        //To Ÿle dzia³a. W orygianlnym pliku bajty s¹ w innej kolejnoœci. Pozatym to zak³ada ze potêg¹ jest indeks,
                        //a w przypadku ma³ej liczby bitmap to nie ma sensu
                        uint mipSize = sortedMipMap.MipSize; //GetMipMapSize(file.Width, file.Height, sortedMipMaps.IndexOf(sortedMipMap), sortedMipMaps.Count);
                        buffer = BitConverter.GetBytes(mipSize);
                        stream.Write(buffer, 0, buffer.Length);

                        ICompressor comp = new ZlibCompressor();
                        buffer = comp.Compress(sortedMipMap.Content);
                        stream.Write(buffer, 0, buffer.Length);
                        sortedMipMap.Length = (uint)buffer.Length;
                    }
                    else
                    {
                        stream.Write(sortedMipMap.Content, 0, sortedMipMap.Content.Length);
                        sortedMipMap.Length = (uint)sortedMipMap.Content.Length;
                    }

                    //Wygl¹da na to ¿e mipMapy musza mieæ offset wzglêden pocz¹tku pliku podzielny przez 4.
                    //Trzeba dope³niæ do liczby podzielnej przez 4 przed zapisem nastêpnego
                    //To dope³nienie zak³ada ¿e nag³ówek ma d³ugoœæ podzielna przez 4, tak ¿e pierwsza MipMapa nie jest przesuniêta.

                    //Plik Edata wie o tym poszerzeniu rozmiaru, bo odczytuje d³ugoœæ pliku z rozmiaru contentu.

                    bool multiMipMaps      = file.MipMaps.Count > 1;
                    bool needSupplementTo4 = (stream.Position % 4) != 0;
                    if (multiMipMaps && needSupplementTo4)
                    {
                        int    supplementSize   = (int)(MathUtilities.RoundToNextDivBy4(stream.Position) - stream.Position);
                        byte[] supplementBuffer = new byte[supplementSize];
                        stream.Write(supplementBuffer, 0, supplementBuffer.Length);
                    }
                }

                stream.Seek(mipOffset, SeekOrigin.Begin);

                // Write the offset collection in the header.
                for (int i = 0; i < file.MipMapCount; i++)
                {
                    buffer = BitConverter.GetBytes(sortedMipMaps[i].Offset);
                    stream.Write(buffer, 0, buffer.Length);
                }

                // Write the size collection into the header.
                for (int i = 0; i < file.MipMapCount; i++)
                {
                    buffer = BitConverter.GetBytes(sortedMipMaps[i].Length + 8); //+ 4 magii i + 4 rozmiaru mapy
                    stream.Write(buffer, 0, buffer.Length);
                }

                return(stream.ToArray());
            }
        }
		// Constructor.
		public ScanlineWriter(ZlibCompressor compressor,
							  int width, PixelFormat format)
				{
					// Initialize the object.
					this.compressor = compressor;
					this.usePaeth = true;
					this.filter = new byte [1];
					this.y = 0;

					// Get the scanline size parameters.
					switch(format)
					{
						case PixelFormat.Format16bppRgb555:
						case PixelFormat.Format16bppRgb565:
						case PixelFormat.Format24bppRgb:
						case PixelFormat.Format32bppRgb:
						{
							bytesPerLine = width * 3;
							bytesPerPixel = 3;
						}
						break;
	
						case PixelFormat.Format1bppIndexed:
						case PixelFormat.Format4bppIndexed:
						case PixelFormat.Format8bppIndexed:
						{
							bytesPerLine = width;
							bytesPerPixel = 1;
							usePaeth = false;
						}
						break;
	
						case PixelFormat.Format16bppArgb1555:
						case PixelFormat.Format32bppPArgb:
						case PixelFormat.Format32bppArgb:
						{
							bytesPerLine = width * 4;
							bytesPerPixel = 4;
						}
						break;
	
						case PixelFormat.Format16bppGrayScale:
						{
							bytesPerLine = width * 2;
							bytesPerPixel = 2;
						}
						break;
	
						case PixelFormat.Format48bppRgb:
						{
							bytesPerLine = width * 6;
							bytesPerPixel = 6;
						}
						break;
	
						case PixelFormat.Format64bppPArgb:
						case PixelFormat.Format64bppArgb:
						{
							bytesPerLine = width * 8;
							bytesPerPixel = 8;
						}
						break;
					}

					// Allocate space for the scanline buffers.
					scanline = new byte [bytesPerLine];
					prevScanline = new byte [bytesPerLine];
					paeth = (usePaeth ? new byte [bytesPerLine] : null);
				}
	// 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);
			}