static ColorPalette getPalette(byte[] palette) { List <byte> paletteFile = new List <byte>(); paletteFile.AddRange(BMP.CreateBmpHeader ( (UInt32)4, (UInt32)4, (UInt32)1, (UInt16)8, (UInt32)palette.Length )); paletteFile.AddRange(palette); paletteFile.AddRange(new byte[4]); Bitmap bmPalette; using (MemoryStream argbStream = new MemoryStream(paletteFile.ToArray())) try { bmPalette = new Bitmap(argbStream); } catch { return(null); } return(bmPalette.Palette); }
public static ExtendedBitmap GetBitmap(StciData RGBData) { byte[] argbFile = convert16ARGBTo32ARGB(RGBData); List <byte> bmpFile = new List <byte>(); bmpFile.AddRange(BMP.CreateBmpHeader ( (UInt32)argbFile.Length, (UInt32)RGBData.Width, (UInt32)RGBData.Height, (UInt16)32, (UInt32)0 )); bmpFile.AddRange(argbFile); using (MemoryStream argbStream = new MemoryStream(bmpFile.ToArray())) { Bitmap bm; try { bm = new Bitmap(argbStream); } catch { bm = new Bitmap(RGBData.Width, RGBData.Height); } bm.RotateFlip(RotateFlipType.Rotate180FlipX); return(new ExtendedBitmap(bm, RGBData._RGB)); //, (UInt16)RGBData.Height, (UInt16)RGBData.Width); } }
public static ColorPalette MakeTransparentPalette(ColorPalette palette, Color bC) { List <byte> paletteFile = new List <byte>(); paletteFile.AddRange(BMP.CreateBmpHeader ( (UInt32)4, (UInt32)4, (UInt32)1, (UInt16)8, (UInt32)(palette.Entries.Length * 4) )); paletteFile.AddRange(new byte[] { bC.B, bC.G, bC.R, bC.A }); for (int i = 1; i < palette.Entries.Length; i++) { Color c = palette.Entries[i]; paletteFile.AddRange(new byte[] { c.B, c.G, c.R, c.A }); } paletteFile.AddRange(new byte[4]); Bitmap bmPalette; using (MemoryStream argbStream = new MemoryStream(paletteFile.ToArray())) try { bmPalette = new Bitmap(argbStream); } catch { return(null); } return(bmPalette.Palette); }
// Анимированный GIF разбиавается покадрово на неанимированные, каждый из которых преобразуется в ExtendedBitmap. public static List <ExtendedBitmap> ConvertGifToBitmaps (string fileName, int foreshrteningNum, out bool containsLocalPalette) { List <ExtendedBitmap> result = new List <ExtendedBitmap>(); //bool itIsStiEditFile = false; containsLocalPalette = false; Bitmap _prevImage = null; using (BinaryReader br = new BinaryReader(new FileStream(fileName, FileMode.Open))) { while (br.BaseStream.Position < br.BaseStream.Length) { List <byte> header = new List <byte>(); byte[] _startBytes = br.ReadBytes(10); header.AddRange(_startBytes); //Заголовок: GIF 89a, UInt16 _canvasWidth = BitConverter.ToUInt16(_startBytes, 6); // ширина экрана, UInt16 _canvasHeight = BitConverter.ToUInt16(_startBytes, 8); // высота экрана. byte flags = br.ReadByte(); header.Add(flags); bool isGlobalPalette = flags > 127; header.AddRange(br.ReadBytes(2)); // Цвет фона, форма пикселя. if (isGlobalPalette) { int paletteDepth = flags % 8 + 1; int paletteLength = (Int32)Math.Pow(2, paletteDepth) * 3; header.AddRange(br.ReadBytes(paletteLength)); } else { containsLocalPalette = true; } byte separator = br.ReadByte(); int imageCount = 0; Int16 shiftX = 0; Int16 shiftY = 0; bool shiftsRead = false; while (!(separator == Convert.ToByte(';'))) { List <byte> image = new List <byte>(header); byte[] appData = new byte[16]; byte _transparentColorIndex = 0; byte _imageBehaviorFlags = 0; while (!(separator == Convert.ToByte(','))) { // Выкидываем расширения if (separator == Convert.ToByte('!')) { byte exCode = br.ReadByte(); byte exLength = br.ReadByte(); while (exLength != 0) { if (exCode == 0xFF) { if (new String(br.ReadChars(8)) == "STI_EDIT") { // itIsStiEditFile = true; br.ReadBytes(exLength - 8); if (!shiftsRead) { br.ReadByte(); shiftX = br.ReadInt16(); shiftY = br.ReadInt16(); shiftsRead = true; } else { appData = br.ReadBytes(br.ReadByte()); } exLength = br.ReadByte(); } else { br.ReadBytes(exLength - 8); exLength = br.ReadByte(); exCode = 0; } } else if (exCode == 0xF9) { // если третий бит = 1, предудущий кадр копируется в последующий _imageBehaviorFlags = br.ReadByte(); br.ReadByte(); // Время задержки в мс. В формате STCI не используется. _transparentColorIndex = br.ReadByte(); br.ReadByte(); // Идентификатор окончания блока. exLength = br.ReadByte(); } else { br.ReadBytes(exLength); exLength = br.ReadByte(); } } } separator = br.ReadByte(); } image.Add(separator); // Заголовок картинки. Int16 offsetX = BitConverter.ToInt16(br.ReadBytes(2), 0); Int16 offsetY = BitConverter.ToInt16(br.ReadBytes(2), 0); image.AddRange(new byte[4]); byte[] width = br.ReadBytes(2); image.AddRange(width); byte[] heigth = br.ReadBytes(2); image.AddRange(heigth); image[6] = width[0]; image[7] = width[1]; image[8] = heigth[0]; image[9] = heigth[1]; flags = br.ReadByte(); // флаги image.Add(flags); if (flags > 127) { containsLocalPalette = true; int paletteDepth = flags % 8 + 1; int paletteLength = (Int32)Math.Pow(2, paletteDepth) * 3; image.AddRange(br.ReadBytes(paletteLength)); } image.Add(br.ReadByte()); // кол-во цветов // Читаем картинку byte blockLength = br.ReadByte(); while (blockLength != 0) { image.Add(blockLength); image.AddRange(br.ReadBytes(blockLength)); blockLength = br.ReadByte(); } image.Add(blockLength); image.Add(Convert.ToByte(';')); imageCount++; Bitmap bm = new Bitmap(new MemoryStream(image.ToArray())); // draw next image above previouse if ((_imageBehaviorFlags >> 2) % 2 == 1) { if (_prevImage != null) { Bitmap _argbBm = BMP.ConvertIndexedToArgb32(bm); Graphics _gr = Graphics.FromImage(_prevImage); _gr.DrawImage(_argbBm, offsetX, offsetY); bm = BMP.Convert32argbToIndexed(_prevImage, bm.Palette); offsetX = (short)-shiftX; offsetY = (short)-shiftY; } else { _prevImage = BMP.ConvertIndexedToArgb32(bm); } } else { offsetX -= shiftX; offsetY -= shiftY; } ExtendedBitmap exBm = new ExtendedBitmap(bm, offsetX, offsetY); exBm.ApplicationData = appData; exBm.TransparentColorIndex = _transparentColorIndex; result.Add(exBm); separator = br.ReadByte(); } } } if (foreshrteningNum != 0) { int length = result.Count / foreshrteningNum; if (length != 0) { for (int i = 0; i < result.Count; i += length) { result[i].ApplicationData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, (byte)length, 2, 0, 0, 0, 0, 0, 0 }; for (int j = i + 1; j < length; j++) { result[j].ApplicationData = new byte[16]; } } } } return(result); }
public static byte[] CreateBmpHeader( Int32 imageLength, Int32 width, Int32 height, Int32 bitPerPixel, Int32 paletteLength) { return(BMP.CreateBmpHeader( (UInt32)imageLength, (UInt32)width, (UInt32)height, (UInt16)bitPerPixel, (UInt32)paletteLength)); }
public static Bitmap Convert32argbToIndexed(Bitmap argbFile, ColorPalette palette) { // if palette = null, create palette. // if file contains more than 256 different colors throw excepiton int _headerSize = 54; int _colorNum = 256; int _paletteSize = 256 * 4; int _width = argbFile.Width; int _height = argbFile.Height; int _imageDataSize = _width * _height; byte[] _indexedBmData = new byte[_headerSize + _paletteSize + _imageDataSize]; bool _isNewPalette = false; if (palette == null) { byte[] _paletteData = new byte[_paletteSize]; palette = BMP.getPalette(_paletteData); _isNewPalette = true; } int _paletteIndex = 0; byte[] _argbBmData = new byte[_headerSize + _imageDataSize * 4]; Bitmap _indexedBm = null; using (MemoryStream _argbStream = new MemoryStream(_argbBmData)) { argbFile.Save(_argbStream, ImageFormat.Bmp); using (MemoryStream _indexedStream = new MemoryStream(_indexedBmData)) { byte[] _header = BMP.CreateBmpHeader( _imageDataSize, argbFile.Width, argbFile.Height, 8, _colorNum); _indexedStream.Write(_header, 0, _headerSize); _indexedStream.Seek(_paletteSize, SeekOrigin.Current); _argbStream.Seek(_headerSize, SeekOrigin.Begin); for (int i = 0; i < _height; i++) { for (int j = 0; j < _width; j++) { // argb data is reversed // TODO GetPixel works very slowly. Use stream instead. //Color _c1 = argbFile.GetPixel(_width - j - 1, _height - i - 1); int _b = _argbStream.ReadByte(); int _g = _argbStream.ReadByte(); int _r = _argbStream.ReadByte(); int _a = _argbStream.ReadByte(); Color _c = Color.FromArgb(_a, _r, _g, _b); int _ci = Array.IndexOf(palette.Entries, _c); if (_ci >= 0) { _indexedStream.WriteByte((byte)_ci); } else { if (_isNewPalette) { if (_paletteIndex < _colorNum) { palette.Entries[_paletteIndex] = _c; _paletteIndex++; } else { string _msg = String.Format( "There are more than {0} colors in input file.", _colorNum); throw new ArgumentException(_msg, "argbFile"); } } else { string _msg = String.Format( "Color R={0} G={1} B={2} is not found in palette.", _c.R, _c.G, _c.B); throw new ArgumentException(_msg, "palette"); } } } } _indexedBm = new Bitmap(_indexedStream); _indexedBm.Palette = palette; } } return(_indexedBm); }
static List <ExtendedBitmap> ConvertEtrleDataToBitmaps (UInt16 startIndex, UInt16 length, ETRLEData data) { byte[] palette = data.palette; List <ExtendedBitmap> bitmaps = new List <ExtendedBitmap>(); for (int objIndex = startIndex; objIndex < startIndex + length; objIndex++) { if (objIndex >= data.ETRLEObjects.Length) { return(bitmaps); } ETRLEObject obj = data.ETRLEObjects[objIndex]; byte[] file = new byte[obj.uiDataLength]; Array.Copy(data.imageData, obj.uiDataOffset, file, 0, obj.uiDataLength); Int32 remainder = (4 - obj.usWidth % 4) % 4; List <byte> argbFile = new List <byte>(); using (BinaryReader br = new BinaryReader(new MemoryStream(file))) { while (br.BaseStream.Position < br.BaseStream.Length) { Int32 firstSectionByte = br.ReadByte(); if (firstSectionByte == 0) { for (int i = 0; i < remainder; i++) { argbFile.Add(0); } } else if (firstSectionByte > 127) { for (int j = 0; j < firstSectionByte - 128; j++) { argbFile.Add(0); } } else { for (int j = 0; j < firstSectionByte; j++) { byte index = br.ReadByte(); argbFile.Add(index); } } } } List <byte> bmpFile = new List <byte>(); bmpFile.AddRange(BMP.CreateBmpHeader ( (UInt32)argbFile.Count, (UInt32)(obj.usWidth), (UInt32)obj.usHeight, (UInt16)8, (UInt32)palette.Length )); bmpFile.AddRange(palette); bmpFile.AddRange(argbFile); byte[] bFile = bmpFile.ToArray(); using (MemoryStream argbStream = new MemoryStream(bFile)) { Bitmap bm; try { bm = new Bitmap(argbStream); } catch { bm = new Bitmap(obj.usWidth, obj.usHeight); } bm.RotateFlip(RotateFlipType.RotateNoneFlipY); ExtendedBitmap exBm = new ExtendedBitmap(bm, obj.sOffsetX, obj.sOffsetY); if (data.pAppData != null) { exBm.ApplicationData = new byte[16]; Array.Copy(data.pAppData, objIndex * 16, exBm.ApplicationData, 0, 16); } bitmaps.Add(exBm); } } return(bitmaps); }