Exemplo n.º 1
0
        private static SKBitmap AutoOrient(SKBitmap bitmap, SKEncodedOrigin origin)
        {
            Stopwatch orient = new Stopwatch("SkiaSharpOrient");

            SKBitmap rotated;

            switch (origin)
            {
            case SKEncodedOrigin.BottomRight:
                rotated = new SKBitmap(bitmap.Height, bitmap.Width);
                using (var canvas = new SKCanvas(rotated))
                {
                    canvas.RotateDegrees(180, bitmap.Width / 2, bitmap.Height / 2);
                    canvas.DrawBitmap(bitmap, 0, 0);
                }
                break;

            case SKEncodedOrigin.RightTop:
                rotated = new SKBitmap(bitmap.Height, bitmap.Width);
                using (var canvas = new SKCanvas(rotated))
                {
                    canvas.Translate(rotated.Width, 0);
                    canvas.RotateDegrees(90);
                    canvas.DrawBitmap(bitmap, 0, 0);
                }
                break;

            case SKEncodedOrigin.LeftBottom:
                rotated = new SKBitmap(bitmap.Height, bitmap.Width);
                using (var canvas = new SKCanvas(rotated))
                {
                    canvas.Translate(0, rotated.Height);
                    canvas.RotateDegrees(270);
                    canvas.DrawBitmap(bitmap, 0, 0);
                }
                break;

            default:
                rotated = bitmap.Copy();
                break;
            }

            orient.Stop();

            return(rotated);
        }
Exemplo n.º 2
0
        private BitmapOptions GetBitmapOptions(SKEncodedOrigin orientation)
        {
            switch (orientation)
            {
            case SKEncodedOrigin.BottomRight:
                return(new BitmapOptions(_bitmap.Width, _bitmap.Height, _bitmap.Width, _bitmap.Height, 180));

            case SKEncodedOrigin.RightTop:
                return(new BitmapOptions(_bitmap.Height, _bitmap.Width, _bitmap.Height, 0, 90));

            case SKEncodedOrigin.LeftBottom:
                return(new BitmapOptions(_bitmap.Height, _bitmap.Width, 0, _bitmap.Height, 270));

            default:
                return(null);
            }
        }
Exemplo n.º 3
0
        private SKBitmap LoadBitmap(Stream stream, out SKEncodedOrigin origin)
        {
            using var managedStream = new SKManagedStream(stream);
            using var codec         = SKCodec.Create(managedStream);

            origin = codec.EncodedOrigin;

            var info   = codec.Info;
            var bitmap = new SKBitmap(info.Width, info.Height, SKImageInfo.PlatformColorType, info.IsOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul);
            var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(out _));

            if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput)
            {
                return(bitmap);
            }

            throw new ArgumentException("Невозможно загрузить изображение из источника.");
        }
Exemplo n.º 4
0
        private static SKBitmap HandleOrientation(SKBitmap bitmap, SKEncodedOrigin orientation)
        {
            SKBitmap rotated;

            switch (orientation)
            {
            case SKEncodedOrigin.BottomRight:

                using (var surface = new SKCanvas(bitmap))
                {
                    surface.RotateDegrees(180, bitmap.Width / 2, bitmap.Height / 2);
                    surface.DrawBitmap(bitmap.Copy(), 0, 0);
                }

                return(bitmap);

            case SKEncodedOrigin.RightTop:
                rotated = new SKBitmap(bitmap.Height, bitmap.Width);

                using (var surface = new SKCanvas(rotated))
                {
                    surface.Translate(rotated.Width, 0);
                    surface.RotateDegrees(90);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);

            case SKEncodedOrigin.LeftBottom:
                rotated = new SKBitmap(bitmap.Height, bitmap.Width);

                using (var surface = new SKCanvas(rotated))
                {
                    surface.Translate(0, rotated.Height);
                    surface.RotateDegrees(270);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);

            default:
                return(bitmap);
            }
        }
Exemplo n.º 5
0
        private SKBitmap LoadBitmap(Stream stream, out SKEncodedOrigin origin)
        {
            using SKManagedStream s = new SKManagedStream(stream);
            using SKCodec codec     = SKCodec.Create(s);
            origin = codec.EncodedOrigin;
            SKImageInfo info   = codec.Info;
            SKBitmap    bitmap = new SKBitmap(info.Width, info.Height, SKImageInfo.PlatformColorType, info.IsOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul);

            SKCodecResult result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(out IntPtr length));

            if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput)
            {
                return(bitmap);
            }
            else
            {
                throw new ArgumentException("Unable to load bitmap from provided data");
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Sets the rotation-to-apply-property to the right enum value. Currently, this supports only non-flipping
        /// origins since the translator only supports non-flipped images as well. The will be extended if I can get an
        /// image, that is flipped, otherwise this is practically not testable
        /// </summary>
        /// <param name="origin"></param>
        protected void SetRotation(SKEncodedOrigin origin)
        {
            switch (origin)
            {
            case SKEncodedOrigin.Default:
                _rotationToApplyForFaceProcessing = RotateFlipType.RotateNoneFlipNone;
                break;

            case SKEncodedOrigin.RightTop:
                _rotationToApplyForFaceProcessing = RotateFlipType.Rotate90FlipNone;
                break;

            case SKEncodedOrigin.BottomRight:
                _rotationToApplyForFaceProcessing = RotateFlipType.Rotate180FlipNone;
                break;

            case SKEncodedOrigin.LeftBottom:
                _rotationToApplyForFaceProcessing = RotateFlipType.Rotate270FlipNone;
                break;
            }
        }
Exemplo n.º 7
0
        private SKBitmap LoadBitmap(Stream stream, out SKEncodedOrigin origin, out SKEncodedImageFormat format)
        {
            using (var s = new SKManagedStream(stream))
            {
                using (var codec = SKCodec.Create(s))
                {
                    origin = codec.EncodedOrigin;
                    format = codec.EncodedFormat;

                    // decode the bitmap at the nearest size
                    var bitmap = SKBitmap.Decode(codec);

                    var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(out IntPtr length));
                    if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput)
                    {
                        return(bitmap);
                    }
                    else
                    {
                        throw new ArgumentException("Unable to load bitmap from provided data.");
                    }
                }
            }
        }
Exemplo n.º 8
0
        private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin)
        {
            //var transformations = {
            //    2: { rotate: 0, flip: true},
            //    3: { rotate: 180, flip: false},
            //    4: { rotate: 180, flip: true},
            //    5: { rotate: 90, flip: true},
            //    6: { rotate: 90, flip: false},
            //    7: { rotate: 270, flip: true},
            //    8: { rotate: 270, flip: false},
            //}

            switch (origin)
            {
            case SKEncodedOrigin.TopRight:
            {
                var rotated = new SKBitmap(bitmap.Width, bitmap.Height);
                using (var surface = new SKCanvas(rotated))
                {
                    surface.Translate(rotated.Width, 0);
                    surface.Scale(-1, 1);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);
            }

            case SKEncodedOrigin.BottomRight:
            {
                var rotated = new SKBitmap(bitmap.Width, bitmap.Height);
                using (var surface = new SKCanvas(rotated))
                {
                    float px = (float)bitmap.Width / 2;
                    float py = (float)bitmap.Height / 2;

                    surface.RotateDegrees(180, px, py);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);
            }

            case SKEncodedOrigin.BottomLeft:
            {
                var rotated = new SKBitmap(bitmap.Width, bitmap.Height);
                using (var surface = new SKCanvas(rotated))
                {
                    float px = (float)bitmap.Width / 2;

                    float py = (float)bitmap.Height / 2;

                    surface.Translate(rotated.Width, 0);
                    surface.Scale(-1, 1);

                    surface.RotateDegrees(180, px, py);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);
            }

            case SKEncodedOrigin.LeftTop:
            {
                // TODO: Remove dual canvases, had trouble with flipping
                using (var rotated = new SKBitmap(bitmap.Height, bitmap.Width))
                {
                    using (var surface = new SKCanvas(rotated))
                    {
                        surface.Translate(rotated.Width, 0);

                        surface.RotateDegrees(90);

                        surface.DrawBitmap(bitmap, 0, 0);
                    }

                    var flippedBitmap = new SKBitmap(rotated.Width, rotated.Height);
                    using (var flippedCanvas = new SKCanvas(flippedBitmap))
                    {
                        flippedCanvas.Translate(flippedBitmap.Width, 0);
                        flippedCanvas.Scale(-1, 1);
                        flippedCanvas.DrawBitmap(rotated, 0, 0);
                    }

                    return(flippedBitmap);
                }
            }

            case SKEncodedOrigin.RightTop:
            {
                var rotated = new SKBitmap(bitmap.Height, bitmap.Width);
                using (var surface = new SKCanvas(rotated))
                {
                    surface.Translate(rotated.Width, 0);
                    surface.RotateDegrees(90);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);
            }

            case SKEncodedOrigin.RightBottom:
            {
                // TODO: Remove dual canvases, had trouble with flipping
                using (var rotated = new SKBitmap(bitmap.Height, bitmap.Width))
                {
                    using (var surface = new SKCanvas(rotated))
                    {
                        surface.Translate(0, rotated.Height);
                        surface.RotateDegrees(270);
                        surface.DrawBitmap(bitmap, 0, 0);
                    }

                    var flippedBitmap = new SKBitmap(rotated.Width, rotated.Height);
                    using (var flippedCanvas = new SKCanvas(flippedBitmap))
                    {
                        flippedCanvas.Translate(flippedBitmap.Width, 0);
                        flippedCanvas.Scale(-1, 1);
                        flippedCanvas.DrawBitmap(rotated, 0, 0);
                    }

                    return(flippedBitmap);
                }
            }

            case SKEncodedOrigin.LeftBottom:
            {
                var rotated = new SKBitmap(bitmap.Height, bitmap.Width);
                using (var surface = new SKCanvas(rotated))
                {
                    surface.Translate(0, rotated.Height);
                    surface.RotateDegrees(270);
                    surface.DrawBitmap(bitmap, 0, 0);
                }

                return(rotated);
            }

            default: return(bitmap);
            }
        }
Exemplo n.º 9
0
        private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, ImageOrientation?orientation, out SKEncodedOrigin origin)
        {
            if (cropWhitespace)
            {
                using (var bitmap = Decode(path, forceAnalyzeBitmap, orientation, out origin))
                {
                    return(CropWhiteSpace(bitmap));
                }
            }

            return(Decode(path, forceAnalyzeBitmap, orientation, out origin));
        }
Exemplo n.º 10
0
        internal SKBitmap Decode(string path, bool forceCleanBitmap, ImageOrientation?orientation, out SKEncodedOrigin origin)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException("File not found", path);
            }

            var requiresTransparencyHack = _transparentImageTypes.Contains(Path.GetExtension(path));

            if (requiresTransparencyHack || forceCleanBitmap)
            {
                using (var stream = new SKFileStream(NormalizePath(path)))
                    using (var codec = SKCodec.Create(stream))
                    {
                        if (codec == null)
                        {
                            origin = GetSKEncodedOrigin(orientation);
                            return(null);
                        }

                        // create the bitmap
                        var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack);

                        // decode
                        _ = codec.GetPixels(bitmap.Info, bitmap.GetPixels());

                        origin = codec.EncodedOrigin;

                        return(bitmap);
                    }
            }

            var resultBitmap = SKBitmap.Decode(NormalizePath(path));

            if (resultBitmap == null)
            {
                return(Decode(path, true, orientation, out origin));
            }

            // If we have to resize these they often end up distorted
            if (resultBitmap.ColorType == SKColorType.Gray8)
            {
                using (resultBitmap)
                {
                    return(Decode(path, true, orientation, out origin));
                }
            }

            origin = SKEncodedOrigin.TopLeft;
            return(resultBitmap);
        }
Exemplo n.º 11
0
        private SKBitmap RotateAndFlip(SKBitmap original, SKEncodedOrigin origin)
        {
            // these are the origins that represent a 90 degree turn in some fashion
            SKEncodedOrigin[] differentOrientations = new SKEncodedOrigin[]
            {
                SKEncodedOrigin.LeftBottom,
                SKEncodedOrigin.LeftTop,
                SKEncodedOrigin.RightBottom,
                SKEncodedOrigin.RightTop
            };

            // check if we need to turn the image
            bool isDifferentOrientation = differentOrientations.Any(o => o == origin);

            // define new width/height
            int width  = isDifferentOrientation ? original.Height : original.Width;
            int height = isDifferentOrientation ? original.Width : original.Height;

            SKBitmap bitmap = new SKBitmap(width, height, original.AlphaType == SKAlphaType.Opaque);

            // todo: the stuff in this switch statement should be rewritten to use pointers
            switch (origin)
            {
            case SKEncodedOrigin.LeftBottom:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(y, original.Width - 1 - x, original.GetPixel(x, y));
                    }
                }

                break;

            case SKEncodedOrigin.RightTop:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(original.Height - 1 - y, x, original.GetPixel(x, y));
                    }
                }

                break;

            case SKEncodedOrigin.RightBottom:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(original.Height - 1 - y, original.Width - 1 - x, original.GetPixel(x, y));
                    }
                }

                break;

            case SKEncodedOrigin.LeftTop:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(y, x, original.GetPixel(x, y));
                    }
                }

                break;

            case SKEncodedOrigin.BottomLeft:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(x, original.Height - 1 - y, original.GetPixel(x, y));
                    }
                }

                break;

            case SKEncodedOrigin.BottomRight:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(original.Width - 1 - x, original.Height - 1 - y, original.GetPixel(x, y));
                    }
                }

                break;

            case SKEncodedOrigin.TopRight:

                for (int x = 0; x < original.Width; x++)
                {
                    for (int y = 0; y < original.Height; y++)
                    {
                        bitmap.SetPixel(original.Width - 1 - x, y, original.GetPixel(x, y));
                    }
                }

                break;
            }

            original.Dispose();

            return(bitmap);
        }
Exemplo n.º 12
0
        public void CodecCanLoadCorrectOrigin(string image, SKEncodedOrigin origin)
        {
            var codec = SKCodec.Create(Path.Combine(PathToImages, image));

            Assert.Equal(origin, codec.EncodedOrigin);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Needed for auto-orienting the image after using the Scaled codec to load
        /// the image.
        /// </summary>
        /// <param name="original"></param>
        /// <param name="origin"></param>
        /// <returns></returns>
        private static SKBitmap AutoOrient(SKBitmap original, SKEncodedOrigin origin)
        {
            Stopwatch orient = new Stopwatch("SkiaSharpOrient");

            var useWidth  = original.Width;
            var useHeight = original.Height;
            Action <SKCanvas> transform = canvas => { };

            switch (origin)
            {
            case SKEncodedOrigin.TopLeft:
                break;

            case SKEncodedOrigin.TopRight:
                // flip along the x-axis
                transform = canvas => canvas.Scale(-1, 1, useWidth / 2, useHeight / 2);
                break;

            case SKEncodedOrigin.BottomRight:
                transform = canvas => canvas.RotateDegrees(180, useWidth / 2, useHeight / 2);
                break;

            case SKEncodedOrigin.BottomLeft:
                // flip along the y-axis
                transform = canvas => canvas.Scale(1, -1, useWidth / 2, useHeight / 2);
                break;

            case SKEncodedOrigin.LeftTop:
                useWidth  = original.Height;
                useHeight = original.Width;
                transform = canvas =>
                {
                    // Rotate 90
                    canvas.RotateDegrees(90, useWidth / 2, useHeight / 2);
                    canvas.Scale(useHeight * 1.0f / useWidth, -useWidth * 1.0f / useHeight, useWidth / 2, useHeight / 2);
                };
                break;

            case SKEncodedOrigin.RightTop:
                useWidth  = original.Height;
                useHeight = original.Width;
                transform = canvas =>
                {
                    canvas.Translate(useWidth, 0);
                    canvas.RotateDegrees(90);
                };
                break;

            case SKEncodedOrigin.RightBottom:
                useWidth  = original.Height;
                useHeight = original.Width;
                transform = canvas =>
                {
                    // Rotate 90
                    canvas.RotateDegrees(90, useWidth / 2, useHeight / 2);
                    canvas.Scale(-useHeight * 1.0f / useWidth, useWidth * 1.0f / useHeight, useWidth / 2, useHeight / 2);
                };
                break;

            case SKEncodedOrigin.LeftBottom:
                useWidth  = original.Height;
                useHeight = original.Width;
                transform = canvas =>
                {
                    canvas.Translate(0, useHeight);
                    canvas.RotateDegrees(270);
                };
                break;

            default:
                break;
            }

            var rotated = new SKBitmap(useWidth, useHeight);

            using (var canvas = new SKCanvas(rotated))
            {
                transform.Invoke(canvas);
                canvas.DrawBitmap(original, 0, 0);
            }

            orient.Stop();

            return(rotated);
        }
Exemplo n.º 14
0
        private async Task <Stream> Pixelate(SKBitmap bitmap, SKEncodedOrigin origin, IFeatureExtractor featureExtractor)
        {
            // fix orientation if encoded origin is not TopLeft/Default
            bitmap = FixOrientation(bitmap, origin);

            // a surface is something like a table we need to actually draw stuff
            var surface = SKSurface.Create(new SKImageInfo(bitmap.Width, bitmap.Height));
            // get the canvas where we actually draw onto
            var canvas = surface.Canvas;

            canvas.Clear(SKColors.Transparent);
            // apply the original image to the canvas
            canvas.DrawBitmap(bitmap, 0, 0);

            // extract the image features
            switch (FaceProcessing)
            {
            case FaceProcessing.PixelateFaces:
            {
                var faces = (await featureExtractor.ExtractFacesAsync()).ToArray();
                Logger.OnExtractedFaces(_imagePath, faces);
                foreach (var face in faces)
                {
                    if (FaceOutline != null)
                    {
                        Pixelate(canvas, SKRectI.Create(face.X, face.Y, face.Width, face.Height), bitmap, FaceOutline,
                                 PixelSizeFunction);
                    }
                    else
                    {
                        Pixelate(canvas, SKRectI.Create(face.X, face.Y, face.Width, face.Height), bitmap,
                                 PixelSizeFunction);
                    }

                    Logger.OnPixelatedFace(_imagePath, face);
                }

                break;
            }

            case FaceProcessing.PixelatePersons:
            {
                var persons = (await featureExtractor.ExtractPersonsAsync()).ToArray();
                Logger.OnExtractedPersons(_imagePath, persons);
                foreach (var person in persons)
                {
                    if (FaceOutline != null)
                    {
                        Pixelate(canvas, SKRectI.Create(person.X, person.Y, person.Width, person.Height), bitmap,
                                 FaceOutline, PixelSizeFunction);
                    }
                    else
                    {
                        Pixelate(canvas, SKRectI.Create(person.X, person.Y, person.Width, person.Height), bitmap,
                                 PixelSizeFunction);
                    }

                    Logger.OnPixelatedPerson(_imagePath, person);
                }

                break;
            }

            case FaceProcessing.Skip:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            switch (CarProcessing)
            {
            case CarProcessing.PixelatePlatesAndTextOnCars:
            {
                var text = (await featureExtractor.ExtractTextAsync()).ToArray();
                Logger.OnExtractedText(_imagePath, text);
                var cars = (await featureExtractor.ExtractCarsAsync()).ToArray();
                Logger.OnExtractedCars(_imagePath, cars);
                var licensePlates = (await featureExtractor.ExtractLicensePlatesAsync()).ToArray();
                Logger.OnExtractedLicensePlates(_imagePath, licensePlates);

                var mergeDistance = (int)(bitmap.Width * MergeFactor);
                var merged        = ImagePatchClusterizer.Clusterize(text, mergeDistance).ToArray();

                foreach (var car in cars)
                {
                    foreach (var patch in merged)
                    {
                        // If patch is inside of the car borders
                        if (patch.Y >= car.Y &&
                            patch.X >= car.X &&
                            patch.Y <= car.Y + car.Height &&
                            patch.X <= car.X + car.Width &&
                            patch.Width <= car.Width + car.X - patch.X &&
                            patch.Height <= car.Height + car.Y - patch.Y)
                        {
                            if (PlateOutline != null)
                            {
                                Pixelate(canvas, SKRectI.Create(patch.X, patch.Y, patch.Width, patch.Height),
                                         bitmap, PlateOutline, PixelSizeFunction);
                            }
                            else
                            {
                                Pixelate(canvas, SKRectI.Create(patch.X, patch.Y, patch.Width, patch.Height),
                                         bitmap, PixelSizeFunction);
                            }

                            Logger.OnPixelatedText(_imagePath, patch);
                        }
                    }
                }

                foreach (var plate in licensePlates)
                {
                    if (PlateOutline != null)
                    {
                        Pixelate(canvas, SKRectI.Create(plate.X, plate.Y, plate.Width, plate.Height), bitmap,
                                 PlateOutline, PixelSizeFunction);
                    }
                    else
                    {
                        Pixelate(canvas, SKRectI.Create(plate.X, plate.Y, plate.Width, plate.Height), bitmap,
                                 PixelSizeFunction);
                    }

                    Logger.OnPixelatedLicensePlate(_imagePath, plate);
                }

                break;
            }

            case CarProcessing.PixelateCars:
            {
                var cars = (await featureExtractor.ExtractCarsAsync()).ToArray();
                Logger.OnExtractedCars(_imagePath, cars);
                foreach (var car in cars)
                {
                    if (PlateOutline != null)
                    {
                        Pixelate(canvas, SKRectI.Create(car.X, car.Y, car.Width, car.Height), bitmap, PlateOutline,
                                 PixelSizeFunction);
                    }
                    else
                    {
                        Pixelate(canvas, SKRectI.Create(car.X, car.Y, car.Width, car.Height), bitmap,
                                 PixelSizeFunction);
                    }

                    Logger.OnPixelatedCar(_imagePath, car);
                }

                break;
            }

            case CarProcessing.Skip:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(surface.Snapshot().Encode(OutputFormat, OutputQuality).AsStream());
        }