georg-jung / MozJpegSharp

MozJPEG wrapper for .Net
MIT License
21 stars 1 forks source link

Pixelation when under .netcore linux #74

Closed maxenko closed 2 years ago

maxenko commented 2 years ago

I am running into pixilation issue when using MozJpegSharp from within docker deployment via standard MS template which is Debian.

When running compression from within VS on windows - results are good. However after deploying the same code to Docker, compressing any image appears to cause fairly noticeable pixilation.

I've tried changing parameters, but the results are the same.

Windows: test_thumb_win

Linux: test_thumb_lin

Source file: test

Any suggestions appreciated.

Encoding with (F#):

let writeMozJpg (img:System.Drawing.Image) path =
        async {
            use bmp = new System.Drawing.Bitmap(img)
            use tjc = new MozJpegSharp.TJCompressor();
            let compressedBytes = tjc.Compress(bmp, MozJpegSharp.TJSubsamplingOption.Chrominance420, 75, MozJpegSharp.TJFlags.AccurateDct)

            if compressedBytes.Length > 0 then
                use file = File.Create(path)
                do! file.AsyncWrite(compressedBytes,0,compressedBytes.Length)
                file.Close()
                return (true, path)
            else
                return (false, String.Empty)
        }

Dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:5.0
EXPOSE 8181

RUN apt update
RUN apt install -y libgdiplus
RUN apt install -y libturbojpeg0

COPY bin/Release/net5.0/publish/ App/
WORKDIR /App
ENTRYPOINT ["dotnet", "matter.App.dll", "appsettings.json"]
georg-jung commented 2 years ago

Are you sure this is related to MozJpegSharp?

Thoughts:

What would be helpful to further diagnose your problem

maxenko commented 2 years ago

@georg-jung thank you for quick response, I will investigate further based on your suggestions.

It works perfect under windows, so I am not entirely sure why resizing would affect it. Its likely the linux library like you're saying.

I am using standard .net for resizing:

    let resizeByWidth (img:System.Drawing.Image) w = 
        let _w          = (float)w
        let _ratio      = _w / (float)img.Width
        let _h          = Math.Max( 1.0, (float)img.Height * _ratio)
        (new Bitmap(img, (int)_w, (int)_h)) :> System.Drawing.Image

which is called from:

    let saveMozJpgThumb toPath stream resX =
        async {
            use img = Image.FromStream stream
            use resized = resizeByWidth img resX
            return! writeMozJpg resized toPath
        }

Looking into other suggestions now, thank you.

georg-jung commented 2 years ago

It works perfect under windows, so I am not entirely sure why resizing would affect it

What I'm saying is that I could imagine that the resizing causes the pixelation on Linux, not saving using MozJpegSharp. Resizing can be done in many different ways. See i.e. here. Now, the code you posted might see how/which way resizing is done as an implementation detail. And the implementations of GDI+ on Windows and libgdiplus on Linux differ. Hope this helps.

maxenko commented 2 years ago

@georg-jung you're correct, this has nothing to do with your library. Apologies for false alarm. I think the defaults are different between implementations.

This works:

    let resizeByWidth (img:System.Drawing.Image) w = 
        let _w          = (float)w
        let _ratio      = _w / (float)img.Width
        let _h          = Math.Max( 1.0, (float)img.Height * _ratio)
        let bmp         = new Bitmap((int)_w, (int)_h)
        use g           = Graphics.FromImage(bmp)

        g.InterpolationMode <- InterpolationMode.High

        let rect = new System.Drawing.Rectangle(0, 0, (int)_w, (int)_h)
        g.DrawImage(img, rect);
        bmp