convert PNG to GeoTIFF with GDAL - image-processing

I have a PNG that I am trying to make into a GeoTIFF. My result ends up being an all-black image with the correct bounds and size (all channels min & max pixel values are 0).
My source image is a 16bit per channel PNG (UInt16). Below is my command. Do I need to do something differently? My image is 1760width x 3466height in the San Diego, CA area.
gdalwarp -t_srs EPSG:4326 -r near -of GTiff -te -117.119811 32.700376 -117.059864 32.799896 -ts 1760 3466 -to SRC_METHOD=NO_GEOTRANSFORM 11bit.png OUTPUT.tif

If your goal is to convert a PNG image with known geographic coordinates of its corners to a GeoTIFF file of the same size as the original image, you can use gdal_translate.
gdal_translate -of GTiff -a_srs EPSG:4326 -a_ullr -117.119811 32.700376 -117.059864 32.799896 11bit.png OUTPUT.tif

Related

ImageMagick convert from pdf to image shrinks image and places it in bottom left corner

I am using this command to convert pages from a pdf to jpeg images:
magick convert -density 300 sample.pdf output.jpeg
I see a white background and the content of the PDF appears as a smaller image stuck to the bottom left corner of the white "canvas". Can anyone help with why this might be happening and how to prevent this "shrinking"?
My PDF has 14 pages. Here is the metadata for a few of those pages:
>magick identify sample.pdf
sample.pdf[0] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 6458B 0.016u 0:00.017
sample.pdf[1] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 6018B 0.016u 0:00.020
sample.pdf[2] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 5732B 0.016u 0:00.023
And here are the actual and expected outputs for one of the pages:
actual output:
expected output:
edit: here is a sample PDF:
https://www.dropbox.com/s/0bzu5brfzbedd7i/sample.pdf?dl=0
I am not sure why you have that behavior. There is something in the PDF, perhaps a crop box, that Imagemagick/Ghostscript is not picking up. But you can get rid of the excess white using -trim
magick sample.pdf -trim sample_%d.jpg
Thanks for the example
> magick identify sample.pdf
> sample.pdf[0] PDF 2286x3600
Apears to be wrong as there is no match
from the PDF contents
/Width 1531
/Im0
/Height 2454
/MediaBox [0 0 1531 2454]
on
Page Size:
/CropBox [0 0 919 1473]
919 pt x 1473 pt
32.42 x 51.96 cm
12.76 x 20.45 inches
Therefore no problems when the images were inserted as # 120 dpi
We can check the image by copy when zoom to 100% in a viewer and paste into say paint, which agrees the image is 1531 x 2454 pixels.
As a result of comments with #fmw42, it was decided to see if GhostScript (which ImageMagick depends on for PDF handling) was having an affect, and certainly processing that PDF using GS v 9.55 without any special switches gave warnings and produced the output below left So the issue seems to be caused by recent GhostScript method of calling/scaling. since using simple GhostScript based image apps (Irfanview using GS plugin on the left) behave the same whilst other viewers have less of a problem even sister product MuPDF as previewed on the right. So the file Media Box as seen and probably used for scaling by Ghostscript seems to be the culprit, but was processed by two other PDF handlers during generation.
One solution would be to use a simpler method of extracting images as PNG thus look at Xpdf command line tools "pdftopng" which gives a good result but you need to calculate that the optimum resolution in this case is 120 (or 240), Typical windows command line does not need .exe but its best to use that when prefixing with a path for use from another location.
pdftopng.exe -r 120 -f 1 -l 1 sample.pdf

How to change GIMP print size with script-fu

I am using GIMP 2.10.24. I have some image and I need to change Print Size Width to 21mm and Height to 30mm.
I can do that with Set Image Print Resolution Dialog (Menu->Image->Print Size):
screenshot
But there is my question: how could I do that using script-fu or python-fu?
Print size, size in pixels, and print definition are completely related:
print size = size in pixels ÷ print definition
So to change the image print definition you use
In Python:
pdb.gimp_image_set_resolution(image, xresolution, yresolution)
In Script-fu:
(gimp-image-set-resolution image xresolution yresolution)
In both case the X/Y resolutions are in dots per inch.
However if you are using Gimp just for this creating a Gimp script is overkill (the learning curve is quite steep). If the image is in a common format (JPEG, PNG, TIFF) the print definition is part of the image metadata (JPEG header, or EXIF data) and can be changed directly without decoding/reencoding the image using CLI utilities. For instance with ExifTool:
exiftool ${your_image} -xResolution=321 -yResolution=321

Convert a bunch of png or webp images to a webp animation

How to convert a bunch of png or webp images into webp animation ?
I tried this:
convert mytiles.png -crop 100x100 +repage tmp.webp
But I just get a bunch of webp images instead of an animation.
Another solution would be to use gif2webp but the homebrew webp package doesn't contain this command unlike what's written in the official documentation.
Convert frames to WebP, then use webpmux
The webpmux program comes with Google’s reference library for WebP, namely libwebp, which you can install through your package manager if not present yet. Its man page reads:
webpmux — create animated WebP files from non-animated WebP images, extract frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
If your individual frames are in another format, you’ll first need to convert them to WebP. For this task you can use ImageMagick (more options here—be sure to disable lossy compression unless you want it):
convert frame001.png -define webp:lossless=true frame001.webp
Then you can combine frames using webpmux. The syntax is the following, where the capitalized words are placeholders:
webpmux \
-frame frame001.webp +D1+X1+Y1+M1±b \
-frame frame002.webp +D2+X2+Y2+M2±b \
-frame frame003.webp +D3+X3+Y3+M3±b \
[-loop L] [-bgcolor A,R,G,B] \
-o animation.webp
Each frame expects a number of settings. All of them but the duration can be left implicit.
Di is the duration of the frame, in milliseconds.
(Xi, Yi) is the spatial offset of the frame in the canvas (counting from the top-left corner, X going right and Y going down).
Mi is the dispose method for this frame, in other words what to do once this frame has expired. It has two possible values:
0: do not dispose, leave the canvas as-is;
1: dispose, i.e. clear the canvas and fill it with background (consumes energy, for that matter).
±b is the blending method for this frame, which specifies how to superimpose this frame on top of the existing canvas (it is only relevant when the frame has an alpha channel, otherwise it overwrites what is below it anyway). This parameter has two possible values:
-b: do not blend, the frame overwrites the existing canvas;
+b: use alpha blending, the frame combines with the existing canvas.
Then come the optional settings that apply to the animation as a whole:
-loop L specifies the number L of times to play the animation. You’ll probably want it to be infinite, which is meant by -loop 0, which is the default value.
-bgcolor A,R,G,B specifies the background color. The values of the four components (alpha, red, green, blue) range from 0 to 255. Viewers may use this color as a background for the canvas, so that the canvas is opaque, but they are not required to; in practice the canvas is overlayed on top of other elements, as in a web page for example, and I have not seen this color used.
See also the WebP specification about animations.
Final tip: since the command line options for each frame are more than just the input file name, you cannot use a wildcard like frame*.webp directly and writing the command line proves cumbersome. Thankfully, you can use your shell to build the command line, e.g with Bash:
frames=( )
for f in frame*.webp ; do
frames+=( -frame "$f" +100+0+0+0+b )
done
webpmux "${frames[#]}" -o animation.webp
The example above creates an animation whose frames are all images matching frame*.webp, have a duration of 100 ms, have no spatial offset, and combine with the previous frames (use alpha blending for new frames and do not dispose of them afterwards).

libvips and padding when doing image pyramids

I am trying to do a pyramid of tiles with a non-square image (width: 32768px and height: 18433px)
I am using libvips as follows:
vips dzsave my_image.tif out_folder --layout google --suffix .png
For the same purpose I have also used gdal2tiles:
python gdal2tiles.py -p raster -z 0-7 -w none my_image.tif
Because my image is not square, some padding is necessary when the 256x256 tiles are created. Padding however is different between vips and gdal2tiles. The former adds padding at the bottom of the tile where as the latter at the top (and is trasparent). See image below. What is shown in the the 256x256 tile at the root of the pyramid (ie zoom level=0). I have manually added the yellow background and the black outline.
With vips, is it possible to have similar padding to gdal2tiles so that the bottom-left corner of the tile coincide with that from the image? I am plotting points on my image, hence it helps to have the origin at the bottom-left.
How can I also have transparent background with vips? (that might better be in a separate post though...)
You can run dzsave as the output of any vips operation by using .dz as the file extension and putting the arguments in square brackets after the filename. For example, this command:
vips dzsave my_image.tif out_folder --layout google --suffix .png
Can also be written as:
vips copy my_image.tif out_folder.dz[layout=google,suffix=.png]
So you can solve your problem by expanding your input image to a square before running dzsave.
For example:
$ vips gravity Chicago.jpg dir.dz[layout=google,suffix=.png,skip_blanks=0] south-west 32768 32768 --extend white
32768 is the nearest power of two above that image width. The skip_blanks option makes dzsave not output tiles equal to the blank background tile.
That command makes this dir/0/0/0.png:
(I added the black lines to show the edges)
To get a transparent background, you need to add an alpha. This would require another command, and is beyond what the vips CLI is really designed for.
I would switch to something like Python. With pyvips, for example, you can write:
import sys
import pyvips
im = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
im = im.addalpha()
# expand to the nearest power of two larger square ... by default, gravity will
# extend with 0 (transparent) pixels
size = 1 << int.bit_length(max(im.width, im.height))
im = im.gravity('south-west', size, size)
im.dzsave(sys.argv[2],
layout='google', suffix='.png', background=0, skip_blanks=0)
Run like this:
$ ./mkpyr.py ~/pics/Chicago.jpg x
To make this x/0/0/0.png:
(added the green background to show the transparency)

ImageMagick: scale JPEG image with a maximum file-size

I have a number of JPEG pictures which I would like to scale down. Another requirement is that the file size should not be larger than say 300kByte.
Is that possible, please help me with an example =)
To restrict the resulting image to a maximum file size, you can use the commandline parameter -define jpeg:extent=max_value, like this:
convert original.jpeg -define jpeg:extent=300kb output.jpg
convert original.jpeg -define jpeg:extent=300kb -scale 50% output.jpg
convert original.jpeg -define jpeg:extent=300kb [...other options...] output.jpg
Note, this will not always work to match the exact size you wanted. You may have asked for 40kb output size, where input is 300kb, and get a result of 48kb.
(Update/Clarification: Output file size may be a bit lower or higher than your file requested size.)
The jpegoptim tool (actual homepage is for multiple programs) works better for me:
jpegoptim -s -S8 *.JPG
-s means to strip all metadata (EXIF, JFIF, XMP, etc.)
-S8 means to target a filesize of about 8 KiB
You can crunch them even better by running it twice, because empirically, most images are smaller as progressive:
jpegoptim -s --all-progressive -S8 *.JPG; jpegoptim -s --all-normal -S8 *.JPG
jpegoptim will normally refuse to write an image that increases the size, so this will give you optimum quality/size.
As for the image dimensions part: You normally define a target size in terms of dimensions first and scale there, only then you define the target file size. This is because, when you display it, you ideally want the image dimensions being an integer multiple or fraction of the final display dimensions, to make scaling easier, or even unnecessary. So, scale to the target dimensions first (with quality 100, and possibly other things like 4:4:4 chroma, and most certainly with dct float), then downsize the file. If you can’t get to the file size range you want, choose smaller target dimensions and restart (from the original image, not the one you scaled down first).

Resources