private static int pngToXnb(string pngFile, string xnbFile, bool compressed, bool reach, bool premultiply) { using (Bitmap png = new Bitmap(pngFile)) { using (FileStream outFs = new FileStream(xnbFile, FileMode.Create, FileAccess.Write)) { using (BinaryWriterWrapper bw = new BinaryWriterWrapper(new BinaryWriter(outFs))) { bw.WriteChars("XNB"); // format-identifier bw.WriteChars("w"); // target-platform bw.WriteByte((byte)5); // xnb-format-version byte flagBits = 0; if (!reach) { flagBits |= 0x01; } if (compressed) { flagBits |= 0x80; } bw.WriteByte(flagBits); // flag-bits; 00=reach, 01=hiprofile, 80=compressed, 00=uncompressed if (compressed) { writeCompressedData(bw, png, premultiply); } else { bw.WriteInt(compressedFileSize(png)); // compressed file size writeData(png, bw, premultiply); } return(1); } } } }
private static void writeCompressedData(BinaryWriterWrapper bw, Bitmap png, bool premultiply) { using (MemoryStream stream = new MemoryStream()) { byte[] uncompressedData; using (BinaryWriterWrapper mw = new BinaryWriterWrapper(new BinaryWriter(stream))) { writeData(png, mw, premultiply); uncompressedData = stream.ToArray(); } byte[] compressedData = XCompress.Compress(uncompressedData); bw.WriteInt(6 + 4 + 4 + compressedData.Length); // compressed file size including headers bw.WriteInt(uncompressedData.Length); // uncompressed data size (exluding headers! only the data) bw.WriteByteArray(compressedData); } }
private static void writeData(Bitmap png, BinaryWriterWrapper bw, bool premultiply) { bw.Write7BitEncodedInt(1); // type-reader-count bw.WriteString(TEXTURE_2D_TYPE); // type-reader-name bw.WriteInt(0); // reader version number bw.Write7BitEncodedInt(0); // shared-resource-count // writing the image pixel data bw.WriteByte(1); // type id + 1 (referencing the TEXTURE_2D_TYPE) bw.WriteInt(0); // surface format; 0=color bw.WriteInt(png.Width); bw.WriteInt(png.Height); bw.WriteInt(1); // mip count bw.WriteInt(imageSize(png)); // number of bytes in the image pixel data BitmapData bitmapData = png.LockBits(new Rectangle(0, 0, png.Width, png.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); try { var length = bitmapData.Stride * bitmapData.Height; byte[] bytes = new byte[length]; Marshal.Copy(bitmapData.Scan0, bytes, 0, length); for (int i = 0; i < bytes.Length; i += 4) { // always swap red and blue channels // premultiply alpha if requested int a = bytes[i + 3]; if (!premultiply || a == 255) { // No premultiply necessary byte b = bytes[i]; bytes[i] = bytes[i + 2]; bytes[i + 2] = b; } else if (a != 0) { byte b = bytes[i]; bytes[i] = (byte)(bytes[i + 2] * a / 255); bytes[i + 1] = (byte)(bytes[i + 1] * a / 255); bytes[i + 2] = (byte)(b * a / 255); } else { // alpha is zero, so just zero everything bytes[i] = 0; bytes[i + 1] = 0; bytes[i + 2] = 0; } } bw.WriteByteArray(bytes); } finally { png.UnlockBits(bitmapData); } }