Insert a text chunk into a png image - linux

I'm looking for a simple command-line tool (on Linux) to insert a text chunk (e.g. copyright) into a png file, resulting in a new png file:
> png-insert-text-chunk "here's my text chunk" < in.png > out.png
Note: by "insert a text chunk", I do not mean "draw some text on the image". I mean: insert the text into the png file as a chunk, in the technical sense. This can be used, for example, to insert a copyright message that isn't displayed on the actual image.

Use ImageMagick's convert and the -set option:
convert IN.png \
-set 'Copyright' 'CC-BY-SA 4.0' \
-set 'Title' 'A wonderful day' \
-set comment 'Photo taken while running' \
OUT.png
The -set option is used to set metadata elements. In the case of PNG these often go into tEXt chunks.

I have searched around for utilities to do this, and not yet found anything that really matches what I want to do. So I decided to build my own, which it turns out is not too hard. The utility png-text-dump displays all text chunks in a PNG image. It depends only on libpng. The utility png-text-append inserts text chunks into a PNG image. It depends only on the standard C library - I had initially tried to implement this using libpng, but actually found it easier to work from scratch using only the PNG specification.

Note: This answer was a response to the original revision of the question where it was not clear if the text had to be written on the image or if the text had to be embedded within the image binary file as metadata. This answer assumed the former. However the question was edited to clarify that it meant the latter. This answer is left intact, in case someone is looking for a solution to the former.
convert -draw "text 20,20 'hello, world'" input.png output.png
The 20,20 in the above example is the co-ordinate where I want to place the text.
You need to use the imagemagick package to get this command.
On Ubuntu or Debian, it can be installed with the command: apt-get install imagemagick.
Here is a slightly more elaborate usage of the command:
convert -font Helvetica -pointsize 20 -draw "text 20,20 'hello, world'" input.png output.png

This can be implemented with python pypng module. The python3 example code is below:
import png
TEXT_CHUNK_FLAG = b'tEXt'
def generate_chunk_tuple(type_flag, content):
return tuple([type_flag, content])
def generate_text_chunk_tuple(str_info):
type_flag = TEXT_CHUNK_FLAG
return generate_chunk_tuple(type_flag, bytes(str_info, 'utf-8'))
def insert_text_chunk(target, text, index=1):
if index < 0:
raise Exception('The index value {} less than 0!'.format(index))
reader = png.Reader(filename=target)
chunks = reader.chunks()
chunk_list = list(chunks)
print(chunk_list[0])
print(chunk_list[1])
print(chunk_list[2])
chunk_item = generate_text_chunk_tuple(text)
chunk_list.insert(index, chunk_item)
with open(target, 'wb') as dst_file:
png.write_chunks(dst_file, chunk_list)
def _insert_text_chunk_to_png_test():
src = r'E:\temp\png\register_05.png'
insert_text_chunk(src, 'just for test!')
if __name__ == '__main__':
_insert_text_chunk_to_png_test()

I believe that pngcrush has this ability: http://pwet.fr/man/linux/commandes/pngcrush

Adding to the comment made by #susam-pal, to change color use the option
-fill color
This option accepts a color name, a hex color, or a numerical RGB, RGBA, HSL, HSLA, CMYK, or CMYKA specification. See Color Names for a description of how to properly specify the color argument.
Enclose the color specification in quotation marks to prevent the "#" or the parentheses from being interpreted by your shell.
For example,
-fill blue
-fill "#ddddff"
-fill "rgb(255,255,255)"
Obtained from link

Related

Black color showing on CMY channels when converted to CMYK using GhostScript

I am trying to generate a PDF using a library called wkhtmltopdf to create an RGB pdf. I am then using ghostscript to convert it to a CMYK format, however, the black text that is in the pdf is not pure black [cmyk(0,0,0,1)].
The black color is visible in other channels.
The command for ghostscript is:
gs -dBATCH -dNoOutputFonts -dNOPAUSE -dTextBlackPt=1 -dBlackPtComp=1 -sTextICCProfile -dNOCACHE -sDEVICE=pdfwrite -sProcessColorModel=DeviceCMYK -sColorConversionStrategy=CMYK -sOutputICCProfile=ps_cmyk.icc -sDefaultRGBProfile=srgb.icc -dOverrideICC=true -dRenderIntent=1 -sOutputFile=cmyk11.pdf test-rgb-cmyk.pdf
Any help would be massively appreciated! Been at this for a few days now. Thanks!
Ghostscript version: 9.26
Example pdf: https://drive.google.com/file/d/1nSM05b0O6fEb_0Z1rr2REbOPQAdwolTA/view?usp=drivesdk
Almost all the switches you are using will have no effect with the pdfwrite device, they are specific to rendering devices (bitmap output). In particular the -dTextBlackPt, -dBlackPtComp and TextICCProfile will do nothing.
In order to properly colour manage the conversion you need to specify input and output ICC profiles. If memory serves, you need to alter the default Gray, RGB and CMYK profiles that Ghostscript uses.
Really I'd need to see an example file (as simple as possible) and it would obviously be useful to know which version of Ghostscript you are using. If it's not the current version then I'd suggest you upgrade anyway.
Examples of Ghostscript commands to convert PDF from sRGB or eciRGB_v2 to eciCMYK_v2 (FOGRA 59) while keeping black plain (K only), not rich (CMYK)
I managed to convert PDF file in RGB to CMYK while keeping RGB black #000000 plain K black, not rich CMYK black.
DeviceLink ICC had to be created from e.g. eciRGB_v2 (or sRGB, if your source is sRGB) profile to the appropriate CMYK profile using collink tool (from argyll package) with the "-f" attribute to hack the black colors.
Ghostscript is then called with a control file declaring use of the profile and its parameters.
Example of making the DeviceLink RGB to CMYK profile
collink -v -f eciRGB_v2.icc eciCMYK_v2.icc eciRGB_v2_to_eciCMYK_v2.icc
Example of a control file to map eciRGB_v2 to eciCMYK_v2 (control-eciRGB_v2.txt)
Image_RGB eciRGB_v2_to_eciCMYK_v2.icc 0 1 0
Graphic_RGB eciRGB_v2_to_eciCMYK_v2.icc 0 1 0
Text_RGB eciRGB_v2_to_eciCMYK_v2.icc 0 1 0
(note must be separated by tabs, not spaces)
Sample ghostscript command to do the actual conversion
gs -o 2-output-cmyk-from-eciRGB.pdf \
-sDEVICE=pdfwrite \
-sColorConversionStrategy=CMYK \
-sSourceObjectICC=control-eciRGB_v2.txt \
1-input-rgb.pdf

ImageMagick - quoted numbers as convert label argument causes the command to fail

my shell hangs on this command:
/usr/local/bin/convert -size 298x71 -background black -fill white -stroke none -gravity center -trim -interline-spacing 0 -font /home/amazingw/public_html/live/fonts/Phillies.ttf label:'150' png:-
The shell just sits there until i press ctrl+c. If I add any letter to the label: argument the command runs fine and I get output.
The font is there but it is missing the number characters in the definition.
Could that cause my command to fail?
This seems like an issue related to input at the console, I am assuming you are using Bash.
If this is the case, Bash is trying to interpret the quotes and is waiting for other input.
after reviewing the imagemagick website for "label:"
Label - Simple Text Label
Basic Labels
Creating a font image using a "label:" image,
is the more typical way of drawing a font
quickly in ImageMagick...
It goes on and gives many examples...
convert -background lightblue -fill blue \
-font Candice -pointsize 72 label:Anthony \
label.gif
None of the examples show single quotes.
I would assume between Bash and ImageMagick's convert program, there is some error on interpretation of input from the console.
I would suggest trying your same command without quotes
/usr/local/bin/convert -size 298x71 -background black -fill white -stroke none -gravity center -trim -interline-spacing 0 -font /home/amazingw/public_html/live/fonts/Phillies.ttf label:150 png:-
I would also take a quick look at the Bash manual about single quotes too.
I was able to test using a modified version of the font which contained the digits. Command went smoothly and an output image was returned. This pretty much narrows it down to an ImageMagick problem with handling labels. Looks like if the label is made out only of characters which are missing in the font (the resulting output image would be empty) - in that case ImageMagick hangs until ctrl+c is pressed - especially problematic as I'm running this from php's proc_open.

Render string in X11 bitmap font

How do I render a string in an ancient X11 bitmap font? I mean something like
-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*
which I can find with xfontsel. I just need a command line tool etc. that displays a given string in that font. A similar TrueType font won't work, since it has to be pixel-perfect (I'm trying to get images of each letter to OCR an image in that font).
I'm not sure if there is a command line tool. But you can always roll your own with Xlib and C.
Somebody seems to have written a simple X11 C program that displays a string using Xlib. Changing a couple of lines and compiling with:
gcc -lX11 -o xrenderstring xrenderstring.c
.. should do it for you.
I've reproduced the entire program in this gist (in case it vanishes from the original source), modified to take two arguments: 1. fontname, 2. string to be rendered.
So you'd call it like (after compiling of course):
./xrenderstring "-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*" "Quick brown fox"
To just render characters in that font:
xfd -fn '-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*'
xfontsel -pattern '-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*'
To render a specific string:
xfontsel -pattern '-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*' -sample 'The quick brown fox jumps the shark'
Found a hackish way. Add the following to ~/.Xdefaults:
xedit*editWindow*font: -*-lucida-medium-r-normal-*-36-*-*-*-*-*-*-*
and then run
$ xrdb -merge ~/.Xdefaults
$ xedit
Then I typed the string in, took a screenshot, and compared it in gimp.
(Turns out the X11 font was not quite the right one after all. My source used Lucida Sans 36 pt (ttf), but without antialiasing and probably wierd hinting.)
You can use ImageMagick.
Added benefits:
can render old-fashioned (fixed) or TTF or other fonts
can render to screen or to image file (PNG, whatever)
Simple
For short text
echo "The quick brown fox jumps over the lazy dog." \
| convert \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
TEXT:- -trim fox.png
To render to screen:
echo "The quick brown fox jumps over the lazy dog." \
| convert \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
TEXT:- -trim MIFF:- | display MIFF:-
Remove -trim to see that ImageMagick uses a canvas to draw.
More control
Canvas size. To avoid two-step computations, create a canvas larger than needed and trim it afterwards.
Control background and foreground colors.
Control PNG parameters (one bit per pixel)
convert -size 2000x20 xc:black \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
-fill white \
-draw "text 0,15 'The quick brown fox jumps over the lazy dog.'" \
-trim +dither -depth 1 fox.png
The resulting image below weighs 592 bytes:
To get independently framed characters (for later composition)
You could put only one character in line above, but applying to several characters independently would cause the resulting images to no longer have a same size nor same common baseline.
for CHAR in H e l o ' ' W r d
do
convert -size 9x13 xc:black \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
-fill white -stroke none \
-draw "text 0,10 '${CHAR}'" \
+dither -depth 2 fixed_char_${CHAR}.png
done
The command below produces a PNG showing that individually framed images keep their common alignment:
montage -mode concatenate -tile x1 fixed_char_H.png fixed_char_e.png \
fixed_char_l.png fixed_char_l.png fixed_char_o.png fixed_char_\ .png \
fixed_char_W.png fixed_char_o.png fixed_char_r.png fixed_char_l.png \
fixed_char_d.png helloworld.png

Wrong colours when converting TIFF image to PNG in ImageMagick

I'm working on a PHP script that automatically converts TIFF images to PNG files.
For that purpose, I use ImageMagick:
$ convert a.tif a.png
It works to some degree, however, the colours are very acute and deviant from the way they are pictured on my PC. To illustrate the problem, please have a look at the enclosed files, the include:
The Windows Live Foto Gallery output (that's pretty much how I want it to be)
The ImageMagick output (the mess I end up with)
The original TIFF file
Has anyone an idea whether, and if so how, I can alter the ImageMagick colour interpretation?
Thanks a lot!
Alright,
thanks to ergosys, the problem was easily solved: I needed to apply ICC colour profiles.
The XMP declared ISO 12647-2:2004, which was to be found at http://eci.org.
$ convert -profile ISOcoated_v2_eci.icc -profile eciRGB_v2.icc a.tif c.png
When converting from a CMYK color space to an RGB color space, as you do when going from tiff to png, you have to convert the color spaces along with the image. Try:
convert -colorspace rgb a.tif a.png
I ran this locally and get a better result from this than from the command line in your question, but my color vision sucks, so I can't guarantee that this is what you were after. =] Hope it gets you on the right track, anyway.

Automate conversion of text to PNG (or another file format with transparency)?

I need to take a list of words and create a PNG file of each, with a transparent background.
I’d like my script to allow for adjustable opacity of the foreground, but I can probably also do it after the fact when the images get imported into Matlab.
I imagine this is doable with ImageMagick and have installed that on my Mac. If someone can give me the one line I’d need to turn a word into a PNG (the word can be the filename too) in Perl or Python, I can probably figure out the rest of the scripting.
I found this to be applicable to your question:
convert -size 560x85 xc:transparent -font Palatino-Bold -pointsize 72 -fill black -draw "text 20,55 'Linux and Life'" linuxandlife.png
Output:
size 560x85 : the size (width x height) of the image
xc:transparent : xc means X window color, use "transparent" to get a transparent background
fond Palatino-Bold : the font of the text ( type "identify -list font" in the terminal to know all the supported fonts)
pointsize 72 : the size of the text
fill black : the color of the text ( check this link to know the names of the supported colors)
draw "text 20,55 'Linux and Life'" : the position of the text and the text itself
linuxandlife.png : the output image
Matplotlib (better known as pylab) would work great for this. Assuming ImageMagick is installed this script should work. (tested on Ubuntu 9.10)
import pylab as py, os
W = ['cat','dog','mouse']
for word in W:
py.clf()
ax = py.axes(alpha=1.0)
py.text(0,.5,word)
py.axis('off')
py.savefig("%s.png"%word)
os.system('convert -trim %s.png %s.png' % (word,word))
This creates three files on my system dog.png, cat.png and mouse.png all cropped with a transparent background.

Resources