linux CLI: how to render Arabic text into bitmap - ruby

I would like to draw Arabic text into bitmap (bmp or png) with command line interface.
I have tried imagemagick and RMagick, but I have problem with RTL language issue. all my rendering are left to right. And google is not helping.
require:
./render "لوحة المفاتيح" out.png
would give a bitmap:
لوحة المفاتيح
Anyone can give me some successful results?

Anyone can give me some successful results?
I can. I use convert from ImageMagick:
echo لوحة المفاتيح > text.txt && \
convert -size 300x200 \
-background white \
-fill black \
-font /usr/share/fonts/truetype/droid/DroidNaskh-Regular.ttf \
-pointsize 24 \
-gravity Center \
label:#text.txt \
text.png
This is the result:
Some notes:
You need to use a font which defines the used characters (in your case an arabic font)
Always use a temporary file with the text inside instead of provide the text directly from the command line: it would lead to weird results
UPDATE I didn't notice the RTL part of the question; I think I got better results using pango (reference):
# On Ubuntu
sudo apt-get install libpango1.0-dev
echo -n لوحة المفاتيح > text.txt
pango-view text.txt --no-display --output text.png
Result:

For Arabic typography, you might want to use Inkscape 0.9 as follows (Window7 cmd):
inkscape "ar.svg" --export-png="C:\Users\Path\TO\output\arabicthabit.png" --export-dpi="900,900" --export-background="rgb(100%,100%,100%)"
Where ar.svg is:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="400"
height="100"
version="1.1">
<text
xml:space="preserve"
style="font-size:30px;font-style:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:'Droid Arabic Naskh';font-weight:bold;"
x="10" y="90"
><tspan>لغةٌ عربيّةٌ</tspan>
</text>
</svg>
You can replace the font-family:'Droid Arabic Naskh' by any font in your system.
Also you can change the output format as stated in the man pages of Inkscape. Moreover, you can start in Inkscape GUI and save the SVG and change what you want in the SVG XML in any scripting language.
Inkscape 0.48 returned buggy Arabic typography.
As for ImageMagick 6.8.9-7, I used Python +Wand(Python Lib)+arabic_reshaper(Python Lib)+bidi.algorithme(Python Lib) to generate correct Arabic typography in images:
from wand.image import Image as wImage
from wand.display import display as wdiplay
from wand.drawing import Drawing
from wand.color import Color
import arabic_reshaper
from bidi.algorithm import get_display
reshaped_text = arabic_reshaper.reshape(u'لغةٌ عربيّة')
artext = get_display(reshaped_text)
fonts = ['C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\DroidNaskh-Bold.ttf',
'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit.ttf',
'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit-Bold-Oblique.ttf',
'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit-Bold.ttf',
'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit-Oblique.ttf',
'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\majalla.ttf',
'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\majallab.ttf',
]
draw = Drawing()
img = wImage(width=1200,height=(len(fonts)+2)*60,background=Color('#ffffff'))
#draw.fill_color(Color('#000000'))
draw.text_alignment = 'right';
draw.text_antialias = True
draw.text_encoding = 'utf-8'
#draw.text_interline_spacing = 1
#draw.text_interword_spacing = 15.0
draw.text_kerning = 0.0
for i in range(len(fonts)):
font = fonts[i]
draw.font = font
draw.font_size = 40
draw.text(img.width / 2, 40+(i*60),artext)
print draw.get_font_metrics(img,artext)
draw(img)
draw.text(img.width / 2, 40+((i+1)*60),u'ناصر test')
draw(img)
img.save(filename='C:\\PATH\\OUTPUT\\arabictest.png'.format(r))
wdiplay(img)

Related

Translate a ImageMagick convert shell script to Python/PIL script

I'm trying to translate some shell scripts using the convert cmd to python script using PIL.
Here's the original shell script:
convert \
-resize 25% \
+repage \
-background white
-quality 95 \
-flatten \
-gravity center \
-extent 200x200 \
img_a.png img_b.jpg
Here's what I've being able to translate so far:
# Paths
img_a_png_filepath = '/foo/bar/img_a.png'
img_a_name = Path(img_a_png_filepath).stem
img_b_name = f'{img_a_name}.jpg'
img_b_jpg_filepath = f'/foo/bar/{img_b_name}'
# Converting to JPEG
img_a_png = Image.open(img_a_png_filepath)
# -background white
white_bg = Image.new('RGBA',img_a_png.size ,(255, 255, 255, 255))
white_bg.paste(img_a_png, (0, 0), img_a_png)
white_bg = white_bg.convert('RGB')
white_bg.save(img_b_name, 'JPEG')
# -resize 25%
img_b_jpg = Image.open(img_b_jpg_filepath)
img_b_jpg = img_b_jpg.resize((img_b_jpg.size[0]*0.25, img_b_jpg.size[0]*0.25))
img_b_jpg.save(img_b_name, 'JPEG')
I guess the original script is trying to crop from the center with the -gravity center and extent 200x200 but I have no clue how to translate both of those options to PIL.
You're nearly there! You've got the white background, the -flatten (using paste) and the resizing.
You just need to do the -extent from the centre, so...
get the width, and halve it int(im.width/2) and subtract 100 to use as the left edge and add 100 to use as the right edge
get the height and do the same to get top and bottom
crop.
If smaller than 200x200 paste onto a 200x200 canvas.
By the way, there's no need to save the images repeatedly as you are currently doing - just carry on processing what you've got.

Using rmagick to colorize an image like in photoshop

So I have this base image:
And in photoshop I do a basic layer color overlay, with the rgb colors:
r: 244, g: 93, b: 0
This gives me the amazingly vibrant:
What I'm trying to do is colorize the same image in rmagick, so if I do the following colorize:
img = Magick::Image.read('brush.png').first
img = img.colorize(100, 100, 100, Magick::Pixel.new(244, 93, 0, 1))
img.format = 'png'
img.to_blob
It gives me this really washed out orange image:
My questions is, how do I colorize this image with those rgb params in imagemagick / rmagick, to get the same vibrant color that I got in photoshop.
Thanks.
At the commandline, I think you want something like this:
convert brush.png \( +clone -fill "rgb(244,93,0)" -colorize 100% \) -compose colorize -composite out.png
So, with the +clone I am creating another layer the same size as your image and entirely filling it 100% with your orange colour and then composing it over your image with the -composite to blend the opacity and colour.
I really don't speak Ruby, but I think it will be along these lines:
#!/usr/bin/ruby
require 'RMagick'
include Magick
infile=ARGV[0]
img=Magick::Image.read(infile).first
w=img.columns
h=img.rows
ovl=Image.new(w,h){self.background_color=Magick::Pixel.new(244*256,93*256,0)}
img.composite!(ovl,0,0,Magick::ColorizeCompositeOp)
img.write('result.png')
Mark Setchell's command line works for me (Windows), with slight modifications...
convert greyscale.png +clone -fill "rgb(244,93,0)" -colorize 100% -compose colorize -composite colour.png
Found this link on recolouring with rmagick...
ftp://belagro.com/Redmine/ruby/lib/ruby/gems/1.8/gems/rmagick-2.12.0/doc/colorize.rb.html
Based on the code in the above link, with the greyscale conversion removed, does the example below work (I don't have ruby)?
# load the greyscale image
img = Magick::Image.read('greyscale.png').first
# Colorize with a 100% blend of the orange color
colorized = img.colorize(1, 1, 1, '#A50026')
# save the colour image
colorized.write('colour.png')
Used a colour picker to get the hex of your orange colour - rgb(244,93,0) = #A50026

How to save Plotchart canvas other than PostScript without displaying it?

I read the section OTHER OUTPUT FORMATS of Plotchart documentation, but still can't figure out how to do it.
I want to:
Save canvas as image without displaying it. So I can run it in batch mode.
Save in other format. (ex: jpeg, png...)
A brief example is appreciated.
I didn't try this solution, but the man page you linked describes a saveplot command to store the plot into a Postscript (or other image format) file.
Once you created your plot widget, you can do something like
.plot saveplot filename.ps -plotregion bbox
where the -plotregion bbox says to save all the plot and not just the visible part (-plotregion window, which is the default).
I found Img library is capable to converts Postscript into various formats, and a quick and dirty way do not display the canvas is to run exit immediately.
Here is an example:
package require Plotchart
package require Img
canvas .c -background white -width 400 -height 200
pack .c -fill both
set s [::Plotchart::createXYPlot .c {0.0 100.0 10.0} {0.0 100.0 20.0}]
foreach {x y} {0.0 32.0 10.0 50.0 25.0 60.0 78.0 11.0 } {
$s plot series1 $x $y
}
$s title "Data series"
set file "test.ps"
$s saveplot $file
set root [file rootname $file]
set image [image create photo -file $file]
foreach {f suffix} {JPEG jpg GIF gif PNG png} {
$image write $root.$suffix -format $f
}
exit

Write a string with caption method using MiniMagick

I'm trying to write a string over a image. Currently I'm using MiniMagick and I can resize and overlap two images, but when I try write a multiline string using caption nothing happens to final image, it's still same as before.
Here is my current code:
image = MiniMagick::Image.open('template.jpg')
image.combine_options do |c|
c.background '#0008'
c.fill '#666'
c.gravity 'center'
c.size '100x50'
c.caption "Lets write some big string here... zzzzz I hope this work =)"
end
image.write('final.jpg')
My refs:
http://www.imagemagick.org/Usage/annotating/
ImageMagick multiline text and background image
http://www.imagemagick.org/www/command-line-options.html#caption
Thanks all
I ended using a system call to get rid this problem, here is the code:
Subexec.run "convert -background '#fff0' \\
-fill '#003300' \\
-gravity west \\
-size 560x180 \\
-pointsize 19 \\
-font \'#{font_path}\' \\
caption:\"#{caption}\" \\
#{photo_path} \\
+swap \\
-gravity NorthWest \\
-geometry +333+113 \\
-composite #{photo_path}"
You need to use Convert with MiniMagick. And caption is great because it will wrap and adjust according to the size, as long as you don't put in pointsize. The syntax is a little tricky though because there aren't many Rails examples out there.
file = Paperclip::Tempfile.new(["processed", ".jpg"])
MiniMagick::Tool::Convert.new do |img|
img.background '#0008'
img.fill '#666'
img.gravity 'center'
img.size '100x50'
img << "caption: Lets write some big string here... zzzzz I hope this work =)"
img << file.path
end
model.picture = file
model.save
file.unlink
Note: You have to add file path last

Add a rectangle to the image using image magic

Good day.
How to impose white_rectangle.jpg on logo.jpg in the image below
using Imagemagic.
And a bonus question: what's Ruby's method can make the task.
def (path_to_image)
# impose white_rectangle.jpg on logo
end
This can easily be accomplished using RMagick:
require 'RMagick'
logo = Magick::Image.read("logo.jpg").first
rect = Magick::Image.read("white_rectangle.jpg").first
result = logo.composite(rect, x, y, Magick::CopyCompositeOp)
result.write "result.jpg"
An alternative is to just draw a white rectangle without using a composite image:
image = Magick::Image.read("logo.jpg").first
gc = Magick::Draw.new
gc.stroke = 'white'
gc.fill = 'white'
gc.rectangle x_start, y_start, x_end, y_end
gc.draw(image)
image.write "result.jpg"
Using ImageMagick command line tools, you can overlay one image with another like this:
$ composite white_rectangle.jpg logo.jpg -geometry +x+y result.jpg

Resources