diff --git a/CommonWPF/AnimatedGifEncoder.cs b/CommonWPF/AnimatedGifEncoder.cs index 2c3dca3..2ce9bd9 100644 --- a/CommonWPF/AnimatedGifEncoder.cs +++ b/CommonWPF/AnimatedGifEncoder.cs @@ -94,7 +94,9 @@ namespace CommonWPF { /// Converts the list of frames into an animated GIF, and writes it to the stream. /// /// Output stream. - public void Save(Stream stream) { + public void Save(Stream stream, out int maxWidth, out int maxHeight) { + maxWidth = maxHeight = -1; + if (Frames.Count == 0) { // nothing to do Debug.Assert(false); @@ -129,8 +131,6 @@ namespace CommonWPF { // otherwise *possible*, but we'd need to decode, update palettes and pixels, and // re-encode.) // - int maxWidth = -1; - int maxHeight = -1; foreach (UnpackedGif gif in gifs) { //gif.DebugDump(); diff --git a/SourceGen/Exporter.cs b/SourceGen/Exporter.cs index 12e2c4a..201a2fe 100644 --- a/SourceGen/Exporter.cs +++ b/SourceGen/Exporter.cs @@ -715,8 +715,11 @@ namespace SourceGen { ".gif"; string pathName = Path.Combine(mImageDirPath, fileName); + int dispWidth, dispHeight; + Visualization vis = visSet[index]; if (vis is VisualizationAnimation) { + // Animated visualization. VisualizationAnimation visAnim = (VisualizationAnimation)vis; int frameDelay = PluginCommon.Util.GetFromObjDict(visAnim.VisGenParams, VisualizationAnimation.FRAME_DELAY_MSEC_PARAM, 330); @@ -745,14 +748,17 @@ namespace SourceGen { // Create new or replace existing image file. try { using (FileStream stream = new FileStream(pathName, FileMode.Create)) { - encoder.Save(stream); + encoder.Save(stream, out dispWidth, out dispHeight); } } catch (Exception ex) { // TODO: add an error report Debug.WriteLine("Error creating animated GIF file '" + pathName + "': " + ex.Message); + dispWidth = dispHeight = 1; } } else { + // Bitmap visualization. + // // Encode a GIF the same size as the original bitmap. GifBitmapEncoder encoder = new GifBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(vis.CachedImage)); @@ -770,6 +776,9 @@ namespace SourceGen { Debug.WriteLine("Error creating GIF file '" + pathName + "': " + ex.Message); } + + dispWidth = (int)vis.CachedImage.Width; + dispHeight = (int)vis.CachedImage.Height; } // Output thumbnail-size IMG element, preserving proportions. I'm assuming @@ -778,17 +787,17 @@ namespace SourceGen { // across all visualization lines, but that can create some monsters (e.g. // a bitmap that's 1 pixel high and 40 wide), so we cap the width. int dimMult = IMAGE_SIZE; - double maxDim = vis.CachedImage.Height; - if (vis.CachedImage.Width > vis.CachedImage.Height * 2) { + double maxDim = dispHeight; + if (dispWidth > dispHeight * 2) { // Too proportionally wide, so use the width as the limit. Allow it to // up to 2x the max width (which can't cause the thumb height to exceed // the height limit). - maxDim = vis.CachedImage.Width; + maxDim = dispWidth; dimMult *= 2; } - int thumbWidth = (int)Math.Round(dimMult * (vis.CachedImage.Width / maxDim)); - int thumbHeight = (int)Math.Round(dimMult * (vis.CachedImage.Height / maxDim)); - //Debug.WriteLine(vis.CachedImage.Width + "x" + vis.CachedImage.Height + " --> " + + int thumbWidth = (int)Math.Round(dimMult * (dispWidth / maxDim)); + int thumbHeight = (int)Math.Round(dimMult * (dispHeight / maxDim)); + //Debug.WriteLine(dispWidth + "x" + dispHeight + " --> " + // thumbWidth + "x" + thumbHeight + " (" + maxDim + ")"); if (index != 0) { diff --git a/SourceGen/RuntimeData/Help/visualization.html b/SourceGen/RuntimeData/Help/visualization.html index 18cf9a7..d0d989a 100644 --- a/SourceGen/RuntimeData/Help/visualization.html +++ b/SourceGen/RuntimeData/Help/visualization.html @@ -189,13 +189,15 @@ stored in a straightforward fashion.

Commodore 64 - Commodore/VisC64

diff --git a/SourceGen/Visualization.cs b/SourceGen/Visualization.cs index b2280c5..e1a8b06 100644 --- a/SourceGen/Visualization.cs +++ b/SourceGen/Visualization.cs @@ -72,6 +72,11 @@ namespace SourceGen { /// public BitmapSource CachedImage { get; set; } + /// + /// Image overlaid on CachedImage. Used to identify thumbnails as animations. + /// + public BitmapSource OverlayImage { get; set; } + /// /// True if CachedImage has something other than the default value. /// @@ -93,6 +98,8 @@ namespace SourceGen { internal static readonly BitmapSource ANIM_OVERLAY_IMAGE = VisualizationAnimation.GenerateAnimOverlayImage(); + internal static readonly BitmapSource BLANK_IMAGE = GenerateBlankImage(); + /// /// Serial number, for reference from other Visualization objects. Not serialized. /// @@ -138,6 +145,7 @@ namespace SourceGen { VisGenIdent = visGenIdent; VisGenParams = visGenParams; CachedImage = BROKEN_IMAGE; + OverlayImage = BLANK_IMAGE; if (oldObj == null) { // not worried about multiple threads @@ -210,6 +218,12 @@ namespace SourceGen { return image; } + private static BitmapSource GenerateBlankImage() { + RenderTargetBitmap bmp = new RenderTargetBitmap(1, 1, 96.0, 96.0, + PixelFormats.Pbgra32); + return bmp; + } + public override string ToString() { return "[Vis: " + Tag + " (" + VisGenIdent + ") count=" + VisGenParams.Count + "]"; diff --git a/SourceGen/VisualizationAnimation.cs b/SourceGen/VisualizationAnimation.cs index 0b250c5..0040ca3 100644 --- a/SourceGen/VisualizationAnimation.cs +++ b/SourceGen/VisualizationAnimation.cs @@ -80,42 +80,28 @@ namespace SourceGen { mSerialNumbers.Add(serial); } - CachedImage = ANIM_OVERLAY_IMAGE; // default to this + CachedImage = BLANK_IMAGE; + OverlayImage = ANIM_OVERLAY_IMAGE; } + /// + /// Generates a cached image for the animation. + /// + /// + /// Currently just using the first frame. We could do fancy things, like make a + /// poster with the first N images. + /// + /// List of visualization sets. public void GenerateImage(SortedList visSets) { - const int IMAGE_SIZE = 64; - - CachedImage = ANIM_OVERLAY_IMAGE; - + CachedImage = BLANK_IMAGE; if (mSerialNumbers.Count == 0) { return; } Visualization vis = VisualizationSet.FindVisualizationBySerial(visSets, mSerialNumbers[0]); - if (vis == null) { - return; + if (vis != null) { + CachedImage = vis.CachedImage; } - - double maxDim = Math.Max(vis.CachedImage.Width, vis.CachedImage.Height); - double dimMult = IMAGE_SIZE / maxDim; - double adjWidth = vis.CachedImage.Width * dimMult; - double adjHeight = vis.CachedImage.Height * dimMult; - Rect imgBounds = new Rect((IMAGE_SIZE - adjWidth) / 2, (IMAGE_SIZE - adjHeight) / 2, - adjWidth, adjHeight); - - DrawingVisual visual = new DrawingVisual(); - //RenderOptions.SetBitmapScalingMode(visual, BitmapScalingMode.NearestNeighbor); - using (DrawingContext dc = visual.RenderOpen()) { - dc.DrawImage(vis.CachedImage, imgBounds); - dc.DrawImage(ANIM_OVERLAY_IMAGE, new Rect(0, 0, IMAGE_SIZE, IMAGE_SIZE)); - } - - RenderTargetBitmap bmp = new RenderTargetBitmap(IMAGE_SIZE, IMAGE_SIZE, 96.0, 96.0, - PixelFormats.Pbgra32); - bmp.Render(visual); - CachedImage = bmp; - //Debug.WriteLine("RENDERED " + Tag); } /// diff --git a/SourceGen/WpfGui/CodeListItemStyle.xaml b/SourceGen/WpfGui/CodeListItemStyle.xaml index 1f89043..ce3aa52 100644 --- a/SourceGen/WpfGui/CodeListItemStyle.xaml +++ b/SourceGen/WpfGui/CodeListItemStyle.xaml @@ -109,8 +109,11 @@ See also https://github.com/fadden/DisasmUiTest - + + + + diff --git a/SourceGen/WpfGui/EditBitmapAnimation.xaml b/SourceGen/WpfGui/EditBitmapAnimation.xaml index efcd752..cae03f9 100644 --- a/SourceGen/WpfGui/EditBitmapAnimation.xaml +++ b/SourceGen/WpfGui/EditBitmapAnimation.xaml @@ -89,8 +89,11 @@ limitations under the License. - + + + + @@ -123,8 +126,11 @@ limitations under the License. - + + + + diff --git a/SourceGen/WpfGui/EditVisualizationSet.xaml b/SourceGen/WpfGui/EditVisualizationSet.xaml index cd21d83..cb438ab 100644 --- a/SourceGen/WpfGui/EditVisualizationSet.xaml +++ b/SourceGen/WpfGui/EditVisualizationSet.xaml @@ -75,8 +75,11 @@ limitations under the License. - + + + +