public static VspHeader GetHeader(byte[] bytes) { VspHeader vspHeader = new VspHeader(); vspHeader.xLocation = BitConverter.ToInt16(bytes, 0); vspHeader.yLocation = BitConverter.ToInt16(bytes, 2); vspHeader.width = BitConverter.ToInt16(bytes, 4) - vspHeader.xLocation; vspHeader.height = BitConverter.ToInt16(bytes, 6) - vspHeader.yLocation; vspHeader.is8Bit = bytes[8]; vspHeader.paletteBank = bytes[9]; if (vspHeader.is8Bit != 0) { //vspHeader.width += 7; //vspHeader.width /= 8; vspHeader.unknownA = BitConverter.ToUInt16(bytes, 0x0A); vspHeader.unknownC = BitConverter.ToInt32(bytes, 0x0c); vspHeader.unknown10 = BitConverter.ToInt32(bytes, 0x10); vspHeader.unknown14 = BitConverter.ToInt32(bytes, 0x14); vspHeader.unknown18 = BitConverter.ToInt32(bytes, 0x18); vspHeader.unknown1C = BitConverter.ToInt32(bytes, 0x1c); } return(vspHeader); }
public static void SaveImage(Stream stream, FreeImageBitmap bitmap) { string comment = bitmap.Comment; var vspHeader = new VspHeader(); if (!String.IsNullOrEmpty(comment)) { vspHeader.ParseComment(comment); } if (bitmap.ColorDepth != 4 && bitmap.ColorDepth != 8) { if (bitmap.ColorDepth > 8) { if (bitmap.ColorDepth == 32) { bitmap.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP); } if (vspHeader.is8Bit == 0) { bitmap.Quantize(FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, 16); } else { bitmap.Quantize(FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, 256); } } //throw new ArgumentException("image must be 4-bit or 8-bit"); } if ((bitmap.Width & 7) != 0) { int slackPixels = (bitmap.Width & 7); int pixelsToAdd = 8 - slackPixels; bitmap.EnlargeCanvas <RGBQUAD>(0, 0, pixelsToAdd, 0, new RGBQUAD(Color.Black)); } if (vspHeader.is8Bit == 0) { vspHeader.height = bitmap.Height; vspHeader.width = bitmap.Width / 8; SaveHeader(vspHeader, stream); SavePalette(bitmap.Palette, stream); SaveImageData(stream, bitmap); } else { vspHeader.height = bitmap.Height; if (vspHeader.width != bitmap.Width - 1) { } vspHeader.width = bitmap.Width - 1; SaveHeader(vspHeader, stream); var pmsHeader = vspHeader.ToPmsHeader(); Pms.SavePalette(stream, bitmap.Palette); Pms.SaveImageData8Bit(stream, bitmap); } }
/* * Get palette from raw data * pal: palette to be stored * b : raw data (pointer to palette) */ public static void GetPalette(Palette palette, byte[] bytes, VspHeader vspHeader) { int red, green, blue, i; int address = 0x0A; for (i = 0; i < 16; i++) { blue = bytes[i * 3 + 0 + address]; red = bytes[i * 3 + 1 + address]; green = bytes[i * 3 + 2 + address]; red = (red & 0x0F) * 17; green = (green & 0x0F) * 17; blue = (blue & 0x0F) * 17; palette[i] = Color.FromArgb(red, green, blue); } }
public static void SaveHeader(VspHeader vspHeader, Stream stream) { var bw = new BinaryWriter(stream); bw.Write((short)vspHeader.xLocation); bw.Write((short)vspHeader.yLocation); bw.Write((short)(vspHeader.width + vspHeader.xLocation)); bw.Write((short)(vspHeader.height + vspHeader.yLocation)); bw.Write((byte)vspHeader.is8Bit); bw.Write((byte)vspHeader.paletteBank); if (vspHeader.is8Bit == 1) { bw.Write((ushort)vspHeader.unknownA); bw.Write(vspHeader.unknownC); bw.Write(vspHeader.unknown10); bw.Write(vspHeader.unknown14); bw.Write(vspHeader.unknown18); bw.Write(vspHeader.unknown1C); } }
public static byte[] GetImage(VspHeader vspHeader, byte[] bytes) { int address = 0x3A; byte[] pic = new byte[vspHeader.height * vspHeader.width * 8]; int c0; byte b0, b1, b2, b3, mask = 0; byte[] bt; int i, l, x, y, pl, loc; bp[0] = _bp[0]; bc[0] = _bc[0]; bp[1] = _bp[1]; bc[1] = _bc[1]; bp[2] = _bp[2]; bc[2] = _bc[2]; bp[3] = _bp[3]; bc[3] = _bc[3]; for (x = 0; x < vspHeader.width; x++) { for (pl = 0; pl < 4; pl++) { y = 0; while (y < vspHeader.height) { c0 = bytes[address++]; if (c0 >= 0x08) { //literal bc[pl][y] = (byte)c0; y++; } else if (c0 == 0x00) { //take L+1 bytes from previous column (same plane) l = bytes[address] + 1; address++; memcpy(bc[pl], bp[pl], y, l); y += l; } else if (c0 == 0x01) { //RLE run: L+1 bytes long l = bytes[address] + 1; address++; b0 = bytes[address++]; memset(bc[pl], y, b0, l); y += l; } else if (c0 == 0x02) { //Alternating RLE run: (L+1)*2 bytes long l = bytes[address] + 1; address++; b0 = bytes[address++]; b1 = bytes[address++]; for (i = 0; i < l; i++) { bc[pl][y] = b0; y++; bc[pl][y] = b1; y++; } } else if (c0 == 0x03) { //Copy from plane 0 xor Mask, set mask to 0 l = bytes[address] + 1; address++; for (i = 0; i < l; i++) { bc[pl][y] = (byte)(bc[0][y] ^ mask); y++; } mask = 0; } else if (c0 == 0x04) { //Copy from plane 1 xor Mask, set mask to 0 l = bytes[address] + 1; address++; for (i = 0; i < l; i++) { bc[pl][y] = (byte)(bc[1][y] ^ mask); y++; } mask = 0; } else if (c0 == 0x05) { //Copy from plane 2 xor Mask, set mask to 0 l = bytes[address] + 1; address++; for (i = 0; i < l; i++) { bc[pl][y] = (byte)(bc[2][y] ^ mask); y++; } mask = 0; } else if (c0 == 0x06) { //set mask to FF mask = 0xff; } else if (c0 == 0x07) { //Escaped literal bc[pl][y] = bytes[address++]; y++; } } } /* conversion from plane -> packed bytes */ for (y = 0; y < vspHeader.height; y++) { loc = (y * vspHeader.width + x) * 8; b0 = bc[0][y]; b1 = bc[1][y]; b2 = bc[2][y]; b3 = bc[3][y]; pic[loc + 0] = (byte)(((b0 >> 7) & 0x01) | ((b1 >> 6) & 0x02) | ((b2 >> 5) & 0x04) | ((b3 >> 4) & 0x08)); pic[loc + 1] = (byte)(((b0 >> 6) & 0x01) | ((b1 >> 5) & 0x02) | ((b2 >> 4) & 0x04) | ((b3 >> 3) & 0x08)); pic[loc + 2] = (byte)(((b0 >> 5) & 0x01) | ((b1 >> 4) & 0x02) | ((b2 >> 3) & 0x04) | ((b3 >> 2) & 0x08)); pic[loc + 3] = (byte)(((b0 >> 4) & 0x01) | ((b1 >> 3) & 0x02) | ((b2 >> 2) & 0x04) | ((b3 >> 1) & 0x08)); pic[loc + 4] = (byte)(((b0 >> 3) & 0x01) | ((b1 >> 2) & 0x02) | ((b2 >> 1) & 0x04) | ((b3) & 0x08)); pic[loc + 5] = (byte)(((b0 >> 2) & 0x01) | ((b1 >> 1) & 0x02) | ((b2) & 0x04) | ((b3 << 1) & 0x08)); pic[loc + 6] = (byte)(((b0 >> 1) & 0x01) | ((b1) & 0x02) | ((b2 << 1) & 0x04) | ((b3 << 2) & 0x08)); pic[loc + 7] = (byte)(((b0) & 0x01) | ((b1 << 1) & 0x02) | ((b2 << 2) & 0x04) | ((b3 << 3) & 0x08)); } /* bc -> bp swap */ bt = bp[0]; bp[0] = bc[0]; bc[0] = bt; bt = bp[1]; bp[1] = bc[1]; bc[1] = bt; bt = bp[2]; bp[2] = bc[2]; bc[2] = bt; bt = bp[3]; bp[3] = bc[3]; bc[3] = bt; } return(pic); }