Welcome Guest! You need to login or register to make posts.

Notification

Icon
Error

Options
Go to last post Go to first unread
aklots  
#1 Posted : Thursday, June 16, 2016 5:57:50 AM(UTC)
aklots

Rank: Newbie

Groups: Member
Joined: 6/3/2016(UTC)
Posts: 7

One (or several) more issue(s) with Aurigma.GraphicsMill.Bitmap:

Case 1 (CMYK file and System.Drawing.Bitmap)

Code:

var nativeBitmap = new System.Drawing.Bitmap("image_cmyk.jpg");
// nativeBitmap.PixelFormat is 8207 (CMYK) - OK

var bitmap = new Aurigma.GraphicsMill.Bitmap(nativeBitmap) // Faill

gives us

Code:

Aurigma.GraphicsMill.UnsupportedPixelFormatException : The pixel format is not supported.
   at Aurigma.GraphicsMill.PixelFormatUtils.TransformPixelFormatGdi(PixelFormat format)
   at Aurigma.GraphicsMill.Bitmap..ctor(Bitmap bitmap)

looks like Aurigma is unable to understand CMYK pixel format with id 8207.

Case 2 (Bitmap convertion)

Code:

using (var bitmap = new Aurigma.GraphicsMill.Bitmap("image_cmyk.jpg"))
{
    // bitmap.PixelFormat is Format32bppCmyk, OK

	var nativeBitmap = bitmap.ToGdiPlusBitmap();

	// nativeBitmap.PixelFormat is Format32bppArgb - Why??

	using (var bitmap2 = new Aurigma.GraphicsMill.Bitmap(nativeBitmap))
	{
		bitmap.Draw(bitmap2, 0, 0, CombineMode.Copy); // crash
	}
}

gives us

Code:

Aurigma.GraphicsMill.UnsupportedPixelFormatException : The specified pixel format is not supported.
   at Aurigma.GraphicsMill.GMException.ThrowManagedException(IntPtr unmanagedException)
   at Aurigma.GraphicsMill.PipelineElement.RunPipeline()
   at Aurigma.GraphicsMill.Pipeline.Run()
   at Aurigma.GraphicsMill.Bitmap.Draw(Bitmap topBitmap, Int32 x, Int32 y, CombineMode combineMode)

And here looks like a different pixel formats issue.

aklots attached the following image(s):
image_cmyk.jpg
Fedor  
#2 Posted : Thursday, June 16, 2016 7:24:39 AM(UTC)
Fedor

Rank: Advanced Member

Groups: Member, Administration, Moderator
Joined: 7/28/2003(UTC)
Posts: 1,558

Thanks: 5 times
Was thanked: 62 time(s) in 61 post(s)
The support of CMYK color space in the System.Drawing library (and underlying GDI+) is very limited and inconsistent. That's why Graphics Mill supports interoperability with the RGB pixel formats only. The ToGdiPlusBitmap method converts a bitmap to the Format32bppArgb pixel format as it allows us to be sure that the image will be processed by GDI+ correctly.

So, actually, the exceptions you get are designed.

I am curious why you need CMYK System.Drawing images? Actually, we have never seen the usage of GDI+ CMYK images in real applications except for detecting CMYK color space.

Best regards,

Fedor Skvortsov

aklots  
#3 Posted : Friday, June 17, 2016 12:48:44 AM(UTC)
aklots

Rank: Newbie

Groups: Member
Joined: 6/3/2016(UTC)
Posts: 7

Ok at first, I must say, I didn't expect ToGdiPlusBitmap to change image's pixel format.

It could be usefull to have this information somewere here.

Idea behind GDI+ CMYK came from two points:

1) it would be nice to work (apply transformation, effects) with all popular types of images (png, gif, jpeg) and pixel formats (32, 24, 8 pbb) without converting them to some common format, like Rgb24bpp.

2) some effects are external - implemented in native code and has no dependency on Aurigma.GraphicsMill.Bitmap.

That is why Aurigma.GraphicsMill.Bitmap must be converted to GDI+ bitmap, passed to external library and than result should be applied to source Aurigma.GraphicsMill.Bitmap. For the last step I'm using Draw() method as a temporary solution. However idea is the same - interoperability with GDI+ without crashes.

Eugene Kosmin  
#4 Posted : Monday, June 20, 2016 2:14:30 AM(UTC)
Eugene Kosmin

Rank: Advanced Member

Groups: Member, Administration, Moderator
Joined: 9/19/2006(UTC)
Posts: 446

Was thanked: 24 time(s) in 24 post(s)
Hi,

PixelFormat Enumeration does not contain CMYK formats, so I am not sure that converting to undocumented pixel format is a good idea.

However, you can perform such conversion manually through access to pixel data:

Code:

static Aurigma.GraphicsMill.Bitmap Convert(System.Drawing.Bitmap bitmap)
{
    const int Format32bppCmyk = 0x200F;
    const int PixelSize = 4;

    if ((int)bitmap.PixelFormat != Format32bppCmyk)
        return new Aurigma.GraphicsMill.Bitmap(bitmap);

    var dstBitmap = new Aurigma.GraphicsMill.Bitmap(bitmap.Width, bitmap.Height, Aurigma.GraphicsMill.PixelFormat.Format32bppCmyk);
    var rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);

    var bits = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

    try
    {
        var srcLine = bits.Scan0;
        var dstLine = dstBitmap.Scan0;

        unsafe
        {
            for (int i = 0; i < bitmap.Height; i++)
            {
                var src = (byte*)srcLine;
                var dst = (byte*)dstLine;

                for (int j = 0; j < bitmap.Width; j++)
                {
                    dst[0] = src[3];
                    dst[1] = src[2];
                    dst[2] = src[1];
                    dst[3] = src[0];

                    dst += PixelSize;
                    src += PixelSize;
                }

                srcLine += bits.Stride;
                dstLine += dstBitmap.Stride;
            }
        }
    }
    finally
    {
        bitmap.UnlockBits(bits);
    }

    return dstBitmap;
}
Best regards,

Eugene Kosmin.

Aurigma Development Team

aklots  
#5 Posted : Monday, June 20, 2016 7:49:03 AM(UTC)
aklots

Rank: Newbie

Groups: Member
Joined: 6/3/2016(UTC)
Posts: 7

Hi Eugene,

Quote:
PixelFormat Enumeration does not contain CMYK formats, so I am not sure that converting to undocumented pixel format is a good idea.

ok, good point.

Quote:
However, you can perform such conversion manually through access to pixel data

Thank you for a nice solution!

Actually now I'm thinking about even more simpler solution, for my case.

I could pass image data to the external, graphics mill independent, component using System.Drawing.Imaging.BitmapData instead of System.Drawing.Bitmap. This way I'll have no conversion at all, only passing pointer.

By the way, do you have an extension method like this:

Code:
        public static System.Drawing.Imaging.BitmapData AsBitmapData(this Aurigma.GraphicsMill.Bitmap bitmap)
        {
            var bitmapData = new BitmapData
            {
                Scan0 = bitmap.Scan0,
                Stride = bitmap.Stride,
                Width = bitmap.Width,
                Height = bitmap.Height,
                PixelFormat = bitmap.PixelFormat,                
            };

            return bitmapData;
        }
?
Eugene Kosmin  
#6 Posted : Monday, June 20, 2016 7:01:48 PM(UTC)
Eugene Kosmin

Rank: Advanced Member

Groups: Member, Administration, Moderator
Joined: 9/19/2006(UTC)
Posts: 446

Was thanked: 24 time(s) in 24 post(s)
Quote:
By the way, do you have an extension method like this:

No, we don’t have.

Quote:
I could pass image data to the external, graphics mill independent, component using System.Drawing.Imaging.BitmapData instead of System.Drawing.Bitmap. This way I'll have no conversion at all, only passing pointer.

Yes, you are right. Pixel layouts are the same for RGB formats, so you can just create BitmapData without copy. But for CMYK format layouts are different, so you need to swap channels CMYK <-> KYMC.

Best regards,

Eugene Kosmin.

Aurigma Development Team

aklots  
#7 Posted : Friday, June 24, 2016 12:55:13 AM(UTC)
aklots

Rank: Newbie

Groups: Member
Joined: 6/3/2016(UTC)
Posts: 7

Ok, I'll keep in mind that. Thanks a lot guys!
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.