private void listView1_SelectedIndexChanged(object sender, EventArgs e) { if (listView1.SelectedIndices.Count <= 0) { return; } if (pictureBox1.Image != null) { Bitmap temp = (Bitmap)pictureBox1.Image; pictureBox1.Image = null; temp.Dispose(); } isLocked = true; PIGImage image = datafile.Bitmaps[listView1.SelectedIndices[0]]; pictureBox1.Image = PiggyBitmapUtilities.GetBitmap(datafile, palette, listView1.SelectedIndices[0]); TransparentCheck.Checked = image.Transparent; SupertransparentCheck.Checked = image.SuperTransparent; NoLightingCheck.Checked = image.NoLighting; CompressCheckBox.Checked = image.RLECompressed; Color color = Color.FromArgb(palette.GetRGBAValue(image.AverageIndex)); ColorPreview.BackColor = color; pictureBox1.Refresh(); isLocked = false; }
/*public void writePiggyImages(string directory, PIGFile piggyfile) * { * int w, h; * byte[] image; * int bytesWritten; * string name; * for (int i = 0; i < piggyfile.images.Count; i++) * { * bytesWritten = 0; * if (!piggyfile.isABM((ushort)i)) * { * image = piggyfile.Bitmaps[i]; * BinaryWriter bw = new BinaryWriter(File.Open(String.Format("{0}{1}.bbm", directory, piggyfile.images[i].name), FileMode.Create)); * //just write the image * WriteBBM(image, * bw.Flush(); * bw.Close(); * bw.Dispose(); * } * else * { * BinaryWriter bw = new BinaryWriter(File.Open(String.Format("{0}{1}.abm", directory, piggyfile.Bitmaps[i].Name), FileMode.Create)); * name = piggyfile.Bitmaps[i].Name; * //write FORM header * bw.Write(0x4D524F46); * //will update later on * long loc = bw.BaseStream.Position; * bw.Write(0); * //Note it as a ANIM * //41 4E 49 4D * bw.Write(0x4D494E41); * bytesWritten += 4; * //write the first frame * bytesWritten += WriteBBM(w, h, image, bw, (piggyfile.images[i].flags & 1) != 0); * while (i < piggyfile.images.Count - 1 && piggyfile.images[i + 1].name == name) * { * i++; * image = piggyfile.loadImage(i); * w = piggyfile.images[i].vx; * h = piggyfile.images[i].vy; * //write animation * bytesWritten += writeABMFrame(w, h, image, bw); * //increment frame * } * bw.BaseStream.Seek(loc, SeekOrigin.Begin); * writeInt32BE(bw, bytesWritten); * bw.Flush(); * bw.Close(); * bw.Dispose(); * } * } * }*/ public void WriteABM(PIGImage[] frames, int numFrames, Palette palette, BinaryWriter bw) { int bytesWritten = 0; PIGImage image = frames[0]; bool transparent = false; for (int i = 0; i < numFrames; i++) { transparent |= frames[i].Transparent; } //write FORM header bw.Write(0x4D524F46); //will update later on long loc = bw.BaseStream.Position; bw.Write(0); //Note it as a ANIM //41 4E 49 4D bw.Write(0x4D494E41); bytesWritten += 4; //write the first frame bytesWritten += WriteBBM(image, palette, transparent, bw); for (int i = 1; i < numFrames; i++) { //write animation bytesWritten += WriteABMFrame(frames[i], palette, bw); } bw.BaseStream.Seek(loc, SeekOrigin.Begin); WriteInt32BE(bw, bytesWritten); bw.Flush(); }
private void CompressCheckBox_CheckedChanged(object sender, EventArgs e) { if (listView1.SelectedItems.Count == 0) { return; } if (isLocked) { return; //will call ourselves in case of an error } isLocked = true; bool currentState = !CompressCheckBox.Checked; try { PIGImage img = datafile.Bitmaps[listView1.SelectedIndices[0]]; img.RLECompressed = CompressCheckBox.Checked; listView1.Items[listView1.SelectedIndices[0]].SubItems[1].Text = img.GetSize().ToString(); } catch (Exception exc) { MessageBox.Show(string.Format("Error compressing image:\r\n{0}", exc.Message)); CompressCheckBox.Checked = currentState; } isLocked = false; }
//I dunno why i'm being as masochistic as I am with this but okay. /// <summary> /// Creates the texture tables for all polygon models in this HXM file. /// </summary> private void BuildModelTextureTables() { //Write down unanimated texture names Dictionary <int, string> TextureNames = new Dictionary <int, string>(); //Write down EClip IDs for tracking animated texture names Dictionary <int, string> EClipNames = new Dictionary <int, string>(); EClip clip; for (int i = 0; i < BaseHAM.EClips.Count; i++) { clip = BaseHAM.EClips[i]; if (clip.ChangingObjectTexture != -1) { EClipNames.Add(clip.ChangingObjectTexture, clip.Name.ToLower()); } } ushort bitmap; string name; for (int i = 0; i < BaseHAM.BaseFile.ObjBitmaps.Count; i++) { bitmap = GetObjBitmap(i); //if (bitmap == 0) continue; PIGImage image = BaseHAM.piggyFile.Bitmaps[bitmap]; name = image.Name.ToLower(); if (!image.IsAnimated) { TextureNames.Add(i, name); } } foreach (Polymodel model in ReplacedModels) { model.UseTextureList = true; int textureID, pointer; for (int i = model.FirstTexture; i < (model.FirstTexture + model.NumTextures); i++) { pointer = GetObjBitmapPointer(i); textureID = GetObjBitmap(pointer); if (EClipNames.ContainsKey(pointer)) { model.TextureList.Add(EClipNames[pointer]); } else if (TextureNames.ContainsKey(pointer)) { model.TextureList.Add(TextureNames[pointer]); } else { model.TextureList.Add("bogus"); } } Console.Write("Model texture list: ["); foreach (string texture in model.TextureList) { Console.Write("{0} ", texture); } Console.WriteLine("]"); model.BaseTexture = FindFirstObjBitmap(model); } }
private string ImageFilename(int index) { PIGImage image = datafile.Bitmaps[index]; if (!image.IsAnimated) { return(image.Name); } else { return(String.Format("{0}+{1}", image.Name, image.DFlags)); } }
public static void DumpPIGToBBM(PIGFile pigFile, Palette palette, string outputFilename) { LBMDecoder encoder = new LBMDecoder(); string directory = Path.GetDirectoryName(outputFilename); int numFrames = 0; PIGImage[] frames = new PIGImage[50]; PIGImage image; for (int i = 0; i < pigFile.Bitmaps.Count; i++) { if (pigFile.Bitmaps[i].IsAnimated) //Special animation hacks { image = pigFile.Bitmaps[i]; if (image.Frame == 0) //Start at the first frame { numFrames = 0; frames[numFrames++] = image; if ((i + 1) >= pigFile.Bitmaps.Count) { return; //out of images } while (image.Name == pigFile.Bitmaps[i + 1].Name) { frames[numFrames] = pigFile.Bitmaps[i + 1]; i++; numFrames++; if ((i + 1) >= pigFile.Bitmaps.Count) { break; //out of images } } BinaryWriter bw = new BinaryWriter(File.OpenWrite(string.Format("{0}{1}{2}.abm", directory, Path.DirectorySeparatorChar, image.Name))); encoder.WriteABM(frames, numFrames, palette, bw); bw.Close(); bw.Dispose(); } } else { image = pigFile.Bitmaps[i]; BinaryWriter bw = new BinaryWriter(File.OpenWrite(string.Format("{0}{1}{2}.bbm", directory, Path.DirectorySeparatorChar, image.Name))); encoder.WriteBBM(image, palette, bw); bw.Close(); bw.Dispose(); } } }
private void InsertMenu_Click(object sender, EventArgs e) { openFileDialog1.Multiselect = true; if (openFileDialog1.ShowDialog() == DialogResult.OK) { foreach (string name in openFileDialog1.FileNames) { Bitmap img = new Bitmap(name); PIGImage bitmap = PiggyBitmapUtilities.CreatePIGImage(img, palette, Path.GetFileName(name).Substring(0, Math.Min(Path.GetFileName(name).Length, 8))); datafile.Bitmaps.Add(bitmap); ListViewItem lvi = GeneratePiggyEntry(datafile.Bitmaps.Count - 1); listView1.Items.Add(lvi); img.Dispose(); } } }
public static Bitmap GetBitmap(IImageProvider piggyFile, Palette palette, int index, int scale = 1) { int[] rgbTable = new int[256]; PIGImage image = piggyFile.Bitmaps[index]; int newWidth = (int)(image.Width * scale); int newHeight = (int)(image.Height * scale); Bitmap bitmap = new Bitmap(newWidth, newHeight); for (int j = 0; j < 256; j++) { rgbTable[j] = ((j == 255 ? 0 : 255) << 24) + (palette[j].R << 16) + (palette[j].G << 8) + (palette[j].B); } int[] rgbData = new int[newWidth * newHeight]; byte[] rawData = image.GetData(); switch (scale) { case 1: Scale1X(image.Width, image.Height, newWidth, newHeight, rawData, rgbData, rgbTable); break; case 2: Scale2X(image.Width, image.Height, newWidth, newHeight, rawData, rgbData, rgbTable); break; case 3: Scale3X(image.Width, image.Height, newWidth, newHeight, rawData, rgbData, rgbTable); break; case 4: Scale4X(image.Width, image.Height, newWidth, newHeight, rawData, rgbData, rgbTable); break; } BitmapData bits = bitmap.LockBits(new Rectangle(0, 0, newWidth, newHeight), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bits.Scan0, newWidth * newHeight); bitmap.UnlockBits(bits); return(bitmap); }
private ListViewItem GeneratePiggyEntry(int i) { PIGImage image = datafile.Bitmaps[i]; ListViewItem lvi = new ListViewItem(image.Name); lvi.SubItems.Add(i.ToString()); lvi.SubItems.Add(image.GetSize().ToString()); lvi.SubItems.Add(string.Format("{0}x{1}", image.Width, image.Height)); if (image.IsAnimated) { lvi.SubItems.Add(image.Frame.ToString()); } else { lvi.SubItems.Add("-1"); } return(lvi); }
private void POGEditor_Load(object sender, EventArgs e) { for (int i = 0; i < datafile.Bitmaps.Count; i++) { PIGImage image = (PIGImage)datafile.Bitmaps[i]; ListViewItem lvi = new ListViewItem(image.Name); lvi.SubItems.Add(image.GetSize().ToString()); if (image.IsAnimated) { lvi.SubItems.Add(image.DFlags.ToString()); } else { lvi.SubItems.Add("-1"); } lvi.SubItems.Add(image.ReplacementNum.ToString()); listView1.Items.Add(lvi); } }
public static PIGImage CreatePIGImage(Bitmap bitmap, byte[] palette, byte[] invCmap, string newname) { if (bitmap.Width >= 4096 || bitmap.Height >= 4096) { throw new Exception("Bitmap resolution is too high for a PIG bitmap"); } PIGImage image = new PIGImage(bitmap.Width, bitmap.Height, 0, 0, 0, 0, newname); byte[] data = new byte[image.Width * image.Height]; byte[] basedata = new byte[image.Width * image.Height * 4]; BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, basedata, 0, basedata.Length); bitmap.UnlockBits(bitmapData); //todo: i dunno it probably can be optimzied int color; for (int i = 0; i < data.Length; i++) { if (basedata[i * 4 + 3] < 255) { image.Transparent = true; color = 255; } else { color = invCmap[(basedata[i * 4 + 2] >> 2) * 4096 + (basedata[i * 4 + 1] >> 2) * 64 + (basedata[i * 4] >> 2)]; } data[i] = (byte)color; } image.Data = data; SetAverageColor(image, palette); //immediately try to compress if at all possible try { image.RLECompressed = true; } catch (Exception) { } //it didn't work return(image); }
private void UpdateImage(int id) { if (pictureBox1.Image != null) { Bitmap temp = (Bitmap)pictureBox1.Image; pictureBox1.Image = null; temp.Dispose(); } PIGImage image = datafile.Bitmaps[listView1.SelectedIndices[0]]; pictureBox1.Image = PiggyBitmapUtilities.GetBitmap(datafile.Bitmaps[id], currentPalette); TransparentCheck.Checked = image.Transparent; SupertransparentCheck.Checked = image.SuperTransparent; NoLightingCheck.Checked = image.NoLighting; CompressCheckBox.Checked = image.RLECompressed; Color color = Color.FromArgb(currentPalette.GetRGBAValue(image.AverageIndex)); ColorPreview.BackColor = color; pictureBox1.Refresh(); }
public static void SetAverageColor(PIGImage image, Palette palette) { byte[] data = image.GetData(); byte c; int totalr = 0, totalg = 0, totalb = 0; for (int i = 0; i < data.Length; i++) { c = data[i]; totalr += palette[c, 0]; totalg += palette[c, 1]; totalb += palette[c, 2]; } totalr /= data.Length; totalg /= data.Length; totalb /= data.Length; image.AverageIndex = (byte)palette.GetNearestColor(totalr, totalg, totalb); }
public static void SetAverageColor(PIGImage image, byte[] palette) { byte[] data = image.GetData(); int c; int totalr = 0, totalg = 0, totalb = 0; for (int i = 0; i < data.Length; i++) { c = data[i] * 3; totalr += palette[c]; totalg += palette[c + 1]; totalb += palette[c + 2]; } totalr /= data.Length; totalg /= data.Length; totalb /= data.Length; image.AverageIndex = (byte)GetNearestColorIndex(totalr, totalg, totalb, palette); }
private void ExportILBMMenu_Click(object sender, EventArgs e) { saveFileDialog1.Filter = "Deluxe Paint Brush|*.bbm"; if (panel.SelectedIndices.Count > 1) { saveFileDialog1.FileName = "ignored"; } else { saveFileDialog1.FileName = ImageFilename(panel.SelectedIndices[0]);//listView1.Items[listView1.SelectedIndices[0]].Text; } if (saveFileDialog1.ShowDialog() == DialogResult.OK) { if (panel.SelectedIndices.Count > 1) { string directory = Path.GetDirectoryName(saveFileDialog1.FileName); foreach (int index in panel.SelectedIndices) { PIGImage image = datafile.Bitmaps[index]; string newpath = directory + Path.DirectorySeparatorChar + ImageFilename(index) + ".bbm"; BinaryWriter bw = new BinaryWriter(File.Open(newpath, FileMode.Create)); lbmDecoder.WriteBBM(image, palette, bw); bw.Flush(); bw.Close(); bw.Dispose(); } } else { if (saveFileDialog1.FileName != "") { PIGImage image = datafile.Bitmaps[panel.SelectedIndices[0]]; BinaryWriter bw = new BinaryWriter(File.Open(saveFileDialog1.FileName, FileMode.Create)); lbmDecoder.WriteBBM(image, palette, bw); bw.Flush(); bw.Close(); bw.Dispose(); } } } }
public static Bitmap GetBitmap(PIGImage image, Palette palette) { Bitmap bitmap = new Bitmap(image.Width, image.Height); int[] rgbData = new int[image.Width * image.Height]; byte[] rawData = image.GetData(); byte b; for (int i = 0; i < rawData.Length; i++) { b = rawData[i]; rgbData[i] = ((b == 255 ? 0 : 255) << 24) + (palette[b].R << 16) + (palette[b].G << 8) + (palette[b].B); } BitmapData bits = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bits.Scan0, image.Width * image.Height); bitmap.UnlockBits(bits); return(bitmap); }
/// <summary> /// /// </summary> //Ultimately, it is too much of a pain to stick to the object bitmap and object bitmap pointer tables //Instead, don't track them at all in the first place. Build a texture list for each model, and only //reconstruct the tables at the time of export public void BuildModelTextureTables() { //Write down unanimated texture names Dictionary <int, string> TextureNames = new Dictionary <int, string>(); //Write down EClip IDs for tracking animated texture names Dictionary <int, string> EClipNames = new Dictionary <int, string>(); EClip clip; for (int i = 0; i < EClips.Count; i++) { clip = EClips[i]; if (clip.ChangingObjectTexture != -1) { EClipNames.Add(clip.ChangingObjectTexture, this.EClips[i].Name.ToLower()); ObjBitmapMapping.Add(this.EClips[i].Name.ToLower(), clip.ChangingObjectTexture); } } ushort bitmap; string name; for (int i = 0; i < BaseFile.ObjBitmaps.Count; i++) { bitmap = BaseFile.ObjBitmaps[i]; //if (bitmap == 0) continue; //UNDONE: it's entirely valid something could have referred to bogus //hack if (bitmap == 65535) { bitmap = 0; } PIGImage image = piggyFile.Bitmaps[bitmap]; name = image.Name.ToLower(); if (!image.IsAnimated) { TextureNames.Add(i, name); if (!ObjBitmapMapping.ContainsKey(name)) { ObjBitmapMapping.Add(name, i); } } } foreach (Polymodel model in Models) { model.UseTextureList = true; int textureID, pointer; for (int i = model.FirstTexture; i < (model.FirstTexture + model.NumTextures); i++) { pointer = BaseFile.ObjBitmapPointers[i]; textureID = BaseFile.ObjBitmaps[pointer]; if (EClipNames.ContainsKey(pointer)) { model.TextureList.Add(EClipNames[pointer]); } else if (TextureNames.ContainsKey(pointer)) { model.TextureList.Add(TextureNames[pointer]); } else { model.TextureList.Add("bogus"); } } Console.Write("Model texture list: ["); foreach (string texture in model.TextureList) { Console.Write("{0} ", texture); } Console.WriteLine("]"); } }
public int WriteBBM(PIGImage image, Palette palette, bool overrideAlpha, BinaryWriter bw) { int bytesWritten = 0; byte[] data = image.GetData(); //write FORM header bw.Write(0x4D524F46); //will update later on long loc = bw.BaseStream.Position; bw.Write(0); //Note it as a PBM bw.Write(0x204D4250); bytesWritten += 4; //Write the BITMAP header bw.Write(0x44484D42);// 42 4D 48 44 WriteInt32BE(bw, 0x14); bytesWritten += 8; //resolution WriteUInt16BE(bw, (ushort)image.Width); WriteUInt16BE(bw, (ushort)image.Height); //offset WriteUInt16BE(bw, 0); WriteUInt16BE(bw, 0); //num planes bw.Write((byte)8); //mask mode if (overrideAlpha) { bw.Write((byte)2); } else { bw.Write((byte)0); } //no compression bw.Write((byte)0); //pad bw.Write((byte)0); //transparent index WriteUInt16BE(bw, 255); //aspect ratio bw.Write((byte)5); bw.Write((byte)6); //screen size WriteUInt16BE(bw, 320); WriteUInt16BE(bw, 200); bytesWritten += 0x14; //Write the palette //43 4D 41 50 bw.Write(0x50414D43); WriteInt32BE(bw, 0x300); bytesWritten += 8; for (int c = 0; c < 256; c++) { bw.Write(palette[c, 0]); bw.Write(palette[c, 1]); bw.Write(palette[c, 2]); } bytesWritten += 0x300; //Write the body //42 4F 44 59 int pixelcount = image.Width * image.Height; bool alignmentHack = false; //To this day I still have no clue what this hack is supposed to be for, //but the original game's IFF decoder seems to require it. It causes problems in DPaint, //which confuses me. if (image.Width % 2 != 0) { pixelcount = (image.Width + 1) * image.Height; alignmentHack = true; } bw.Write(0x59444F42); WriteInt32BE(bw, pixelcount); bytesWritten += 8; if (alignmentHack) { for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { bw.Write(data[y * image.Width + x]); } bw.Write((byte)0); } } else { for (int i = 0; i < pixelcount; i++) { bw.Write(data[i]); } } bytesWritten += pixelcount; long end = bw.BaseStream.Position; bw.BaseStream.Seek(loc, SeekOrigin.Begin); WriteInt32BE(bw, bytesWritten); bw.BaseStream.Seek(end, SeekOrigin.Begin); return(bytesWritten + 8); }
public int WriteABMFrame(PIGImage image, Palette palette, BinaryWriter bw) { int bytesWritten = 0; byte[] data = image.GetData(); //write FORM header bw.Write(0x4D524F46); //will update later on long loc = bw.BaseStream.Position; bw.Write(0); //Note it as a PBM bw.Write(0x204D4250); bytesWritten += 4; //Write the ANHD header //41 4E 48 44 bw.Write(0x44484E41); WriteInt32BE(bw, 40); bytesWritten += 8; //delta mode bw.Write((byte)0); //mask bw.Write((byte)0); //wh for xor mode WriteInt16BE(bw, (short)image.Width); WriteInt16BE(bw, (short)image.Height); //xy for xor mode WriteInt16BE(bw, 0); WriteInt16BE(bw, 0); //abstime WriteInt32BE(bw, 1); //reltime WriteInt32BE(bw, 1); //interleave bw.Write((byte)0); //pad bw.Write((byte)0); //flags WriteInt32BE(bw, 0); //pad bw.Write(new byte[16]); bytesWritten += 40; //Write the body //42 4F 44 59 int pixelcount = image.Width * image.Height; bool alignmentHack = false; //To this day I still have no clue what this hack is supposed to be for, //but the original game's IFF decoder seems to require it. It causes problems in DPaint, //which confuses me. if (image.Width % 2 != 0) { pixelcount = (image.Width + 1) * image.Height; alignmentHack = true; } bw.Write(0x59444F42); WriteInt32BE(bw, pixelcount); bytesWritten += 8; if (alignmentHack) { for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { bw.Write(data[y * image.Width + x]); } bw.Write((byte)0); } } else { for (int i = 0; i < pixelcount; i++) { bw.Write(data[i]); } } bytesWritten += pixelcount; long end = bw.BaseStream.Position; bw.BaseStream.Seek(loc, SeekOrigin.Begin); WriteInt32BE(bw, bytesWritten); bw.BaseStream.Seek(end, SeekOrigin.Begin); return(bytesWritten + 8); }