Resize an image with 54x54 squares (540x540) to 54x54pixel lossless - imagemagick

I've got an 540x540 image of 54x54 color squares (same sizes).
When I resize it to 54x54px it looks horrible (blurred), shouldn't a resize like this be perfectly done with imagemagick?
is I possible to get it perfect?
I've tested convert source.png -resize destination.png and -adaptive-resize but the result is the same..

I see what your confusion is now... the problem is not that the process is lossy, rather it is because the -resize is doing more sophisticated processing than you want in order to make an attractive job that you would want for, say, photographs. You want a very simple point sampling process which will produce simple blocks of pure, uncombined colour.
I'll make a start image:
magick -size 10x10 xc:red +noise random -scale 540x540 start.png
And scale it down, by taking a point sample in each block:
magick start.png -sample 10x10 small.png
And back up:
magick result.png -scale 540x540 reincarnated.png

Related

convert doesn't conserve size when scaling down and up

In order to make applying blur faster I'm first scaling my image down and then scale it back up:
convert - -scale 10% -blur 0x2.5 -resize 1000% RGB:-
This works most of the time but sometimes the output resolution is slightly different from the original input. Is there a way to force the pipeline to be size-preserving?
You should be able to access the original geometry of the image via %G, so you can do:
convert input.jpg -scale 10% -blur 0x2.5 -resize '%G!' RGB:-
If you are using Windows, you probably want "%G!" in double rather than single quotes.
If you are using v7 ImageMagick, replace convert with magick.
I think you are getting errors because if you take 10% of 72 pixels (say), you will get a whole number of pixels, i.e. 7 pixels and then when you scale back up by a factor of 10 you'll get 70 rather than your initial 72.
If you are using Imagemagick 7, you can do the following:
magick input.jpg -set option:wd "%w" -set option:ht "%h" -scale "%[fx:wd/10]x%[fx:ht/10]" -blur 0x2.5 -resize "%[fx:wd]x%[fx:ht]\!" RGB:-
This stores the input width and height. Then uses the stored values to scale by 1/10 of those dimensions, then does the blur, then resizes exactly back to the origin input size. Note the ! that forces the resize to the exact dimensions.
or simpler without storing the input width and height:
magick lena.jpg -scale "%[fx:w/10]x%[fx:h/10]" -blur 0x2.5 -resize "%[fx:w]x%[fx:h]\!" lena_x.jpg

How can I specify a background in Imagemagick mogrify based on the colour of an existing pixel?

I want to use mogrify to set the background colour of a large number of images to be whatever colour is at a specific pixel, to make them square.
The vast majority have a single colour in the image background, or are photos in front of a single colour (so with only slight variations from shadows, etc.).
(The specific purpose in this case is to make the images all the same size and square for StyleGAN2-ADA training, so I want to avoid big "letterbox" rectangles where possible as it would be seen by the discriminator as relevant to the image, where a more faded-in background that approximately matches would be more likely to be ignored. Specifically, I have thousands of pictures of single dolls and action figures from various sources, some of which are "trimmed out" to have a truly solid colour background, others of which are against solid colour tables/walls/etc, for instance, from eBay images and such.)
Since they do not all have the same colour in the image background (the colour in the image, as opposed to the 'background colour' setting as per ImageMagick's jargon), I need to sample a pixel and set the background, but I can't figure out how. I tried things based on methods used to set the whole image to one colour, to no avail.
I have tried:
mogrify -verbose -resize 1024x1024 -gravity center -background 'p{10,10}' -extent 1024x1024 -resize 256x256 *.jpg
and
mogrify -verbose -resize 1024x1024 -gravity center -background "%[pixel:p{10,10}]" -extent 1024x1024 -resize 256x256 *.jpg
and neither works. I can't find any other possibilities in the documentation.
EDITED TO ADD: While testing various commands I came across a way to modify your original command to make it work on ImageMagick versions as far back as IMv6.8.
mogrify -resize 1024x1024 -set background "%[pixel:p{10,10}]" \
-gravity center -extent 1024x1024 -resize 256x256 *.jpg
The significant difference is setting the background color in an unusual way. Instead of the normal option -background <color>, this command uses -set background <color>. Then it behaves as expected using that +10+10 color as the background in the "mogrify" command.
For ImageMagick v7 use magick mogrify instead of just mogrify.
The following was my original answer. The suggestion for IMv6 "convert" may be quite useful for some workflows, but the answer above seems to be the simplest, most direct route.
PREVIOUS ANSWER:
ImageMagick v6 won't do that inline parsing of the color, but there are ways to get the same result, usually with IM's "convert" in a "for" loop in your shell. I don't know which shell you're using so I don't know how you'd write a "for" loop, but running this command inside the loop on each image should give you the results you described...
convert $image -resize 1024x1024 ( +clone -crop 1x1+10+10 ) +swap \
-resize 1024x1024 -gravity center -composite -resize 256x256 $image
That reads in the image, resizes it, makes a clone inside the parentheses, and extracts that pixel at +10+10. After the parentheses that single pixel get resized to a 1024x1024 square. Then setting the gravity to "center" and compositing the input image over that colored square gives you the result you described.

crop / swap parts of image with magick mogrify

I am trying to crop and swap different parts of a big 800x800 image and re-create 800x800 image using imagemagick with this command.
magick mogrify titli.gif -crop 2x4# +repage -reverse -append -path converted titli.gif
my problem is "-append" creates tall image (400x1600) & "+append" creates wide image (3200x200)
How can I get a large image of original size 800x800 but with cropped and swapped (reversed) parts set in "mosaic or tiled" style...
If I understand the question, you shouldn't need "mogrify" to do that. Just "magick" should accomplish that task.
It looks like you'll have to crop the image into 8 pieces, reverse them, and "-append" them vertically as you've done.
Then after that, and in the same command, you'll need to crop that result in half vertically and "+append" those two pieces horizontally to get the 800x800 output.
This example command shows how it works...
magick in.png -crop 2x4# -reverse -append -crop 1x2# +append out.png
If you're doing any more operations within the same command you'll probably want to use "+repage" after the "+append" to reset the image geometry back to WxH+0+0.

Cropping images with ImageMagic produces wrong size images - why?

There is a bunch of images that represent the pages, scanned from a book and already cropped with ImageMagic. They are all uniform, 629x625 pixels. I need to process them further to prepare for creation of a PDF: split them into odd and even pages. They are named canvas-00.png through canvas-53.png
When I use the following command to get the odd pages first, I get completely butchered images 275x563 pixels extracted from a wrong horizontal offset:
convert canvas-??.png -crop 314x625+0+0 ~/Pictures/odd/canvas.png
What am I doing wrong?
PS: Originally the images were larger, contained extra margins with scanner's lid visible, and I successfully cropped them to 629x625 using a very similar command, but of course with non-zero offset of +140+71. So it baffles me that a visibly more trivial command with zero offset does not work at all.
I suspect you have page offsets "remembered" in your PNG files and you need to clear them.
As an example, let's create an image 500x300 pixels:
convert xc:red xc:lime +append \
\( xc:blue xc:magenta +append \) -append -resize 500x300\! start.png
Now let's crop out a piece towards the bottom right corner, which I intentionally made magenta so you can see which piece I got:
convert start.png -crop 200x100+250+150 z.png
But if we now look at it with identify you can see it "remembers" where it was in the original picture:
identify z.png
Output
z.png PNG 200x100 500x300+250+150 16-bit sRGB 51.1KB 0.000u 0:00.000
This will then potentially affect (i.e. mess up) anything you do in future with the image. The solution is to use +repage to reset all the page geometry and layout so it forgets. You can either do this when cropping, or when using the cropped image later - depending whether you want to retain the crop information or not. (Sometimes you do want it when you are doing jigsaw puzzle processing and maybe want to reassemble the pieces later).
convert start.png -crop 200x100+250+150 +repage z.png
identify z.png
z.png PNG 200x100 200x100+0+0 16-bit sRGB 51.1KB 0.000u 0:00.000
In your case, if you already cropped and saved without repaging, you can load your images and repage prior to actual use:
convert canvas-??.png +repage -crop 817x1040+0+0 ~/Pictures/odd/canvas.png

ImageMagick cropping large image into xyz tiles

i'm having a large jpg, which has a resolution of x * 256 / x * 256. I want to cut this image into 256x256 tiles with a naming convention {zoom}-{x}-{y}.jpg. In the past i've used ZoomifyExpress Converter which does the cutting and zooming. I also want 6 different zoom levels. I've started so far with this command:
convert example.jpg -crop 256x256 +gravity -set filename:tile
./tiles/%[fx:page.x/256]-%[fx:page.y/256] %[filename:tile].jpg
This produces a lot of x-y.jpg tiles.I don't know how i can add different zoomlevels. I'm relativly new to ImageMagick and this feels like a basic thing to do. Hopefully somebody can help me out. Thanks in advance.
I found the solution:
I just resize the image to the appropriate size and then crop it. The first number in the filename is the zoom level.
convert example.jpg -resize 256x256 -crop 256x256 -set filename:tile
./tiles/0-%[fx:page.x/256]-%[fx:page.y/256] %[filename:tile].jpg
convert example.jpg -resize 512x512 -crop 256x256 -set filename:tile
./tiles/1-%[fx:page.x/(256)]-%[fx:page.y/(256)] %[filename:tile].jpg
.. and so on until i reach the highest resolution.

Resources