koszeggy / KGySoft.Drawing

KGy SOFT Drawing is a library for advanced image, icon and graphics handling.
https://kgysoft.net/drawing
Other
58 stars 8 forks source link

ImageExtensions.ConvertPixelFormat() fails for images with PixelFormat == Cmyk32 #10

Closed davidei1955 closed 2 years ago

davidei1955 commented 2 years ago

ConvertPixelFormat() throws: System.InvalidOperationException: 'Internal Error: Unexpected pixel format 8207' The failing line is: var newImage = original.ConvertPixelFormat(PixelFormat.Format8bppIndexed, PredefinedColorsQuantizer.FromCustomFunction(c => c.ToGray()));

The failing image is attached. Paint, Paint.net, and Photos can all open the image https://user-images.githubusercontent.com/79710713/174828173-be47e13d-a8e5-42ea-97d8-9be913ebde9c.jpg .

koszeggy commented 2 years ago

Thank you for the report. I'm aware about the issue and I plan to extend the new KnownPixelFormat enum (so far available as a preview in KGySoft.Drawing.Core, which is the new package of the platform and technology-independent APIs) with a new Format32bppCmyk field so CMYK format will be natively supported.

As I already implemented CMYK format for WPF (also in preview so far) it will not be a big deal even for the Core package.

However, GDI+ Bitmap is a bit different. Its CMYK support is actually quite a hack: it uses an unnamed System.Drawing.Imaging.PixelFormat value (8207) and is not supported on all platforms. Actually you can open the posted image even in my ImagingTools: in Windows Vista or above you will see 8207 as the displayed pixel format. Windows XP behaves differently though: CMYK JPEG images are loaded with Format24bppRgb pixel format, and CMYK TIFF images with Format32bppArgb format (if the source image uses 8 bits for each channel).

What you can expect from me: I was already planning to add CMYK support also to KGySoft.Drawing (starting with 7.0.0 this contains only the GDI+ specific APIs) but maybe only as source format. Meaning, ImageExtensions.ConvertPixelFormat will support it as source format but (probably) not as a target format.

What you can do today: If you need to use CMYK source images you can try the following workarounds today:

davidei1955 commented 2 years ago

Thanks for the quick response! My current usage requirement is only as a source input to ConvertPixelFormat(), so 'source only' is fine. My workaround is to convert the cmyk image to rgb thusly: public static Bitmap AsRgb(this Bitmap img) { if (((int) img.PixelFormat) != 8207) { //8207 == PixelFormat.Cmyk32 return img; } try { return img.To24bppRgb(); } finally { img.Dispose(); } }

koszeggy commented 2 years ago

The CMYK support of Bitmap (only as input format) has been released in 7.0.0-preview.2 (see the change log)