예제 #1
0
        public void Round()
        {
            Assert.AreEqual(rectI, rectD.Round());
            Assert.AreEqual(rectI, new RectD(0.6, 1.6, 3.6, 4.6).Round());
            Assert.AreEqual(rectI, new RectD(1.4, 2.4, 4.4, 5.4).Round());

            Assert.AreEqual(rectI, rectF.Round());
            Assert.AreEqual(rectI, new RectF(0.6f, 1.6f, 3.6f, 4.6f).Round());
            Assert.AreEqual(rectI, new RectF(1.4f, 2.4f, 4.4f, 5.4f).Round());
        }
예제 #2
0
        /// <summary>
        /// Draws an image frame that is centered within the specified <see cref="RectD"/>.
        /// </summary>
        /// <param name="targetBitmap">
        /// The <see cref="WriteableBitmap"/> for the drawing, assuming that <paramref
        /// name="targetContext"/> is a null reference.</param>
        /// <param name="targetContext">
        /// The <see cref="DrawingContext"/> for the drawing, assuming that <paramref
        /// name="targetBitmap"/> is a null reference.</param>
        /// <param name="target">
        /// The region within <paramref name="targetContext"/> on which the copied image frame is
        /// centered.</param>
        /// <param name="sourceBitmap">
        /// A <see cref="WriteableBitmap"/> containing the image frame to copy.</param>
        /// <param name="source">
        /// The region within <paramref name="sourceBitmap"/> that covers the image frame to copy.
        /// </param>
        /// <param name="scalingX">
        /// An <see cref="ImageScaling"/> value indicating the horizontal scaling of the <paramref
        /// name="source"/> region to fit the specified <paramref name="target"/> region.</param>
        /// <param name="scalingY">
        /// An <see cref="ImageScaling"/> value indicating the vertical scaling of the <paramref
        /// name="source"/> region to fit the specified <paramref name="target"/> region.</param>
        /// <param name="colorShift">
        /// An optional <see cref="ColorVector"/> applied to all pixels within the drawing. Specify
        /// <see cref="ColorVector.Empty"/> if colors should remain unchanged.</param>
        /// <param name="offset">
        /// An optional pixel offset that is added to the centered location within the <paramref
        /// name="target"/> region.</param>
        /// <param name="scalingVector">
        /// An optional scaling vector for the drawing. Specify <see cref="PointI.Empty"/> if no
        /// scaling vector should be applied.</param>
        /// <exception cref="ArgumentException">
        /// <paramref name="targetBitmap"/> and <paramref name="targetContext"/> are both valid or
        /// both null references.</exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="sourceBitmap"/> is a null reference.</exception>
        /// <remarks><para>
        /// <b>DrawFrame</b> expects that the specified <paramref name="target"/> region equals the
        /// <see cref="RegularPolygon.Bounds"/> of the desired <see cref="RegularPolygon"/> shape.
        /// <b>DrawFrame</b> does not apply a mask or draw an outline around the frame.
        /// </para><para>
        /// Either the specified <paramref name="targetBitmap"/> or the specified <paramref
        /// name="targetContext"/> must be valid, but not both. <b>DrawFrame</b> internally draws to
        /// a <see cref="WriteableBitmap"/> whenever possible to preserve visual quality, then
        /// copies the result to the specified drawing target if different. Alpha blending is
        /// performed only when drawing to a valid <paramref name="targetContext"/>.
        /// </para><para>
        /// If <paramref name="targetBitmap"/> is valid, it must be locked before <b>DrawFrame</b>
        /// is called. If <paramref name="targetContext"/> is valid, the specified <paramref
        /// name="scalingVector"/> is applied to its transformation matrix; otherwise, negative
        /// components indicate mirroring along the corresponding axis of the <paramref
        /// name="targetBitmap"/>.</para></remarks>

        internal static void DrawFrame(WriteableBitmap targetBitmap,
                                       DrawingContext targetContext, RectD target,
                                       WriteableBitmap sourceBitmap, RectI source,
                                       ImageScaling scalingX, ImageScaling scalingY,
                                       ColorVector colorShift, PointI offset, PointI scalingVector)
        {
            // exactly one drawing target must be valid
            if ((targetContext == null && targetBitmap == null) ||
                (targetContext != null && targetBitmap != null))
            {
                ThrowHelper.ThrowArgumentExceptionWithFormat(
                    "targetBitmap", Tektosyne.Strings.ArgumentConflict, targetContext);
            }

            if (sourceBitmap == null)
            {
                ThrowHelper.ThrowArgumentNullException("sourceBitmap");
            }

            // copy source tile to buffer bitmap
            var frameBitmap = new WriteableBitmap(
                source.Width, source.Height, 96, 96, PixelFormats.Pbgra32, null);

            frameBitmap.Lock();
            frameBitmap.Read(0, 0, sourceBitmap, source);

            // shift color channels if desired
            if (!colorShift.IsEmpty)
            {
                frameBitmap.Shift(colorShift.R, colorShift.G, colorShift.B);
            }

            frameBitmap.Unlock();

            // round target coordinates for bitmaps
            RectI targetI = target.Round();

            // use WPF drawing for Stretch scaling, else bitmap copying
            if (scalingX == ImageScaling.Stretch || scalingY == ImageScaling.Stretch)
            {
                // create intermediate context if necessary
                DrawingVisual visual = null;
                if (targetContext == null)
                {
                    visual        = new DrawingVisual();
                    targetContext = visual.RenderOpen();
                }

                // draw frame to target or intermediate context
                DrawFrameCore(targetContext, target, frameBitmap,
                              scalingX, scalingY, offset, scalingVector);

                // copy intermediate context to target bitmap
                if (visual != null)
                {
                    targetContext.Close();
                    var bitmap = new RenderTargetBitmap(
                        targetI.Right, targetI.Bottom, 96, 96, PixelFormats.Pbgra32);
                    bitmap.Render(visual);
                    targetBitmap.Read(targetI.X, targetI.Y, bitmap, targetI);
                }
            }
            else
            {
                // create intermediate bitmap if necessary
                if (targetContext != null)
                {
                    Debug.Assert(targetBitmap == null);
                    targetBitmap = new WriteableBitmap(
                        targetI.Right, targetI.Bottom, 96, 96, PixelFormats.Pbgra32, null);
                    targetBitmap.Lock();
                }

                // draw frame to target or intermediate bitmap
                DrawFrameCore(targetBitmap, targetI, frameBitmap,
                              scalingX, scalingY, offset, scalingVector);

                // copy intermediate bitmap to target context
                if (targetContext != null)
                {
                    targetBitmap.Unlock();
                    targetContext.DrawImage(targetBitmap,
                                            new Rect(0, 0, targetBitmap.Width, targetBitmap.Height));
                }
            }
        }