Изменение размера большого изображения показывает пустым - PullRequest
0 голосов
/ 06 сентября 2018

При изменении размера большого изображения (> 6 МБ, 14034px на 9921px) процесс проходит без ошибок, но само изображение не отображается при сохранении, только белый фоновый холст.

Код отлично работает с небольшими изображениями.

Есть ли ограничение на размер обрабатываемого файла?

    using (SKMemoryStream sourceStream = new SKMemoryStream(imageData))
    {
        using (SKCodec codec = SKCodec.Create(sourceStream))
        {
            sourceStream.Seek(0);

            using (SKImage image = SKImage.FromEncodedData(SKData.Create(sourceStream)))
            {
                int newHeight = image.Height;
                int newWidth = image.Width;

                if (maxHeight > 0 && newHeight > maxHeight)
                {
                    double scale = (double)maxHeight / newHeight;
                    newHeight = maxHeight;
                    newWidth = (int)Math.Floor(newWidth * scale);
                }

                if (maxWidth > 0 && newWidth > maxWidth)
                {
                    double scale = (double)maxWidth / newWidth;
                    newWidth = maxWidth;
                    newHeight = (int)Math.Floor(newHeight * scale);
                }

                var info = codec.Info.ColorSpace.IsSrgb ? new SKImageInfo(newWidth, newHeight) : new SKImageInfo(newWidth, newHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul, SKColorSpace.CreateSrgb());
                using (SKSurface surface = SKSurface.Create(info))
                {
                    using (SKPaint paint = new SKPaint())
                    {
                        // High quality without antialiasing
                        paint.IsAntialias = true;
                        paint.FilterQuality = SKFilterQuality.High;

                        // Draw the bitmap to fill the surface
                        surface.Canvas.Clear(SKColors.White);
                        var rect = new SKRect(0, 0, newWidth, newHeight);
                        surface.Canvas.DrawImage(image, rect, paint);
                        surface.Canvas.Flush();

                        using (SKImage newImage = surface.Snapshot())
                        {
                            using (SKData newImageData = newImage.Encode(convertToJpeg ? SKEncodedImageFormat.Jpeg : (codec.EncodedFormat == SKEncodedImageFormat.Gif ? SKEncodedImageFormat.Png : codec.EncodedFormat), 
                                codec.EncodedFormat == SKEncodedImageFormat.Gif || codec.EncodedFormat == SKEncodedImageFormat.Png || !downsampleJpeg ? 100 : 85))
                            {
                                return newImageData.ToArray();
                            }
                        }
                    }
                }
            }
        }
    }

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Я обрезаю изображение и отображаю два растровых изображения

    SKRect display = CalculateDisplayRect(dest, scale * bitmap.Width, scale * bitmap.Height,
                                                          horizontal, vertical);
 SKRect newDest = new SKRect(display.Left, display.Top, display.Right, display.Bottom/2);
                    SKRect newSource = new SKRect(display.Left, display.Top, display.Right, display.Bottom / 2);
                    //canvas.DrawBitmap(bitmap, display, paint);
                    canvas.DrawBitmap(bitmap, newSource, newDest, paint);
                    SKRect newDest2 = new SKRect(display.Left, display.Top+ display.Bottom / 2, display.Right, display.Bottom );
                    SKRect newSource2 = new SKRect(display.Left, display.Top+ display.Bottom / 2, display.Right, display.Bottom );
                    //canvas.DrawBitmap(bitmap, display, paint);
                    canvas.DrawBitmap(bitmap, newSource2, newDest2, paint);


 static SKRect CalculateDisplayRect(SKRect dest, float bmpWidth, float bmpHeight,
                                           BitmapAlignment horizontal, BitmapAlignment vertical)
        {
            float x = 0;
            float y = 0;

            switch (horizontal)
            {
                case BitmapAlignment.Center:
                    x = (dest.Width - bmpWidth) / 2;
                    break;

                case BitmapAlignment.Start:
                    break;

                case BitmapAlignment.End:
                    x = dest.Width - bmpWidth;
                    break;
            }

            switch (vertical)
            {
                case BitmapAlignment.Center:
                    y = (dest.Height - bmpHeight) / 2;
                    break;

                case BitmapAlignment.Start:
                    break;

                case BitmapAlignment.End:
                    y = dest.Height - bmpHeight;
                    break;
            }

            x += dest.Left;
            y += dest.Top;

            return new SKRect(x, y, x + bmpWidth, y + bmpHeight);
        }
0 голосов
/ 10 сентября 2018

Я посмотрел на это и вижу, что это связано с максимальным размером буфера памяти. При рисовании Skia может понимать память только до максимального размера size_t.

При работе с x86 это составляет 4 294 967 295 байт. На моей машине x64 это значительно больше.

Я попытался изменить размер изображения RGBA с 46,080x31,320, но при запуске под x86 он не удался. Это связано с тем, что skia вычисляет значение 5 772 902 400 байт, которое переполняется. При запуске под x64 операция изменения размера завершается успешно.

Я открыл дискуссию на форумах Skia, чтобы посмотреть, что разработчики предлагают в качестве обходного пути: https://groups.google.com/forum/#!topic/skia-discuss/886WuVcQUGo

...