I think the problem is to be found in the method:
PdfSharp.Pdf.Advanced.PdfImage.cs InitializeJpeg()In the code the graphic that was previously loaded in memory is being saved to a memory stream object:
Code:
memory = new MemoryStream();
image.gdiImage.Save(memory, ImageFormat.Jpeg);
This Save call is actually converting the graphic to a color image. I checked this by adding another save line right after the original one:
Code:
image.gdiImage.Save(@"c:\temp\fromDotNet.jpg");
When I re-ran the application with this new graphic (instead of the original one) the graphic's properties are changed. So Where the code sets the ColorSpace to /DeviceGray for the original value,
Code:
Elements[Keys.ColorSpace] = new PdfName("/DeviceGray");
Running the code on the updated image executes the /DeviceRGB command.
Code:
Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB");
I stepped through the application, and manually called the code to record the ColorSpace as "/DeviceRGB" instead of "/DeviceGray" and the output document rendered correctly.
So I see various possible fixes for this issue:
1) Add an encoder for the graphic that matches the original settings. - I have no idea what would be required to do this.
2) Use the memory stream's saved settings - I suspect that this would require reloading the graphic, unless a specific encoder was used. I don't have enough experience with GDI to know if saving the file without any settings always results in the default encoder settings. If that is the case, that would explain why the BitsPerComponent is a static 8 instead of a variable 8,16,24, or 32. It maybe sufficient to merely set this to "/DeviceRGB"
3) Save off a copy of the original file at the point it is loaded and do not re-save it. - I suspect that this may not be the answer for a few reasons, one it functionally doubles the amount of memory required for a graphic and it is very possible that a graphic may not be loaded from disk. In this situation, there would be no data available, and the original problem returns.
4) Use the InitializeNonJpeg() or a variation. - I did not evaluate this code, as the JPG code appears sufficient except for mismatched properties.
By way of additional verification of this being the root cause, checking the values of the supplied graphic:
.PixelFormat = PixelFormat.Format8bppIndexed
Reloading the image (from the saved memory stream) gives this values:
.PixelFormat = PixelFormat.Format24bppRgb
So there definitely is a difference.
This may also explain why the "/Decode" for the ColorSpaceYcck needed to be inverted. I don't have any images of this type, but it may be worth rechecking if using another version.
I'm attaching a copy of the PdfImage.cs with option #2 - using a copy of the image from the saved memory stream. I haven't changed any of the elements to use the new "renderedImage" image object except those that cause the item to choose a different ColorSpace. Code is designated as "// NEW"
Unfortunately, I am working in VS 2005 so I cannot determine how to adjust the WPF code, if any change is needed.