internal override void Read(byte[] buffer) { var rleStream = new MemoryStream(rleData); var rleReader = new RleReader(rleStream); var bufferIndex = 0; for (int i = 0; i < Size.Height; i++) { var bytesRead = rleReader.Read(buffer, bufferIndex, BytesPerRow); if (bytesRead != BytesPerRow) { throw new Exception("RLE row decompressed to unexpected length."); } bufferIndex += bytesRead; } }
private byte[] DecodeRleData(byte[] rleData, int[] dataLengths) { var totalDataLength = dataLengths.Sum(); var data = new byte[totalDataLength]; var rleStream = new MemoryStream(rleData); var rleReader = new RleReader(rleStream); int offset = 0; for (int i = 0; i < dataLengths.Length; i++) { var count = dataLengths[i]; rleReader.Read(data, offset, count); offset += count; } return(data); }
/// <summary> /// Reads a Sun Raster (.RAS) image from a stream. /// </summary> /// <param name="stream">Stream from which to read the image.</param> /// <returns>Bitmap that contains the image that was read.</returns> public static Bitmap Load(Stream stream) { BinaryReader reader = new BinaryReader(stream); UInt32 tempDword = Util.BigEndian(reader.ReadUInt32()); if (tempDword != 0x59a66a95) { throw new ApplicationException("This is not a valid RAS file."); } int imgWidth = (int)Util.BigEndian(reader.ReadUInt32()); int imgHeight = (int)Util.BigEndian(reader.ReadUInt32()); int imgBpp = (int)Util.BigEndian(reader.ReadUInt32()); UInt32 dataLength = Util.BigEndian(reader.ReadUInt32()); UInt32 rasType = Util.BigEndian(reader.ReadUInt32()); UInt32 mapType = Util.BigEndian(reader.ReadUInt32()); UInt32 mapLength = Util.BigEndian(reader.ReadUInt32()); RleReader rleReader = new RleReader(stream, rasType == 2); if ((imgWidth < 1) || (imgHeight < 1) || (imgWidth > 32767) || (imgHeight > 32767) || (mapLength > 32767)) { throw new ApplicationException("This RAS file appears to have invalid dimensions."); } if ((imgBpp != 32) && (imgBpp != 24) && (imgBpp != 8) && (imgBpp != 4) && (imgBpp != 1)) { throw new ApplicationException("Only 1, 4, 8, 24, and 32 bit images are supported."); } byte[] bmpData = new byte[imgWidth * 4 * imgHeight]; byte[] colorPalette = null; if (mapType > 0) { colorPalette = new byte[mapLength]; stream.Read(colorPalette, 0, (int)mapLength); } try { if (imgBpp == 1) { int dx = 0, dy = 0; int b, bytePtr = 0; byte val; while (dy < imgHeight) { b = rleReader.ReadByte(); if (b == -1) { break; } for (int i = 7; i >= 0; i--) { if ((b & (1 << i)) != 0) { val = 0; } else { val = 255; } bmpData[bytePtr++] = val; bmpData[bytePtr++] = val; bmpData[bytePtr++] = val; bytePtr++; dx++; if (dx == imgWidth) { dx = 0; dy++; break; } } } } else if (imgBpp == 4) { int bytePtr = 0; byte[] scanline = new byte[imgWidth + 1]; for (int dy = 0; dy < imgHeight; dy++) { int tempByte; for (int i = 0; i < imgWidth; i++) { tempByte = rleReader.ReadByte(); scanline[i++] = (byte)((tempByte >> 4) & 0xF); scanline[i] = (byte)(tempByte & 0xF); } if (imgWidth % 2 == 1) { rleReader.ReadByte(); } if ((mapType > 0) && (mapLength == 48)) { for (int dx = 0; dx < imgWidth; dx++) { bmpData[bytePtr++] = colorPalette[scanline[dx] + 32]; bmpData[bytePtr++] = colorPalette[scanline[dx] + 16]; bmpData[bytePtr++] = colorPalette[scanline[dx]]; bytePtr++; } } else { for (int dx = 0; dx < imgWidth; dx++) { bmpData[bytePtr++] = scanline[dx]; bmpData[bytePtr++] = scanline[dx]; bmpData[bytePtr++] = scanline[dx]; bytePtr++; } } } } else if (imgBpp == 8) { int bytePtr = 0; byte[] scanline = new byte[imgWidth]; for (int dy = 0; dy < imgHeight; dy++) { for (int i = 0; i < imgWidth; i++) { scanline[i] = (byte)rleReader.ReadByte(); } if (imgWidth % 2 == 1) { rleReader.ReadByte(); } if ((mapType > 0) && (mapLength == 768)) { for (int dx = 0; dx < imgWidth; dx++) { bmpData[bytePtr++] = colorPalette[scanline[dx] + 512]; bmpData[bytePtr++] = colorPalette[scanline[dx] + 256]; bmpData[bytePtr++] = colorPalette[scanline[dx]]; bytePtr++; } } else { for (int dx = 0; dx < imgWidth; dx++) { bmpData[bytePtr++] = scanline[dx]; bmpData[bytePtr++] = scanline[dx]; bmpData[bytePtr++] = scanline[dx]; bytePtr++; } } } } else if (imgBpp == 24) { int bytePtr = 0; byte[] scanline = new byte[imgWidth * 3]; for (int dy = 0; dy < imgHeight; dy++) { for (int i = 0; i < imgWidth * 3; i++) { scanline[i] = (byte)rleReader.ReadByte(); } if ((imgWidth * 3) % 2 == 1) { stream.ReadByte(); } for (int dx = 0; dx < imgWidth; dx++) { bmpData[bytePtr++] = scanline[dx * 3]; bmpData[bytePtr++] = scanline[dx * 3 + 1]; bmpData[bytePtr++] = scanline[dx * 3 + 2]; bytePtr++; } } } else if (imgBpp == 32) { int bytePtr = 0; byte[] scanline = new byte[imgWidth * 4]; for (int dy = 0; dy < imgHeight; dy++) { for (int i = 0; i < imgWidth * 4; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (int dx = 0; dx < imgWidth; dx++) { bmpData[bytePtr++] = scanline[dx * 4]; bmpData[bytePtr++] = scanline[dx * 4 + 1]; bmpData[bytePtr++] = scanline[dx * 4 + 2]; bmpData[bytePtr++] = scanline[dx * 4 + 3]; } } } } catch (Exception e) { //give a partial image in case of unexpected end-of-file System.Diagnostics.Debug.WriteLine("Error while processing RAS file: " + e.Message); } Bitmap theBitmap = new Bitmap((int)imgWidth, (int)imgHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Drawing.Imaging.BitmapData bmpBits = theBitmap.LockBits(new Rectangle(0, 0, theBitmap.Width, theBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Runtime.InteropServices.Marshal.Copy(bmpData, 0, bmpBits.Scan0, bmpData.Length); theBitmap.UnlockBits(bmpBits); return(theBitmap); }
public static Bitmap Load(Stream stream) { int imgWidth = -1; int imgHeight = -1; int imgBpp = -1; Bitmap theBitmap = null; BinaryReader reader = new BinaryReader(stream); byte tempByte = (byte)stream.ReadByte(); if (tempByte != 10) { throw new ApplicationException("This is not a PCX file."); } tempByte = (byte)stream.ReadByte(); if (tempByte < 0 || tempByte > 5) { throw new ApplicationException("Invalid PCX version."); } tempByte = (byte)stream.ReadByte(); if (tempByte != 1) { throw new ApplicationException("Invalid encoding char."); } imgBpp = stream.ReadByte(); UInt16 xmin = reader.ReadUInt16(); UInt16 ymin = reader.ReadUInt16(); UInt16 xmax = reader.ReadUInt16(); UInt16 ymax = reader.ReadUInt16(); imgWidth = xmax - xmin + 1; imgHeight = ymax - ymin + 1; if ((imgWidth < 1) || (imgHeight < 1) || (imgWidth > 32767) || (imgHeight > 32767)) { throw new ApplicationException("This PCX file appears to have invalid dimensions."); } reader.ReadUInt16(); //horiontal resolution reader.ReadUInt16(); //vertical resolution byte[] colorPalette = new byte[48]; stream.Read(colorPalette, 0, 48); stream.ReadByte(); int numPlanes = stream.ReadByte(); int bytesPerLine = reader.ReadUInt16(); if (bytesPerLine == 0) { bytesPerLine = xmax - xmin + 1; } if (imgBpp == 8 && numPlanes == 1) { colorPalette = new byte[768]; stream.Seek(-768, SeekOrigin.End); stream.Read(colorPalette, 0, 768); } //fix color palette if it's a 1-bit image, and there's no palette information if (imgBpp == 1) { if ((colorPalette[0] == colorPalette[3]) && (colorPalette[1] == colorPalette[4]) && (colorPalette[2] == colorPalette[5])) { colorPalette[0] = colorPalette[1] = colorPalette[2] = 0; colorPalette[3] = colorPalette[4] = colorPalette[5] = 0xFF; } } byte[] bmpData = new byte[(imgWidth + 1) * 4 * imgHeight]; stream.Seek(128, SeekOrigin.Begin); int x = 0, y = 0, i, j; RleReader rleReader = new RleReader(stream); try { if (imgBpp == 1) { int b, p; byte val; byte[] scanline = new byte[bytesPerLine]; byte[] realscanline = new byte[bytesPerLine * 8]; for (y = 0; y < imgHeight; y++) { //add together all the planes... Array.Clear(realscanline, 0, realscanline.Length); for (p = 0; p < numPlanes; p++) { x = 0; for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); for (b = 7; b >= 0; b--) { if ((scanline[i] & (1 << b)) != 0) { val = 1; } else { val = 0; } realscanline[x] |= (byte)(val << p); x++; } } } for (x = 0; x < imgWidth; x++) { i = realscanline[x]; bmpData[4 * (y * imgWidth + x)] = colorPalette[i * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[i * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[i * 3]; } } } else { if (numPlanes == 1) { if (imgBpp == 8) { byte[] scanline = new byte[bytesPerLine]; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (x = 0; x < imgWidth; x++) { i = scanline[x]; bmpData[4 * (y * imgWidth + x)] = colorPalette[i * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[i * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[i * 3]; } } } else if (imgBpp == 4) { byte[] scanline = new byte[bytesPerLine]; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (x = 0; x < imgWidth; x++) { i = scanline[x / 2]; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 4) & 0xF) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 4) & 0xF) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 4) & 0xF) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[(i & 0xF) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[(i & 0xF) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[(i & 0xF) * 3]; } } } else if (imgBpp == 2) { byte[] scanline = new byte[bytesPerLine]; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (x = 0; x < imgWidth; x++) { i = scanline[x / 4]; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 6) & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 6) & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 6) & 0x3) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 4) & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 4) & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 4) & 0x3) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 2) & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 2) & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 2) & 0x3) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[(i & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[(i & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[(i & 0x3) * 3]; } } } } else if (numPlanes == 3) { byte[] scanlineR = new byte[bytesPerLine]; byte[] scanlineG = new byte[bytesPerLine]; byte[] scanlineB = new byte[bytesPerLine]; int bytePtr = 0; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanlineR[i] = (byte)rleReader.ReadByte(); } for (i = 0; i < bytesPerLine; i++) { scanlineG[i] = (byte)rleReader.ReadByte(); } for (i = 0; i < bytesPerLine; i++) { scanlineB[i] = (byte)rleReader.ReadByte(); } for (int n = 0; n < imgWidth; n++) { bmpData[bytePtr++] = scanlineB[n]; bmpData[bytePtr++] = scanlineG[n]; bmpData[bytePtr++] = scanlineR[n]; bytePtr++; } } } }//bpp } catch (Exception e) { System.Diagnostics.Debug.WriteLine("Error while processing PCX file: " + e.Message); } theBitmap = new Bitmap((int)imgWidth, (int)imgHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Drawing.Imaging.BitmapData bmpBits = theBitmap.LockBits(new Rectangle(0, 0, theBitmap.Width, theBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Runtime.InteropServices.Marshal.Copy(bmpData, 0, bmpBits.Scan0, imgWidth * 4 * imgHeight); theBitmap.UnlockBits(bmpBits); return(theBitmap); }
public static Bitmap Load(Stream stream) { var binaryReader = new BinaryReader(stream); if (BigEndian(binaryReader.ReadUInt32()) != 1504078485u) { throw new ApplicationException("This is not a valid RAS file."); } var num = (int)BigEndian(binaryReader.ReadUInt32()); var num2 = (int)BigEndian(binaryReader.ReadUInt32()); var num3 = (int)BigEndian(binaryReader.ReadUInt32()); BigEndian(binaryReader.ReadUInt32()); var num4 = BigEndian(binaryReader.ReadUInt32()); var num5 = BigEndian(binaryReader.ReadUInt32()); var num6 = BigEndian(binaryReader.ReadUInt32()); var rleReader = new RleReader(stream, num4 == 2u); if (num < 1 || num2 < 1 || num > 32767 || num2 > 32767 || num6 > 32767u) { throw new ApplicationException("This RAS file appears to have invalid dimensions."); } if (num3 != 32 && num3 != 24 && num3 != 8 && num3 != 4 && num3 != 1) { throw new ApplicationException("Only 1, 4, 8, 24, and 32 bit images are supported."); } var array = new byte[num * 4 * num2]; byte[] array2 = null; if (num5 > 0u) { array2 = new byte[num6]; stream.Read(array2, 0, (int)num6); } try { if (num3 == 1) { var num7 = 0; var i = 0; var num8 = 0; while (i < num2) { var num9 = rleReader.ReadByte(); if (num9 == -1) { break; } for (var j = 7; j >= 0; j--) { byte b; if ((num9 & 1 << j) != 0) { b = 0; } else { b = byte.MaxValue; } array[num8++] = b; array[num8++] = b; array[num8++] = b; num8++; num7++; if (num7 == num) { num7 = 0; i++; break; } } } } else if (num3 == 4) { var num10 = 0; var array3 = new byte[num + 1]; for (var k = 0; k < num2; k++) { for (var l = 0; l < num; l++) { var num11 = rleReader.ReadByte(); array3[l++] = (byte)(num11 >> 4 & 15); array3[l] = (byte)(num11 & 15); } if (num % 2 == 1) { rleReader.ReadByte(); } if (num5 > 0u && num6 == 48u) { for (var m = 0; m < num; m++) { array[num10++] = array2[(int)(array3[m] + 32)]; array[num10++] = array2[(int)(array3[m] + 16)]; array[num10++] = array2[(int)array3[m]]; num10++; } } else { for (var n = 0; n < num; n++) { array[num10++] = array3[n]; array[num10++] = array3[n]; array[num10++] = array3[n]; num10++; } } } } else if (num3 == 8) { var num12 = 0; var array4 = new byte[num]; for (var num13 = 0; num13 < num2; num13++) { for (var num14 = 0; num14 < num; num14++) { array4[num14] = (byte)rleReader.ReadByte(); } if (num % 2 == 1) { rleReader.ReadByte(); } if (num5 > 0u && num6 == 768u) { for (var num15 = 0; num15 < num; num15++) { array[num12++] = array2[(int)array4[num15] + 512]; array[num12++] = array2[(int)array4[num15] + 256]; array[num12++] = array2[(int)array4[num15]]; num12++; } } else { for (var num16 = 0; num16 < num; num16++) { array[num12++] = array4[num16]; array[num12++] = array4[num16]; array[num12++] = array4[num16]; num12++; } } } } else if (num3 == 24) { var num17 = 0; var array5 = new byte[num * 3]; for (var num18 = 0; num18 < num2; num18++) { for (var num19 = 0; num19 < num * 3; num19++) { array5[num19] = (byte)rleReader.ReadByte(); } if (num * 3 % 2 == 1) { stream.ReadByte(); } for (var num20 = 0; num20 < num; num20++) { array[num17++] = array5[num20 * 3]; array[num17++] = array5[num20 * 3 + 1]; array[num17++] = array5[num20 * 3 + 2]; num17++; } } } else if (num3 == 32) { var num21 = 0; var array6 = new byte[num * 4]; for (var num22 = 0; num22 < num2; num22++) { for (var num23 = 0; num23 < num * 4; num23++) { array6[num23] = (byte)rleReader.ReadByte(); } for (var num24 = 0; num24 < num; num24++) { array[num21++] = array6[num24 * 4]; array[num21++] = array6[num24 * 4 + 1]; array[num21++] = array6[num24 * 4 + 2]; array[num21++] = array6[num24 * 4 + 3]; } } } } catch (Exception) { } var bitmap = new Bitmap(num, num2, PixelFormat.Format32bppRgb); var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); Marshal.Copy(array, 0, bitmapData.Scan0, array.Length); bitmap.UnlockBits(bitmapData); return(bitmap); }
public static Bitmap Load(Stream stream) { byte[] headerBytes = new byte[0x80]; stream.Read(headerBytes, 0, headerBytes.Length); if (headerBytes[0] != 0) { throw new ApplicationException("This is not a valid MacPaint file."); } string fileType = Encoding.ASCII.GetString(headerBytes, 0x41, 4); if (fileType != "PNTG") { throw new ApplicationException("This is not a valid MacPaint file."); } int fileNameLen = headerBytes[1]; string fileName = Encoding.ASCII.GetString(headerBytes, 2, fileNameLen); // Not much other useful stuff in the header... stream.Read(headerBytes, 0, 4); uint startMagic = Util.BigEndian(BitConverter.ToUInt32(headerBytes, 0)); if (startMagic != 0x2) { // I have actually seen MacPaint files that do not have this magic value... //throw new ApplicationException("This is not a valid MacPaint file."); } // Skip over pattern data stream.Seek(304, SeekOrigin.Current); // Skip over padding data stream.Seek(204, SeekOrigin.Current); byte[] bmpData = new byte[(MAC_PAINT_WIDTH + 1) * 4 * MAC_PAINT_HEIGHT]; int x = 0, y = 0; RleReader rleReader = new RleReader(stream); try { int b; byte curByte; int bmpPtr = 0; bool val; while (bmpPtr < bmpData.Length) { curByte = (byte)rleReader.ReadByte(); for (b = 7; b >= 0; b--) { val = (curByte & (1 << b)) != 0; bmpData[bmpPtr] = (byte)(val ? 0 : 0xFF); bmpData[bmpPtr + 1] = (byte)(val ? 0 : 0xFF); bmpData[bmpPtr + 2] = (byte)(val ? 0 : 0xFF); bmpPtr += 4; x++; if (x >= MAC_PAINT_WIDTH) { x = 0; y++; } } } } catch (Exception e) { //give a partial image in case of unexpected end-of-file System.Diagnostics.Debug.WriteLine("Error while processing MacPaint file: " + e.Message); } var bmp = new Bitmap(MAC_PAINT_WIDTH, MAC_PAINT_HEIGHT, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Drawing.Imaging.BitmapData bmpBits = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Runtime.InteropServices.Marshal.Copy(bmpData, 0, bmpBits.Scan0, MAC_PAINT_WIDTH * 4 * MAC_PAINT_HEIGHT); bmp.UnlockBits(bmpBits); return(bmp); }
/// <summary> /// Reads a PCX image from a stream. /// </summary> /// <param name="stream">Stream from which to read the image.</param> /// <returns>Bitmap that contains the image that was read.</returns> public static Bitmap Load(Stream stream) { int imgWidth = -1; int imgHeight = -1; int imgBpp = -1; Bitmap theBitmap = null; BinaryReader reader = new BinaryReader(stream); byte tempByte = (byte)stream.ReadByte(); if (tempByte != 10) { throw new ApplicationException("This is not a valid PCX file."); } tempByte = (byte)stream.ReadByte(); if (tempByte < 3 || tempByte > 5) { throw new ApplicationException("Only Version 3, 4, and 5 PCX files are supported."); } tempByte = (byte)stream.ReadByte(); if (tempByte != 1) { throw new ApplicationException("Invalid PCX compression type."); } imgBpp = stream.ReadByte(); if (imgBpp != 8 && imgBpp != 4 && imgBpp != 2 && imgBpp != 1) { throw new ApplicationException("Only 8, 4, 2, and 1-bit PCX samples are supported."); } UInt16 xmin = Util.LittleEndian(reader.ReadUInt16()); UInt16 ymin = Util.LittleEndian(reader.ReadUInt16()); UInt16 xmax = Util.LittleEndian(reader.ReadUInt16()); UInt16 ymax = Util.LittleEndian(reader.ReadUInt16()); imgWidth = xmax - xmin + 1; imgHeight = ymax - ymin + 1; if ((imgWidth < 1) || (imgHeight < 1) || (imgWidth > 32767) || (imgHeight > 32767)) { throw new ApplicationException("This PCX file appears to have invalid dimensions."); } Util.LittleEndian(reader.ReadUInt16()); //hdpi Util.LittleEndian(reader.ReadUInt16()); //vdpi byte[] colorPalette = new byte[48]; stream.Read(colorPalette, 0, 48); stream.ReadByte(); int numPlanes = stream.ReadByte(); int bytesPerLine = Util.LittleEndian(reader.ReadUInt16()); if (bytesPerLine == 0) { bytesPerLine = xmax - xmin + 1; } /* * HACK: Set the following parameter to true if you want to interpret the bit plane data as literal color states, * instead of indices into the palette. This was done by certain older versions of PaintBrush in EGA mode. * If the colors in your decoded picture look weird, try tweaking this setting. */ bool bitPlanesLiteral = false; // TODO: use this for something? It doesn't seem to be consistent or meaningful between different versions. Util.LittleEndian(reader.ReadUInt16()); if (imgBpp == 8 && numPlanes == 1) { colorPalette = new byte[768]; stream.Seek(-768, SeekOrigin.End); stream.Read(colorPalette, 0, 768); } //fix color palette if it's a 1-bit image, and there's no palette information if (imgBpp == 1) { if ((colorPalette[0] == colorPalette[3]) && (colorPalette[1] == colorPalette[4]) && (colorPalette[2] == colorPalette[5])) { colorPalette[0] = colorPalette[1] = colorPalette[2] = 0; colorPalette[3] = colorPalette[4] = colorPalette[5] = 0xFF; } } byte[] bmpData = new byte[(imgWidth + 1) * 4 * imgHeight]; stream.Seek(128, SeekOrigin.Begin); int x = 0, y = 0, i; RleReader rleReader = new RleReader(stream); try { if (imgBpp == 1) { int b, p; byte val; byte[] scanline = new byte[bytesPerLine]; byte[] realscanline = new byte[bytesPerLine * 8]; for (y = 0; y < imgHeight; y++) { //add together all the planes... Array.Clear(realscanline, 0, realscanline.Length); for (p = 0; p < numPlanes; p++) { x = 0; for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); for (b = 7; b >= 0; b--) { if ((scanline[i] & (1 << b)) != 0) { val = 1; } else { val = 0; } realscanline[x] |= (byte)(val << p); x++; } } } for (x = 0; x < imgWidth; x++) { i = realscanline[x]; if (numPlanes == 1) { bmpData[4 * (y * imgWidth + x)] = (byte)((i & 1) != 0 ? 0xFF : 0); bmpData[4 * (y * imgWidth + x) + 1] = (byte)((i & 1) != 0 ? 0xFF : 0); bmpData[4 * (y * imgWidth + x) + 2] = (byte)((i & 1) != 0 ? 0xFF : 0); } else { if (bitPlanesLiteral) { bmpData[4 * (y * imgWidth + x)] = (byte)((i & 1) != 0 ? 0xFF : 0); bmpData[4 * (y * imgWidth + x) + 1] = (byte)((i & 2) != 0 ? 0xFF : 0); bmpData[4 * (y * imgWidth + x) + 2] = (byte)((i & 4) != 0 ? 0xFF : 0); } else { bmpData[4 * (y * imgWidth + x)] = colorPalette[i * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[i * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[i * 3]; } } } } } else { if (numPlanes == 1) { if (imgBpp == 8) { byte[] scanline = new byte[bytesPerLine]; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (x = 0; x < imgWidth; x++) { i = scanline[x]; bmpData[4 * (y * imgWidth + x)] = colorPalette[i * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[i * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[i * 3]; } } } else if (imgBpp == 4) { byte[] scanline = new byte[bytesPerLine]; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (x = 0; x < imgWidth; x++) { i = scanline[x / 2]; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 4) & 0xF) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 4) & 0xF) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 4) & 0xF) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[(i & 0xF) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[(i & 0xF) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[(i & 0xF) * 3]; } } } else if (imgBpp == 2) { byte[] scanline = new byte[bytesPerLine]; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanline[i] = (byte)rleReader.ReadByte(); } for (x = 0; x < imgWidth; x++) { i = scanline[x / 4]; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 6) & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 6) & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 6) & 0x3) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 4) & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 4) & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 4) & 0x3) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[((i >> 2) & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[((i >> 2) & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[((i >> 2) & 0x3) * 3]; x++; bmpData[4 * (y * imgWidth + x)] = colorPalette[(i & 0x3) * 3 + 2]; bmpData[4 * (y * imgWidth + x) + 1] = colorPalette[(i & 0x3) * 3 + 1]; bmpData[4 * (y * imgWidth + x) + 2] = colorPalette[(i & 0x3) * 3]; } } } } else if (numPlanes == 3) { byte[] scanlineR = new byte[bytesPerLine]; byte[] scanlineG = new byte[bytesPerLine]; byte[] scanlineB = new byte[bytesPerLine]; int bytePtr = 0; for (y = 0; y < imgHeight; y++) { for (i = 0; i < bytesPerLine; i++) { scanlineR[i] = (byte)rleReader.ReadByte(); } for (i = 0; i < bytesPerLine; i++) { scanlineG[i] = (byte)rleReader.ReadByte(); } for (i = 0; i < bytesPerLine; i++) { scanlineB[i] = (byte)rleReader.ReadByte(); } for (int n = 0; n < imgWidth; n++) { bmpData[bytePtr++] = scanlineB[n]; bmpData[bytePtr++] = scanlineG[n]; bmpData[bytePtr++] = scanlineR[n]; bytePtr++; } } } }//bpp } catch (Exception e) { //give a partial image in case of unexpected end-of-file System.Diagnostics.Debug.WriteLine("Error while processing PCX file: " + e.Message); } theBitmap = new Bitmap((int)imgWidth, (int)imgHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Drawing.Imaging.BitmapData bmpBits = theBitmap.LockBits(new Rectangle(0, 0, theBitmap.Width, theBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb); System.Runtime.InteropServices.Marshal.Copy(bmpData, 0, bmpBits.Scan0, imgWidth * 4 * imgHeight); theBitmap.UnlockBits(bmpBits); return(theBitmap); }
public static Bitmap Load(Stream stream) { var num = -1; var num2 = -1; var binaryReader = new BinaryReader(stream); var b = (byte)stream.ReadByte(); if (b != 10) { throw new ApplicationException("This is not a valid PCX file."); } b = (byte)stream.ReadByte(); if (b < 3 || b > 5) { throw new ApplicationException("Only Version 3, 4, and 5 PCX files are supported."); } b = (byte)stream.ReadByte(); if (b != 1) { throw new ApplicationException("Invalid PCX compression type."); } var num3 = stream.ReadByte(); if (num3 != 8 && num3 != 4 && num3 != 2 && num3 != 1) { throw new ApplicationException("Only 8, 4, 2, and 1-bit PCX samples are supported."); } var num4 = LittleEndian(binaryReader.ReadUInt16()); var num5 = LittleEndian(binaryReader.ReadUInt16()); var num6 = LittleEndian(binaryReader.ReadUInt16()); var num7 = (int)LittleEndian(binaryReader.ReadUInt16()); num = (int)(num6 - num4 + 1); num2 = num7 - (int)num5 + 1; if (num < 1 || num2 < 1 || num > 32767 || num2 > 32767) { throw new ApplicationException("This PCX file appears to have invalid dimensions."); } LittleEndian(binaryReader.ReadUInt16()); LittleEndian(binaryReader.ReadUInt16()); var array = new byte[48]; stream.Read(array, 0, 48); stream.ReadByte(); var num8 = stream.ReadByte(); var num9 = (int)LittleEndian(binaryReader.ReadUInt16()); if (num9 == 0) { num9 = (int)(num6 - num4 + 1); } if (num3 == 8 && num8 == 1) { array = new byte[768]; stream.Seek(-768L, SeekOrigin.End); stream.Read(array, 0, 768); } if (num3 == 1 && array[0] == array[3] && array[1] == array[4] && array[2] == array[5]) { array[0] = (array[1] = (array[2] = 0)); array[3] = (array[4] = (array[5] = byte.MaxValue)); } var array2 = new byte[(num + 1) * 4 * num2]; stream.Seek(128L, SeekOrigin.Begin); var rleReader = new RleReader(stream); try { if (num3 == 1) { var array3 = new byte[num9]; var array4 = new byte[num9 * 8]; for (var i = 0; i < num2; i++) { Array.Clear(array4, 0, array4.Length); for (var j = 0; j < num8; j++) { var k = 0; for (var l = 0; l < num9; l++) { array3[l] = (byte)rleReader.ReadByte(); for (var m = 7; m >= 0; m--) { byte b2; if (((int)array3[l] & 1 << m) != 0) { b2 = 1; } else { b2 = 0; } var array5 = array4; var num10 = k; array5[num10] |= (byte)(b2 << j); k++; } } } for (var k = 0; k < num; k++) { var l = (int)array4[k]; array2[4 * (i * num + k)] = array[l * 3 + 2]; array2[4 * (i * num + k) + 1] = array[l * 3 + 1]; array2[4 * (i * num + k) + 2] = array[l * 3]; } } } else if (num8 == 1) { if (num3 == 8) { var array6 = new byte[num9]; for (var i = 0; i < num2; i++) { for (var l = 0; l < num9; l++) { array6[l] = (byte)rleReader.ReadByte(); } for (var k = 0; k < num; k++) { var l = (int)array6[k]; array2[4 * (i * num + k)] = array[l * 3 + 2]; array2[4 * (i * num + k) + 1] = array[l * 3 + 1]; array2[4 * (i * num + k) + 2] = array[l * 3]; } } } else if (num3 == 4) { var array7 = new byte[num9]; for (var i = 0; i < num2; i++) { for (var l = 0; l < num9; l++) { array7[l] = (byte)rleReader.ReadByte(); } for (var k = 0; k < num; k++) { var l = (int)array7[k / 2]; array2[4 * (i * num + k)] = array[(l >> 4 & 15) * 3 + 2]; array2[4 * (i * num + k) + 1] = array[(l >> 4 & 15) * 3 + 1]; array2[4 * (i * num + k) + 2] = array[(l >> 4 & 15) * 3]; k++; array2[4 * (i * num + k)] = array[(l & 15) * 3 + 2]; array2[4 * (i * num + k) + 1] = array[(l & 15) * 3 + 1]; array2[4 * (i * num + k) + 2] = array[(l & 15) * 3]; } } } else if (num3 == 2) { var array8 = new byte[num9]; for (var i = 0; i < num2; i++) { for (var l = 0; l < num9; l++) { array8[l] = (byte)rleReader.ReadByte(); } for (var k = 0; k < num; k++) { var l = (int)array8[k / 4]; array2[4 * (i * num + k)] = array[(l >> 6 & 3) * 3 + 2]; array2[4 * (i * num + k) + 1] = array[(l >> 6 & 3) * 3 + 1]; array2[4 * (i * num + k) + 2] = array[(l >> 6 & 3) * 3]; k++; array2[4 * (i * num + k)] = array[(l >> 4 & 3) * 3 + 2]; array2[4 * (i * num + k) + 1] = array[(l >> 4 & 3) * 3 + 1]; array2[4 * (i * num + k) + 2] = array[(l >> 4 & 3) * 3]; k++; array2[4 * (i * num + k)] = array[(l >> 2 & 3) * 3 + 2]; array2[4 * (i * num + k) + 1] = array[(l >> 2 & 3) * 3 + 1]; array2[4 * (i * num + k) + 2] = array[(l >> 2 & 3) * 3]; k++; array2[4 * (i * num + k)] = array[(l & 3) * 3 + 2]; array2[4 * (i * num + k) + 1] = array[(l & 3) * 3 + 1]; array2[4 * (i * num + k) + 2] = array[(l & 3) * 3]; } } } } else if (num8 == 3) { var array9 = new byte[num9]; var array10 = new byte[num9]; var array11 = new byte[num9]; var num11 = 0; for (var i = 0; i < num2; i++) { for (var l = 0; l < num9; l++) { array9[l] = (byte)rleReader.ReadByte(); } for (var l = 0; l < num9; l++) { array10[l] = (byte)rleReader.ReadByte(); } for (var l = 0; l < num9; l++) { array11[l] = (byte)rleReader.ReadByte(); } for (var n = 0; n < num; n++) { array2[num11++] = array11[n]; array2[num11++] = array10[n]; array2[num11++] = array9[n]; num11++; } } } } catch (Exception) { } var bitmap = new Bitmap(num, num2, PixelFormat.Format32bppRgb); var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); Marshal.Copy(array2, 0, bitmapData.Scan0, num * 4 * num2); bitmap.UnlockBits(bitmapData); return(bitmap); }