public static void ToReplacedColor(BitmapHolder bmp, int r, int g, int b, int a)
        {
            var nWidth = bmp.Width;
            var nHeight = bmp.Height;
            var len = bmp.PixelCount;

            for (var i = 0; i < len; i++)
            {
                var c = bmp.GetPixelAsInt(i);
                var currentAlpha = (c >> 24) & 0x000000FF;
                var aNew = (int)(currentAlpha * (a / currentAlpha));

                var rNew = r;
                var gNew = g;
                var bNew = b;

                if (rNew > 255)
                    rNew = 255;

                if (gNew > 255)
                    gNew = 255;

                if (bNew > 255)
                    bNew = 255;

                bmp.SetPixel(i, (aNew << 24) | (rNew << 16) | (gNew << 8) | bNew);
            }
        }
        public static void ToSepia(BitmapHolder bmp)
        {
            var nWidth = bmp.Width;
            var nHeight = bmp.Height;
            var len = bmp.PixelCount;

            for (var i = 0; i < len; i++)
            {
                var c = bmp.GetPixelAsInt(i);
                var a = (c >> 24) & 0x000000FF;
                var r = (c >> 16) & 0x000000FF;
                var g = (c >> 8) & 0x000000FF;
                var b = (c) & 0x000000FF;

                var rNew = (int)Math.Min((.393 * r) + (.769 * g) + (.189 * (b)), 255.0);
                var gNew = (int)Math.Min((.349 * r) + (.686 * g) + (.168 * (b)), 255.0);
                var bNew = (int)Math.Min((.272 * r) + (.534 * g) + (.131 * (b)), 255.0);

                if (rNew > 255)
                    rNew = 255;

                if (gNew > 255)
                    gNew = 255;

                if (bNew > 255)
                    bNew = 255;

                bmp.SetPixel(i, (a << 24) | (rNew << 16) | (gNew << 8) | bNew);
            }
        }
Пример #3
0
        public static void ToCropped(BitmapHolder source, int x, int y, int width, int height)
        {
            var srcWidth = source.Width;
            var srcHeight = source.Height;

            // If the rectangle is completely out of the bitmap
            if (x > srcWidth || y > srcHeight)
            {
                return;
            }

            // Clamp to boundaries
            if (x < 0) x = 0;
            if (x + width > srcWidth) width = srcWidth - x;
            if (y < 0) y = 0;
            if (y + height > srcHeight) height = srcHeight - y;

            // Copy the pixels line by line using fast BlockCopy
            var result = new int[width * height];

            for (var line = 0; line < height; line++)
            {
                var srcOff = ((y + line) * srcWidth + x) * Helpers.SizeOfArgb;
                var dstOff = line * width * Helpers.SizeOfArgb;
                Helpers.BlockCopy(source.Pixels, srcOff, result, dstOff, width * Helpers.SizeOfArgb);
            }

            source.SetPixels(result, width, height);
        }
        public static BitmapHolder ToTransformedCorners(BitmapHolder source, double topLeftCornerSize, double topRightCornerSize, double bottomLeftCornerSize, double bottomRightCornerSize,
            CornerTransformType cornersTransformType, double cropWidthRatio, double cropHeightRatio)
        {
            double sourceWidth = source.Width;
            double sourceHeight = source.Height;

            double desiredWidth = sourceWidth;
            double desiredHeight = sourceHeight;

            double desiredRatio = cropWidthRatio / cropHeightRatio;
            double currentRatio = sourceWidth / sourceHeight;

            if (currentRatio > desiredRatio)
                desiredWidth = (cropWidthRatio * sourceHeight / cropHeightRatio);
            else if (currentRatio < desiredRatio)
                desiredHeight = (cropHeightRatio * sourceWidth / cropWidthRatio);

            topLeftCornerSize = topLeftCornerSize * (desiredWidth + desiredHeight) / 2 / 100;
            topRightCornerSize = topRightCornerSize * (desiredWidth + desiredHeight) / 2 / 100;
            bottomLeftCornerSize = bottomLeftCornerSize * (desiredWidth + desiredHeight) / 2 / 100;
            bottomRightCornerSize = bottomRightCornerSize * (desiredWidth + desiredHeight) / 2 / 100;

            float cropX = (float)((sourceWidth - desiredWidth) / 2);
            float cropY = (float)((sourceHeight - desiredHeight) / 2);

            //TODO not implemented

            return source;
        }
Пример #5
0
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     var transformed = ToFlipped(source, _flipType);
     
     source = null; // Free resource as we return a new WriteableBitmap
     return transformed;
 }
        protected override BitmapHolder Transform(BitmapHolder source)
        {
            if (EnableSolidColor)
            {
                ToReplacedColor(source, R, G, B, A);
                return source;
            }

            RGBAWMatrix = FFColorMatrix.ColorToTintMatrix(R, G, B, A);

            return base.Transform(source);
        }
        public static BitmapHolder ToCropped(BitmapHolder source, double zoomFactor, double xOffset, double yOffset, double cropWidthRatio, double cropHeightRatio)
        {
            double sourceWidth = source.Width;
            double sourceHeight = source.Height;

            double desiredWidth = sourceWidth;
            double desiredHeight = sourceHeight;

            double desiredRatio = cropWidthRatio / cropHeightRatio;
            double currentRatio = sourceWidth / sourceHeight;

            if (currentRatio > desiredRatio)
                desiredWidth = (cropWidthRatio * sourceHeight / cropHeightRatio);
            else if (currentRatio < desiredRatio)
                desiredHeight = (cropHeightRatio * sourceWidth / cropWidthRatio);

            xOffset = xOffset * desiredWidth;
            yOffset = yOffset * desiredHeight;

            desiredWidth = desiredWidth / zoomFactor;
            desiredHeight = desiredHeight / zoomFactor;

            float cropX = (float)(((sourceWidth - desiredWidth) / 2) + xOffset);
            float cropY = (float)(((sourceHeight - desiredHeight) / 2) + yOffset);

            if (cropX < 0)
                cropX = 0;

            if (cropY < 0)
                cropY = 0;

            if (cropX + desiredWidth > sourceWidth)
                cropX = (float)(sourceWidth - desiredWidth);

            if (cropY + desiredHeight > sourceHeight)
                cropY = (float)(sourceHeight - desiredHeight);

            int width = (int)desiredWidth;
            int height = (int)desiredHeight;

            // Copy the pixels line by line using fast BlockCopy
            var result = new int[width * height];

            for (var line = 0; line < height; line++)
            {
                var srcOff = (((int)cropY + line) * source.Width + (int)cropX) * ColorExtensions.SizeOfArgb;
                var dstOff = line * width * ColorExtensions.SizeOfArgb;
                Helpers.BlockCopy(source.Pixels, srcOff, result, dstOff, width * ColorExtensions.SizeOfArgb);
            }

            return new BitmapHolder(result, width, height);
        }
        public static void ToGrayscale(BitmapHolder bmp)
        {
            var nWidth = bmp.Width;
            var nHeight = bmp.Height;
            var px = bmp.Pixels;
            var len = bmp.Pixels.Length;

            for (var i = 0; i < len; i++)
            {
                var c = px[i];
                var a = (c >> 24) & 0x000000FF;
                var r = (c >> 16) & 0x000000FF;
                var g = (c >> 8) & 0x000000FF;
                var b = (c) & 0x000000FF;

                // Convert to gray with constant factors 0.2126, 0.7152, 0.0722
                var gray = (r * 6966 + g * 23436 + b * 2366) >> 15;
                r = g = b = gray;

                px[i] = (a << 24) | (r << 16) | (g << 8) | b;
            }
        }
        public static void ToGrayscale(BitmapHolder bmp)
        {
            var nWidth = bmp.Width;
            var nHeight = bmp.Height;

            var len = bmp.PixelCount;

            for (var i = 0; i < len; i++)
            {
                var c = bmp.GetPixelAsInt(i);
                var a = (c >> 24) & 0x000000FF;
                var r = (c >> 16) & 0x000000FF;
                var g = (c >> 8) & 0x000000FF;
                var b = (c) & 0x000000FF;

                // Convert to gray with constant factors 0.2126, 0.7152, 0.0722
                var gray = (r * 6966 + g * 23436 + b * 2366) >> 15;
                r = g = b = gray;

                bmp.SetPixel(i, (a << 24) | (r << 16) | (g << 8) | b);
            }
        }
Пример #10
0
        public static BitmapHolder ToFlipped(BitmapHolder bmp, FlipType flipMode)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            var w = bmp.Width;
            var h = bmp.Height;
            var p = bmp.Pixels;
            var i = 0;
            BitmapHolder result = new BitmapHolder(new int[bmp.Pixels.Length], w, h);

            if (flipMode == FlipType.Vertical)
            {
                var rp = result.Pixels;
                for (var y = h - 1; y >= 0; y--)
                {
                    for (var x = 0; x < w; x++)
                    {
                        var srcInd = y * w + x;
                        rp[i] = p[srcInd];
                        i++;
                    }
                }
            }
            else
            {
                var rp = result.Pixels;
                for (var y = 0; y < h; y++)
                {
                    for (var x = w - 1; x >= 0; x--)
                    {
                        var srcInd = y * w + x;
                        rp[i] = p[srcInd];
                        i++;
                    }
                }
            }

            return result;
        }
Пример #11
0
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     RoundedTransformation.ToRounded(source, 0, 1f, 1f);
     return source;
 }
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToRotated(source, _degrees, _ccw, _resize);
 }
        public static BitmapHolder ToRotated(BitmapHolder source, double degrees, bool ccw, bool resize)
        {
			if (degrees == 0 || degrees % 360 == 0)
				return source;
			
            if (ccw)
                degrees = 360d - degrees;

            // rotating clockwise, so it's negative relative to Cartesian quadrants
            double cnAngle = -1.0 * (Math.PI / 180) * degrees;

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

            // interpolated "top" pixels
            double fTopRed, fTopGreen, fTopBlue, fTopAlpha;

            // interpolated "bottom" pixels
            double fBottomRed, fBottomGreen, fBottomBlue, fBottomAlpha;

            // final interpolated color components
            int iRed, iGreen, iBlue, iAlpha;

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

            iWidth = source.Width;
            iHeight = source.Height;

			if (!resize || (degrees % 180 == 0))
            {
                newWidth = iWidth;
                newHeight = iHeight;
            }
            else
            {
                var rad = degrees / (180 / Math.PI);
                newWidth = (int)Math.Ceiling(Math.Abs(Math.Sin(rad) * iHeight) + Math.Abs(Math.Cos(rad) * iWidth));
                newHeight = (int)Math.Ceiling(Math.Abs(Math.Sin(rad) * iWidth) + Math.Abs(Math.Cos(rad) * iHeight));
            }


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

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

            var newp = new int[newWidth * newHeight];
            var oldp = source.Pixels;
            var oldw = source.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 = 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;
                        }
                        if (y < 0)
                        {
                            fPolarAngle = 1.5 * Math.PI;
                        }
                        else
                        {
                            fPolarAngle = 0.5 * Math.PI;
                        }
                    }
                    else
                    {
                        fPolarAngle = Math.Atan2(y, x);
                    }

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

                    // convert polar to Cartesian
                    fTrueX = fDistance * Math.Cos(fPolarAngle);
                    fTrueY = 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];

                    fTopAlpha = (1 - fDeltaX) * ((clrTopLeft >> 24) & 0xFF) + fDeltaX * ((clrTopRight >> 24) & 0xFF);
                    fTopRed = (1 - fDeltaX) * ((clrTopLeft >> 16) & 0xFF) + fDeltaX * ((clrTopRight >> 16) & 0xFF);
                    fTopGreen = (1 - fDeltaX) * ((clrTopLeft >> 8) & 0xFF) + fDeltaX * ((clrTopRight >> 8) & 0xFF);
                    fTopBlue = (1 - fDeltaX) * (clrTopLeft & 0xFF) + fDeltaX * (clrTopRight & 0xFF);

                    // linearly interpolate horizontally between bottom neighbors
                    fBottomAlpha = (1 - fDeltaX) * ((clrBottomLeft >> 24) & 0xFF) + fDeltaX * ((clrBottomRight >> 24) & 0xFF);
                    fBottomRed = (1 - fDeltaX) * ((clrBottomLeft >> 16) & 0xFF) + fDeltaX * ((clrBottomRight >> 16) & 0xFF);
                    fBottomGreen = (1 - fDeltaX) * ((clrBottomLeft >> 8) & 0xFF) + fDeltaX * ((clrBottomRight >> 8) & 0xFF);
                    fBottomBlue = (1 - fDeltaX) * (clrBottomLeft & 0xFF) + fDeltaX * (clrBottomRight & 0xFF);

                    // linearly interpolate vertically between top and bottom interpolated results
                    iRed = (int)(Math.Round((1 - fDeltaY) * fTopRed + fDeltaY * fBottomRed));
                    iGreen = (int)(Math.Round((1 - fDeltaY) * fTopGreen + fDeltaY * fBottomGreen));
                    iBlue = (int)(Math.Round((1 - fDeltaY) * fTopBlue + fDeltaY * fBottomBlue));
                    iAlpha = (int)(Math.Round((1 - fDeltaY) * fTopAlpha + fDeltaY * fBottomAlpha));

                    // make sure color values are valid
                    if (iRed < 0) iRed = 0;
                    if (iRed > 255) iRed = 255;
                    if (iGreen < 0) iGreen = 0;
                    if (iGreen > 255) iGreen = 255;
                    if (iBlue < 0) iBlue = 0;
                    if (iBlue > 255) iBlue = 255;
                    if (iAlpha < 0) iAlpha = 0;
                    if (iAlpha > 255) iAlpha = 255;

                    var a = iAlpha + 1;
                    newp[i * newWidth + j] = (iAlpha << 24)
                                           | ((byte)((iRed * a) >> 8) << 16)
                                           | ((byte)((iGreen * a) >> 8) << 8)
                                           | ((byte)((iBlue * a) >> 8));
                }
            }

            return new BitmapHolder(newp, newWidth, newHeight);
        }
        public static BitmapHolder ToTransformedCorners(BitmapHolder source, double topLeftCornerSize, double topRightCornerSize, double bottomLeftCornerSize, double bottomRightCornerSize,
            CornerTransformType cornersTransformType, double cropWidthRatio, double cropHeightRatio)
        {
            double sourceWidth = source.Width;
            double sourceHeight = source.Height;

            double desiredWidth = sourceWidth;
            double desiredHeight = sourceHeight;

            double desiredRatio = cropWidthRatio / cropHeightRatio;
            double currentRatio = sourceWidth / sourceHeight;

            if (currentRatio > desiredRatio)
                desiredWidth = (cropWidthRatio * sourceHeight / cropHeightRatio);
            else if (currentRatio < desiredRatio)
                desiredHeight = (cropHeightRatio * sourceWidth / cropWidthRatio);

            double cropX = ((sourceWidth - desiredWidth) / 2);
            double cropY = ((sourceHeight - desiredHeight) / 2);

            BitmapHolder bitmap = null;

            if (cropX != 0 || cropY != 0)
            {
                bitmap = CropTransformation.ToCropped(source, (int)cropX, (int)cropY, (int)(desiredWidth), (int)(desiredHeight));
            }
            else
            {
                bitmap = new BitmapHolder(source.Pixels, source.Width, source.Height);
            }

            topLeftCornerSize = topLeftCornerSize * (desiredWidth + desiredHeight) / 2 / 100;
            topRightCornerSize = topRightCornerSize * (desiredWidth + desiredHeight) / 2 / 100;
            bottomLeftCornerSize = bottomLeftCornerSize * (desiredWidth + desiredHeight) / 2 / 100;
            bottomRightCornerSize = bottomRightCornerSize * (desiredWidth + desiredHeight) / 2 / 100;

            int topLeftSize = (int)topLeftCornerSize;
            int topRightSize = (int)topRightCornerSize;
            int bottomLeftSize = (int)bottomLeftCornerSize;
            int bottomRightSize = (int)bottomRightCornerSize;

            int w = bitmap.Width;
            int h = bitmap.Height;

            int transparentColor = Colors.Transparent.ToInt();

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (x <= topLeftSize && y <= topLeftSize)
                    { //top left corner
                        if (!CheckCorner(topLeftSize, topLeftSize, topLeftSize, cornersTransformType, Corner.TopLeftCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                    else if (x >= w - topRightSize && y <= topRightSize && topRightSize > 0)
                    { // top right corner
                        if (!CheckCorner(w - topRightSize, topRightSize, topRightSize, cornersTransformType, Corner.TopRightCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                    else if (x >= w - bottomRightSize && y >= h - bottomRightSize && bottomRightSize > 0)
                    { // bottom right corner
                        if (!CheckCorner(w - bottomRightSize, h - bottomRightSize, bottomRightSize, cornersTransformType, Corner.BottomRightCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                    else if (x <= bottomLeftSize && y >= h - bottomLeftSize && bottomLeftSize > 0)
                    { // bottom left corner
                        if (!CheckCorner(bottomLeftSize, h - bottomLeftSize, bottomLeftSize, cornersTransformType, Corner.BottomLeftCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                }
            }

            return bitmap;
        }
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToTransformedCorners(source, TopLeftCornerSize, TopRightCornerSize, BottomLeftCornerSize, BottomRightCornerSize,
         CornersTransformType, CropWidthRatio, CropHeightRatio);
 }
Пример #16
0
        protected override BitmapHolder Transform(BitmapHolder source)
        {
            ToLegacyBlurred(source, (int)_radius);

            return source;
        }
Пример #17
0
        // Source: http://incubator.quasimondo.com/processing/superfast_blur.php
        public static void ToLegacyBlurred(BitmapHolder source, int radius)
        {
            int w = source.Width;
            int h = source.Height;
            int wm = w - 1;
            int hm = h - 1;
            int wh = w * h;
            int div = radius + radius + 1;
            int[] r = new int[wh];
            int[] g = new int[wh];
            int[] b = new int[wh];
            int rsum, gsum, bsum, x, y, i, p, p1, p2, yp, yi, yw;
            int[] vmin = new int[Math.Max(w, h)];
            int[] vmax = new int[Math.Max(w, h)];

            int[] dv = new int[256 * div];
            for (i = 0; i < 256 * div; i++)
            {
                dv[i] = (i / div);
            }

            yw = yi = 0;

            for (y = 0; y < h; y++)
            {
                rsum = gsum = bsum = 0;
                for (i = -radius; i <= radius; i++)
                {
                    p = source.Pixels[yi + Math.Min(wm, Math.Max(i, 0))];
                    rsum += (p & 0xff0000) >> 16;
                    gsum += (p & 0x00ff00) >> 8;
                    bsum += p & 0x0000ff;
                }
                for (x = 0; x < w; x++)
                {

                    r[yi] = dv[rsum];
                    g[yi] = dv[gsum];
                    b[yi] = dv[bsum];

                    if (y == 0)
                    {
                        vmin[x] = Math.Min(x + radius + 1, wm);
                        vmax[x] = Math.Max(x - radius, 0);
                    }
                    p1 = source.Pixels[yw + vmin[x]];
                    p2 = source.Pixels[yw + vmax[x]];

                    rsum += ((p1 & 0xff0000) - (p2 & 0xff0000)) >> 16;
                    gsum += ((p1 & 0x00ff00) - (p2 & 0x00ff00)) >> 8;
                    bsum += (p1 & 0x0000ff) - (p2 & 0x0000ff);
                    yi++;
                }
                yw += w;
            }

            for (x = 0; x < w; x++)
            {
                rsum = gsum = bsum = 0;
                yp = -radius * w;
                for (i = -radius; i <= radius; i++)
                {
                    yi = Math.Max(0, yp) + x;
                    rsum += r[yi];
                    gsum += g[yi];
                    bsum += b[yi];
                    yp += w;
                }
                yi = x;
                for (y = 0; y < h; y++)
                {
                    // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                    source.Pixels[yi] = (int)((0xff000000 & source.Pixels[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]);
                    if (x == 0)
                    {
                        vmin[y] = Math.Min(y + radius + 1, hm) * w;
                        vmax[y] = Math.Max(y - radius, 0) * w;
                    }
                    p1 = x + vmin[y];
                    p2 = x + vmax[y];

                    rsum += r[p1] - r[p2];
                    gsum += g[p1] - g[p2];
                    bsum += b[p1] - b[p2];

                    yi += w;
                }
            }
        }
Пример #18
0
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToCropped(source, ZoomFactor, XOffset, YOffset, CropWidthRatio, CropHeightRatio);
 }
        protected async override Task <WriteableBitmap> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            BitmapHolder imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                bool allowUpscale = Parameters.AllowUpscale ?? Configuration.AllowUpscale;
                if (source != ImageSource.Stream && imageInformation.Type == ImageInformation.ImageType.WEBP)
                {
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }
                else if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
                {
                    imageIn = await imageData.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false);
                }
                else
                {
                    return(await imageData.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false));
                }
            }
            finally
            {
                imageData.TryDispose();
            }

            ThrowIfCancellationRequested();

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                await _decodingLock.WaitAsync(CancellationTokenSource.Token).ConfigureAwait(false); // Applying transformations is both CPU and memory intensive

                ThrowIfCancellationRequested();

                try
                {
                    foreach (var transformation in transformations)
                    {
                        ThrowIfCancellationRequested();

                        var old = imageIn;

                        try
                        {
                            IBitmap bitmapHolder = transformation.Transform(imageIn, path, source, isPlaceholder, Key);
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.PixelData != imageIn.PixelData)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            try
            {
                return(await imageIn.ToBitmapImageAsync());
            }
            finally
            {
                imageIn.FreePixels();
                imageIn = null;
            }
        }
        protected override BitmapHolder Transform(BitmapHolder source)
        {
            ToColorSpace(source, _rgbawMatrix);

            return source;
        }
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToFlipped(source, FlipType);
 }
Пример #22
0
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return RoundedTransformation.ToRounded(source, 0, 1f, 1f, _borderSize, _borderHexColor);
 }
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToRotated(source, Degrees, CCW, Resize);
 }
Пример #24
0
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToCropped(source, _zoomFactor, _xOffset, _yOffset, _cropWidthRatio, _cropHeightRatio);
 }
        protected async override Task <WriteableBitmap> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            BitmapHolder imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                // Special case to handle WebP decoding on Windows
                string ext = null;
                if (!string.IsNullOrWhiteSpace(path))
                {
                    if (source == ImageSource.Url && Uri.IsWellFormedUriString(path, UriKind.RelativeOrAbsolute))
                    {
                        ext = Path.GetExtension(new Uri(path).LocalPath).ToLowerInvariant();
                    }
                    else
                    {
                        ext = Path.GetExtension(path).ToLowerInvariant();
                    }
                }

                bool allowUpscale = Parameters.AllowUpscale ?? Configuration.AllowUpscale;
                if (source != ImageSource.Stream && ext == ".webp")
                {
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }
                else if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
                {
                    imageIn = await imageData.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false);
                }
                else
                {
                    return(await imageData.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false));
                }
            }
            finally
            {
                imageData?.Dispose();
            }

            ThrowIfCancellationRequested();

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                await _decodingLock.WaitAsync().ConfigureAwait(false); // Applying transformations is both CPU and memory intensive

                try
                {
                    foreach (var transformation in transformations)
                    {
                        ThrowIfCancellationRequested();

                        var old = imageIn;

                        try
                        {
                            IBitmap bitmapHolder = transformation.Transform(imageIn, path, source, isPlaceholder, Key);
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.PixelData != imageIn.PixelData)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            try
            {
                return(await imageIn.ToBitmapImageAsync());
            }
            finally
            {
                imageIn.FreePixels();
                imageIn = null;
            }
        }
Пример #26
0
 protected abstract BitmapHolder Transform(BitmapHolder source);
Пример #27
0
        public static BitmapHolder ToCropped(BitmapHolder source, int x, int y, int width, int height)
        {
            var srcWidth = source.Width;
            var srcHeight = source.Height;

            // Clamp to boundaries
            if (x < 0) x = 0;
            if (x + width > srcWidth) width = srcWidth - x;
            if (y < 0) y = 0;
            if (y + height > srcHeight) height = srcHeight - y;

            // Copy the pixels line by line using fast BlockCopy
            var result = new int[width * height];

            for (var line = 0; line < height; line++)
            {
                var srcOff = ((y + line) * srcWidth + x) * ColorExtensions.SizeOfArgb;
                var dstOff = line * width * ColorExtensions.SizeOfArgb;
                Helpers.BlockCopy(source.Pixels, srcOff, result, dstOff, width * ColorExtensions.SizeOfArgb);
            }

            return new BitmapHolder(result, width, height);
        }
 protected override BitmapHolder Transform(BitmapHolder source)
 {
     return ToRounded(source, (int)Radius, CropWidthRatio, CropHeightRatio, BorderSize, BorderHexColor);
 }
 // helper function, draws pixel and mirrors it
 static void SetPixel4(BitmapHolder bitmap, int centerX, int centerY, int deltaX, int deltaY, int color)
 {
     bitmap.SetPixel(centerX + deltaX, centerY + deltaY, color);
     bitmap.SetPixel(centerX - deltaX, centerY + deltaY, color);
     bitmap.SetPixel(centerX + deltaX, centerY - deltaY, color);
     bitmap.SetPixel(centerX - deltaX, centerY - deltaY, color);
 }
        public static BitmapHolder ToRounded(BitmapHolder source, int rad, double cropWidthRatio, double cropHeightRatio, double borderSize, string borderHexColor)
        {
            double sourceWidth = source.Width;
            double sourceHeight = source.Height;

            double desiredWidth = sourceWidth;
            double desiredHeight = sourceHeight;

            double desiredRatio = cropWidthRatio / cropHeightRatio;
            double currentRatio = sourceWidth / sourceHeight;

            if (currentRatio > desiredRatio)
                desiredWidth = (cropWidthRatio * sourceHeight / cropHeightRatio);
            else if (currentRatio < desiredRatio)
                desiredHeight = (cropHeightRatio * sourceWidth / cropWidthRatio);

            double cropX = ((sourceWidth - desiredWidth) / 2);
            double cropY = ((sourceHeight - desiredHeight) / 2);

            BitmapHolder bitmap = null;

            if (cropX != 0 || cropY != 0)
            {
                bitmap = CropTransformation.ToCropped(source, (int)cropX, (int)cropY, (int)(desiredWidth), (int)(desiredHeight));
            }
            else
            {
                bitmap = new BitmapHolder(source.Pixels, source.Width, source.Height);
            }

            if (rad == 0)
                rad = (int)(Math.Min(desiredWidth, desiredHeight) / 2);
            else rad = (int)(rad * (desiredWidth + desiredHeight) / 2 / 500);

            int w = (int)desiredWidth;
            int h = (int)desiredHeight;

            int transparentColor = Colors.Transparent.ToInt();

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (x <= rad && y <= rad)
                    { //top left corner
                        if (!CheckRoundedCorner(rad, rad, rad, Corner.TopLeftCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                    else if (x >= w - rad && y <= rad)
                    { // top right corner
                        if (!CheckRoundedCorner(w - rad, rad, rad, Corner.TopRightCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                    else if (x >= w - rad && y >= h - rad)
                    { // bottom right corner
                        if (!CheckRoundedCorner(w - rad, h - rad, rad, Corner.BottomRightCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                    else if (x <= rad && y >= h - rad)
                    { // bottom left corner
                        if (!CheckRoundedCorner(rad, h - rad, rad, Corner.BottomLeftCorner, x, y))
                            bitmap.Pixels[y * w + x] = transparentColor;
                    }
                }
            }

            //TODO draws a border - we should optimize that and add some anti-aliasing
            if (borderSize > 0d)
            {
                borderSize = (borderSize * (desiredWidth + desiredHeight) / 2d / 500d);
                int borderColor = Colors.Transparent.ToInt();

                try
                {
                    if (!borderHexColor.StartsWith("#", StringComparison.Ordinal))
                        borderHexColor.Insert(0, "#");
                    borderColor = borderHexColor.ToColorFromHex().ToInt();
                }
                catch (Exception)
                {
                }

                int intBorderSize = (int)Math.Ceiling(borderSize);

                for (int i = 2; i < intBorderSize; i++)
                {
                    CircleAA(bitmap, i, borderColor);
                }
            }

            return bitmap;
        }
        public static void ToColorSpace(BitmapHolder bmp, float[][] rgbawMatrix)
        {
            var r0 = rgbawMatrix[0][0];
            var r1 = rgbawMatrix[0][1];
            var r2 = rgbawMatrix[0][2];
            var r3 = rgbawMatrix[0][3];

            var g0 = rgbawMatrix[1][0];
            var g1 = rgbawMatrix[1][1];
            var g2 = rgbawMatrix[1][2];
            var g3 = rgbawMatrix[1][3];

            var b0 = rgbawMatrix[2][0];
            var b1 = rgbawMatrix[2][1];
            var b2 = rgbawMatrix[2][2];
            var b3 = rgbawMatrix[2][3];

            var a0 = rgbawMatrix[3][0];
            var a1 = rgbawMatrix[3][1];
            var a2 = rgbawMatrix[3][2];
            var a3 = rgbawMatrix[3][3];

            var rOffset = rgbawMatrix[4][0];
            var gOffset = rgbawMatrix[4][1];
            var bOffset = rgbawMatrix[4][2];
            var aOffset = rgbawMatrix[4][3];

            var nWidth = bmp.Width;
            var nHeight = bmp.Height;
            var len = bmp.PixelCount;

            for (var i = 0; i < len; i++)
            {
                var c = bmp.GetPixelAsInt(i);
                var a = (c >> 24) & 0x000000FF;
                var r = (c >> 16) & 0x000000FF;
                var g = (c >> 8) & 0x000000FF;
                var b = (c) & 0x000000FF;

                var rNew = (int)(r * r0 + g * g0 + b * b0 + a * a0 + rOffset);
                var gNew = (int)(r * r1 + g * g1 + b * b1 + a * a1 + gOffset);
                var bNew = (int)(r * r2 + g * g2 + b * b2 + a * a2 + bOffset);
                var aNew = (int)(r * r3 + g * g3 + b * b3 + a * a3 + aOffset);

                if (rNew > 255)
                    rNew = 255;

                if (gNew > 255)
                    gNew = 255;

                if (bNew > 255)
                    bNew = 255;

                if (aNew > 255)
                    aNew = 255;

                if (rNew < 0)
                    rNew = 0;

                if (gNew < 0)
                    gNew = 0;

                if (bNew < 0)
                    bNew = 0;

                if (aNew < 0)
                    aNew = 0;

                bmp.SetPixel(i, (aNew << 24) | (rNew << 16) | (gNew << 8) | bNew);
            }
        }
        static void CircleAA(BitmapHolder bitmap, int size, int color)
        {
            if (size % 2 != 0)
                size++;

            int centerX = bitmap.Width / 2;
            double radiusX = (bitmap.Width - size) / 2;
            int centerY = bitmap.Height / 2;
            double radiusY = (bitmap.Height - size) / 2;

            const int maxTransparency = 127; // default: 127
            double radiusX2 = radiusX * radiusX;
            double radiusY2 = radiusY * radiusY;

            // upper and lower halves
            int quarter = (int)Math.Round(radiusX2 / Math.Sqrt(radiusX2 + radiusY2));

            for (int x = 0; x <= quarter; x++)
            {
                double y = Math.Floor(radiusY * Math.Sqrt(1 - x * x / radiusX2));
                double error = y - Math.Floor(y);
                int transparency = (int)Math.Round(error * maxTransparency);
                int alpha = color | (transparency << 24);
                int alpha2 = color | ((maxTransparency - transparency) << 24);
                SetPixel4(bitmap, centerX, centerY, x, (int)Math.Floor(y), alpha);
                SetPixel4(bitmap, centerX, centerY, x, (int)Math.Floor(y) + 1, alpha2);
            }

            // right and left halves
            quarter = (int)Math.Round(radiusY2 / Math.Sqrt(radiusX2 + radiusY2));

            for (int y = 0; y <= quarter; y++)
            {
                double x = Math.Floor(radiusX * Math.Sqrt(1 - y * y / radiusY2));
                double error = x - Math.Floor(x);
                int transparency = (int)Math.Round(error * maxTransparency);
                int alpha = color | (transparency << 24);
                int alpha2 = color | ((maxTransparency - transparency) << 24);
                SetPixel4(bitmap, centerX, centerY, (int)Math.Floor(x), y, alpha);
                SetPixel4(bitmap, centerX, centerY, (int)Math.Floor(x) + 1, y, alpha2);
            }
        }