SixLabors / ImageSharp

:camera: A modern, cross-platform, 2D Graphics library for .NET
https://sixlabors.com/products/imagesharp/
Other
7.41k stars 852 forks source link

A png image that is resized down to 1024x723 using the jpeg encoder still has a large (19MB) size. #2086

Closed saintarian closed 2 years ago

saintarian commented 2 years ago

Prerequisites

ImageSharp version

2.1.0

Other ImageSharp packages and versions

None

Environment (Operating system, version and so on)

MacOS 12.1 on M1 chip

.NET Framework version

6.0

Description

I expect the image size after resize to be less than max number of pixels (1024723) number of channels (3). It ends up being ~19MB. Running the code below (an xunit test) shows the issue.

output of magick identify -verbose original.png :

Image:
  Filename: original.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 2480x3508+0+0
  Resolution: 118.11x118.11
  Print size: 20.9974x29.7011
  Units: PixelsPerCentimeter
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianness: Undefined
  Depth: 8-bit
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
  Channel statistics:
    Pixels: 8699840
    Red:
      min: 0  (0)
      max: 255 (1)
      mean: 189.452 (0.742948)
      median: 180 (0.705882)
      standard deviation: 63.802 (0.250204)
      kurtosis: 1.30141
      skewness: -1.59459
      entropy: 0.859234
    Green:
      min: 0  (0)
      max: 255 (1)
      mean: 151.78 (0.595215)
      median: 153 (0.6)
      standard deviation: 75.4617 (0.295928)
      kurtosis: -1.2865
      skewness: -0.580092
      entropy: 0.907428
    Blue:
      min: 0  (0)
      max: 255 (1)
      mean: 136.935 (0.537001)
      median: 105 (0.411765)
      standard deviation: 66.6707 (0.261454)
      kurtosis: -1.48007
      skewness: -0.315278
      entropy: 0.909112
  Image statistics:
    Overall:
      min: 0  (0)
      max: 255 (1)
      mean: 159.389 (0.625055)
      median: 146 (0.572549)
      standard deviation: 68.6448 (0.269195)
      kurtosis: -1.0269
      skewness: -0.709272
      entropy: 0.891925
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Matte color: grey74
  Background color: white
  Border color: srgb(223,223,223)
  Transparent color: none
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 2480x3508+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: Zip
  Orientation: Undefined
  Profiles:
    Profile-xmp: 19227987 bytes
  Properties:
    date:create: 2022-04-13T18:07:22+00:00
    date:modify: 2022-04-12T20:26:24+00:00
    png:IHDR.bit-depth-orig: 8
    png:IHDR.bit_depth: 8
    png:IHDR.color-type-orig: 2
    png:IHDR.color_type: 2 (Truecolor)
    png:IHDR.interlace_method: 0 (Not interlaced)
    png:IHDR.width,height: 2480, 3508
    png:pHYs: x_res=11811, y_res=11811, units=1
    png:sRGB: intent=0 (Perceptual Intent)
    signature: a47f4c08c826c34b1abacfed65844509a8839d793c955dc503df6b3fce047c07
  Artifacts:
    verbose: true
  Tainted: False
  Filesize: 28.9882MiB
  Number pixels: 8699840
  Pixels per second: 10.8128MP
  User time: 0.500u
  Elapsed time: 0:01.804
  Version: ImageMagick 7.1.0-19 Q16-HDRI x86_64 2021-12-22 https://imagemagick.org

Output of magick identify -verbose resized.jpg :

Image:
  Filename: resized.jpeg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 723x1024+0+0
  Resolution: 300x300
  Print size: 2.41x3.41333
  Units: PixelsPerInch
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianness: Undefined
  Depth: 8-bit
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
  Channel statistics:
    Pixels: 740352
    Red:
      min: 0  (0)
      max: 255 (1)
      mean: 189.262 (0.742204)
      median: 180 (0.705882)
      standard deviation: 61.3584 (0.240621)
      kurtosis: 1.37133
      skewness: -1.5653
      entropy: 0.890046
    Green:
      min: 0  (0)
      max: 255 (1)
      mean: 151.687 (0.594851)
      median: 154 (0.603922)
      standard deviation: 72.9081 (0.285914)
      kurtosis: -1.29141
      skewness: -0.536618
      entropy: 0.943911
    Blue:
      min: 0  (0)
      max: 255 (1)
      mean: 136.941 (0.537023)
      median: 106 (0.415686)
      standard deviation: 64.3935 (0.252524)
      kurtosis: -1.48432
      skewness: -0.274613
      entropy: 0.937204
  Image statistics:
    Overall:
      min: 0  (0)
      max: 255 (1)
      mean: 159.297 (0.624693)
      median: 146.667 (0.575163)
      standard deviation: 66.22 (0.259686)
      kurtosis: -1.03134
      skewness: -0.670374
      entropy: 0.92372
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Matte color: grey74
  Background color: white
  Border color: srgb(223,223,223)
  Transparent color: none
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 723x1024+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 75
  Orientation: Undefined
  Properties:
    date:create: 2022-04-13T18:32:21+00:00
    date:modify: 2022-04-12T18:36:19+00:00
    jpeg:colorspace: 2
    jpeg:sampling-factor: 2x2,1x1,1x1
    signature: eb60b28a24cb785d09c0be390034efe01a83b899186895575658a6535e693d51
  Artifacts:
    verbose: true
  Tainted: False
  Filesize: 18.5004MiB
  Number pixels: 740352
  Pixels per second: 7.64465MP
  User time: 0.090u
  Elapsed time: 0:01.096
  Version: ImageMagick 7.1.0-19 Q16-HDRI x86_64 2021-12-22 https://imagemagick.org
identify: CorruptImageProfile `resized.jpeg' (XMP) @ warning/profile.c/ValidateXMPProfile/1934.

Steps to Reproduce

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Processing;
using Xunit;

public class ImageSharpResizeTest
{
    [Fact]
    public async Task TestResizedSize()
    {
        //string url = "https://storage.googleapis.com/doppel_nfts/b397a975-cc66-4cfe-85a0-ba8a613a6f7b";
        string url = "https://nyckel-public.s3.us-west-2.amazonaws.com/resize-issue-original.png";
        using var client = new HttpClient();
        using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);

        using (var stream = await response.Content.ReadAsStreamAsync())
        using (var resizedStream = new MemoryStream())
        using (var image = await SixLabors.ImageSharp.Image.LoadAsync(stream))
        {
            var resizeOptions = new ResizeOptions
            {
                Size = new SixLabors.ImageSharp.Size { Width = 1024, Height = 1024 },
                Mode = ResizeMode.Max
            };
            image.Mutate(x => x.Resize(resizeOptions));
            await image.SaveAsync(resizedStream, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder());

            var bytes = resizedStream.ToArray();
            Console.WriteLine($"Resized image size: {bytes.Length}");
            // resized image size should be less than max number of pixels (1024*1024) * number of channels (3)
            Assert.True(bytes.Length < 1024 * 1024 * 3);
        }
    }
}

Images

Using links because images are large:

Original: https://nyckel-public.s3.us-west-2.amazonaws.com/resize-issue-original.png

Resized: https://nyckel-public.s3.us-west-2.amazonaws.com/resize-issue-resized.jpeg

tocsoft commented 2 years ago

based on the output you provided you can see the image has a 19mb XMP profile (we don't touch that when re-encoding, we leave that up to you to manage) you need to make sure you null out that profile before calling save.

image.Metadata.XmpProfile = null;

you for other images withthsi same behaviour it might be a different profile at fault so you might want to also set the ExifProfile, IccProfile, and IptcProfiles to null too... but your millage may vary

tocsoft commented 2 years ago

it was this section of output you provided that you want to lookout for.

  Profiles:
    Profile-xmp: 19227987 bytes
saintarian commented 2 years ago

Got it - thank you @tocsoft! That did it.