I looked at the BitBlt function, which by default ignores color management, but then I found SetICMMode , which says Quote:"Specifically, if a device independent bitmap (DIB) is used as the source for a blit, and the blit is performed into a DC that has WCS enabled, color matching will be performed." Based on that, I added a call to SetICMMode to query the mode (updated code below) of the printer device context, and on the Cute PDF printer ICM mode is ON and on the Microsoft PDF printer it is OFF. This is causing the output between these two printers to be different. In affect, if ICM mode is ON, then the color profile is being applied by Windows Color Mangament (WCM) and it should not be applied to the image before DrawOn (BitBlt) otherwise, the profile has been applied twice. To test this hypothesis, I updated the code so that it uses whatever the printer ICM mode is and calls DrawOn without and with the specificed profile applied. I then switch the ICM mode of the printer context, and DrawOn the image again without and with the profile. For the Microsoft PDF printer the results looked like this:  WinPDF_SRGB_ICMON_OFF.png (158kb) downloaded 7 time(s).So, the upper left has no profile applied, the upper right has the profile applied using Aurigma, the lower left has the profile applied by WCM, and the lower right has the profile applied once by Aurigma and again by WCM. Using a sRGB color profile image, the upper right and lower left are the same (virtually, there are differences in the jpg artifacts). For the CutePDF printer the results looked like this:  CutePDF_SRGB_ICMON_OFF.png (224kb) downloaded 9 time(s).Since CutePDF ICM is ON by default, the results are switched compared to the Microsoft PDF. The upper left has the profile applied by WCM, the upper right has the profile applied once by Aurigma and again by WCM, the lower left has no profile applied, and the lower right has the profile applied using Aurigma. Using a sRGB color profile image, the upper left and lower right are the same. Note there are some slight color differences between WCM and Aurigma applying the same profile when the source image is not sRGB (AdobeRGB in this case).  CutePDF_ICMON_noAG_vs_ICMOFF_withAG.png (84kb) downloaded 7 time(s). This example is the CutePDF with WCM applying the left side of each swatch (via ICM ON) and Aurigma applying the right side (via ICM OFF and applying the color transform). Which application of the printer's profile is correct? Or do I have to put in support to either have Aurigma apply the output profile, or WCM apply the output profile? Code:
//string inputFile = @"C:\temp\ColorTestChart_SRGB_900.tif";
string inputFile = @"C:\temp\ColorTestChart_ARGB_900.tif";
string input[h]Profile[/h] = @"C:\Windows\System32\spool\drivers\color\sRGB Color Space [h]Profile[/h].icm";
//https://www.inkowl.com/page/performance-d-icc-[h]profile[/h]s/
string output[h]Profile[/h] = @"C:\Windows\System32\spool\drivers\color\Performance-D - 4 colors - Sublimation Transfer Paper - InkOwl [h]Profile[/h].icm";
void Main()
{
PrintImage();
}
private void PrintImage()
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
Color[h]Profile[/h] printerSurface[h]Profile[/h];
ICM_MODE icmMode = ICM_MODE.ICM_QUERY;
try
{
IntPtr hdc = ev.Graphics.GetHdc();
//Get HDC color [h]profile[/h]
printerSurface[h]Profile[/h] = Color[h]Profile[/h].FromHdc(hdc);
icmMode = (ICM_MODE)SetICMMode(hdc, (int)ICM_MODE.ICM_QUERY);
Debug.WriteLine($"ICM Mode of the printer device context {icmMode}");
}
finally
{
ev.Graphics.ReleaseHdc();
}
int leftMargin = 50;
int xPos = leftMargin;
int yPos = 0;
System.Drawing.Font f = new System.Drawing.Font("Ariel", 20, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
ev.Graphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
int textHeight = (int)ev.Graphics.MeasureString("Testing 123", f).Height + 5;
ev.Graphics.DrawString($"{((PrintDocument)sender).PrinterSettings.PrinterName} - Default ICM Mode: {icmMode} - Input Image: {inputFile}", f, System.Drawing.Brushes.Black, xPos, yPos);
yPos += textHeight;
int imageHeight = 10;
using (Bitmap input = new Bitmap(inputFile))
{
imageHeight = input.Height;
string [h]profile[/h]Name = input.Color[h]Profile[/h] != null ? input.Color[h]Profile[/h].Description : "sRGB(NotSet)";
ev.Graphics.DrawString($"Org w/SP ({[h]profile[/h]Name}) -No PP", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image without printer surface [h]profile[/h]
input.DrawOn(ev.Graphics, xPos, yPos + textHeight, CombineMode.Alpha, 1);
xPos += input.Width + 20;
ConvertInternalImageToColor[h]Profile[/h](input, input[h]Profile[/h], printerSurface[h]Profile[/h], ColorTransformationIntent.Perceptual);
ev.Graphics.DrawString($"Org w/SP ({[h]profile[/h]Name}) w/PP(Perceptual)", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image with printer driver surface [h]profile[/h] applied
input.DrawOn(ev.Graphics, xPos, yPos + textHeight, CombineMode.Alpha, 1);
xPos += input.Width + 20;
}
//New line
xPos = leftMargin;
yPos += imageHeight + textHeight + 10;
//swap ICM Mode
try
{
IntPtr hdc = ev.Graphics.GetHdc();
icmMode = (ICM_MODE)SetICMMode(hdc, icmMode == ICM_MODE.ICM_ON ? (int)ICM_MODE.ICM_OFF : (int)ICM_MODE.ICM_ON);
icmMode = (ICM_MODE)SetICMMode(hdc, (int)ICM_MODE.ICM_QUERY);
Debug.WriteLine($"ICM Mode of the printer device context, after switching is: {icmMode}");
}
finally
{
ev.Graphics.ReleaseHdc();
}
//Draw the images the same way, again, with the new mode
using (Bitmap input = new Bitmap(inputFile))
{
string [h]profile[/h]Name = input.Color[h]Profile[/h] != null ? input.Color[h]Profile[/h].Description : "sRGB(NotSet)";
ev.Graphics.DrawString($"Org w/SP ({[h]profile[/h]Name}) -No PP -ICM Mode: {icmMode}", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image without printer surface [h]profile[/h]
input.DrawOn(ev.Graphics, xPos, yPos + textHeight, CombineMode.Alpha, 1);
xPos += input.Width + 20;
ConvertInternalImageToColor[h]Profile[/h](input, input[h]Profile[/h], printerSurface[h]Profile[/h], ColorTransformationIntent.Perceptual);
ev.Graphics.DrawString($"Org w/SP ({[h]profile[/h]Name}) w/PP(Perceptual) -ICM Mode: {icmMode}", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image with printer driver surface [h]profile[/h] applied
input.DrawOn(ev.Graphics, xPos, yPos + textHeight, CombineMode.Alpha, 1);
xPos += input.Width + 20;
}
//New line
xPos = leftMargin;
yPos += imageHeight + textHeight + 10;
using (var gdiBmp = new System.Drawing.Bitmap(inputFile))
{
ev.Graphics.DrawString("Org GDI w/SP (ARGB) -No PP", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image without printer surface [h]profile[/h]
ev.Graphics.DrawImage(gdiBmp, xPos, yPos + textHeight);
xPos = leftMargin;
yPos += gdiBmp.Height + textHeight + 10;
}
}
private static void ConvertInternalImageToColor[h]Profile[/h](Aurigma.GraphicsMill.Bitmap imgToConvert, string source[h]Profile[/h], Aurigma.GraphicsMill.Color[h]Profile[/h] outputPF, ColorTransformationIntent renderIntent)
{
Aurigma.GraphicsMill.Color[h]Profile[/h] sourcePF = imgToConvert.Color[h]Profile[/h];
if (sourcePF == null)
{
sourcePF = new Color[h]Profile[/h](source[h]Profile[/h]);
}
if (sourcePF.Description != outputPF.Description ||
sourcePF.Model != outputPF.Model ||
sourcePF.Manufacturer != outputPF.Manufacturer ||
sourcePF.ColorSpace != outputPF.ColorSpace)
{
imgToConvert.ColorManagement.ColorManagementEngine = ColorManagementEngine.LittleCms;
imgToConvert.Color[h]Profile[/h] = sourcePF;
imgToConvert.ColorManagement.TransformationIntent = renderIntent;
imgToConvert.ColorManagement.Destination[h]Profile[/h] = outputPF;
if (outputPF.ColorSpace == ColorSpace.Cmyk)
{
imgToConvert.ColorManagement.Convert(PixelFormat.Format32bppCmyk);
}
else if (outputPF.ColorSpace == ColorSpace.Rgb)
{
imgToConvert.ColorManagement.Convert(PixelFormat.Format24bppRgb);
}
}
}
enum ICM_MODE
{
ICM_OFF = 1,
ICM_ON = 2,
ICM_QUERY = 3,
ICM_DONE_OUTSIDEDC = 4
}
[DllImport("gdi32.dll", EntryPoint = "SetICMMode", SetLastError = true)]
static extern int SetICMMode([In] IntPtr hdc, int mode);
I have included the pdfs, sRGB version of the test image, and the linqPad script  SamplePDF_Linq_ICM_Modes.zip (2,580kb) downloaded 7 time(s).
|
We are facing issues with color profiles while printing to a Windows Printer. I found this article in the forum and I think I adapted it correctly for GraphicsMill 9.3.7. I'm getting unexpected color results though when using DrawOn to draw the Aurigma bitmap to the printer's (gdi+) graphics. If I do not apply the printers color profile, I get one result, if I apply the printer profile I get a second one. It should be noted that if I just open the image using gdi and draw it, I get the same result (color wise) as using DrawOn without the color profile. I am using CuteWriter PDF to print the output of the code below. (The linqpad file, profile, and sample pdf outputs are in a zip file at the end of this post) This is the test image I'm printing:  ColorTestChart_ARGB_300.png (49kb) downloaded 9 time(s).This is the result using Cute PDF with no color profile set in Windows Color Management:  SamplePrintedWithCutePDFAndNo(srgb)Profile.png (49kb) downloaded 17 time(s).The left is just DrawOn, the right is after I applied the color profile. I then went into color management (Printer Properties -> Color Management -> Chose the CuteWriter PDF printer and assigned the [url=https://www.inkowl.com/page/performance-d-icc- profiles/]OwlInk [/url] dyesub color profile, as dyesub profiles really affect the colors so it is noticeable. Running the script again, I got the following output. Note that both the just DrawOn and the applied profile then DrawOn are both affected.  SamplePrintedWithCutePDFAndOwlDyesub6ColorProfile.png (58kb) downloaded 10 time(s).So, should I be applying the color profile as was mentioned in the original article? Code:
string inputFile = @"C:\temp\ColorTestChart_ARGB_900.tif";
string input[h]Profile[/h] = @"C:\Windows\System32\spool\drivers\color\sRGB Color Space [h]Profile[/h].icm";
//https://www.inkowl.com/page/performance-d-icc-[h]profile[/h]s/
void Main()
{
PrintImage();
}
private void PrintImage()
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
Color[h]Profile[/h] printerSurface[h]Profile[/h];
try
{
IntPtr hdc = ev.Graphics.GetHdc();
//Get HDC color [h]profile[/h]
printerSurface[h]Profile[/h] = Color[h]Profile[/h].FromHdc(hdc);
}
finally
{
ev.Graphics.ReleaseHdc();
}
int leftMargin = 50;
int xPos = leftMargin;
int yPos = 0;
System.Drawing.Font f = new System.Drawing.Font("Ariel", 20,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
ev.Graphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
using (Bitmap input = new Bitmap(inputFile))
{
ev.Graphics.DrawString("Org w/SP (ARGB) -No PP", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image without printer surface [h]profile[/h]
input.DrawOn(ev.Graphics, xPos, yPos + 40, CombineMode.Alpha, 1);
xPos += input.Width + 10;
ConvertInternalImageToColor[h]Profile[/h](input, input[h]Profile[/h], printerSurface[h]Profile[/h], ColorTransformationIntent.Perceptual);
ev.Graphics.DrawString("Org w/SP (ARGB) w/PP", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image with printer driver surface [h]profile[/h] applied
input.DrawOn(ev.Graphics, xPos, yPos + 40, CombineMode.Alpha, 1);
xPos = leftMargin;
yPos += input.Height + 40;
}
using (var gdiBmp = new System.Drawing.Bitmap(inputFile))
{
ev.Graphics.DrawString("Org GDI w/SP (ARGB) -No PP", f, System.Drawing.Brushes.Black, xPos, yPos);
//draw original image without printer surface [h]profile[/h]
ev.Graphics.DrawImage(gdiBmp, xPos, yPos + 40);
xPos += gdiBmp.Width + 10;
}
}
private static void ConvertInternalImageToColor[h]Profile[/h](
Aurigma.GraphicsMill.Bitmap imgToConvert,
string source[h]Profile[/h],
Aurigma.GraphicsMill.Color[h]Profile[/h] outputPF,
ColorTransformationIntent renderIntent)
{
Aurigma.GraphicsMill.Color[h]Profile[/h] sourcePF = imgToConvert.Color[h]Profile[/h];
if (sourcePF == null)
{
sourcePF = new Color[h]Profile[/h](source[h]Profile[/h]);
}
if (sourcePF.Description != outputPF.Description ||
sourcePF.Model != outputPF.Model ||
sourcePF.Manufacturer != outputPF.Manufacturer ||
sourcePF.ColorSpace != outputPF.ColorSpace)
{
imgToConvert.ColorManagement.ColorManagementEngine = ColorManagementEngine.LittleCms;
imgToConvert.Color[h]Profile[/h] = sourcePF;
imgToConvert.ColorManagement.TransformationIntent = renderIntent;
imgToConvert.ColorManagement.Destination[h]Profile[/h] = outputPF;
if (outputPF.ColorSpace == ColorSpace.Cmyk)
{
imgToConvert.ColorManagement.Convert(PixelFormat.Format32bppCmyk);
}
else if (outputPF.ColorSpace == ColorSpace.Rgb)
{
imgToConvert.ColorManagement.Convert(PixelFormat.Format24bppRgb);
}
}
}
 SamplePDFsProfileAndLinq.zip (2,322kb) downloaded 6 time(s).
|
We have a CMYK Pdf coming in from a client with transparency. We are trying to convert this to a PNG without an alpha channel. When we do this, the image that is generated is a pure white image only. We are stuck and have no idea what to do at this point. It handles when the user puts a transparent RGB image, but does not handle a CMYK image with alpha. Here is our code: Code:using (var reader = ImageReader.Create(OriginalFilepath))
using (var converter = new Aurigma.GraphicsMill.Transforms.ColorConverter(PixelFormat.Format24bppRgb))
using (var writer = ImageWriter.Create(WorkingFilepath))
{
// If no color [h]profile[/h] is set
converter.DefaultSource[h]Profile[/h] = reader.Color[h]Profile[/h];
if (reader.Color[h]Profile[/h] == null)
converter.DefaultSource[h]Profile[/h] = new Color[h]Profile[/h](Configuration.[h]Profile[/h]sDirectory + "ISOcoated_v2_eci.icc");
if (reader.PixelFormat.IsRgb && reader.PixelFormat != PixelFormat.Format24bppRgb)
{
converter.BackgroundColor = RgbColor.White;
// Assign some default color [h]profile[/h]
converter.DefaultSource[h]Profile[/h] = Color[h]Profile[/h].FromSrgb();
converter.Destination[h]Profile[/h] = Color[h]Profile[/h].FromSrgb();
}
if (reader.PixelFormat.IsCmyk)
{
converter.BackgroundColor = new CmykColor(0, 0, 0, 0, 100);
converter.ColorManagementEngine = ColorManagementEngine.LittleCms;
converter.Destination[h]Profile[/h] = Color[h]Profile[/h].FromSrgb();
}
Pipeline.Run(reader + converter + writer);
}
}
Any help would be appreciated.
|
My Photoshop CS6 gives me a warning about invalid ICC profile when I open the original image. Maybe this is a cause of the problem. Since the 6x versions, color management workflow was significantly changed, and I guess that's why the image can be handled with elder versions.
I don't think there is something you can do with GM 5. The version you have is the latest 5x.
And I'm not sure how did you get your result. When I tried to run the code with GM5, I got CMInappropriateProfileException without any output.
|
I am converting a jpeg image with a colour profile of : Coated FOGRA39 (ISO 12647-2:2004) to RGB with a colour profile of sRGB using the following code: Code:private sub ConvertToRGB(byref img as Aurigma.GraphicsMill.bitmap, [h]profile[/h] as string)
'Choose LittleCMS color management engine
img.ColorManagement.ColorManagementEngine = Aurigma.GraphicsMill.Transforms.ColorManagementEngine.LittleCms
if [h]profile[/h] = "" andAlso img.IsCMYK then
'Assign output RGB [h]profile[/h] for conversion
img.ColorManagement.RgbColor[h]Profile[/h] = Aurigma.GraphicsMill.Color[h]Profile[/h].FromSrgb
elseif [h]profile[/h] <> "" then
[h]profile[/h] = "C:\windows\system32\spool\drivers\color\" & [h]profile[/h] & ".icc"
try
img.ColorManagement.RgbColor[h]Profile[/h] = New Aurigma.GraphicsMill.Color[h]Profile[/h]([h]profile[/h])
catch e as exception
throw new Exception("Could not find RGB Colour [h]Profile[/h]: " & e.message)
end try
end if
if img.color[h]Profile[/h] is nothing then
if img.isRGB then
img.Color[h]Profile[/h] = Aurigma.GraphicsMill.Color[h]Profile[/h].FromSrgb
else
img.Color[h]Profile[/h] = new Color[h]Profile[/h]("C:\windows\system32\spool\drivers\color\RSWOP.icm")
end if
end if
'Convert to RGB
if img.ColorManagement.RgbColor[h]Profile[/h] isnot nothing then
img.ColorManagement.ConvertToContinuous(Aurigma.GraphicsMill.ColorSpace.Rgb, False, img.IsExtended)
end if
end sub
It seems that the red in the converted image is much brighter. See attached  Converted RGB image.jpg (72kb) downloaded 20 time(s). Original CMYK image.jpg (717kb) downloaded 20 time(s).Not sure if there is something that can be done about this or if this is expected when converting between these colour profiles?
|