How do I import a png file in Postscript with Ghostscript? - filter

I'm trying to place a png image on a postscript document for conversion to a pdf file using Ghostscript (v 9.15) ps2pdf. I've found that the following code works nicely with a jpg file, but I need to import png files instead. It looks like i must need a different filter, but I can't find one that works. Does anyone have a solution?
239 % number of pixels in the horizontal axis
67 % number of pixels in the vertical axis
8 % bits per color channel (1, 2, 4, or 8)
[239 0 0 -67 0 67] % transform array... maps unit square to pixel [ w 0 0 -h 0 h ]
(My_Logo.jpg) (r) file % see page 587 and page 77 for more details
/DCTDecode filter % see page 589
false % pull channels from separate sources
3 % 3 color channels (RGB)
colorimage % see page 544 and page 288 for more detail

PostScript doesn't support PNG directly, it does support JPEG which is why your code above works.
If you want to read image data from a PNG file you will need to open the file, strip the header, then read each chunk individually parsing the data from it. It might be easiest to write the bitmap data to an intermediate file, but its perfectly possible to write a stream decoder to supply the data as required for a procedural image data source.
Fortunately PostScript (level 3 for certain, most versions of level 2) does support Flate, so you don't have to write the decompression code in PostScript, you can use the filter directly.
You will need to specify a colour space, depending on whether the PNG uses a palette or not.
PostScript is a programming language, so this is all possible, it will take an experienced PostScript programmer a couple of days to write and debug it I should think.
NOTE! PostScript does not support transparency, so you cannot apply alpha channels from PNG files at all.

Related

Storing format for an image with its legend

I am trying to store images of plants and their legends (as text) together. However I can't find a straightforward way to do this.
I can of course use an "advanced" text editor (by advanced, I mean with formatting, not just raw text) in which I would import the image and write the text, before exporting in PDF. I have also thought about html, which could be used to create one stand-alone local web page for each pair image-legend. But still, there would be 2 files per pair : one for the image and one for the html code.
However those are quite heavy procedures and I would be much more satisfied if I could "simply" use a rawer format in which the image's data and the text are sort of concatenated, or so...
Do you know of any format of this kind ? If not I'd better just code it myself...
Thank you in advance !
Images can be polyglots of image plus text (not advisable)
Images can hold text as steganography (also unadvisable)
Images can hold textual metadata think Exif, Jpg comments, Tiff tags or IPTC
You could even add a legend strip into base of image, but that's not "text". At time of placement you paste both image and text.
HTML can hold image as text.base64 but the textual image requires 133% storage
FB2 is similar in that it is xml with encoded images but the advantage of being stored as zipped FB2Z thus nearest your concatenated requirement
PDF can hold both natively and if done right with less overhead than html but a bit more than exif.img
If done well as PDF/A both the image and text can be perfectly extracted raw from a PDF so image could be discarded, however, it is all too often that they are mashed beyond pure extraction or even reuse.
But in my case I can extract the image at 100% scale so its returned from this mini PDF here is the text
Hello, Flowers!
Microsoft Windows Welcome Scan
This was the code to store both together using cross platform Artifex Mutool
mutool create -o "output.pdf" -O ascii "Page1.txt" ["page2.txt" ...]
%%MediaBox 0 0 595 842
%%Font Helv Helvetica Latin
%%Image Flowers1 C:/Users/name/Documents/WelcomeScan.jpg
% Draw an image. x width, H line elevation (y skew), x skew, y height, left offset, bottom offset, units are pt.'s cm is not centimetres
q 512 0.0 0.0 384 41.5 400 cm /Flowers1 Do Q
% Draw a rectangle. move line fill
q 1 0.5 1 rg 41.5 370 m 553.5 370 l 553.5 270 l 41.5 270 l f Q
% Show some text.
q 0 0 1 rg
BT /Helv 24 Tf 210 330 Td (Hello, Flowers!) Tj ET
BT /Helv 24 Tf 100 290 Td (Microsoft Windows Welcome Scan) Tj ET
Q
Notes
%%MediaBox is Paper Size in points thus above = A4 Portrait
%%Font needs to be added for text Style (Language) to use later
%%Image needs internal name(s) and full path for pre-load Note this image is 1024x768 when extracted # 100% but will be displayed by choice at 50% (512x384)
Lines starting with single % are comments to remind me of pseudo PS directives to layout content. The blocks q ... Q are the guts of the page and are heavily abbreviated (after the value) thus 1 0.5 1 rg is 50% green in RGB ! Remove them in a working template or else they may be added to the PDF :-)
The trick is knowing how a PDF works page wise and places vectors or scaled images or text from bottom left origin bounded by a media box. Mutool takes the script and adds all the necessary overhead data for a valid PDF.
All the above can be easily templated and run with CMD or BASH, much in the same way an ePub can be templated then call TAR to convert folder into folder.epub, but the more complex ePub structure is not so easy to write in a script, thus suggest using a scriptable lib.
ePub is the goto answer since xhtml and image are zipped in their native formats, and can be easily printed to PDF or converted to normal HTML + images

Swapping Jpeg RGB Channels (RGB->BGR)

I have a Jpeg RGB single-scan clip (with Adobe App14 marker, and R, G, B components all interleaved in the same scan). I am wondering if there is way to edit the Jpeg clip header (or append other headers like EXIF) so that decoders can interpret the R channel as B and vice versa without changing the rest of the bitstream?
I had tried swapping the ordering of "Scan component selectors" in the scan header, and the decoder (Windows Photo Viewer in this case) successfully displayed Red as Blue and Blue as Red afterwards. However, the ITU-T.81 Jpeg specification specifically said that "Csj:Scan component selector: Each Csj shall match one of the Ci values specified in the frame header, and the ordering in the scan header shall follow the ordering in the frame header." So I guess changing the Scan component selector ordering is not a valid option unless there is any updated specification saying that this is no longer the restriction.
Does anyone know other ways to swap the RGB channels by either appending some sort of app data or modifying Jpeg frame or scan headers without touching the scan data at all?
Thank you for your inputs.
If you have the image in raw format you can modify the exif CFA using exiftool. The array may vary depending on the sensor and format.
For swapping dng files, you can use the following
exiftool.exe -subifd:cfapattern2="2 1 1 0" file.dng
Where
0 = Red,
1 = Green,
2 = Blue,
If your desperate you could always consider converting your Jpg to Raw and then back again

matplotlib.pyplot.imsave backend

I'm working in Spyder with matplotlib.pyplot and want to save numpy array to images.
The documentation of imsave() says, that the format to which I can save depends on the backend. So what exactly is the backend? I seem to be able to save .tiff images, but f.e. I want them to be saved as 8-bit tiffs instead of RGB-Tiffs. Any Idea where I can change that?
If you are trying to save an array as a tiff (with no axis markers ect) from mat, you might be better off using PIL.
(this assumes you are using ipython --pylab, so rand is defined)
write:
import PIL.Image as Image
im = Image.new('L',(100,100))
im.putdata(np.floor(rand(100,100) * 256).astype('uint8').ravel())
im.save('test.tif')
The ravel() is important, putdata expects a sequence (ie, 1D) not an array.
read :
im2 = Image.open('test.tif')
figure()
imshow(im2)
and the output file:
$ tiffinfo test.tif
TIFF Directory at offset 0x8 (8)
Image Width: 100 Image Length: 100
Bits/Sample: 8
Compression Scheme: None
Photometric Interpretation: min-is-black
Rows/Strip: 100
Planar Configuration: single image plane

How to display JPEG image on microcontroller LCD?

I am recently developing some firmware on the STM3210E development board which has an ARM cortex M3 processor. It has been interfaced to a 240x320 LCD. After going through the demo firmware, I realised that images are encoded in 32 bit variables (correct me if I am wrong) stored in array as shown below.
uint32_t STM32Banner[50] = {0x6461EB7A, 0x646443BC, 0x64669BFE, 0x6468F440, 0x646B4C82,
0x646DA4C4, 0x646FFD06, 0x64725548, 0x6474AD8A, 0x647705CC,
0x64795E0E, 0x647BB650, 0x647E0E92, 0x648066D4, 0x6482BF16,
0x64851758, 0x64876F9A, 0x6489C7DC, 0x648C201E, 0x648E7860,
0x6490D0A2, 0x649328E4, 0x64958126, 0x6497D968, 0x649A31AA,
0x649C89EC, 0x649EE22E, 0x64A13A70, 0x64A392B2, 0x64A5EAF4,
0x64A84336, 0x64AA9B78, 0x64ACF3BA, 0x64AF4BFC, 0x64B1A43E,
0x64B3FC80, 0x64B654C2, 0x64B8AD04, 0x64BB0546, 0x64BD5D88,
0x64BFB5CA, 0x64C20E0C, 0x64C4664E, 0x64C6BE90, 0x64C916D2,
0x64CB6F14, 0x64CDC756, 0x64D01F98, 0x64D277DA, 0x64D4D01C}
Could you please explain me how to convert a JPEG/PNG/BMP image to this format (RGB565) ?
You have two choices:
Write your own set of decoders.
Use available free decoders
The first solution is only really viable for BMP (and perhaps GIF), which is quite a simple format compared to PNG and JPEG. Even so, writing a BMP decoder that handles all different versions and specialties of BMP gracefully takes quite a bit of work (I have tried it). Hacking together something that can extract the image data from the most common BMP formats is quite easy though.
The second solution is probably the way to go for the other formats. Most open-source decoders are available under LGPL or similar, so licensing shouldn't really be a problem. For JPEG images use libJPEG, for PNG use libPNG and for GIF use giflib.
Most of the decoders do not support decoding to RGB565 so you will have to write a converter to convert from RGB888 to RGB565.
use a program like GIMP to convert to an uncompressed bmp (what you normally get when you save-as bmp).
A bmp has something like a 54 byte header then it goes into the data. Each line is pixels either 3 bytes (RGB) or four bytes (RGBX) per pixel. The width is aligned on a 4 byte boundary so if you have three bytes per and multiply that by the width in pixels if that is not a multiple of four (say 3 bits wide * 3 = 9 as a simple example) then there will be some padding. You know from opening the file in gimp how wide it is, you probably want to use gimp to adjust the image to match your lcd screen anyway. The first bytes of data after the header are the pixel in the lower left corner of the image, you might need to flip the image in the y axis, or just start off this way and see what happens.
Knowing the size of your image, (from opening it with gimp), you can do a little math to see if the size of the file matches with what I am saying, if it is dramatically smaller then there is some compression going on and you need to save again and change the settings for the bmp.
Once you have this figured out then write a simple program to extract the pixels from the bmp and save them in the format you desire. Even better read the code and docs and understand how to program the lcd and you can get from raw pixels to the lcd without having to to through their specific format/code.

Simple way to add an image in postscript

I am trying to write a document in postscript.
Thus far I've been able to write simple text, and work with lines and shapes.
I'm now trying to add some images to the document. After searching on-line I can't seem to find any clear way to do this.
the snip it below is a hello world:
%!PS
/Times
20 selectfont
20 800 moveto
(Hello World!) show
showpage
All I want to do is simply insert an image (eg PNG, JPG, GIF) by specifying the x and y, co-ordinates.
Any help would be much appreciated.
There is a simple method and Postscript does support the jpeg format. If you are using ghostscript you may have to use the -dNOSAFER option to open files. Here is an example:
gsave
360 72 translate % set lower left of image at (360, 72)
175 47 scale % size of rendered image is 175 points by 47 points
500 % number of columns per row
133 % number of rows
8 % bits per color channel (1, 2, 4, or 8)
[500 0 0 -133 0 133] % transform array... maps unit square to pixel
(myJPEG500x133.jpg) (r) file /DCTDecode filter % opens the file and filters the image data
false % pull channels from separate sources
3 % 3 color channels (RGB)
colorimage
grestore
Use a program like convert and then remove any extra code it generated.
You can download the PostScript Language Reference, third edition from adobe (this is the "bible book" for postscript). Chapter 4.10 Images would be a good starting point.
Is this a late answer! The problem with -dNOSAFER prevented me from using the other solutions, so I did the following:
Use Python to read the JPG file as binary and make it a string, compatible with /ASCIIHexDecode:
''.join(["%02x" % ord(c) for c in open(filename, "rb").read()])
Then instead of reading and decoding the image file from the postscript file, paste the above computed string in the postscript file, and filter it, first through /ASCIIHexDecode then /DCTDecode:
(ffd8ffe000104a46494600010102002700270000ffdb004300030202020202030202020303030304060404040404080606050609080a0a090809090a0c0f0c0a0b0e0b09090d110d0e0f101011100a0c12131210130f101010ffdb00430103030304030408040408100b090b1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010ffc00011080010001003011100021101031101ffc400160001010100000000000000000000000000060507ffc40026100002020201030207000000000000000001020304051106071221001315163132414252ffc400160101010100000000000000000000000000070403ffc4002911000201030105090100000000000000000102030004210711123151531314324142617381d1d3ffda000c03010002110311003f00de311d00e0478be19acddc79b0f8ba734aef8aa8a59a4af1c9bdc96159beef275e4efd1ccfa5f2aceea2f8e09f41e7f252a47ab4c4093ba71ceced387b7828b724e87705b588c8478ecac114e28d89e36f83d65d7643ee7eb60b03a23f1f5dff002daaacf4ae479954df1e3d33fd2b593599628d89b0071d5fae9d3bc5750b8a3f1ae3cc9cd3031b4789c689236ce568de374af543ab21b51b2b03138208076a3cef4c8b935acaf3bb05c12685036e285e550b3bccf8a41c7b2327ce78c9a6188b917b2995ab20676a8102af6dc76624c680011f9d8f0005095da5b491ccaec303f0d4f292ebba01cecf23cc57ffd9>)
/ASCIIHexDecode
filter % ascii to bytes
0 dict
/DCTDecode % jpg to explicit
filter
the above snippet replaces (myJPEG500x133.jpg) (r) file /DCTDecode filter in the otherwise very helpful #Hath995 answer.
if you want something else than JPEG but still RGB (i.e.: you want something for which postscript has no decoder), and you can use Python to prepare your postscript file, you can use PIL, like this (it ignores the transparency byte, which is a on/off operation in postscript):
import PIL.Image
i = PIL.Image.open("/tmp/from-template.png")
import itertools
''.join(["%02x" % g
for g in itertools.chain.from_iterable(
k[:3] for k in i.getdata())])
for indexed files I would not know, but it can't be difficult to work it out.

Resources