Exemplo n.º 1
0
        /// <summary>
        /// Constructor for a replacement Visualization.
        /// </summary>
        /// <param name="tag">Unique identifier.</param>
        /// <param name="visGenIdent">Visualization generator identifier.</param>
        /// <param name="visGenParams">Parameters for visualization generator.</param>
        /// <param name="oldObj">Visualization being replaced, or null if this is new.</param>
        public Visualization(string tag, string visGenIdent,
                             ReadOnlyDictionary <string, object> visGenParams, Visualization oldObj)
        {
            Debug.Assert(!string.IsNullOrEmpty(tag));
            Debug.Assert(!string.IsNullOrEmpty(visGenIdent));
            Debug.Assert(visGenParams != null);

            Tag          = tag;
            VisGenIdent  = visGenIdent;
            VisGenParams = visGenParams;
            CachedImage  = BROKEN_IMAGE;
            OverlayImage = BLANK_IMAGE;

            if (oldObj == null)
            {
                // not worried about multiple threads
                SerialNumber = sNextSerial++;
            }
            else
            {
                Debug.Assert(oldObj.SerialNumber >= 0 && oldObj.SerialNumber < sNextSerial);
                SerialNumber = oldObj.SerialNumber;
            }
            //Debug.WriteLine("NEW VIS: Serial=" + SerialNumber);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates a cached image for the animation.
        /// </summary>
        /// <remarks>
        /// Currently just using the first frame.  We could do fancy things, like make a
        /// poster with the first N images.
        /// </remarks>
        /// <param name="visSets">List of visualization sets.</param>
        public void GenerateImage(SortedList <int, VisualizationSet> visSets)
        {
            CachedImage = BLANK_IMAGE;
            if (mSerialNumbers.Count == 0)
            {
                return;
            }
            Visualization vis = VisualizationSet.FindVisualizationBySerial(visSets,
                                                                           mSerialNumbers[0]);

            if (vis != null)
            {
                CachedImage = vis.CachedImage;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generate one or more GIF image files, and output references to them.
        /// </summary>
        /// <param name="offset">Visualization set file offset.</param>
        /// <param name="sb">String builder for the HTML output.</param>
        private void OutputVisualizationSet(int offset, StringBuilder sb)
        {
            const int IMAGE_SIZE         = 64;
            const int MAX_WIDTH_PER_LINE = 768;

            if (!mProject.VisualizationSets.TryGetValue(offset,
                                                        out VisualizationSet visSet))
            {
                sb.Append("Internal error - visualization set missing");
                Debug.Assert(false);
                return;
            }
            if (visSet.Count == 0)
            {
                sb.Append("Internal error - empty visualization set");
                Debug.Assert(false);
                return;
            }

            string imageDirFileName = Path.GetFileName(mImageDirPath);
            int    outputWidth      = 0;

            for (int index = 0; index < visSet.Count; index++)
            {
                string fileName = "vis" + offset.ToString("x6") + "_" + index.ToString("d2");

                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);
                    AnimatedGifEncoder encoder = new AnimatedGifEncoder();

                    // Gather list of frames.
                    for (int i = 0; i < visAnim.Count; i++)
                    {
                        Visualization avis = VisualizationSet.FindVisualizationBySerial(
                            mProject.VisualizationSets, visAnim[i]);
                        if (avis != null)
                        {
                            encoder.AddFrame(BitmapFrame.Create(avis.CachedImage), frameDelay);
                        }
                        else
                        {
                            Debug.Assert(false);        // not expected
                        }
                    }

#if false
                    // try feeding the animated GIF into our GIF unpacker
                    using (MemoryStream ms = new MemoryStream()) {
                        encoder.Save(ms);
                        Debug.WriteLine("TESTING");
                        UnpackedGif anim = UnpackedGif.Create(ms.GetBuffer());
                        anim.DebugDump();
                    }
#endif

                    // Create new or replace existing image file.
                    fileName += "_ani.gif";
                    string pathName = Path.Combine(mImageDirPath, fileName);
                    try {
                        using (FileStream stream = new FileStream(pathName, FileMode.Create)) {
                            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));

                    // Create new or replace existing image file.
                    fileName += ".gif";
                    string pathName = Path.Combine(mImageDirPath, fileName);
                    try {
                        using (FileStream stream = new FileStream(pathName, FileMode.Create)) {
                            encoder.Save(stream);
                        }
                    } catch (Exception ex) {
                        // Something went wrong with file creation.  We don't have an error
                        // reporting mechanism, so this will just appear as a broken or stale
                        // image reference.
                        // TODO: add an error report
                        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
                // images will be small enough that generating a separate thumbnail would be
                // counter-productive.  This seems to look best if the height is consistent
                // 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  = 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   = dispWidth;
                    dimMult *= 2;
                }
                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 (outputWidth > MAX_WIDTH_PER_LINE)
                {
                    // Add a line break.  In "pre" mode the bitmaps just run off the right
                    // edge of the screen.  The way we're doing it is imprecise and doesn't
                    // flow with changes to the browser width, but it'll do for now.
                    sb.AppendLine("<br/>");
                    for (int i = 0; i < mColStart[(int)Col.Label]; i++)
                    {
                        sb.Append(' ');
                    }
                    outputWidth = 0;
                }
                else if (index != 0)
                {
                    sb.Append("&nbsp;");
                }
                outputWidth += thumbWidth;

                sb.Append("<img class=\"vis\" alt=\"vis\" src=\"");
                sb.Append(imageDirFileName);
                sb.Append('/');
                sb.Append(fileName);
                sb.Append("\" width=\"" + thumbWidth + "\" height=\"" + thumbHeight + "\"/>");
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Constructor.  Mostly pass-through, but we want to set the overlay image.
 /// </summary>
 public VisWireframeAnimation(string tag, string visGenIdent,
                              ReadOnlyDictionary <string, object> visGenParams, Visualization oldObj,
                              WireframeObject wireObj)
     : base(tag, visGenIdent, visGenParams, oldObj)
 {
     // wireObj may be null when loading from project file
     mWireObj     = wireObj;
     OverlayImage = ANIM_OVERLAY_IMAGE;
 }