Beispiel #1
0
        public BasicStats GetStats(BitmapAdapter bitmap, ImageManipulationInfo manipulationInfo)
        {
            // Console.WriteLine(manipulationInfo.ToString());
            var fast = new FastBitmap.FastBitmap(bitmap.GetSegment(manipulationInfo));

            return(GetBasicStats(fast, new Rectangle(0, 0, fast.Width, fast.Height)));
        }
Beispiel #2
0
 public IEnumerable <Bitmap> GetRefinedMatches2(FastBitmap.FastBitmap bitmap, ImageManipulationInfo manipulationInfo)
 {
     ImageSegments[] matches = _matchFinder.Value.GetMatches(_statsGenerator.GetStats(bitmap, manipulationInfo));
     return(_matchFinder.Value.RefineMatches2(_statsGenerator.GetAdvancedStats(bitmap, manipulationInfo.Rectangle), matches,
                                              _loader, _statsGenerator)
            .Select(m => new { Image = new BitmapAdapter(m.Image.ToBitmap()), Segments = m.ManipulationInfos })
            .SelectMany(m => m.Segments.Select(m.Image.GetSegment)));
 }
Beispiel #3
0
        public Bitmap GetSegment(ImageManipulationInfo manipulationInfo)
        {
            var targetBitmap = new Bitmap(manipulationInfo.Width, manipulationInfo.Height);

            FastBitmap.FastBitmap segment = new FastBitmap.FastBitmap(targetBitmap);
            segment.Lock();
            segment.CopyRegion(_bitmap,
                               manipulationInfo.Rectangle,
                               manipulationInfo.AsZeroBasedRectangleOfSameSize());
            segment.Unlock();
            return(targetBitmap);
        }
Beispiel #4
0
        private ImageAndStats GetMatchableSegments(PhysicalImage physicalImage)
        {
            var img = _loader.LoadImage(physicalImage.ImagePath);
            // For movie stills with widescreen bars above/below, start further down and end higher up
            IEnumerable <Rectangle> rects = GetSegmentRectangles(new Rectangle(6, 6, img.Width - 12, img.Height - 12));
            // IEnumerable<Rectangle> rects = GetSegmentRectangles(new Rectangle(0, 0, img.Width, img.Height));
            var segmentStats = new List <SegmentAndStats>();

            foreach (var rectangle in rects)
            {
                var imageManipulationInfo   = new ImageManipulationInfo(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
                Stats.BasicStats basicStats = GetStats(physicalImage,
                                                       imageManipulationInfo);
                segmentStats.Add(new SegmentAndStats(imageManipulationInfo, basicStats));
            }

            return(new ImageAndStats(physicalImage, segmentStats));
        }
        private void WriteSourceAndFill(SourceAndMatch match)
        {
            FastBitmap.FastBitmap fillImage = new FastBitmap.FastBitmap(match.ReplacementImage);

            fillImage.Lock();

            ImageManipulationInfo hole = match.SourceSegment;

            for (int xOffset = 0; xOffset < hole.Width; xOffset++)
            {
                for (int yOffset = 0; yOffset < hole.Height; yOffset++)
                {
                    Color holeColor = _target.GetPixel(hole.StartX + xOffset, hole.StartY + yOffset);
                    Color fillColor = fillImage.GetPixel(xOffset, yOffset);
                    _newImage.SetPixel(hole.StartX + xOffset, hole.StartY + yOffset, GetNewColor(holeColor, fillColor));
                }
            }

            fillImage.Unlock();
        }
Beispiel #6
0
        public IEnumerable <Bitmap> GetRefinedMatches2(PhysicalImage image, ImageManipulationInfo manipulationInfo)
        {
            var bitmap = _loader.LoadImage(image.ImagePath);

            return(GetRefinedMatches2(bitmap, manipulationInfo));
        }
Beispiel #7
0
 public Bitmap GetBitmap(PhysicalImage physicalImage, ImageManipulationInfo manipulationInfo)
 {
     return(BitmapAdapter.FromPath(physicalImage.ImagePath, _loader)
            .GetSegment(manipulationInfo));
 }
Beispiel #8
0
 public SourceAndMatch(ImageManipulationInfo sourceSegment, Bitmap replacementImage)
 {
     SourceSegment    = sourceSegment;
     ReplacementImage = replacementImage;
 }
Beispiel #9
0
 public BasicStats GetStats(FastBitmap.FastBitmap bitmap, ImageManipulationInfo manipulationInfo)
 {
     return(GetBasicStats(bitmap, manipulationInfo.Rectangle));
 }
Beispiel #10
0
 public BasicStats GetStats(PhysicalImage image, ImageManipulationInfo manipulationInfo)
 {
     global::FastBitmap.FastBitmap bitmap = _loader.LoadImage(image.ImagePath);
     return(GetStats(bitmap, manipulationInfo));
 }
    /// <summary>
    /// Given some image data as a stream, transform the image to fit within the given size (of bytes) and save to the given savePath
    /// </summary>
    /// <param name="fileData"></param>
    /// <param name="maxSize"></param>
    /// <returns></returns>
    public async Task <ImageManipulationInfo> FitToSizeAndSave(Stream fileData, string savePath, int maxSize) //, double resizeFactor, double resizeFactorReduce)
    {
        var result = new ImageManipulationInfo {
            RenderCount = 0,
            LoadCount   = 1,
            SizeInBytes = fileData.Length
        };

        logger.LogTrace($"FitToSize called with size {maxSize}, image bytes {result.SizeInBytes}");

        await SingleManipLock.WaitAsync();

        try
        {
            using var memStream = new MemoryStream();

            await fileData.CopyToAsync(memStream);

            fileData.Seek(0, SeekOrigin.Begin);

            IImageFormat?format;

            //This will throw an exception if it's not an image (most likely)
            using (var image = Image.Load(fileData, out format))
            {
                double sizeFactor = ResizeFactor;
                result.Width    = image.Width;
                result.Height   = image.Height;
                result.MimeType = format.DefaultMimeType;

                //while (fileConfig.tryResize && imageByteCount > config.MaxSize && sizeFactor > 0)
                while (result.SizeInBytes > maxSize && sizeFactor > 0)
                {
                    double resize = 1 / Math.Sqrt(result.SizeInBytes / (maxSize * sizeFactor));
                    logger.LogWarning($"User image too large ({result.SizeInBytes}), trying ONE resize by {resize}");
                    result.Width  = (int)(result.Width * resize);
                    result.Height = (int)(result.Height * resize);
                    image.Mutate(x => x.Resize(result.Width, result.Height, KnownResamplers.Lanczos3));
                    result.RenderCount++;

                    memStream.SetLength(0);
                    image.Save(memStream, format);
                    result.SizeInBytes = memStream.Length;

                    //Keep targeting an EVEN more harsh error margin (even if it's incorrect because
                    //it stacks with previous resizes), also this makes the loop guaranteed to end
                    sizeFactor -= ResizeFactorReduce;
                }

                //If the image is still too big, bad ok bye
                if (result.SizeInBytes > maxSize)
                {
                    throw new RequestException("File too large!");
                }
            }

            logger.LogDebug($"New image size: {result.SizeInBytes}");
            memStream.Seek(0, SeekOrigin.Begin);

            using (var stream = System.IO.File.Create(savePath))
            {
                await memStream.CopyToAsync(stream);
            }
        }
        finally
        {
            SingleManipLock.Release();
        }

        return(result);
    }
    /// <summary>
    /// Given an image as a stream, perform the given modifications to it and save it to the given path
    /// </summary>
    /// <param name="fileData"></param>
    /// <param name="savePath"></param>
    /// <param name="modify"></param>
    /// <returns></returns>
    public async Task <ImageManipulationInfo> MakeThumbnailAndSave(Stream fileData, string savePath, GetFileModify modify) //, bool highQualityResize)
    {
        var result = new ImageManipulationInfo {
            RenderCount = 0,
            LoadCount   = 1
        };

        await SingleManipLock.WaitAsync();

        try
        {
            await Task.Run(() =>
            {
                IImageFormat?format;

                using var image = Image.Load(fileData, out format);

                result.MimeType = format.DefaultMimeType;

                //var maxDim = Math.Max(image.Width, image.Height);
                var isGif = format.DefaultMimeType == GifMime;
                var isJpg = format.DefaultMimeType == JpegMime;

                //Square ALWAYS happens, it can happen before other things.
                if (modify.crop)
                {
                    var minDim = Math.Min(image.Width, image.Height);
                    image.Mutate(x => x.Crop(new Rectangle((image.Width - minDim) / 2, (image.Height - minDim) / 2, minDim, minDim)));
                    result.RenderCount++;
                }

                //This must come after the crop!
                var isNowLarger = (modify.size > Math.Max(image.Width, image.Height));

                //Saving as png also works, but this preserves the format (even if it's a little heavier compute, it's only a one time thing)
                if (modify.freeze && isGif)
                {
                    while (image.Frames.Count > 1)
                    {
                        image.Frames.RemoveFrame(1);
                    }
                    result.RenderCount++;
                }

                if (modify.size > 0 && !(isGif && isNowLarger)) //&& (modify.size > image.Width || modify.size > image.Height)))
                {
                    var width  = 0;
                    var height = 0;

                    //Preserve aspect ratio when not square
                    if (image.Width > image.Height)
                    {
                        width = modify.size;
                    }
                    else
                    {
                        height = modify.size;
                    }

                    if (HighQualityResize)
                    {
                        image.Mutate(x => x.Resize(width, height, isNowLarger ? KnownResamplers.Spline : KnownResamplers.Lanczos3));
                    }
                    else
                    {
                        image.Mutate(x => x.Resize(width, height));
                    }

                    result.RenderCount++;
                }

                result.Width  = image.Width;
                result.Height = image.Height;

                using (var stream = System.IO.File.OpenWrite(savePath))
                {
                    IImageEncoder?encoder = null;

                    if (HighQualityResize && modify.size <= MinJpegHighQualitySize && isJpg)
                    {
                        encoder = new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder()
                        {
                            Quality = JpegHighQuality,
                        };
                    }

                    if (encoder != null)
                    {
                        image.Save(stream, encoder);
                    }
                    else
                    {
                        image.Save(stream, format);
                    }

                    result.SizeInBytes = stream.Length;
                }
            });
        }
        finally
        {
            SingleManipLock.Release();
        }


        return(result);
    }