Imagemagick unwanted black background on rotated transparent images - background

I have a website that generates polaroid-like images stacked on eachother at different angles.
Up until now everything worked well, but now i've started getting some black background around my transparent .png's.
You can see the problem here. The images in the last album are all messed up.
I'm using imagemagick (6.5.4.7-3.fc12).
my commands look something like this:
the first one is contained whitin a foreach and generates a bunch of pngs rotated at different angles
convert '{$sf}' -auto-orient -thumbnail 120x120 -gravity center -bordercolor snow -background black -polaroid {$angle} {$i}.png
the second command takes the previously generated images and stacks them toghater
convert '*.png' -background transparent -alpha on -gravity center -layers merge -extent 190x190 +repage -thumbnail 115x115 -gravity center -extent 120x120 'result.png'
As far as I got with the debuging, the black background is already present in the images generated with the first command and they only appear when I rotate the images. If I only use -polaroid 0 instead of the +polaroid, then the resulting images are ok.
My guess is that the problem is not with the code itself, but rather ImageMagick or something else got upgraded on my server and that started this whole mess.
I also tried all kinds of combinations with setting -alpha and everything else i could find in the imagemagick docs that is even just slightly related to transparency, but nothing seems to work.

After all sorts of testing I finally got to the conclusion that the problem was not with my convert commands.
The solution to my problem was to reinstall/update ImageMagick.

//It romove the unwanted black/white background and make it transparent backgraund.
ImageInfo info1 = new ImageInfo(
"/opt/apache-tomcat-6.0.18/webapps/newcpclient_branch/upload/sample/ATT00003.jpg");
MagickImage blankImage = new MagickImage(info1);
**blankImage.setBackgroundColor(PixelPacket.queryColorDatabase("#FFFF8800"));**
blankImage = blankImage.rotateImage(250.0);
blankImage.setFileName("/opt/apache-tomcat-6.0.18/webapps/newcpclient_branch/upload/sample/transparent.png");
blankImage.writeImage(info1);

You have -background set to 'black' in your first line. That means you don't get transparency. Does it work if you set it to 'none'?
Edit:
import os
import random as ra
for i in range(10):
image = 'convert C:/image.png -auto-orient -thumbnail 120x120 -gravity center -bordercolor snow -background none -polaroid '+str(ra.uniform(0,360))+' C:/test/image_polaroid_'+str(i)+'.png'
os.system(image)
image = 'convert -size 500x500 xc:transparent C:/test/result.png'
os.system(image)
for i in range(10):
image = 'composite -gravity center C:/test/image_polaroid_'+str(i)+'.png C:/test/result.png C:/test/result.png'
os.system(image)
Edit 2:
import os
import random as ra
for i in range(10):
image = 'convert C:/image.png -background none -polaroid 0 C:/test/image_polaroid_'+str(i)+'.png'
os.system(image)
image = 'mogrify -rotate '+str(ra.randint(0,360))+' -background none C:/test/image_polaroid_'+str(i)+'.png'
os.system(image)

Related

Convert a region of each PDF page to grayscale

I have a PDF that I want to print and a small region of each page has a thick rainbow at the left border. It is on each page. In order to save color ressources I would like to convert only this region to grayscale - or remove it completely with a white rectangle. I have looked into imagemagick but could not find a suitable solution to keep all the other color on the pages.
I have also thought of exporting each page to a separate PDF, apply a rectangle filter to each pdf and then combine it again. But I would prefer a simpler approach as the quality of the graphs seem to decrease each time I convert a pdf.
You do not have to extract each page to do that in ImageMagick. You can process it all in one command. Here is an example.
Create PDF:
convert lena.jpg mandril3.jpg zelda1.jpg test.pdf
Create white image:
convert -size 100x100 xc:white white.png
Apply white image to every page of PDF:
convert test.pdf null: white.png -geometry +50+50 -layers composite result.pdf

How to avoid gray outline artefacts when converting an eps image to pdf?

To generate vector graphics figures with LaTeX labels, I use gnuplot and the cairolatex terminal, creating the image via plot "data.txt" u 1:2:3 matrix with image notitle followed by:
latex figuregen.tex
dvips -E -ofile.eps figuregen
# Correct the bounding box automatically:
epstool --copy --bbox file.eps filename.eps
## Create a pdf:
ps2pdf -dPDFSETTINGS=/prepress -dSubsetFonts=true -dEmbedAllFonts=true -dMaxSubsetPct=100 -dCompatibilityLevel=1.3 -dEPSCrop filename.eps filename.pdf
Here is a zoom on a specific region of the original eps image:
White regions actually correspond to NaN values in the data file.
Now using the pdf file converted from eps:
In the pdf version, there are now unwanted outlines around all the NaN pixels, creating an awful lot of noise in the higher portion of the image.
I want to have these images as pdf, free of artefacts, and preserve high-quality LaTeX labels. I suspect that there might be a ps2pdf option to deactivate this kind of unwanted behaviour but I just cannot find it.
I tried things such as: -dGraphicsAlphaBits=1, -dNOINTERPOLATE, -dALLOWPSTRANSPARENCY, -dNOTRANSPARENCY, -dCompatibilityLevel=1.4 or -dCompatibilityLevel=1.5, but without success.
I also tried fixing this directly in gnuplot, but without success (see e.g. below).
Would any of you know how to solve this issue?
Thank you very much for your time!
EDIT
What's even more surprising and problematic is that these artefacts also appear when printed.
Note however that they do not appear at extreme levels of zoom in evince when only a small part of the data set is plotted.
MWE:
# plot.plt
set size ratio -1
set palette defined ( 0 '#D73027', 1 '#F46D43', 2 '#FDAE61', 3 '#FEE090', 4 '#FFFFD9', 5 '#E0F3F8', 6 '#ABD9E9', 7 '#74ADD1', 8 '#4575B4' )
#set yr [300:0] ### no artefacts if zoom is higher than 1310% in evince
set yr [400:100] ### no artefacts if zoom is higher than 1780% in evince
#set yr [450:0] ### artefacts at all zoom levels if we show more data, or all of it
set term cairolatex dashed color; set output "temp.tex"
plot "data.txt" u 1:2:3 matrix with image notitle
set output #Closes the temporary output file.
!sed -e 's|/Title|%/Title|' -e 's|/Subject|%/Subject|' -e 's|/Creator|%/Creator|' -e 's|/Author|%/Author|' < temp.tex > graph.tex
and, for completeness:
% figuregen.tex
\documentclass[dvips]{article}
\pagestyle{empty}
\usepackage[dvips]{graphicx} %
\begin{document}
\input graph.tex
\end{document}
If needed, part of the data can be found in text form here; enough to reproduce the issue: https://paste.nomagic.uk/?e0343cc8f759040a#DkRxNiNrH6d3QMZ985CxhA21pG2HpVEShrfjg84uvAdt
EDIT 2
In fact, same artefact issues appear when using set terminal cairolatex pdf
set terminal cairolatex standalone pdf size 16cm,10.5cm dashed transparent
set output "plot.tex"
directly with pdflatex
gnuplot<plot.plt
pdflatex plot.tex
(Note, this is using Gnuplot Version 5.2 patchlevel 6).
The actual problem is, that NaN values are set to transparent black pixels (#00000000).
The transparency causes these gray outline artifacts, depending on the zooming level. If you zoom close enough, then you see no artifacts.
But as soon as the image pixels are smaller than your monitor pixels, the values are interpolated for screen display. Its seems that pdf viewers like evince (I tested also okular and mupdf) interpolate both color and alpha channels, so that the alpha value of the Nan pixels is changed, and the underlying black appears as gray border around the color pixels.
I tried several ways. The easiest one, which actually worked for me was to use the tikz terminal with option externalimages which saves images created with image as separate png file.
These png file also contains transparency, and the final result has the same artifacts.
But you can use imagemagick's convert to change the transparent NaN pixels of the png to white with
convert temp.001.png -alpha off -fill white -opaque black temp.001.png
So, a fully working plot file is
# plot.plt
set size ratio -1
set palette defined ( 0 '#D73027', 1 '#F46D43', 2 '#FDAE61', 3 '#FEE090', 4 '#FFFFD9', 5 '#E0F3F8', 6 '#ABD9E9', 7 '#74ADD1', 8 '#4575B4' )
set ytics 100
set yrange reverse
set term tikz standalone externalimages background "white"; set output "temp.tex"
plot "data.txt" u 1:2:3 matrix with image notitle
# temp.001.png is the external image which contains only the 'with image' part
# We must remove the #00000000 color, which represents the NaN pixels
# I couldn't replace the colors directly, but I could first remove the alpha channel
# and then change black to white, because no other black pixel appear
!convert temp.001.png -alpha off -fill white -opaque black temp.001.png
set output #Closes the temporary output file.
!sed -e 's|/Title|%/Title|' -e 's|/Subject|%/Subject|' -e 's|/Creator|%/Creator|' -e 's|/Author|%/Author|' < temp.tex > graph.tex
!pdflatex graph.tex
Mupdf screen shot for graph.pdf:
Note, that I used standalone to be able to directly compile the resulting file, so that I could check the result.
A more cumbersome alternative would be to "manually" plot with image to a png file, and include that in a second plot, like I described in Big data surface plots: Call gnuplot from tikz to generate bitmap and include automatically? Then you can have more influence on how the png is generated.
Just for the records, with image pixels seems to do the "trick" and will create a file without grey surrounding of NaN datapoints. Tested with gnuplot 5.2.6.
plot FILE u 1:2:3 matrix with image pixels notitle
Code:
### avoid shading around NaN datapoints
reset session
set size ratio -1
FILE = "data.txt"
set palette defined ( 0 '#D73027', 1 '#F46D43', 2 '#FDAE61', 3 '#FEE090', 4 '#FFFFD9', 5 '#E0F3F8', 6 '#ABD9E9', 7 '#74ADD1', 8 '#4575B4' )
set term cairolatex dashed color
set output "temp.tex"
plot FILE u 1:2:3 matrix with image pixels notitle
set output
### end of code
Result: (a PNG of a screenshot, since it looks like I cannot add a PDF here)

GraphicsMagick crop PDF

I've got a 8.5x11 PDF at 300dpi. It has a single UPC label in the top left corner of the PDF. Imagine that there could be 30 labels on a 1 sheet, but we just have 1 label.
I'm trying to crop the PDF to be just the size of the 1 label. So far I've got this
gm convert -density 300 single.pdf out.pdf
Which doesn't do any cropping. When I crop to say 300x100 it makes a 20MB file with 30000 pages.
I have not a clue how to use -crop to actually crop to the correct size. I need it to be 3.5inches by 1.125 inches.
Using the following input PDF (here converted to a PNG):
the following command will crop the label:
gm wiz.pdf -crop 180x50+1+1 cropped.pdf
This label is sized 180x50 pixels.
For an 8.5x11in PDF at 300 PPI you'd have a 2450x3300 pixels PDF (which I doubt you do, but that's another question) and you'd need to use -crop 1050x337+0+0 (more exactly, 1050x337.5+0+0 -- but you cannot crop half pixels!).
Note, the +0+0 part crops the top left corner. If you need offset to the right by N pixels and to the bottom by M pixels use +N+M...
Using ImageMagick instead...
You could also use ImageMagick's convert command:
convert wiz.pdf[180x50+1+1] cropped.pdf
Comment about image sizes...
One additional comment about this remark:
"I have not a clue how to use -crop to actually crop to the correct size."
There is no other real size for raster images than pixels. ABC pixels wide and XYZ pixels high...
There is no such thing as an absolute, real size for a digital image that you can measure in inches... unless you additionally can state the resolution at which a given image is rendered on a display or a print device!
An 8.50x11in sized image at 300 PPI will translate to 2550x3300 pixels.
However, if your image does not contain this amount of pixels (which is the real, absolute size of any raster image), you may still be able to render it at 300 PPI -- but its size in inches will be different from 8.5x11in!
So, whenever you want to crop, use the absolute number of pixels you want. Don't use resolution/density at all on your command line!

Is possible to check if a PNG image has transparent background?

I'm using a crop & resize function for images, but I need to let it crop/resize ONLY png files WITH transparent backgrounds, at least 1 pixel in the image should be transparent for the image to be accepted.
Is possible to check if a PNG image has transparent background/pixels?
I'm using PHP and GD libraries.
EDIT: Ok, I've figured out how to do this on PHP with GD libraries. Look how clean it looks! :)
<?php
$im = imagecreatefrompng("php.png");
$rgba = imagecolorat($im,1,1);
$alpha = ($rgba & 0x7F000000) >> 24;
var_dump($alpha);
?>
Any ideas how to do an array for the x/y coordenates to check all the image pixels looking for at least 1 pixel = $alpha = 127?
You can call out to imagemagick for it:
https://www.imagemagick.org/discourse-server/viewtopic.php?t=18596
convert my_image.png -format "%[opaque]" info:
False
Well you can certainly run through all the pixels and check to see if any of them have an alpha that is not 255. What language and libraries are you using?
One way to handle this in Imagemagick is to check the mean value of the alpha channel. If 1, then it is opaque. Otherwise, the alpha channel has some transparency either somewhere or partial transparency.
convert logo: -channel a -separate -format "%[fx:mean]" info:
1
convert logo: -transparent white -format "%[fx:mean]" info:
0.894907
So you can do:
convert image -format "%[fx:mean==1?1:0]" info:
If the return value is 1, then it is fully opaque. If the return value is 0, then there is some transparency somewhere.

Centering a .jpg image in PDF using Imagemagick?

I'm using convert version ImageMagick 6.6.2-6 2011-03-16, and I'd like to use it to generate an A4 pdf from an image, where the image will be non-scaled and centered.
I'm running the following (as a modification of Overlaying Images with ImageMagick):
# generate a 100x100 JPG with just red color
convert -size 100x100 xc:red red.jpg
# generate PDF from JPG
convert -page A4 xc:white red.jpg -gravity center -composite -format pdf out.pdf
... but, basically nothing shows? Same thing happens for a png image...
Note that
Just 'convert -page A4 red.jpg out.pdf' works - but the image is not centered; (-gravity center causes image not to show)
If the image is png, 'convert -page A4 -gravity center red.png out.pdf' does indeed work fine
... however, I'd like convert to embed the contents of the JPEG stream directly - hence, I wouldn't like to convert the JPG to PNG first.
So, would it be possible to use convert to center a JPG image in an A4 PDF page directly?
Many thanks in advance for any answers,
Cheers!
EDIT2: #John Keyes answer works for the example above; where the image is "smaller" than the PDF size -- however if the image is bigger, e.g.:
$ convert -size 1228x1706 -background \#f44 -rotate 45 gradient:\#f00-\#fff red.jpg
$ identify red.jpg
red.jpg JPEG 2075x2075 2075x2075+0+0 8-bit DirectClass 120KB 0.000u 0:00.000
... then it will fail. However, it turns out: "if you change -extent to 50x50, then play with -gravity, you'll see changes" - except, the question is: which extent do you change, that of the image - or that of the final PDF?
Well, it turns out - it is the extent of the final PDF... To find that size as convert sees it, check the page: Magick::Geometry - however, note that the "Postscript page size specifications" like "A4+43+43>" unfortunately, cause convert to crash in this context... But at least the respective numbers for the size (595x842) can be copied from the page; and finally this works:
convert -page A4 -gravity center -resize 595x842 -extent 595x842 red.jpg out.pdf
... and actually, the -extent part is not really needed - the -resize part is the important one to have the large image show..
However, the problem here is that the image included seems to be resampled - however, I'd just like to show it scaled so it fits the page, but would otherwise like the original JPG stream to be inserted in the file.. So I guess the question is still partially open :)
EDIT: Related:
ImageMagick Gravity parameter - Stack Overflow
ImageMagick and Geometry Issue - resizing with > - Stack Overflow
command line - Resizing and croping images to an aspect ratio of 6x4 with width of 1024 pixels - Unix and Linux - Stack Exchange
conversion - using imagemagick or ghostscript (or something) to scale PDF to fit page? - Stack Overflow
The following works perfectly for me:
convert -page A4 red.jpg -gravity center -format pdf out.pdf
and if you change the order of the "files" it works too:
convert -page A4 red.jpg xc:white -gravity center -composite -format pdf out.pdf
I think the red.jpg is centered but the white is drawn on top of it.
Well, this is outside of imagemagick, but here is a solution in Latex, using tikz package (using How to define a figure size so that it consumes the rest of a page? #14514), which seems to reliably place images on page, and preserve them fully:
% note: need to run pdflatex twice!! First time generates blank pages!
% convert -size 1228x1706 -background \#f44 -rotate 45 gradient:\#f00-\#fff red.jpg
% convert -size 595x1400 xc:red redlong.jpg
\documentclass[a4paper]{letter}
\usepackage{graphicx}
\usepackage[hmargin=0.5cm,vmargin=0.5cm]{geometry} % sets page margins
\usepackage{tikz}
\usetikzlibrary{calc}
\newcommand{\imagepage}[1]{
\tikz[overlay,remember picture]\coordinate (image-start); \par
\vfill
\null\hfill
\begin{tikzpicture}[overlay,remember picture]
\path let \p0 = (0,0), \p1 = (image-start) in
node [inner sep=0pt,outer sep=0pt,anchor=center] at (current page.center) {%
\pgfmathsetmacro\imgheight{\y1-\y0}%
\includegraphics[height=\imgheight pt,width=\textwidth,keepaspectratio]{#1}%
};
\end{tikzpicture}%
}
\begin{document}
% there must be a \n\n after {letter!}
\begin{letter}
\imagepage{red.jpg}
\end{letter}
\begin{letter}
\imagepage{redlong.jpg}
\end{letter}
% see also \resizebox{\textwidth}{!}{\includegraphics{red.jpg}}
\end{document}
Note, the letter documentclass is used to allow that each image is split on separate page..