Last active
August 29, 2015 14:24
-
-
Save devinacker/717b0f40180dea48c369 to your computer and use it in GitHub Desktop.
paint.net plugin for Nippon Ichi Software .tx2 images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* this is unfinished */ | |
using System; | |
using System.Windows.Forms; | |
using PaintDotNet; | |
using System.Drawing; | |
public class TX2FileType : FileType { | |
public TX2FileType() : base ("TX2", FileTypeFlags.SupportsLoading, | |
new string[] { ".tx2" }) | |
{ | |
} | |
private ushort ReadUShort(System.IO.Stream stream) { | |
return (ushort)(stream.ReadByte() + (stream.ReadByte() << 8)); | |
} | |
private uint ReadUInt(System.IO.Stream stream) { | |
return (uint)(stream.ReadByte() + (stream.ReadByte() << 8) + (stream.ReadByte() << 16) + (stream.ReadByte() << 24)); | |
} | |
protected override Document OnLoad(System.IO.Stream input) { | |
ushort width = ReadUShort(input); | |
ushort height = ReadUShort(input); | |
if (width * height == 0) { | |
MessageBox.Show("Invalid image dimensions."); | |
return null; | |
} | |
ushort colors = ReadUShort(input); /* only values 16 and 256 have been observed */ | |
if (colors != 16 && colors != 256) { | |
MessageBox.Show("Unsupported color depth. Image must be either 16 or 256 colors."); | |
return null; | |
} | |
ushort unknown = ReadUShort(input); | |
ushort colors2 = ReadUShort(input); /* purpose unknown, but always seems to be the same as colors */ | |
ushort palettes = ReadUShort(input); /* number of palettes. only 1 and 16 observed thus far */ | |
if (palettes > 1) { | |
MessageBox.Show("Image contains multiple palettes. Only the first palette will be used for now."); | |
} else if (palettes == 0) { | |
MessageBox.Show("Image must contain at least one palette."); | |
return null; | |
} | |
// TODO: this assumes a max of 16 palettes and 256 colors | |
var palette = new Color[16, 256]; | |
// TODO: use multiple bitmaps (one per palette) | |
// TODO: use actual paletted bitmaps? (does paint.NET care about this?) | |
var bitmap = new Bitmap(width, height); | |
// read all palettes | |
input.Seek(0x10, System.IO.SeekOrigin.Begin); | |
for (uint p = 0; p < palettes; p++) { | |
for (uint c = 0; c < colors; c++) { | |
uint ci = c; | |
// 256 color images have some weird bit switching going on for color indexes | |
if (colors == 256) { | |
ci = (c & 0xE7) | ((c & 8) << 1) | ((c & 16) >> 1); | |
} | |
uint color = ReadUInt(input); | |
// non-transparent images use 0x80 for all alpha bytes | |
// TODO: verify this with images which use transparency as well | |
var colorA = (int)((color & 0xFF000000) >> 23); | |
if (colorA > 255) colorA = 255; | |
var colorB = (int)((color & 0xFF0000) >> 16); | |
var colorG = (int)((color & 0xFF00) >> 8); | |
var colorR = (int)(color & 0xFF); | |
palette[p, ci] = Color.FromArgb(colorA, colorR, colorG, colorB); | |
} | |
} | |
// read actual bitmap data now | |
// NOTE: this assumes (possibly incorrectly) that the image width is an even number | |
// TODO: swizzle pixels if needed | |
for (int y = 0; y < height; y++) { | |
for (int x = 0; x < width; x++) { | |
byte px1, px2; | |
// get next two pixels | |
if (colors == 256) { | |
px1 = (byte)input.ReadByte(); | |
px2 = (byte)input.ReadByte(); | |
} else { | |
var b = input.ReadByte(); | |
px1 = (byte)(b & 0xf); | |
px2 = (byte)(b >> 4); | |
} | |
// TODO: support all palettes, not just the first | |
bitmap.SetPixel(x, y, palette[0, px1]); | |
x++; | |
bitmap.SetPixel(x, y, palette[0, px2]); | |
} | |
} | |
return Document.FromImage(bitmap); | |
} | |
} | |
public class TX2FileTypeFactory : IFileTypeFactory { | |
public FileType[] GetFileTypeInstances() { | |
return new FileType[] { new TX2FileType() }; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment