简体   繁体   中英

C# Image to Postscript ends up off-center

I've created a library that can create a Postscript file from input data in C#. However, when creating images using the following code, the images are appearing incorrectly. It's like they're off-center. From left to right, you see the right edge of the image first and then the left of the image displays in the rest of the image's allotted space. For clarity's sake, it's like taking the word "hello," and instead displaying "ohell."

I'm using the following C# code to create a List object filled with lines that output directly to a postscript file. It looks pretty standard to me, although I noticed a couple of peculiarities that I had to code around. For some reason, my 75 width image wanted to display as 76 pixels in width, so I added the section to add a pixel to it. I don't know why this is, and I have not done enough testing yet to see what all this screws up. Additionally, normally, the Image Matrixes I use have negative height followed by height, but the image was appearing upside down, so I had to swap it.

public virtual List<string> AddImage(Image img, int x, int y, int height, int width)
{
    string sDataSource;
    List<string> destinationList = new List<string>();
    int iImgWidth = img.Width;

    if (iImgWidth % 2 != 0)
    {
        iImgWidth += 1;
    }

    using (MemoryStream ms2 = new MemoryStream())
    {
       Bitmap bmp = (img as Bitmap).Clone(
           new Rectangle(0, 0, img.Width, img.Height), 
           PixelFormat.Format24bppRgb);
       bmp.Save(ms2, ImageFormat.Bmp);

       sDataSource = $"<{string.Join("", ms2.ToArray().Select(a => a.ToString("X2")))}>";
    }

    destinationList.Add($"{x} {y} translate");
    destinationList.Add($"{width} {height} scale");
    destinationList.Add(
        $"/DeviceRGB setcolorspace {{ << /ImageType 1 /Width {iImgWidth} /Height {img.Height} /ImageMatrix [{iImgWidth} 0 0 {img.Height} 0 {img.Height}] /BitsPerComponent 8 /Decode [0 1 0 1 0 1] ");
    destinationList.Add($"/DataSource {sDataSource} >> image }} exec ");

    return destinationList;
}

I've got the output narrowed down to the following, and it's still displaying incorrectly.

%!PS-Adobe-3.1
0 649 translate
27 20 scale
/DeviceRGB setcolorspace { << /ImageType 1 /Width 76 /Height 56 /ImageMatrix [76 0 0 56 0 -56] /BitsPerComponent 8 /Decode [0 1 0 1 0 1] 
/DataSource <... (hex code)> >> image } exec 
showpage

Can anyone point me in the right direction? I've been struggling with this for days.

There are two likely possibilities, you've mentioned both of them in your post, but without the original image data its not possible to tell whether your suppositions are correct.

The first is that you've got the image upside down. In PostScript 0,0 is the lower left of the page, and increasing y moves up the page. Images normally start at the top left, and progress down the page.

So normally the image matrix would be [w 0 0 -h 0 h] whereas what you seem to be emitting is [w 0 0 h 0 -h] . Of course this could be correct, its not possible to be certain without knowing the progression order of samples in the original image.

Its also possible that you've got the bitmap data incorrect, or the width wrong (the fact that you have a width other than what you expected is suspicious), so that the PostScript interpreter starts with half a raster width of white. After that, it draws what you expect as the first (left) part of the image until it has read (and rendered) sufficient data for the whole raster line.

Then the interpreter moves to the next line of image and reads the following data. This data then consists of the right hand portion of the first raster line, followed by the left hand portion of the second line.

And so on. It then appears that the image has been wrapped round.

This is, of course, speculation, because you haven't supplied an example of the input data, or the final PostScript program. I'd suggest that you post an full example output somewhere and link to it here. The original image would probably be useful too, in order to demonstrate the original sample order.

[after looking at the files]

Well, starting from the JPEG, which I assume is the original file, I see that the data in your hex string does not match the data in the decompressed JPEG, nor what I would expect.

Given that most of the image is white, I would expect to see RGB triplets of 0xFF 0xFF 0xFF, your data beings with:

424D0E0901000000000036000000280000009600000096000000010018000000000000000000232E0000232E00000000000000000000

I've no idea what that is, but I'm reasonably confident its not part of the original image data. It looks like your hex string is 135710 bytes. Now, width of 150 * 3 bytes (for RGB = 450 * 150 for the height results in expected data of 67,500 bytes * 2 for hex representation means your data should be 135000 bytes. So it looks to me like your string 'probably' has about 710 bytes too many in it, or 118 RGB triplets too many. I may have screwed up some arithmetic there but that turns out to be everything up to the first 'FF' in your string which is suspicious :-)

I don't speak C# so I can't look at your code (in fact I can't even figure out from the SourceForge project where the actual code is). However it looks to me like you have a problem either decoding the JPEG or opening the output file or something. Removing the odd stuff at the beginning of the data stream doesn't solve the problem, but then I don't know how much is extraneous.....

Given the nature of this problem I think the first thing I would do is use some other tool to extract the image data (just the RGB triplets). Then have my own code write out the same data, ideally these should be identical, but there can be minor differences in JPEG dequantisation. However the data length should at least be the same and the content should be very similar.

There's some odd 'blue' pixels appearing at the edge of the image, I suspect there's something wrong with the decoding you are applying here. Looking at the original I cannot see where that effect is coming from, there is no vertical line in the original that I can see.

In passing you should be aware that some PostScript implementations have a limit on string lengths of 64KB, and your string is already over that limit. As a result your file won't run with Adobe Acrobat Distiller, or any other Adobe PostScript interpreter. If you want to create larger images, you are going to have to change your approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM