Beispiel #1
0
        static unsafe int GetPixel(int penWidth, int *penData, float x, float y)
        {
            var left   = (int)x;
            var right  = x.Ceiling();
            var top    = (int)y;
            var bottom = y.Ceiling();

            var i = left + top * penWidth;

            if (left - x == 0 && y - top == 0)
            {
                return(penData[i]);
            }

            var j = i + 1;
            var k = i + penWidth;
            var l = i + 1 + penWidth;

            var lt = penData[i];
            var rt = penData[j];
            var lb = penData[k];
            var rb = penData[l];

            return(Colours.Blend(lt, rt, lb, rb, x - left, y - top));
        }
Beispiel #2
0
            public unsafe override void RenderPixel(IBuffer target, int index, int color, bool blend, float? delta = null)
            {
                if (IsDisposed)
                    throw new System.Exception("Object is disposed!");

                if (index < 0 || index >= target.Length)
                    return;

                target.XYOf(index, out int x, out int y);

                int i = index;

                if (blend && FillMode != FillMode.Erase)
                {
                    if (delta != null)
                        target[i] = Colours.Blend(target[i], color, delta.Value);
                    else
                        target[i] = Colours.Blend(target[i], color);
                }
                else
                    target[i] = color;

                NotifyDrawPoint(x, y);
            }
Beispiel #3
0
        /* The MIT License(MIT)
         * Copyright(c) 2009-2015 Rene Schulte
         * Permission is hereby granted, free of charge, to any person obtaining a copy
         * of this software and associated documentation files(the "Software"), to deal
         * the Software without restriction, including without limitation the rights
         * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         * copies of the Software, and to permit persons to whom the Software is
         * furnished to do so, subject to the following conditions:
         *
         * The above copyright notice and this permission notice shall be included  all
         * copies or substantial portions of the Software.
         *
         * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         * SOFTWARE.*/
        public static unsafe IGraphics RotatedCopy(this IGraphics surface, Angle angle, bool crop = false)
        {
            bool isAngle = angle.Valid;
            // rotating clockwise, so it's negative relative to Cartesian quadrants
            float cnAngle = -Geometry.Radian * angle.Degree;

            // general iterators
            int i, j;
            // calculated indices  Cartesian coordinates
            int   x, y;
            float fDistance, fPolarAngle;
            // for use  neighboring indices  Cartesian coordinates
            int iFloorX, iCeilingX, iFloorY, iCeilingY;
            // calculated indices  Cartesian coordinates with trailing decimals
            float fTrueX, fTrueY;
            // for interpolation
            float fDeltaX, fDeltaY;

            int iCentreX, iCentreY;
            int iDestCentreX, iDestCentreY;
            int iWidth, iHeight, newWidth, newHeight;

            iWidth  = surface.Width;
            iHeight = surface.Height;

            if (crop)
            {
                newWidth  = iWidth;
                newHeight = iHeight;
            }
            else
            {
                var rad    = angle.Degree / Geometry.RadianInv;
                var nAngle = new Angle(rad);

                newWidth  = (int)Math.Ceiling(Math.Abs(nAngle.Sin * iHeight) + Math.Abs(nAngle.Cos * iWidth));
                newHeight = (int)Math.Ceiling(Math.Abs(nAngle.Sin * iWidth) + Math.Abs(nAngle.Cos * iHeight));
            }


            iCentreX = iWidth / 2;
            iCentreY = iHeight / 2;

            iDestCentreX = newWidth / 2;
            iDestCentreY = newHeight / 2;

            var result = surface.ToPen(newWidth, newHeight) as IGraphics;

            if (!angle.Valid)
            {
                return(result);
            }

            var newp = (int *)result.Pixels;
            var oldp = (int *)surface.Pixels;
            var oldw = surface.Width;

            // assigning pixels of destination image from source image
            // with bilinear interpolation

            for (i = 0; i < newHeight; ++i)
            {
                for (j = 0; j < newWidth; ++j)
                {
                    // convert raster to Cartesian
                    x = j - iDestCentreX;
                    y = iDestCentreY - i;

                    // convert Cartesian to polar
                    fDistance = (float)Math.Sqrt(x * x + y * y);
                    if (x == 0)
                    {
                        if (y == 0)
                        {
                            // center of image, no rotation needed
                            newp[i * newWidth + j] = oldp[iCentreY * oldw + iCentreX];
                            continue;
                        }
                        fPolarAngle  = Geometry.PI;
                        fPolarAngle *= y < 0 ? 1.5f : .5f;
                    }
                    else
                    {
                        fPolarAngle = (float)Math.Atan2(y, x);
                    }

                    // the crucial rotation part
                    // "reverse" rotate, so minus instead of plus
                    fPolarAngle -= cnAngle;

                    // convert polar to Cartesian
                    fTrueX = (float)(fDistance * Math.Cos(fPolarAngle));
                    fTrueY = (float)(fDistance * Math.Sin(fPolarAngle));

                    // convert Cartesian to raster
                    fTrueX = fTrueX + iCentreX;
                    fTrueY = iCentreY - fTrueY;

                    iFloorX   = (int)(Math.Floor(fTrueX));
                    iFloorY   = (int)(Math.Floor(fTrueY));
                    iCeilingX = (int)(Math.Ceiling(fTrueX));
                    iCeilingY = (int)(Math.Ceiling(fTrueY));

                    // check bounds
                    if (iFloorX < 0 || iCeilingX < 0 || iFloorX >= iWidth || iCeilingX >= iWidth || iFloorY < 0 ||
                        iCeilingY < 0 || iFloorY >= iHeight || iCeilingY >= iHeight)
                    {
                        continue;
                    }

                    fDeltaX = fTrueX - iFloorX;
                    fDeltaY = fTrueY - iFloorY;

                    var clrTopLeft     = oldp[iFloorY * oldw + iFloorX];
                    var clrTopRight    = oldp[iFloorY * oldw + iCeilingX];
                    var clrBottomLeft  = oldp[iCeilingY * oldw + iFloorX];
                    var clrBottomRight = oldp[iCeilingY * oldw + iCeilingX];

                    newp[i * newWidth + j] = Colours.Blend(clrTopLeft, clrTopRight, clrBottomLeft, clrBottomRight, fDeltaX, fDeltaY);
                }
            }
            return(result);
        }
Beispiel #4
0
            public unsafe override void RenderLine(IBuffer target, IBufferPen reader, int destVal, int destAxis, int start, int end, int axis, bool horizontal, float? delta = null)
            {
                if (!GetAxisLineInfo(target, ref destVal, ref destAxis, ref start, ref end, horizontal, out int destIndex, out int length))
                    return;

                ReadLine(reader, start, (start + length), axis, horizontal, out IntPtr source, out int sIndex, out length);

                if (length == 0)
                    return;

                int* src = (int*)source;

                float? alpha;

                if (FillMode == FillMode.Erase)
                    alpha = null;
                else
                    alpha = delta;

                if (IsRotated(Entity.Buffer))
                {
                    var j = sIndex;
                    if (length < 2)
                        return;
                    var last = destVal + length - 1;
                    for (float i = destVal; i <= last; i++)
                    {
                        bool blend = i == start || i == last;
                        target.WritePixel(i, destAxis, horizontal, src[j], blend);
                        j++;
                    }
                    return;
                }

                int* dest = (int*)target.Pixels;
                if (horizontal)
                {
                    if (alpha != null)
                        Colours.Blend(src, sIndex, length, dest, destIndex, alpha);
                    else
                        CopyMemory(src, sIndex, dest, destIndex, length);

                    NotifyAxisLine(destVal, destAxis, horizontal, length);
                }
                else
                {
                    if (alpha != null)
                    {
                        for (int i = sIndex; i < sIndex + length; i++)
                        {
                            dest[destIndex] = Colours.Blend(dest[destIndex], src[i], alpha.Value);
                            destIndex += target.Width;
                        }
                    }
                    else
                    {
                        for (int i = sIndex; i < sIndex + length; i++)
                        {
                            dest[destIndex] = src[i];
                            destIndex += target.Width;
                        }
                    }
                    NotifyAxisLine(destVal, destAxis, horizontal, length);
                }

            }