Welcome Guest Search | Active Topics | Members

HOWTO: Drawing graphics/text on CMYK images Options
ericksontc
Posted: Tuesday, October 16, 2007 2:49:22 PM
Rank: Member
Groups: Member

Joined: 4/15/2007
Posts: 3
Points: 0
Location: Chico,CA
I should have posted this a few months ago, but I have been extremely busy. I recently had a project for a client, and mid-way through the project they decided that they wanted to generate CMYK images (final output of PDF). The Aurigma documentation and forums all state that drawing to CMYK images is not possible. So I had a problem.

The documentation explains that the only way to output a CMYK image to create a RGB image then convert to CMYK before saving. My issue with this approach is that you can not draw true CMYK images, the colors will not be correct. The colors will be converted versions of RGB colors, and as you know RGB does not exactly convert to CMYK. I needed to figure out a way to do it. So I did.

The method: First, GetGdiplusGraphics/GetGdiGraphics can't work on CMYK images, but can work on RGB. From the Channels Array of a CMYK bitmap you can get the four gray scale (8-bit) channels of the image. Convert them to RGB (24-bit). Now you can draw on them. Draw shapes/text on each associated color channel the RGB gray specified by by the CMYK percentage. For example: if the CMYK color is (84%,14%,100%,3%), draw the shape to the Cyan color channel with the RGB (.84*256,.84*256,.84*256) or #D7D7D7. Finally, convert them back to gray scale, put back in the CMYK image.

I must admit that this article is what made me think of the idea.

The following is an example that draws rectangles:
Code:
//For saving the original startup folder of the this file
protected string startupFolder;

private void Page_Load(object sender, System.EventArgs e)
{
      //Save the original startup folder of the this application for loading files
      startupFolder = Server.MapPath("./");                  

      Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(Aurigma.GraphicsMill.RgbColor.White, 1038, 688,
             Aurigma.GraphicsMill.PixelFormat.Format40bppAcmyk);
      
      //Create the color to draw with
      Aurigma.GraphicsMill.CmykColor rectColor = Aurigma.GraphicsMill.CmykColor.FromCmyk(214, 99, 255, 94);
      
      //Draw a CMYK rectangle
      //drawRectangleCMYK(bitmap,x,y,width,height,CMYKcolor,opacity,rotation);
      bitmap = drawRectangleCMYK(bitmap,100,100,50,50,rectColor,128,45);
      bitmap = drawRectangleCMYK(bitmap,125,125,50,50,rectColor,128,45);
      bitmap = drawRectangleCMYK(bitmap,200,200,50,50,rectColor,255,0);
      bitmap = drawRectangleCMYK(bitmap,300,300,50,50,rectColor,255,180);
      
      //save the output
      bitmap.Save(startupFolder+[color=CC0000]"cmyk32.jpg", new JpegEncoderOptions(100, true));
}
                        
private Aurigma.GraphicsMill.Bitmap drawRectangleCMYK(Aurigma.GraphicsMill.Bitmap bitmap, float fX,float fY, float fWidth,
                                    float fHeight, Aurigma.GraphicsMill.CmykColor CMYKcolor, int iOpacity, float fRotation) {

      //Create rotation matrix
      System.Drawing.Drawing2D.Matrix matrix = new System.Drawing.Drawing2D.Matrix();
      matrix.RotateAt(fRotation, new System.Drawing.PointF(fX+fWidth/2,fY+fHeight/2));

      //Get the color channels
      Aurigma.GraphicsMill.ColorChannel[] channels = {Aurigma.GraphicsMill.ColorChannel.Cyan,
                                                                  Aurigma.GraphicsMill.ColorChannel.Magenta,
                                                                  Aurigma.GraphicsMill.ColorChannel.Yellow,
                                                                  Aurigma.GraphicsMill.ColorChannel.Black};

      //Get the colors
      int[] colors = {CMYKcolor.C,CMYKcolor.M,CMYKcolor.Y,CMYKcolor.K};

      //For storing the working color channel
      Aurigma.GraphicsMill.Bitmap colorChannel;

      //Begin processing each color channel
      for(int i = 0;i<4;i++) {
            
            colorChannel = bitmap.Channels[channels[ i ]];
            
            //Convert it to RGB, so that GetGdiplusGraphics can work with it
            //if you only need GetGdiGraphics, then there is no need to change colorSpaces
            colorChannel.ColorManagement.ConvertToContinuous(Aurigma.GraphicsMill.ColorSpace.Rgb,false, false);
            
            //Can't use GetGdiGraphics, we want Anti-alias
            System.Drawing.Graphics graphics = colorChannel.GetGdiplusGraphics();

            //Turn on AntiAliasing on draw
            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            //Create a solid brush colored with the RGB color and opacity specified      
            System.Drawing.SolidBrush brush = new
                        System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(iOpacity, colors[ i ], colors[ i ], colors[ i ]));
            
            //Apply rotation
            graphics.Transform = matrix;
                                    
            //Draw the filled rectangle
            graphics.FillRectangle(brush, fX, fY, fWidth, fHeight);
            
            //Convert RGB back to grayscale
            colorChannel.ColorManagement.ConvertToContinuous(Aurigma.GraphicsMill.ColorSpace.GrayScale,false, false);
            
            //Put the channel back in the image
            bitmap.Channels[channels[ i ]] = colorChannel;
      }                                    
      
      return bitmap;
}


It requires a lot more CPU and RAM than regular RGB, but it works.

Brad Erickson
Owner/Developer
Erickson Technology Consulting
Alex Kon
Posted: Tuesday, October 16, 2007 10:59:00 PM
Rank: Advanced Member
Groups: Administration , Member

Joined: 1/31/2005
Posts: 386
Points: 403
Hello Brad,

I am very pleased to read such posts on our forum. It is really impressive! Thank you!

Do not you mind if we will extend our knowledge base article with your approach? Our developers, insipred with your idea, already proposed to implement all operations in unsafe mode with some optimizations, which may significantly improve perfomance.

Best wishes, Alex.
ericksontc
Posted: Wednesday, October 17, 2007 12:45:03 AM
Rank: Member
Groups: Member

Joined: 4/15/2007
Posts: 3
Points: 0
Location: Chico,CA
Hi Alex,
Thanks for the compliment. I didn't realize the company would be excited that I figured out a way to draw to CMYK with their product. It think it would be great if you could update your code and KB article with my idea. Maybe I could get a mention on the page? ;)
The code could be optimized more, but I wanted to leave it easily readable. I have seen a couple requests for CMYK functionality on your site, so I wanted to make sure that those people would be able to work with CMYK in their projects. Thanks for an easy to use SDK.

Brad Erickson
Owner/Developer
Erickson Technology Consulting
cybeh
Posted: Wednesday, October 24, 2007 7:21:51 PM
Rank: Member
Groups: Member

Joined: 1/14/2006
Posts: 6
Points: 0
Hi,

Just wondering if this possible to be convert to an vObject?

As I really need to draw everything in CMYK and not RGB. Thanks.
Dmitry
Posted: Sunday, October 28, 2007 2:39:45 AM
Rank: Advanced Member
Groups: Administration , Member

Joined: 8/3/2003
Posts: 586
Points: 588
Hello,

Unfortunately Vector Objects does not support CMYK color space because of Windows GDI limitation.

There is a workaround but it is not trivial and simple to implement... You can use Vector Objects just to display your graphics primitives and let user make transformations (drag, resize and so on) over these promitives. After user completes his/here creation, you should render output image in CMYK by yourself. To perform this task you should draw graphics primitives (text, line, rectangle and so on) in CMYK as described above (I suppose you do not need to do something with image v-objects because they are in CMYK and you just have to load them). After that you will have CMYK image for each primitive. So then you should get transormations for each v-object and apply it onto corrsponding image. After that you need to merge images together.

Sincerely yours,
Dmitry Sevostyanov.
Users browsing this topic
Guest


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.

Main Forum RSS : RSS

YAFVision Theme Created by Jaben Cargman (Tiny Gecko)
Yet Another Forum.net version 1.9.1.6 running under Cuyahoga.
Copyright © 2003-2006 Yet Another Forum.net. All rights reserved.