public static byte[] MakePixelData(byte[] input, ref int w, ref int h, XLIMOrientation x = XLIMOrientation.None) { int width = w; w = XLIMUtil.nlpo2(w); h = XLIMUtil.nlpo2(h); if (!(Math.Min(w, h) < 32)) { w = h = Math.Max(w, h); // resize } byte[] pixels = new byte[w * h * 4]; var orienter = new XLIMOrienter(w, h, x); for (uint i = 0; i < pixels.Length / 4; i++) { var c = orienter.Get(i); var offset = (c.X * 4) + (c.Y * width); Array.Copy(input, offset, pixels, i * 4, 4); } return(pixels); }
public static byte[] getPixelData(Bitmap img, int format, bool rectangle = true) { int w = img.Width; int h = img.Height; bool perfect = w == h && w != 0 && (w & (w - 1)) == 0; if (!perfect) // Check if square power of two, else resize { // Square Format Checks if (rectangle && Math.Min(img.Width, img.Height) < 32) { w = XLIMUtil.nlpo2(img.Width); h = XLIMUtil.nlpo2(img.Height); } else { w = h = Math.Max(XLIMUtil.nlpo2(w), XLIMUtil.nlpo2(h)); // else resize } } using (MemoryStream mz = new MemoryStream()) using (BinaryWriter bz = new BinaryWriter(mz)) { int p = XLIMUtil.gcm(w, 8) / 8; if (p == 0) { p = 1; } for (uint i = 0; i < w * h; i++) { XLIMOrienter.d2xy(i % 64, out uint x, out uint y); // Get Shift Tile uint tile = i / 64; // Shift Tile Coordinate into Tilemap x += (uint)(tile % p) * 8; y += (uint)(tile / p) * 8; // Don't write data Color c; if (x >= img.Width || y >= img.Height) { c = Color.FromArgb(0, 0, 0, 0); } else { c = img.GetPixel((int)x, (int)y); if (c.A == 0) { c = Color.FromArgb(0, 86, 86, 86); } } switch (format) { case 0: bz.Write((byte)GetL8(c)); break; // L8 case 1: bz.Write((byte)GetA8(c)); break; // A8 case 2: bz.Write((byte)GetLA4(c)); break; // LA4(4) case 3: bz.Write((ushort)GetLA8(c)); break; // LA8(8) case 4: bz.Write((ushort)GetHILO8(c)); break; // HILO8 case 5: bz.Write((ushort)GetRGB565(c)); break; // RGB565 case 6: { bz.Write(c.B); bz.Write(c.G); bz.Write(c.R); break; } case 7: bz.Write((ushort)GetRGBA5551(c)); break; // RGBA5551 case 8: bz.Write((ushort)GetRGBA4444(c)); break; // RGBA4444 case 9: bz.Write((uint)GetRGBA8888(c)); break; // RGBA8 case 10: throw new Exception("ETC1 not supported."); case 11: throw new Exception("ETC1A4 not supported."); case 12: { byte val = (byte)(GetL8(c) / 0x11); // First Pix // L4 { c = img.GetPixel((int)x, (int)y); if (c.A == 0) { c = Color.FromArgb(0, 0, 0, 0); } } val |= (byte)((GetL8(c) / 0x11) << 4); i++; bz.Write(val); break; } case 13: { byte val = (byte)(GetA8(c) / 0x11); // First Pix // L4 { c = img.GetPixel((int)x, (int)y); } val |= (byte)((GetA8(c) / 0x11) << 4); i++; bz.Write(val); break; } } } if (!perfect) { while (mz.Length < XLIMUtil.nlpo2((int)mz.Length)) // pad { bz.Write((byte)0); } } return(mz.ToArray()); } }
// BCLIM Data Writing public static int write16BitColorPalette(Bitmap img, ref MemoryStream ms) { using (Stream pixelcolors = new MemoryStream()) using (BinaryWriter bz = new BinaryWriter(pixelcolors)) { // Set up our basis. bool under16colors = false; int colors = getColorCount(img); Color[] pcs = new Color[colors]; if (colors < 16) { under16colors = true; } uint div = 1; if (under16colors) { div = 2; } if (colors > 70) { throw new Exception("Too many colors"); } // Set up a new reverse image to build into. int w = XLIMUtil.gcm(img.Width, 8); int h = XLIMUtil.gcm(img.Height, 8); w = Math.Max(XLIMUtil.nlpo2(w), XLIMUtil.nlpo2(h)); h = w; byte[] pixelarray = new byte[w * h]; const int colorformat = 2; int ctr = 1; pcs[0] = Color.FromArgb(0, 0xFF, 0xFF, 0xFF); int p = XLIMUtil.gcm(w, 8) / 8; if (p == 0) { p = 1; } int d = 0; for (uint i = 0; i < pixelarray.Length; i++) { d = (int)(i / div); // Get Tile Coordinate uint x; uint y; XLIMOrienter.d2xy(i % 64, out x, out y); // Get Shift Tile uint tile = i / 64; // Shift Tile Coordinate into Tilemap x += (uint)(tile % p) * 8; y += (uint)(tile / p) * 8; if (x >= img.Width || y >= img.Height) // Don't try to access any pixel data outside of our bounds. { i++; continue; } // Goto next tile. // Get Color of Pixel Color c = img.GetPixel((int)x, (int)y); // Color Table Building Logic int index = Array.IndexOf(pcs, c); if (c.A == 0) { index = 0; } if (index < 0) // If new color { pcs[ctr] = c; index = ctr; ctr++; } // Add it to color list // Add pixel to pixeldata if (under16colors) { index = index << 4; } pixelarray[i / div] = (byte)index; if (!under16colors) { continue; } c = img.GetPixel((int)x + 1, (int)y); index = Array.IndexOf(pcs, c); if (c.A == 0) { index = 0; } if (index < 0) // If new color { pcs[ctr] = c; index = ctr; ctr++; } pixelarray[i / div] |= (byte)index; i++; } // Write Intro bz.Write((ushort)colorformat); bz.Write((ushort)ctr); // Write Colors for (int i = 0; i < ctr; i++) { bz.Write((ushort)GetRGBA5551(pcs[i])); // Write byte array. } // Write Pixel Data for (uint i = 0; i < d; i++) { bz.Write(pixelarray[i]); } // Write Padding while (pixelcolors.Length < XLIMUtil.nlpo2((int)pixelcolors.Length)) { bz.Write((byte)0); } // Copy to main CLIM. pixelcolors.Position = 0; pixelcolors.CopyTo(ms); } return(7); }