Bug 707290 - image in xps convert to pdf failed.
Summary: image in xps convert to pdf failed.
Status: RESOLVED FIXED
Alias: None
Product: GhostXPS
Classification: Unclassified
Component: General (show other bugs)
Version: 10.02.0
Hardware: PC Windows 11
: P2 enhancement
Assignee: Tor Andersson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-10-24 02:35 UTC by lanwah
Modified: 2024-04-26 01:26 UTC (History)
1 user (show)

See Also:
Customer:
Word Size: ---


Attachments
xps file (14.79 KB, application/vnd.ms-xpsdocument)
2023-10-24 02:35 UTC, lanwah
Details
image base64 string (8.34 KB, text/plain)
2023-10-24 02:35 UTC, lanwah
Details
source picture resolution (54.02 KB, image/png)
2023-10-26 01:11 UTC, lanwah
Details

Note You need to log in before you can comment on or make changes to this bug.
Description lanwah 2023-10-24 02:35:08 UTC
Created attachment 24994 [details]
xps file

When XPS files are generated by a virtual printer (Microsoft XPS Document Writer), the images will not be displayed when converting xps to pdf.
The attached xps file has been uploaded
img base64.txt is the base64 string of the image
Comment 1 lanwah 2023-10-24 02:35:47 UTC
Created attachment 24995 [details]
image base64 string
Comment 2 Ken Sharp 2023-10-24 08:00:05 UTC
This isn't a problem with pdfwrite. Rendering the XPS file produces an empty page. If it doesn't render properly it certainly won't produce a correct PDF file from the pdfwrite device.
Comment 3 lanwah 2023-10-24 08:10:08 UTC
(In reply to Ken Sharp from comment #2)
> This isn't a problem with pdfwrite. Rendering the XPS file produces an empty
> page. If it doesn't render properly it certainly won't produce a correct PDF
> file from the pdfwrite device.

I have uploaded the xps file in the attachment, and the generated xps file is correct
Comment 4 Ken Sharp 2023-10-24 08:18:19 UTC
(In reply to lanwah from comment #3)
> (In reply to Ken Sharp from comment #2)
> > This isn't a problem with pdfwrite. Rendering the XPS file produces an empty
> > page. If it doesn't render properly it certainly won't produce a correct PDF
> > file from the pdfwrite device.
> 
> I have uploaded the xps file in the attachment, and the generated xps file
> is correct

I did not say there was a problem with the XPS file.

What I said was that if you render the XPS file with GhostXPS then the result is an empty page, therefore the problem is with the XPS interpreter, not the pdfwrite device.
Comment 5 Ken Sharp 2023-10-25 15:40:59 UTC
For the record; the problem is that the embedded JPEG image has X_Density = Y_Density = 0, ie it declares a resolution of zero dpi.

If I force the code to assume 96 dpi then the images render correctly.

This commit 4dc6cbedb4ef789c8c8ebd4c83095d0198050350 for MUPDF additionally reads the resolution from the EXIF and APP13 marker and uses these, possibly in preference, to get a non-zero resolution. I would guess something similar needs to be done.
Comment 6 lanwah 2023-10-26 01:09:42 UTC
(In reply to Ken Sharp from comment #5)
> For the record; the problem is that the embedded JPEG image has X_Density =
> Y_Density = 0, ie it declares a resolution of zero dpi.
> 
> If I force the code to assume 96 dpi then the images render correctly.
> 
> This commit 4dc6cbedb4ef789c8c8ebd4c83095d0198050350 for MUPDF additionally
> reads the resolution from the EXIF and APP13 marker and uses these, possibly
> in preference, to get a non-zero resolution. I would guess something similar
> needs to be done.

Thank you for your answer.

I get the source image form the base64 string ,i find that the dpi is 96(attachment file 1.png).

I draw the image to xps like this:
Graphics.DrawImage(img2, 96, 300);

I Convert the xps file to pdf file this:

        /// <summary>
        /// Converts XPS file to PDF using provided pathes.
        /// </summary>
        /// <param name="xpsFilePath">XPS file path.</param>
        /// <param name="pdfFilePath">PDF file path.</param>
        /// <param name="utilitiesPath">Path ghost xps utilities.</param>
        public static void Convert(string xpsFilePath, string pdfFilePath, string utilitiesPath = null)
        {
            if (string.IsNullOrEmpty(xpsFilePath))
            {
                throw new ArgumentNullException(nameof(xpsFilePath), "Xps file path can't be empty. Please, specify a valid xps file path.");
            }

            if (string.IsNullOrEmpty(pdfFilePath))
            {
                throw new ArgumentNullException(nameof(pdfFilePath), "Pdf file path can't be empty. Please, specify a valid pdf file path.");
            }

            var ghostStartInfo = new ProcessStartInfo
            {
                WorkingDirectory = Environment.CurrentDirectory,
                FileName = Environment.Is64BitOperatingSystem ? $"{utilitiesPath}gxpswin64.exe" : $"{utilitiesPath}gxpswin32.exe",
                Arguments = $"-dNOPAUSE -dBATCH -dSAFER -sOutputFile=\"{pdfFilePath}\" -sDEVICE=pdfwrite \"{xpsFilePath}\"",
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardError = true
            };

            using (var ghostProcess = Process.Start(ghostStartInfo))
            {
                ghostProcess.WaitForExit();

                if(ghostProcess.ExitCode != 0)
                {
                    var message = ghostProcess.StandardError.ReadToEnd();

                    throw new XpsConverterException(message);
                }
            }
        }
Another question I have is: what types of images in xps can be converted to pdf, so far I have found that only png images in xps can be converted successfully.
Comment 7 lanwah 2023-10-26 01:11:12 UTC
Created attachment 24997 [details]
source picture resolution
Comment 8 lanwah 2023-10-26 01:14:41 UTC
(In reply to Ken Sharp from comment #4)
> (In reply to lanwah from comment #3)
> > (In reply to Ken Sharp from comment #2)
> > > This isn't a problem with pdfwrite. Rendering the XPS file produces an empty
> > > page. If it doesn't render properly it certainly won't produce a correct PDF
> > > file from the pdfwrite device.
> > 
> > I have uploaded the xps file in the attachment, and the generated xps file
> > is correct
> 
> I did not say there was a problem with the XPS file.
> 
> What I said was that if you render the XPS file with GhostXPS then the
> result is an empty page, therefore the problem is with the XPS interpreter,
> not the pdfwrite device.

Thanke you for you answer.

I do nothing with the xps file. 
I convert the xps to pdf like this:

        /// <summary>
        /// Converts XPS file to PDF using provided pathes.
        /// </summary>
        /// <param name="xpsFilePath">XPS file path.</param>
        /// <param name="pdfFilePath">PDF file path.</param>
        /// <param name="utilitiesPath">Path ghost xps utilities.</param>
        public static void Convert(string xpsFilePath, string pdfFilePath, string utilitiesPath = null)
        {
            if (string.IsNullOrEmpty(xpsFilePath))
            {
                throw new ArgumentNullException(nameof(xpsFilePath), "Xps file path can't be empty. Please, specify a valid xps file path.");
            }

            if (string.IsNullOrEmpty(pdfFilePath))
            {
                throw new ArgumentNullException(nameof(pdfFilePath), "Pdf file path can't be empty. Please, specify a valid pdf file path.");
            }

            var ghostStartInfo = new ProcessStartInfo
            {
                WorkingDirectory = Environment.CurrentDirectory,
                FileName = Environment.Is64BitOperatingSystem ? $"{utilitiesPath}gxpswin64.exe" : $"{utilitiesPath}gxpswin32.exe",
                Arguments = $"-dNOPAUSE -dBATCH -dSAFER -sOutputFile=\"{pdfFilePath}\" -sDEVICE=pdfwrite \"{xpsFilePath}\"",
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardError = true
            };

            using (var ghostProcess = Process.Start(ghostStartInfo))
            {
                ghostProcess.WaitForExit();

                if(ghostProcess.ExitCode != 0)
                {
                    var message = ghostProcess.StandardError.ReadToEnd();

                    throw new XpsConverterException(message);
                }
            }
        }
Comment 9 Ken Sharp 2023-10-26 08:38:08 UTC
(In reply to lanwah from comment #6)

> Thank you for your answer.
> 
> I get the source image form the base64 string ,i find that the dpi is
> 96(attachment file 1.png).

It doesn't matter what the .png file says. The image in the XPS file is a JPEG, not a PNG and it has no resolution defined. It also lacks an EXIF or an APP13 marker, so the resolution genuinely is not defined.

This commit f999c9ee55423d6669c396f26d68edc57c17b8cf forces an undefined resolution to be treated as 96 dpi which resolves the problem. As I noted in comment #5 above, the specification says that we should also read EXIF or APP13 markers, and the commit does not address that, so I have altered this to an enhancement, requiring that work to be done.


 
> I draw the image to xps like this:
> Graphics.DrawImage(img2, 96, 300);

Doesn't matter how you create the XPS file, it is what the XPS file contains that matters. Your XPS file contains a JPEG image, not a PNG and that JPEG image does not define a resolution.


> Another question I have is: what types of images in xps can be converted to
> pdf, so far I have found that only png images in xps can be converted
> successfully.

The XPS specification is available here

https://www.microsoft.com/en-us/download/details.aspx?id=51478
Comment 10 Ken Sharp 2023-10-26 08:38:22 UTC
(In reply to lanwah from comment #6)

> Thank you for your answer.
> 
> I get the source image form the base64 string ,i find that the dpi is
> 96(attachment file 1.png).

It doesn't matter what the .png file says. The image in the XPS file is a JPEG, not a PNG and it has no resolution defined. It also lacks an EXIF or an APP13 marker, so the resolution genuinely is not defined.

This commit f999c9ee55423d6669c396f26d68edc57c17b8cf forces an undefined resolution to be treated as 96 dpi which resolves the problem. As I noted in comment #5 above, the specification says that we should also read EXIF or APP13 markers, and the commit does not address that, so I have altered this to an enhancement, requiring that work to be done.


 
> I draw the image to xps like this:
> Graphics.DrawImage(img2, 96, 300);

Doesn't matter how you create the XPS file, it is what the XPS file contains that matters. Your XPS file contains a JPEG image, not a PNG and that JPEG image does not define a resolution.


> Another question I have is: what types of images in xps can be converted to
> pdf, so far I have found that only png images in xps can be converted
> successfully.

The XPS specification is available here

https://www.microsoft.com/en-us/download/details.aspx?id=51478
Comment 11 Ken Sharp 2024-04-25 13:05:41 UTC
Enhancement completed with commit 	dde12cc2aab267741c52277bcb78d75f271845a5
Comment 12 lanwah 2024-04-26 01:26:15 UTC
(In reply to Ken Sharp from comment #11)
> Enhancement completed with commit 	dde12cc2aab267741c52277bcb78d75f271845a5

Thank you for your contribution.