예제 #1
0
        // Convert bitmap:
        // 1. Trim to square
        // 2. Resize to 28x28 pixels
        // 3. Grayscale with high contrast
        SKBitmap ConvertBitmap(SKBitmap bitmap, float contr = contrast)
        {
            // 0. bitmap initialized?
            if (bitmap == null)
            {
                return(null);
            }

            // 1. Square bitmap (if not done by media plugin)
            if (bitmap.Width != bitmap.Height)
            {
                // Calculate size and start coordinates of square
                int size = Math.Min(bitmap.Width, bitmap.Height);
                int left = (bitmap.Width - size) / 2;
                int top  = (bitmap.Height - size) / 2;

                // Cut centered square
                bitmap.ExtractSubset(bitmap, new SKRectI(left, top, left + size, top + size));
            }

            // 2. Resize to 28x28 pixels (if not done by media plugin)
            if (bitmap.Width != 28)
            {
                SKBitmap bitmap_copy = bitmap.Copy();
                bitmap = new SKBitmap(28, 28, bitmap.ColorType, bitmap.AlphaType);
                bitmap_copy.Resize(bitmap, SKBitmapResizeMethod.Box);
            }

            // 3. Convert bitmap to grayscale and apply contrast to emphasize lines
            // Second grayscale conversion to highlight pen color again which may be suppressed by resizing
            bitmap = ConvertBitmapToGray(bitmap, contr);

            return(bitmap);
        }
예제 #2
0
 // Working with a fix sized texture (512x512, 1024x1024, etc.).
 public Texture(SKBitmap image)
 {
     bmp            = image.Copy();
     this.width     = bmp.Width;
     this.height    = bmp.Height;
     internalBuffer = (byte *)bmp.GetPixels();
 }
예제 #3
0
        private static SKBitmap LoadFile(string filepath)
        {
            using var image = Pfim.Pfim.FromFile(filepath);
            if (image.Format != Pfim.ImageFormat.Rgba32 || image.Compressed)
            {
                throw new InvalidOperationException("Unexpected image format");
            }

            var info = new SKImageInfo(image.Width, image.Height, SKColorType.Bgra8888, SKAlphaType.Unpremul);

            unsafe
            {
                fixed(byte *pData = image.Data)
                {
                    using var bmp = new SKBitmap(info);
                    if (!bmp.InstallPixels(info, (IntPtr)pData, image.Stride))
                    {
                        throw new InvalidOperationException("Failed to load pixmap content");
                    }

                    //Copying the bitmap seems to be the only reliable way to avoid
                    //AccessViolationExceptions in Skia, even though we created it above
                    return(bmp.Copy());
                }
            }
        }
예제 #4
0
        public IImageBuffer SKBitmapToImageBuffer(SKBitmap bitmap)
        {
            if (bitmap == null)
            {
                return(null);
            }

            if (bitmap.ColorType != SKColorType.Rgba8888 && bitmap.ColorType != SKColorType.Bgra8888 && bitmap.ColorType != SKColorType.Gray8)
            {
                // try to convert image to 32BPP bitmap if source pixel format is unknown
                if (!bitmap.CanCopyTo(SKColorType.Rgba8888))
                {
                    throw new NotSupportedException("SKImage Input pixel format not supported.");
                }

                using (bitmap = bitmap.Copy(SKColorType.Rgba8888))
                {
                    return(ToImageBuffer(bitmap));
                }
            }
            else
            {
                return(ToImageBuffer(bitmap));
            }
        }
예제 #5
0
        /// <summary>
        /// Crop the image to fit within the dimensions specified.
        /// </summary>
        /// <param name="original"></param>
        /// <param name="maxSize"></param>
        /// <returns></returns>
        private SKBitmap Crop(SKBitmap original, SKSize maxSize)
        {
            var cropSides     = 0;
            var cropTopBottom = 0;

            // calculate amount of pixels to remove from sides and top/bottom
            if ((float)maxSize.Width / original.Width < maxSize.Height / original.Height) // crop sides
            {
                cropSides = original.Width - (int)Math.Round((float)original.Height / maxSize.Height * maxSize.Width);
            }
            else
            {
                cropTopBottom = original.Height - (int)Math.Round((float)original.Width / maxSize.Width * maxSize.Height);
            }

            if (cropSides > 0 || cropTopBottom > 0)
            {
                // setup crop rect
                var cropRect = new SKRectI
                {
                    Left   = cropSides / 2,
                    Top    = cropTopBottom / 2,
                    Right  = original.Width - cropSides + cropSides / 2,
                    Bottom = original.Height - cropTopBottom + cropTopBottom / 2
                };

                return(Crop(original, cropRect));
            }
            else
            {
                return(original.Copy());
            }
        }
예제 #6
0
        /// <summary>
        /// Returns Texture Atlas' Bitmap
        /// </summary>
        /// <param name="colorType">The color type of the resulting bitmap</param>
        /// <returns>The texture atlas' bitmap</returns>
        private SKBitmap GetBitmap(SKColorType colorType = SKColorType.Rgba8888)
        {
            using (SKBitmap bmp = new SKBitmap(Width, Height, colorType, SKAlphaType.Premul)) //Premul needed for transparency !
            {
                bmp.Erase(SKColors.Transparent);                                              //DIDNT WORK WITHOUT THIS !!!! ctor of SKBitmap sometimes returned bitmap that was not clear ..
                                                                                              //When clicked several times on Generate atlas (with for example genetic, maxIterations 12300)

                using (SKCanvas canvas = new SKCanvas(bmp))
                {
                    foreach (var img in Rects)
                    {
                        canvas.DrawBitmap(img.Image.Bitmap, img.Rect);
                    }
                }

                //It may return Null, if SKColorType == Unknown, as it is not supported now
                var res = bmp.Copy();  //We have to return copy because we do not want to allow someone who got the bitmap to write into it
                if (res == null)
                {
                    res = new SKBitmap(Width, Height);
                    res.Erase(SKColors.Transparent);
                }

                return(res);
            }
        }
예제 #7
0
        public IBitmap Clone(PixelFormat format)
        {
            if (_bitmap != null)
            {
                return(new SkiaBitmap(_bitmap.Copy(format.ToSKColorType())));
            }

            return(null);
        }
예제 #8
0
        public static SKBitmap HandleOrientation(SKBitmap bitmap, ExifOrientation exifOrientation)
        {
            SKBitmap rotated;

            switch (exifOrientation)
            {
            case ExifOrientation.Rotate180:

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

                return(bitmap);

            case ExifOrientation.MirrorHorizontal:
                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 ExifOrientation.MirrorVertical:
                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);

            case ExifOrientation.Rotate90:

                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);

            default:
                return(bitmap);
            }
        }
예제 #9
0
 public IBitmapImpl LoadBitmap(PixelFormat format, IntPtr data, int width, int height, int stride)
 {
     using (var tmp = new SKBitmap())
     {
         tmp.InstallPixels(new SKImageInfo(width, height, format.ToSkColorType(), SKAlphaType.Premul)
                           , data, stride);
         return(new BitmapImpl(tmp.Copy()));
     }
 }
예제 #10
0
        /// <summary>
        /// Resize using SkiaSharp - this can do 100 images in about 30s (2020 i5 MacBook Air).
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destFiles"></param>
        public void CreateThumbs(FileInfo source, IDictionary <FileInfo, ThumbConfig> destFiles, out string imageHash)
        {
            try
            {
                int desiredWidth = destFiles.Max(x => x.Value.width);

                using var sourceBitmap = LoadOrientedBitmap(source, desiredWidth);

                imageHash = GetHash(sourceBitmap);

                Stopwatch thumbs = new Stopwatch("SkiaSharpThumbs");

                // Dropping this from High to Low doesn't have that much of an effect
                // in terms of performance.
                var quality   = SKFilterQuality.Low;
                var srcBitmap = sourceBitmap;

                foreach (var pair in destFiles.OrderByDescending(x => x.Value.width))
                {
                    var dest   = pair.Key;
                    var config = pair.Value;

                    float widthScaleFactor = (float)srcBitmap.Width / (float)config.width;
                    float heighScaleFactor = (float)srcBitmap.Height / (float)config.height;
                    float scaleFactor      = Math.Min(widthScaleFactor, heighScaleFactor);

                    using var scaledImage = new SKBitmap((int)(srcBitmap.Width / scaleFactor), (int)(srcBitmap.Height / scaleFactor));
                    srcBitmap.ScalePixels(scaledImage.PeekPixels(), quality);

                    var cropSize = new SKSize {
                        Height = config.height, Width = config.width
                    };
                    using var cropped = config.cropToRatio ? Crop(scaledImage, cropSize) : scaledImage;

                    using SKData data = cropped.Encode(SKEncodedImageFormat.Jpeg, 90);

                    using (var stream = new FileStream(dest.FullName, FileMode.Create, FileAccess.Write))
                        data.SaveTo(stream);

                    // Now, use the previous scaled image as the basis for the
                    // next smaller thumbnail. This should reduce processing
                    // time as we only work on the large image on the first
                    // iteration
                    srcBitmap = scaledImage.Copy();

                    // TODO: Dispose
                }

                thumbs.Stop();
            }
            catch (Exception ex)
            {
                Logging.Log($"Exception during Skia processing: {ex.Message}");
                throw;
            }
        }
예제 #11
0
        private SKBitmap RotateBitmap(SKBitmap bitmap, int degrees)
        {
            using (var surface = new SKCanvas(bitmap))
            {
                surface.RotateDegrees(degrees, bitmap.Width / 2, bitmap.Height / 2);
                surface.DrawBitmap(bitmap.Copy(), 0, 0);
            }

            return(bitmap);
        }
예제 #12
0
 internal ImageEditorViewModel(SKBitmap bitmap, ImageEditorConfig config)
 {
     Config        = config;
     cropperCanvas = new ImageCropperCanvasView(bitmap, config.CropAspectRatio);
     mainCanvas    = new TouchManipulationCanvasView(config);
     mainCanvas.AddBitmapToCanvas(bitmap.Copy(), BitmapType.Main);
     mainCanvas.TextBitmapClicked += MainCanvas_TextBitmapClicked;
     mainCanvas.TrashEnabled      += MainCanvas_TrashVisebled;
     ColorCollect = SkiaHelper.GetColors();
     CropCollect  = CropItem.GetCropItems(config.CanChangeCropAspectRatio);
     Message      = config?.LoadingText;
 }
예제 #13
0
        public static SKBitmap LayerImage(SKBitmap baseLayer, SKBitmap overLayer, int x, int y)
        {
            if (baseLayer == null)
            {
                return(overLayer);
            }
            var img  = baseLayer.Copy();
            var rect = new SKRect(x, y, overLayer.Width + x, overLayer.Height + y);

            using var gr = new SKCanvas(img);
            gr.DrawBitmap(overLayer, rect);
            return(img);
        }
예제 #14
0
        /// <summary>
        /// Loads an image at a given path
        /// </summary>
        /// <remarks>Does not check for the existence of the image</remarks>
        /// <param name="path">Path of the image to be loaded</param>
        /// <returns>The loaded image</returns>
        private static PPImage FastLoad(string path)
        {
            SKBitmap result = null;

            using (var sr = File.OpenRead(path))
                using (var stream = new SKManagedStream(sr))
                {
                    result = SKBitmap.Decode(stream);
                    result = result.Copy();
                }

            return(new PPImage(result, path));
        }
 internal ImageEditorViewModel(SKBitmap bitmap, ImageEditorConfig config)
 {
     Config        = config;
     cropperCanvas = new ImageCropperCanvasView(bitmap, config.CropAspectRatio);
     mainCanvas    = new TouchManipulationCanvasView(config);
     mainCanvas.AddBitmapToCanvas(bitmap.Copy(), BitmapType.Main);
     mainCanvas.TextBitmapClicked += MainCanvas_TextBitmapClicked;
     mainCanvas.TrashEnabled      += MainCanvas_TrashVisebled;
     ColorCollect = SkiaHelper.GetColors();
     CropCollect  = CropItem.GetCropItems(config.CanChangeCropAspectRatio);
     Message      = config?.LoadingText;
     MessagingCenter.Subscribe <Xamarin.Forms.Application>(this, "BBDroidBackButton", (sender) => OnBackPressed());
 }
예제 #16
0
        public static SKBitmap ChangeAllColorTo(SKBitmap img, SKColor c)
        {
            if (img == null)
            {
                return(null);
            }

            var bmp  = img.Copy();
            var data = GetBitmapData(img);

            ChangeAllColorTo(data, c);
            SetBitmapData(bmp, data);
            return(bmp);
        }
예제 #17
0
        public static SKBitmap ChangeOpacity(SKBitmap img, double trans)
        {
            if (img == null)
            {
                return(null);
            }

            var bmp  = img.Copy();
            var data = GetBitmapData(img);

            SetAllTransparencyTo(data, trans);
            SetBitmapData(bmp, data);
            return(bmp);
        }
예제 #18
0
        public static SKBitmap ToGrayscale(SKBitmap img)
        {
            if (img == null)
            {
                return(null);
            }

            var bmp  = img.Copy();
            var data = GetBitmapData(img);

            SetAllColorToGrayScale(data);
            SetBitmapData(bmp, data);
            return(bmp);
        }
예제 #19
0
 F9PImageData(SKBitmap skBitamp, string key)
 {
     RangeLists = skBitamp.PatchRanges();
     if (RangeLists?.PatchesX != null && RangeLists.PatchesX.Count > 0 && RangeLists.PatchesY != null && RangeLists.PatchesY.Count > 0)
     {
         SKBitmap unmarkedBitmap = new SKBitmap(skBitamp.Width - 1, skBitamp.Height - 1, SKColorType.Rgba8888, SKAlphaType.Unpremul);
         skBitamp.ExtractSubset(unmarkedBitmap, SKRectI.Create(1, 1, skBitamp.Width - 2, skBitamp.Height - 2));
         skBitamp.Dispose();
         skBitamp = unmarkedBitmap.Copy();
     }
     _width   = skBitamp.Width;
     _height  = skBitamp.Height;
     SKBitmap = skBitamp;
     Key      = key;
 }
예제 #20
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);
        }
예제 #21
0
 public void QueueLoad(string tex, SKBitmap image)
 {
     if (textures.ContainsKey(tex))
     {
         return;
     }
     if (image.ColorType != SKColorType.Bgra8888)
     {
         SKBitmap img;
         using (image)
         {
             img = image.Copy(SKColorType.Bgra8888);
         }
         image = img;
     }
     loadTexQueue[tex] = image;
 }
        private async void SKElement_OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            Debug.WriteLine($"Enter OnPaintSurface: ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

            if (backgroundTask == null)
            {
                backgroundTask = Task.Run(() =>
                {
                    Debug.WriteLine($"Enter Background: ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

                    using (var bitmap = new SKBitmap(e.Info.Width, e.Info.Height))
                    {
                        using (var canvas = new SKCanvas(bitmap))
                            using (var paint = new SKPaint())
                            {
                                canvas.DrawCircle(e.Info.Width / 2f, e.Info.Height / 2f, 100, paint);
                            }

                        return(bitmap.Copy());
                    }
                });
            }
            else
            {
                // When task is awaited below we will get a second call to this method but we just ignore that for now
                Debug.WriteLine($"Exit OnPaintSurface Because Background Processing: ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                return;
            }

            if (backgroundTask != null)
            {
                Debug.WriteLine($"Before Background Await: ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                backgroundBitmap = await backgroundTask;
                Debug.WriteLine($"After Background Await: ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
            }

            if (backgroundBitmap != null)
            {
                Debug.WriteLine($"DrawBitmap: ReadyToDraw={backgroundBitmap.ReadyToDraw}");
                Debug.WriteLine($"DrawBitmap: ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

                // This call will throw an AccessViolationException, but why?
                e.Surface.Canvas.DrawBitmap(backgroundBitmap, 0, 0);
            }
        }
예제 #23
0
        // Got the code from https://stackoverflow.com/a/45620498/1074470
        private static SKBitmap HandleOrientation(SKBitmap bitmap, SKCodecOrigin orientation)
        {
            SKBitmap rotated;

            switch (orientation)
            {
            case SKCodecOrigin.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 SKCodecOrigin.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 SKCodecOrigin.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);
            }
        }
예제 #24
0
        private SKBitmap DrawFrame(Model model)
        {
            SKBitmap currentFrame = new SKBitmap(1602, 1050);

            switch (model.Layout)
            {
            case LayoutType.Normal:
                currentFrame      = DrawNormal(model);
                _lastframe        = currentFrame;
                _lostHpCheckpoint = model.SideData.Health > previousHP ? 0 : model.SideData.Health == previousHP ? _lostHpCheckpoint : previousHP;
                _lostMpCheckpoint = model.SideData.Magic > previousMP ? 0 : model.SideData.Magic == previousMP ? _lostMpCheckpoint : previousMP;
                previousHP        = model.SideData.Health;
                previousMP        = model.SideData.Magic;
                break;

            case LayoutType.ConsoleSwitch:
                currentFrame      = DrawConsoleSwitch(model);
                _lastframe        = currentFrame;
                _lostHpCheckpoint = model.SideData.Health > previousHP ? 0 : model.SideData.Health;
                _lostMpCheckpoint = model.SideData.Magic > previousMP ? 0 : model.SideData.Magic;
                previousHP        = model.SideData.Health;
                previousMP        = model.SideData.Magic;
                break;

            case LayoutType.TextOnly:
                currentFrame = DrawTextBox(model, _lastframe);
                break;

            case LayoutType.MapOnly:
                currentFrame = DrawMap(model);
                break;

            case LayoutType.ConsoleFull:
                currentFrame = DrawConsoleFull(model);
                break;

            default:
                break;
            }
            SKBitmap forupdate = currentFrame.Copy();

            return(forupdate);
        }
예제 #25
0
        private SKBitmap DrawTextBox(Model model, SKBitmap lastframe)
        {
            SKBitmap overlayImage = lastframe.Copy();

            using (SKCanvas g = new SKCanvas(overlayImage))
            {
                var font = new SKPaint {
                    Typeface    = SKTypeface.FromFamilyName("Courier New"),
                    TextSize    = 12,
                    IsAntialias = true,
                };
                var darkPen = new SKPaint()
                {
                    Color       = SKColors.Black,
                    StrokeWidth = 2,
                    Style       = SKPaintStyle.StrokeAndFill
                };
                var rect2 = new SKRect(25, 25, 25 + 1000, 25 + 430);
                g.DrawRect(rect2, darkPen);
                darkPen = new SKPaint()
                {
                    Color       = new SKColor(255, 125, 98, 60),
                    StrokeWidth = 2,
                    Style       = SKPaintStyle.Stroke
                };
                g.DrawRect(rect2, darkPen);

                float x = 50;
                float y = 34;
                for (int i = 0; i < model.TileNames.Length; i++)
                {
                    if (i % model.LineLength == 0)//next line
                    {
                        x  = 50;
                        y += 16;
                    }
                    g.WriteCharacter(model.TileNames[i], font, x, y);
                    x += 12;
                }
            }

            return(overlayImage);
        }
예제 #26
0
        public void Save(string fileName)
        {
#if DESKTOP
            if (Bitmap.ColorType != SKColorType.Bgra8888)
            {
                using (var tmp = new BitmapImpl(Bitmap.Copy(SKColorType.Bgra8888)))
                    tmp.Save(fileName);
                return;
            }

            IntPtr length;
            using (var sdb = new System.Drawing.Bitmap(PixelWidth, PixelHeight, Bitmap.RowBytes,

                                                       System.Drawing.Imaging.PixelFormat.Format32bppArgb,

                                                       Bitmap.GetPixels(out length)))
                sdb.Save(fileName);
#else
            //SkiaSharp doesn't expose image encoders yet
#endif
        }
예제 #27
0
        /// <summary>
        /// Overlays 'overlayImage' over 'originalImage' with <see cref="CAMBlendMode"/>
        /// </summary>
        /// <returns>The resulting image.</returns>
        /// <param name="originalImage">The image to use as the background.</param>
        /// <param name="overlayImage">The image to overlay on the background.</param>
        public static SKBitmap OverlayImage(SKBitmap originalImage, SKBitmap overlayImage)
        {
            if (originalImage.Width != overlayImage.Width || originalImage.Height != overlayImage.Height)
            {
                String errorMessage = String.Format("originalImage and overlayImage are not the same dimensions: original ~ {0}x{1} | overlay ~ {2}x{3}",
                                                    originalImage.Width, originalImage.Height,
                                                    overlayImage.Width, overlayImage.Height);
                throw new ArgumentException(errorMessage);
            }

            SKBitmap output   = originalImage.Copy();
            SKCanvas skCanvas = new SKCanvas(output);

            SKPaint skPaint = new SKPaint();

            skPaint.BlendMode = CAMBlendMode;

            skCanvas.DrawBitmap(overlayImage, 0, 0, skPaint);

            skCanvas.Flush();

            return(output);
        }
예제 #28
0
        /// <summary>
        /// Constructs an image from a given SKBitmap and obtains it's file name from a given pat
        /// </summary>
        /// <param name="skBmp">The SKBitmap from which an image should be created</param>
        /// <param name="filePath">The path of the image</param>
        /// <param name="isRotated">Whether the image is rotated by 90 degrees</param>
        public PPImage(SKBitmap skBmp, string filePath, bool isRotated = false)
        {
            if (skBmp == null)
            {
                throw new ArgumentNullException($"The {nameof(skBmp)} cannot be null");
            }

            Bitmap              = skBmp.Copy();
            ImagePath           = filePath;
            ImageName           = System.IO.Path.GetFileName(filePath);
            OriginalWidth       = FinalWidth = skBmp.Width;
            OriginalHeight      = FinalHeight = skBmp.Height;
            NoWhiteSpaceXOffset = NoWhiteSpaceYOffset = 0;
            IsRotated           = isRotated;
            Aliases             = Enumerable.Empty <(string AliasedName, string AliasedPath)>();
            bitmapHash          = new Lazy <string>(() =>
            {
                using (var sha = new SHA256Managed())
                {
                    return(Convert.ToBase64String(sha.ComputeHash(Bitmap.Bytes)));
                }
            }, true);
        }
예제 #29
0
 public void Dispose()
 {
     using (var tmp = _bitmap.Copy(_nfo.ColorType))
         tmp.CopyPixelsTo(_fb, _nfo.BytesPerPixel * _nfo.Height * _rowBytes, _rowBytes);
     _bitmap.Dispose();
 }
예제 #30
0
        ///<inheritdoc/>
        public override Task InjectAsync(Stream source, Stream destination, Stream data, IProgress <double> progress = null, CancellationToken cancellationToken = default)
        {
            SKBitmap inputImage = SKBitmap.Decode(source);

            int width  = inputImage.Width;
            int height = inputImage.Height;

            List <byte> ls_data = new List <byte>();

            ls_data.AddRange(data.ReadAllBytes());

            if (Eof != null)
            {
                ls_data.AddRange(Eof);
            }

            BitArray message = new BitArray(ls_data.ToArray());

            int count = message.Count;

            if (EnsureSuccess)
            {
                int maxWritable = (UseAlphaChannel ? 4 : 3) * LsbDepth * width * height;

                if (count > maxWritable)
                {
                    throw new InsufficientSpaceException("A successful write cannot be ensured because the data is too large");
                }
            }

            SKBitmap outputImage = inputImage.Copy();

            int pos = 0;

            for (int y = 0; y < height; y++)
            {
                bool stop = false;
                for (int x = 0; x < width; x++)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                    }

                    if (pos == count)
                    {
                        stop = true;
                        break;
                    }

                    SKColor pixel = inputImage.GetPixel(x, y);

                    int[] vals = new int[] { pixel.Alpha, pixel.Red, pixel.Green, pixel.Blue };

                    for (int v = 0; v < vals.Length; v++)
                    {
                        if (!UseAlphaChannel && v == 0)
                        {
                            continue;
                        }

                        BitArray bitArray = new BitArray(new[] { vals[v] });
                        for (int i = 0; i < LsbDepth; i++)
                        {
                            if (pos == count)
                            {
                                stop = true;
                                break;
                            }

                            bitArray[i] = message[pos];
                            pos++;
                        }

                        vals[v] = (int)bitArray.ToULong();
                        if (stop)
                        {
                            break;
                        }
                    }

                    pixel = new SKColor((byte)vals[1], (byte)vals[2], (byte)vals[3], (byte)vals[0]);

                    outputImage.SetPixel(x, y, pixel);

                    if (progress != null)
                    {
                        progress.Report(pos / (double)count);
                    }
                }

                if (stop)
                {
                    break;
                }
            }

            outputImage.Encode(destination, SKEncodedImageFormat.Png, 100);

            return(Task.CompletedTask);
        }