/// <summary>
        /// Overlay one stroke on the image.
        /// </summary>
        /// <param name="img"></param>
        /// <param name="s"></param>
        /// <param name="size"></param>
        /// PRI2: I believe we can use the DibGraphicsBuffer (see opaque ink handling above) to improve the
        /// look of the transparency.  This currently has the following shortcoming:  The colors produced by the exported gif
        /// from CP's highlight pens have some whiteness which causes a little fog over the dark colors
        /// below, for example the yellow highlight over a black background results in a lighter dark color,
        /// no longer quite black.  In contrast the native ink mixing gives us nearly the original black.  It is as if
        /// the colors are on colored but clear mylar that overlay one another.  It's probably possible to get this effect
        /// with DrawImage somehow??
        private void addTransparentStroke(Image img, Microsoft.Ink.Strokes s, double size)
        {
            Microsoft.Ink.Ink tmpInk = new Microsoft.Ink.Ink();
            tmpInk.AddStrokesAtRectangle(s, s.GetBoundingBox());
            //Make a GIF Image from the Stroke.  Note that this image is assumed to be in a 500x500 pixel space.
            byte[] ba     = tmpInk.Save(Microsoft.Ink.PersistenceFormat.Gif);
            Image  inkImg = Image.FromStream(new MemoryStream(ba));

            Graphics g = Graphics.FromImage(img);

            //Get the origin from the ink Bounding Box (in ink space)
            Rectangle inkBB = tmpInk.GetBoundingBox();

            //Convert the origin of the ink rectangle to pixel space (500x500)
            Microsoft.Ink.Renderer r = new Microsoft.Ink.Renderer();
            Point inkOrigin          = inkBB.Location;

            r.InkSpaceToPixel(g, ref inkOrigin);

            //Convert the transparency coefficient from 0-255 with 0==opaque to the range of 0-1 with 1==opaque.
            int   t1 = Math.Abs(tmpInk.Strokes[0].DrawingAttributes.Transparency - 255);
            float t2 = (float)t1 / 255f;

            //Setting transparency with a ColorMatrix
            float[][] ptsArray =
            {
                new float[] { 1, 0, 0,  0, 0 }, //r
                new float[] { 0, 1, 0,  0, 0 }, //g
                new float[] { 0, 0, 1,  0, 0 }, //b
                new float[] { 0, 0, 0, t2, 0 }, //alpha
                new float[] { 0, 0, 0,  0, 1 }
            };
            ColorMatrix     clrMatrix     = new ColorMatrix(ptsArray);
            ImageAttributes imgAttributes = new ImageAttributes();

            imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            //Adjust Y origin to account for horizontal scroll.  (scrollPos becomes more positive as ink goes upward.)
            float scrolledYInkOrigin = (float)inkOrigin.Y - (500 * (float)scrollPos); //Still in 500x500 space

            //Scale and locate the destination rectangle of the ink within the slide image:
            RectangleF destRect = new RectangleF(
                (float)inkOrigin.X * ((float)img.Width / 500f) * (float)size,
                scrolledYInkOrigin * ((float)img.Height / 500f) * (float)size,
                (float)inkImg.Width * ((float)img.Width / 500f) * (float)size,
                (float)inkImg.Height * ((float)img.Height / 500f) * (float)size);

            Rectangle destRect2 = new Rectangle((int)destRect.X, (int)destRect.Y, (int)destRect.Width, (int)destRect.Height);

            //Draw the overlay:
            g.DrawImage(inkImg, destRect2, 0, 0, inkImg.Width, inkImg.Height, GraphicsUnit.Pixel, imgAttributes);
            g.Dispose();
        }
        /// <summary>
        /// Adding multiple strokes (which can't be erased individually because there are no Guids)
        /// Specifically, this is for student submission overlays.
        /// There are also some CP3 scenarios such as when the instructor opens a CP3 file that has pre-existing ink.
        /// </summary>
        /// <param name="ink"></param>
        public void AddInk(Microsoft.Ink.Ink newInk)
        {
            if ((newInk != null) && (newInk.Strokes.Count > 0))
            {
                //separate transparent and opaque strokes
                List <int> transparentStrokes = new List <int>();
                List <int> opaqueStrokes      = new List <int>();

                //iterate over strokes, adding the ink ids to the correct list
                foreach (Microsoft.Ink.Stroke s in newInk.Strokes)
                {
                    if ((s.DrawingAttributes.Transparency != 0) && (s.DrawingAttributes.Transparency != 255))
                    {
                        transparentStrokes.Add(s.Id);
                    }
                    else
                    {
                        opaqueStrokes.Add(s.Id);
                    }
                }

                //Add transparent strokes to transparentInk.
                if (transparentStrokes.Count > 0)
                {
                    Microsoft.Ink.Strokes tStrokes = newInk.CreateStrokes((int[])transparentStrokes.ToArray());
                    if (transparentInk == null)
                    {
                        transparentInk = new Microsoft.Ink.Ink();
                    }
                    transparentInk.AddStrokesAtRectangle(tStrokes, tStrokes.GetBoundingBox());
                    dirtyBit = true;
                }

                //Add opaque strokes to opaqueInk.
                if (opaqueStrokes.Count > 0)
                {
                    Microsoft.Ink.Strokes oStrokes = newInk.CreateStrokes((int[])opaqueStrokes.ToArray());
                    if (opaqueInk == null)
                    {
                        opaqueInk = new Microsoft.Ink.Ink();
                    }
                    opaqueInk.AddStrokesAtRectangle(oStrokes, oStrokes.GetBoundingBox());
                    dirtyBit = true;
                }
            }
        }
Example #3
0
        /// <summary>
        ///  Loads Ink Data from a specified ISF or JNT file
        /// </summary>
        /// <param name="inkDataFileName">
        /// The file to load the Ink Data from.</param>
        protected void LoadRecordedData(string inkDataFileName)
        {
            // First, reset the Ink object
            PlaybackInk.DeleteStrokes();

            if (!File.Exists(inkDataFileName))
            {
                MessageBox.Show("Cannot find file: " + inkDataFileName);
                return;
            }

            // Read in the specified file
            FileStream isfStream = new FileStream(inkDataFileName, FileMode.Open, FileAccess.Read);

            // Verify the filestream creation was successful
            if (null != isfStream && isfStream.Length > 0)
            {
                byte[] isfBytes = new byte[isfStream.Length];

                // read in the ISF doc
                isfStream.Read(isfBytes, 0, (int)isfStream.Length);

                // Load the ink into a new Temporary object
                // Once an Ink object has been "dirtied" it cannot load ink
                Microsoft.Ink.Ink TemporaryInk = new Microsoft.Ink.Ink();

                // Load the ISF into the ink object
                TemporaryInk.Load(isfBytes);

                // Add the loaded strokes to our Ink object
                PlaybackInk.AddStrokesAtRectangle(TemporaryInk.Strokes, TemporaryInk.Strokes.GetBoundingBox());

                // Close the file stream
                isfStream.Close();
            }
        }