mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-07 14:31:00 +00:00
Update visualization bitmap API
The existing API was better suited to direct color than indexed color. The NES visualizer was using a slightly silly hack to avoid duplicate colors; this has been removed.
This commit is contained in:
parent
92f304a030
commit
75ccffe393
@ -25,6 +25,10 @@ namespace CommonUtil {
|
||||
/// <remarks>
|
||||
/// This has only been tested with the GIF images created by the Windows Media GifEncoder,
|
||||
/// which are GIF89a with no global color table.
|
||||
///
|
||||
/// References:
|
||||
/// https://www.w3.org/Graphics/GIF/spec-gif87.txt
|
||||
/// https://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
||||
/// </remarks>
|
||||
public class UnpackedGif {
|
||||
//
|
||||
|
@ -308,20 +308,23 @@ namespace PluginCommon {
|
||||
/// </summary>
|
||||
int Height { get; }
|
||||
|
||||
//void SetPixelIndex(int x, int y, byte colorIndex);
|
||||
//int GetPixel(int x, int y); // returns ARGB value
|
||||
|
||||
/// <summary>
|
||||
/// Returns a densely-packed array of color indices or ARGB values.
|
||||
/// Returns a densely-packed array of color indices or ARGB values. Color index
|
||||
/// values may be remapped from what was originally set to improve compression.
|
||||
///
|
||||
/// Do not modify.
|
||||
/// </summary>
|
||||
byte[] GetPixels();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the color palette as a series of 32-bit ARGB values. Will be null for
|
||||
/// direct-color images.
|
||||
/// Do not modify.
|
||||
/// Returns the color palette as a series of 32-bit ARGB values. Duplicate entries
|
||||
/// may have been merged to improve compression.
|
||||
///
|
||||
/// Will be null for direct-color images. Do not modify.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's possible, but weird, for the array to have a length of zero.
|
||||
/// </remarks>
|
||||
int[] GetPalette();
|
||||
|
||||
// TODO(maybe): report pixel aspect ratio?
|
||||
|
@ -22,6 +22,9 @@ namespace PluginCommon {
|
||||
/// <summary>
|
||||
/// Bitmap with 8-bit palette indices, for use with visualization generators.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The bitmap is initially filled with color index 0.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
public class VisBitmap8 : IVisualization2d {
|
||||
public const int MAX_DIMENSION = 4096;
|
||||
@ -34,7 +37,7 @@ namespace PluginCommon {
|
||||
|
||||
private byte[] mData;
|
||||
private int[] mPalette;
|
||||
private int mNextColorIdx;
|
||||
private int mMaxColorIndex;
|
||||
|
||||
|
||||
/// <summary>
|
||||
@ -51,10 +54,11 @@ namespace PluginCommon {
|
||||
Height = height;
|
||||
|
||||
mData = new byte[width * height];
|
||||
mPalette = new int[256];
|
||||
mNextColorIdx = 0;
|
||||
mPalette = new int[256]; // entries initialize to 0, i.e. transparent black
|
||||
mMaxColorIndex = 0;
|
||||
}
|
||||
|
||||
//[Obsolete("use GetPixelIndex()")]
|
||||
public int GetPixel(int x, int y) {
|
||||
byte pix = mData[x + y * Width];
|
||||
return mPalette[pix];
|
||||
@ -75,9 +79,9 @@ namespace PluginCommon {
|
||||
throw new ArgumentException("Bad x/y: " + x + "," + y + " (width=" + Width +
|
||||
" height=" + Height + ")");
|
||||
}
|
||||
if (colorIndex < 0 || colorIndex >= mNextColorIdx) {
|
||||
if (colorIndex < 0 || colorIndex >= mMaxColorIndex) {
|
||||
throw new ArgumentException("Bad color: " + colorIndex + " (nextCol=" +
|
||||
mNextColorIdx + ")");
|
||||
mMaxColorIndex + ")");
|
||||
}
|
||||
mData[x + y * Width] = colorIndex;
|
||||
}
|
||||
@ -87,9 +91,9 @@ namespace PluginCommon {
|
||||
/// </summary>
|
||||
/// <param name="colorIndex">Color index.</param>
|
||||
public void SetAllPixelIndices(byte colorIndex) {
|
||||
if (colorIndex < 0 || colorIndex >= mNextColorIdx) {
|
||||
if (colorIndex < 0 || colorIndex >= mMaxColorIndex) {
|
||||
throw new ArgumentException("Bad color: " + colorIndex + " (nextCol=" +
|
||||
mNextColorIdx + ")");
|
||||
mMaxColorIndex + ")");
|
||||
}
|
||||
for (int i = 0; i < mData.Length; i++) {
|
||||
mData[i] = colorIndex;
|
||||
@ -98,13 +102,15 @@ namespace PluginCommon {
|
||||
|
||||
// IVisualization2d
|
||||
public byte[] GetPixels() {
|
||||
// TODO: remap any duplicate colors to reduce size of GIF
|
||||
return mData;
|
||||
}
|
||||
|
||||
// IVisualization2d
|
||||
public int[] GetPalette() {
|
||||
int[] pal = new int[mNextColorIdx];
|
||||
for (int i = 0; i < mNextColorIdx; i++) {
|
||||
// TODO: remove any duplicate colors to reduce size of GIF
|
||||
int[] pal = new int[mMaxColorIndex];
|
||||
for (int i = 0; i < mMaxColorIndex; i++) {
|
||||
pal[i] = mPalette[i];
|
||||
}
|
||||
return pal;
|
||||
@ -116,20 +122,21 @@ namespace PluginCommon {
|
||||
/// effect.
|
||||
/// </summary>
|
||||
/// <param name="color">32-bit ARGB color value.</param>
|
||||
//[Obsolete("use SetColor()")]
|
||||
public void AddColor(int color) {
|
||||
if (mNextColorIdx == 256) {
|
||||
if (mMaxColorIndex == 256) {
|
||||
Debug.WriteLine("Palette is full");
|
||||
return;
|
||||
}
|
||||
// I'm expecting palettes to only have a few colors, so O(n^2) is fine for now.
|
||||
for (int i = 0; i < mNextColorIdx; i++) {
|
||||
for (int i = 0; i < mMaxColorIndex; i++) {
|
||||
if (mPalette[i] == color) {
|
||||
Debug.WriteLine("Color " + color.ToString("x6") +
|
||||
" already exists in palette (" + i + ")");
|
||||
return;
|
||||
}
|
||||
}
|
||||
mPalette[mNextColorIdx++] = color;
|
||||
mPalette[mMaxColorIndex++] = color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -140,10 +147,33 @@ namespace PluginCommon {
|
||||
/// <param name="r">Red value.</param>
|
||||
/// <param name="g">Green value.</param>
|
||||
/// <param name="b">Blue value.</param>
|
||||
//[Obsolete("use SetColor()")]
|
||||
public void AddColor(byte a, byte r, byte g, byte b) {
|
||||
AddColor(Util.MakeARGB(a, r, g, b));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Nth entry in the color palette.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The size of the color palette will expand to hold the largest index. For best
|
||||
/// results, start with index 0 and count up, avoiding duplicates.
|
||||
/// </remarks>
|
||||
/// <param name="index">Palette index, 0-255.</param>
|
||||
/// <param name="a">Alpha value.</param>
|
||||
/// <param name="r">Red value.</param>
|
||||
/// <param name="g">Green value.</param>
|
||||
/// <param name="b">Blue value.</param>
|
||||
public void SetColor(int index, byte a, byte r, byte g, byte b) {
|
||||
if (index < 0 || index > 255) {
|
||||
throw new ArgumentException("Invalid index: " + index);
|
||||
}
|
||||
mPalette[index] = Util.MakeARGB(a, r, g, b);
|
||||
if (index >= mMaxColorIndex) {
|
||||
mMaxColorIndex = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws an 8x8 character cell on the bitmap.
|
||||
/// </summary>
|
||||
|
@ -886,7 +886,7 @@ namespace SourceGen {
|
||||
#if false
|
||||
// try feeding the animated GIF into our GIF unpacker
|
||||
using (MemoryStream ms = new MemoryStream()) {
|
||||
encoder.Save(ms);
|
||||
encoder.Save(ms, out dispWidth, out dispHeight);
|
||||
Debug.WriteLine("TESTING");
|
||||
UnpackedGif anim = UnpackedGif.Create(ms.GetBuffer());
|
||||
anim.DebugDump();
|
||||
|
@ -276,29 +276,29 @@ namespace RuntimeData.Nintendo {
|
||||
}
|
||||
|
||||
private void SetPalette(VisBitmap8 vb, Palette pal) {
|
||||
vb.AddColor(0, 0, 0, 0); // 0=transparent
|
||||
vb.AddColor(0xff, 0x01, 0x01, 0x01); // 1=near black (so VB doesn't uniquify)
|
||||
vb.AddColor(0xff, 0xfe, 0xfe, 0xfe); // 2=near white
|
||||
vb.SetColor((byte)Color.Transparent, 0x00, 0x00, 0x00, 0x00);
|
||||
vb.SetColor((byte)Color.Black, 0xff, 0x00, 0x00, 0x00);
|
||||
vb.SetColor((byte)Color.White, 0xff, 0xff, 0xff, 0xff);
|
||||
|
||||
switch (pal) {
|
||||
case Palette.Greyscale:
|
||||
default:
|
||||
vb.AddColor(0xff, 0x00, 0x00, 0x00); // black
|
||||
vb.AddColor(0xff, 0x80, 0x80, 0x80); // dark grey
|
||||
vb.AddColor(0xff, 0xb0, 0xb0, 0xb0); // medium grey
|
||||
vb.AddColor(0xff, 0xe0, 0xe0, 0xe0); // light grey
|
||||
vb.SetColor((byte)Color.Color0, 0xff, 0x00, 0x00, 0x00); // black
|
||||
vb.SetColor((byte)Color.Color1, 0xff, 0x80, 0x80, 0x80); // dark grey
|
||||
vb.SetColor((byte)Color.Color2, 0xff, 0xb0, 0xb0, 0xb0); // medium grey
|
||||
vb.SetColor((byte)Color.Color3, 0xff, 0xe0, 0xe0, 0xe0); // light grey
|
||||
break;
|
||||
case Palette.Pinkish:
|
||||
vb.AddColor(0xff, 0x49, 0x99, 0xfe); // sky blue
|
||||
vb.AddColor(0xff, 0xff, 0xbd, 0xaf); // pinkish
|
||||
vb.AddColor(0xff, 0xcd, 0x50, 0x00); // dark orange
|
||||
vb.AddColor(0xff, 0x00, 0x00, 0x00); // black
|
||||
vb.SetColor((byte)Color.Color0, 0xff, 0x49, 0x99, 0xfe); // sky blue
|
||||
vb.SetColor((byte)Color.Color1, 0xff, 0xff, 0xbd, 0xaf); // pinkish
|
||||
vb.SetColor((byte)Color.Color2, 0xff, 0xcd, 0x50, 0x00); // dark orange
|
||||
vb.SetColor((byte)Color.Color3, 0xff, 0x00, 0x00, 0x00); // black
|
||||
break;
|
||||
case Palette.Greenish:
|
||||
vb.AddColor(0xff, 0x49, 0x99, 0xfe); // sky blue
|
||||
vb.AddColor(0xff, 0x00, 0xa4, 0x00); // medium green
|
||||
vb.AddColor(0xff, 0xfc, 0xfc, 0xfc); // near white
|
||||
vb.AddColor(0xff, 0xff, 0x99, 0x2b); // orange
|
||||
vb.SetColor((byte)Color.Color0, 0xff, 0x49, 0x99, 0xfe); // sky blue
|
||||
vb.SetColor((byte)Color.Color1, 0xff, 0x00, 0xa4, 0x00); // medium green
|
||||
vb.SetColor((byte)Color.Color2, 0xff, 0xfc, 0xfc, 0xfc); // near white
|
||||
vb.SetColor((byte)Color.Color3, 0xff, 0xff, 0x99, 0x2b); // orange
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -15,19 +15,17 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using CommonWPF;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using CommonUtil;
|
||||
using CommonWPF;
|
||||
|
||||
namespace SourceGen.WpfGui {
|
||||
/// <summary>
|
||||
/// Export an image from the visualization editor.
|
||||
@ -157,9 +155,19 @@ namespace SourceGen.WpfGui {
|
||||
GifBitmapEncoder encoder = new GifBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(outImage));
|
||||
|
||||
#if false
|
||||
// try feeding the GIF into our GIF unpacker
|
||||
using (MemoryStream ms = new MemoryStream()) {
|
||||
encoder.Save(ms);
|
||||
Debug.WriteLine("TESTING");
|
||||
UnpackedGif anim = UnpackedGif.Create(ms.GetBuffer());
|
||||
anim.DebugDump();
|
||||
}
|
||||
#else
|
||||
using (FileStream stream = new FileStream(pathName, FileMode.Create)) {
|
||||
encoder.Save(stream);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// Error handling is a little sloppy, but this shouldn't fail often.
|
||||
|
Loading…
x
Reference in New Issue
Block a user