SixLabors / ImageSharp

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

SixLabors create an invalid file after conversion #2300

Closed sedjura closed 1 month ago

sedjura commented 1 year ago

Prerequisites

ImageSharp version

3.0.0-alpha.0.65

Other ImageSharp packages and versions

3.0.0-alpha.0.65

Environment (Operating system, version and so on)

Windows\Linux

.NET Framework version

6

Description

For version 65 of nightly sixlabors package we've met issue with image conversion We take original image from resources and convert it without options by sixlabors to jpg Result image in brokenImageModel.jpg file can be opened in MS Paint but cannot be edited or saved properly it can cause failures on s3 or cdn storages during upload with "File signature doesn't match" exception

Steps to Reproduce

1) Run console application from https://github.com/sedjura/SixLaborsBrokenImage or run code below 2) In application directory code will generate brokenImage.jpg 3) Open it with MS Paint and try to save 4) Paint will refuse to save it due to unknown error

using SixLaborsBrokenConversion.Properties;

namespace SixLaborsBrokenConversion;

/// <summary>
///     For version 65 of nightly sixlabors package we've met issue with image conversion
///     We take original image from resources and convert it without options by sixlabors to jpg
///     Result image in brokenImageModel.jpg file can be opened in MS Paint but cannot be
///     edited or saved properly
///     it can cause failures on s3 or cdn storages during upload with
///     "File signature doesn't match" exception
/// </summary>
internal class Program
{
    const string BrokenFilePath = @"./brokenImageModel.jpg";

    static async Task Main(string[] args)
    {
        //get fine image from project resources
        var sixLaborsImage = Image.Load(Resources.imageModel);

        using var ms = new MemoryStream();

        // fill ms stream with original image converted to sixlabors jpeg image
        await sixLaborsImage.SaveAsJpegAsync(ms, CancellationToken.None);

        // save image to file
        await using var fileStream = File.Create(BrokenFilePath);
        ms.Seek(0, SeekOrigin.Begin);
        await ms.CopyToAsync(fileStream);

        // try to open and save it with MS Paint
        // ???
        // Failure
    }
}

Images

imageModel Без имени

JimBobSquarePants commented 1 year ago

OK. I've figured out where the issue lies but not what the cause is yet.

Debugging

Issue2300.zip

I created a new program based off the sample and source image. I rand the program using both v2.1.3 stable and 3.0.0-alpha.0.65 with the same result.

This saves the input using ImageSharp then reloads and saves the output using System.Drawing and Magick.NET both of those libraries are able to resave the output without issue.

I'm also able to load/resave the output image using Paint.NET and Affinity Designer

However, Paint does not like it.

image

The error from s3 seems to be a red herring as the file header is correct. I'm not sure what is going on there; perhaps some stream mismanagement in the OP codebase given the odd approach in the sample code (MemoryStream + File.Create)?

image

The Workaround

Setting the XmpProfile to null allows Paint to save the image.

sixLaborsImage.Metadata.XmpProfile = null;

However, JpegSnoop and EXIFTools report no issues with the XMP data

image
ExifTool Version Number         : 12.51
File Name                       : issue2300-out.jpg
Directory                       : C:/Users/james/Downloads/exiftool-12.51
File Size                       : 176 kB
File Modification Date/Time     : 2022:11:30 22:28:04+10:00
File Access Date/Time           : 2022:11:30 22:29:06+10:00
File Creation Date/Time         : 2022:11:30 22:27:16+10:00
File Permissions                : -rw-rw-rw-
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Exif Byte Order                 : Little-endian (Intel, II)
Photometric Interpretation      : RGB
Orientation                     : Horizontal (normal)
Samples Per Pixel               : 3
Resolution Unit                 : inches
Make                            : Canon
Camera Model Name               : Canon EOS 6D Mark II
X Resolution                    : 300
Y Resolution                    : 300
Software                        : Adobe Photoshop CC 2019 (Windows)
Modify Date                     : 2022:08:01 14:14:52
Exposure Program                : Manual
ISO                             : 125
Sensitivity Type                : Recommended Exposure Index
Recommended Exposure Index      : 125
Exif Version                    : 0230
Metering Mode                   : Multi-segment
Flash                           : On, Fired
Sub Sec Time Original           : 31
Color Space                     : sRGB
Exif Image Width                : 1600
Exif Image Height               : 1086
Focal Plane Resolution Unit     : inches
File Source                     : Digital Camera
Scene Type                      : Directly photographed
Custom Rendered                 : Normal
Exposure Mode                   : Manual
White Balance                   : Manual
Scene Capture Type              : Standard
Exposure Time                   : 1/100
F Number                        : 14.0
Date/Time Original              : 2022:07:21 12:02:36
Create Date                     : 2022:07:21 12:02:36
Shutter Speed Value             : 1/100
Aperture Value                  : 14.0
Exposure Compensation           : 0
Subject Distance                : 0 m
Focal Length                    : 100.0 mm
Focal Plane X Resolution        : 6673.796875
Focal Plane Y Resolution        : 6720.51709
Serial Number                   : 253052001963
Lens Info                       : 100mm f/?
Lens Model                      : Canon EF 100mm f/2.8L Macro IS USM
Lens Serial Number              : 00000be619
GPS Version ID                  : 2.3.0.0
XMP Toolkit                     : Adobe XMP Core 5.6-c145 79.163499, 2018/08/13-16:40:22
Creator Tool                    : Capture One 21 Macintosh
Metadata Date                   : 2022:08:01 14:14:52+05:00
Lens                            : Canon EF 100mm f/2.8L Macro IS USM
Flash Compensation              : 0
Firmware                        : Firmware Version 1.1.1
Approximate Focus Distance      : 0
Legacy IPTC Digest              : DB67E203F8F2EB8D51E330FF1EDD2A3E
Color Mode                      : RGB
ICC Profile Name                : sRGB IEC61966-2.1
Document ID                     : 4D9EAADCC78E72E50C922E44FC6A2F6A
Instance ID                     : xmp.iid:ea1964e8-e6a4-ef46-a330-e775c9353f56
Original Document ID            : 4D9EAADCC78E72E50C922E44FC6A2F6A
Format                          : image/jpeg
History Action                  : saved
History Instance ID             : xmp.iid:ea1964e8-e6a4-ef46-a330-e775c9353f56
History When                    : 2022:08:01 14:14:52+05:00
History Software Agent          : Adobe Photoshop CC 2019 (Windows)
History Changed                 : /
Profile CMM Type                : Linotronic
Profile Version                 : 2.1.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 1998:02:09 06:49:00
Profile File Signature          : acsp
Primary Platform                : Microsoft Corporation
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : Hewlett-Packard
Device Model                    : sRGB
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Perceptual
Connection Space Illuminant     : 0.9642 1 0.82491
Profile Creator                 : Hewlett-Packard
Profile ID                      : 0
Profile Copyright               : Copyright (c) 1998 Hewlett-Packard Company
Profile Description             : sRGB IEC61966-2.1
Media White Point               : 0.95045 1 1.08905
Media Black Point               : 0 0 0
Red Matrix Column               : 0.43607 0.22249 0.01392
Green Matrix Column             : 0.38515 0.71687 0.09708
Blue Matrix Column              : 0.14307 0.06061 0.7141
Device Mfg Desc                 : IEC http://www.iec.ch
Device Model Desc               : IEC 61966-2.1 Default RGB colour space - sRGB
Viewing Cond Desc               : Reference Viewing Condition in IEC61966-2.1
Viewing Cond Illuminant         : 19.6445 20.3718 16.8089
Viewing Cond Surround           : 3.92889 4.07439 3.36179
Viewing Cond Illuminant Type    : D50
Luminance                       : 76.03647 80 87.12462
Measurement Observer            : CIE 1931
Measurement Backing             : 0 0 0
Measurement Geometry            : Unknown
Measurement Flare               : 0.999%
Measurement Illuminant          : D65
Technology                      : Cathode Ray Tube Display
Red Tone Reproduction Curve     : (Binary data 2060 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 2060 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 2060 bytes, use -b option to extract)
Current IPTC Digest             : 073bbeec490551a755cc93756674f617
City                            : .%G
Application Record Version      : 4
Date Created                    : 2022:07:21
Time Created                    : 12:02:36+00:00
Digital Creation Date           : 2022:07:21
Image Width                     : 1600
Image Height                    : 1086
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Aperture                        : 14.0
Image Size                      : 1600x1086
Megapixels                      : 1.7
Scale Factor To 35 mm Equivalent: 5.9
Shutter Speed                   : 1/100
Date/Time Original              : 2022:07:21 12:02:36.31
Date/Time Created               : 2022:07:21 12:02:36+00:00
Circle Of Confusion             : 0.005 mm
Depth Of Field                  : inf (0.00 m - inf)
Field Of View                   : 3.5 deg
Focal Length                    : 100.0 mm (35 mm equivalent: 589.2 mm)
Hyperfocal Distance             : 140.06 m
Light Value                     : 13.9
Lens ID                         : Canon EF 100mm f/2.8L Macro IS USM
-- press ENTER --

I'm all ears.

tocsoft commented 1 year ago

could there be a rouge null byte in the header somewhere that causes paint to freak out... and could posibly be the cause on the s3 stream failing too when it reaches that byte?

JimBobSquarePants commented 1 year ago

In the XMP chunk header? Yeah maybe. Odd that s3 would parse that far though.

sedjura commented 1 year ago

Thanks a lot for a quick answer. Actually I tried setting XMP profile to null but error still shows up. After that I also set ExifProfile to null and everything worked. For proper conversion I need to set both of them. sixLaborsImage.Metadata.ExifProfile = null; sixLaborsImage.Metadata.XmpProfile = null;

JimBobSquarePants commented 1 year ago

That doesn’t reflect what I am seeing. EXIF works fine for me.

br3aker commented 1 year ago

I'll take a look, something is very odd.

br3aker commented 1 year ago

That's strange but ImageSharp writes significantly less metadata after reencoding:

  1. APP1 EXIF metadata marker
    
    // Original image
    *** Marker: APP1 (xFFE1) ***
    OFFSET: 0x00000014
    Length          = 3288
    Identifier      = [Exif]
    Identifier TIFF = 0x[4D4D002A 00000008]
    Endian          = Motorola (big)
    TAG Mark x002A  = 0x002A

// Resaved by ImageSharp Marker: APP1 (xFFE1) OFFSET: 0x00000014 Length = 968 <= no thumbnail here, probably Identifier = [Exif] Identifier TIFF = 0x[49492A00 08000000] Endian = Intel (little) TAG Mark x002A = 0x002A


2. APP13 with IPTC blocks:

// Original image Marker: APP13 (xFFED) OFFSET: 0x00000CEE Length = 4462 Identifier = [Photoshop 3.0]

// Resaved by ImageSharp Marker: APP13 (xFFED) OFFSET: 0x00001ED9 Length = 85 <= a lot less Identifier = [Photoshop 3.0]



Well, deleting APP13 marker solves this issue, so actual EXIF metadata is **not** affected.
@sedjura if possible, can you please test given image with `sixLaborsImage.Metadata.IptcProfile = null;`?

As far as I know APP13 can be 'referenced' from APP1 segment, given that ImageSharp does truncate APP1 segment in this case - I suppose stated problem could be caused by breaking this reference. I debugged this image decoding and found out that APP13 marker is **not** fully decoded. I hadn't really checked any of the metadata-related code, is app13 photoshop metadata decoding fully supported?

Yet another interesting detail is that given image contains thumbnail in APP1 marker which ImageSharp currently doesn't support and doesn't write back which possibly could mess up APP13 marker.
sedjura commented 1 year ago

@br3aker I tried set up null IPTC profile and everything works to me.

br3aker commented 1 year ago

There's definately something wrong here, even though IPTC profile in APP13 segment from re-encoded image lost a lot of data - it is valid. No 'standard' metadata software reports any errors but Paint fails? That's strange. If anybody have access to Photoshop - please re-save given image re-encoded by ImageSharp and post resulting image here (so we can inspect whether IPTC metadata is resaved by PS), if everything works there - I'd suggest that there's a bug in Paint.

sedjura commented 1 year ago

I created a thread in Paint.Net community, maybe there we will have an answer https://forums.getpaint.net/topic/121422-cant-edit-and-save-jpg-image-in-paint-while-other-editors-works/

br3aker commented 1 year ago

I created a thread in Paint.Net community, maybe there we will have an answer https://forums.getpaint.net/topic/121422-cant-edit-and-save-jpg-image-in-paint-while-other-editors-works/

Wrong destination - Paint.NET and MS Paint are different things :P

JimBobSquarePants commented 1 year ago

@br3aker thanks for taking a peek. In the zip I shared above there's actually version of the image resaved using several applications that could be useful for comparison.

JimBobSquarePants commented 1 month ago

I'm going to close this. Following the link to the Paint.NET support channels it looks like everything but MS Paint is absolutely happy with the encoded image. That suggests the issue is with MS Paint.