Crop image to smaller layer? Tile smaller layer to match larger? - imagemagick-convert

goal
I have a folder with multiple PNGs of various sizes from 16x16 to 64x64 (yes, tiny). Let's call these the "misc." images. I am using ImageMagick to extract an image suitable for use as an Overlay blend layer from each one that I can apply to an arbitrary image and recreate the same relative "texture" as was in the misc. image. I have the base image that was used to create each of these misc textures - the issue is that the base is a singular 16x16 image and was tiled to the appropriate size before the "texture" was applied.
For one operation, I subtract the misc. image from the base, and for the other I subtract the base from the misc. image - extracting relative highlights and shadows. I then combine the two results with a 50% gray image. I need my result to be the same size as the misc. image, not a cropped 16x16 sample of the top left corner (or wherever). This works fine when the misc. image is 16x16 (like the base) but gets tricky when I'm trying to figure out how to handle the ones with a tiled base.
What I've tried
I've managed to get this to work when my base image is the top layer, using composite and -tile:
for %%f in (*.png) do magick composite "..\raw.png" "%%f" -tile -compose minus ..\sub\%%f
but when I try it the other way around
for %%f in (*.png) do magick composite "%%f" "..\raw.png" -tile -compose minus ..\add\%%f
the resulting image is always the size of raw.png (16x16), it doesn't tile raw.png to match the misc file.
I've tried creating a 64x64 tiled base ("raw_4x4.png") and with
magick composite ctm\array-2x2.png raw_4x4.png -compose minus result_0.png
my result is 64x64, with the subtraction only performed on the top left corner of the image.
I've also tried using convert with the same results (note I remembered to swap the base and layer images correctly!):
magick convert raw_4x4.png ctm\array-2x2.png -compose minus -composite result_0.png
I'm drawing a blank now. Is there an option to tile the "base" layer to match the misc. one regardless of which one is the image background? Or to get the actual size of the misc. image and tile the base layer to match dynamically? Or some other way to do this that I'm not thinking of right now?
--- EDIT ---
Context: Trying to create an add-on to the Chisel minecraft mod, supporting some extra blocks I'm interested in, without having to handcraft a couple of hundred textures. I'm fine with going in afterward and tweaking some but I'd rather the base get done programmatically :P
so for example
Texture: that I want to extract. (This is "gray concrete brick array"). The tricky bit is I don't know what the pixel size of this image will be, except some whole-number multiple of 16x16. The output image must match this size.
Base: with the 16x16 tiling texture used to create "texture" (this is the plain gray concrete texture, which is not a solid color)
in Gimp, I subtract Texture from Base and place in one layer folder ("folder Sub") and then I subtract Base from Layer and place in "folder Add".
I set the blend mode of folder sub to subtract, and the blend mode of folder add to addition, and place a grey texture at the bottom of the stack.
I also place a neutral layer at the top and set the bend mode to copy saturation, to desaturate my result.
The result of this should be (in this case) a 32x32 image ready to be blended "Overlay" with some arbitrary little texture in order to transfer e.g. the "brick" texture above to it.

Related

Use GIMP to resize image in one layer only

This is my set up. I have 2 layers with transparency (I don't know if transparency matters here). Layers are the same size, 5x7 inches. Each layer has their image (say I draw a square on it and a circle on the other).
I want to resize ONLY the square.
The problem is when I scale the square I end up either scaling both, the circle AND the square, equally and they retain their layer size, or BOTH layers are rezise and no longer 5x7 inches. I've tried 'Tools-Transform-Scale' and 'Image-Resize canvas or image', but I can't find the tool to just resize ONE of the images.
Any ideas what I'm doing wrong?
Thanks
What you want is the Scale tool, and it will resize only the active layer if it is in Scale: layer mode (you seem to have it in Scale: image mode)(*).
Otherwise, to clear up things:
Image > Canvas size changes the size of the canvas, but nothing is stretched/compressed, the layers retain their size or are extended with transparency or white.
Image > Scale image scales everything in the image (layers, channels, paths...)
(*) Also,if what you apply a transform such as Scale to an item that has the chainlink, the same transform will be applied to all other chainlinked items (other layers, but also paths).

Corrupted resized textures with Metal on Retina screens

I want to draw a series of textures into METAL view in order to present a complete image. On a regular screen, the images are presented on exactly 1:1 scale (Meaning a 100x100 pixels texture will be presented in a 100x100 pixels square)
Drawing it on a retina display, will actually give me a 200x200 square.
Now, there may be 2 different approaches:
1) Generate entire image into 100x100 square and let Metal View to upscale it to 200x200 square - It works.
2) Upscale each texture and generate image directly into 200x200 square. Why to take this approach? Because some of the textures (Like texts) are generated dynamically, and can be generated in a better resolution. Something impossible if you take the first approach.
Unfortunately, in this approach, some ugly square is visible around each texture.
I tried to play with sizes, clamp options etc, yet I could not find any solution.
Any help would be highly appreciated!
Image from regular screen
Image from retina screen
Found a solution. In Fragment shader, texture sampler was defined as:
constexpr sampler s = sampler(coord::normalized, address::repeat, filter::nearest);
instead of:
constexpr sampler s = sampler(coord::normalized, address::clamp_to_edge, filter::nearest);

Convert PDF to a bw image with sharp edges

I need to convert many PDF pages to images, containing simple shapes such as rectangles or triangles. Texts and composed shapes consist of lines are also in the PDFs.
Example shape from a screenshot out of a PDF:
Note: The screenshot is unsharp because I've used Windows' print function in order to separate a single page. It seems to be that this function converts PDFs to images and then saves them as PDF file.
Requirements of images:
sharp edges, a staircase is desired without any grey values
lines of equal thickness
relatively low resolution (<300 dpi would be wonderful)
black & white only
I'd like to work with ImageMagick because it provides a lot of features. I guess anti-aliasing, black-threshold and sharpen are relevant to this, but I haven't reached my desired results.
PDF example of a similar shape
Something like this, maybe?
magick -density 288 -background white ~/Desktop/drawsvg.pdf -flatten -colorspace gray result.png

Inserting Images on the Custom UI Editor

I'm using the custom UI editor to upload images to a custom ribbon tab. I need the images to look like this:
but currently they are looking like this:
These images are directly from Microsoft shapes. I tried saving them the shapes directly but they were really messy. There must be a way to get the shapes perfect as per the first image - I'm just not sure how.
Any help would be appreciated.
Your images need to be saved in exactly 16x16 pixel size. Anything else, and they will be scaled to fit a 16x16 area, and thus have fuzzy lines.
Your top image (the rectangle) measures 16 pixels wide by 10 pixels tall. If that is the extent of that image, then when you import it, it will get stretched. You need to also include the white (or empty) space around the image (in this case, above and below) when you create the image.
The example above shows the exact same 16x10 px rectangle, in two different formats. The top image included the white space above and below the rectangle and was saved as a 16x16 px image. The bottom image only had the 16x10 px rectangle and was saved as a 16x10 px image, so it was stretched by the UI editor to fit the 16x16 available space.

Cropping an image with a focus area (face) using ImageMagick

I'm struggling to find the right approach to resize and crop and image, with a focus area. In my case the focus area is a face detected in the image, and I need to make sure that this area is visible in the cropped version.
I have focus area given by eg. face_height, face_width, face_center_x and face_center_y. These values are percentages of dimensions of the original image.
What I want to do, is getting a eg. 60x60 thumbnail. The normal approach would be to resize so either height or width of the image is equal 60px and then crop a 60x60 from center, like this:
mogrify -resize 60x -gravity 'Center' -crop 60x60 image.jpg
What approach can be taken focus my crop around a given area instead?
I'm thinking of a solution that includes several paths:
If the face area is bigger than the wanted thumbnail, resize the image just enough to make the whole face visible in 60x60 pixels, then crop
If the face area is smaller than the wanted thumbnail, then crop "expand" my face area until my wanted thumb can fit inside the area. Then crop. I guess I need to make sure that this doesn't exceed the bounds of the original image.
Is there a smarter approach? Can you try make some example code?
Thanks!
I'd first do the arithmetic in script or program, then feed exact coordinates to ImageMagick.
The arithmetic steps:
It'll be easier to operate with exact pixel values than percentages, so convert face_height, face_width, face_center_x and face_center_y to pixel values.
You'll want rectangular thumbnail, so pick the longest side and operate with that:
longest_side = max(face_height, face_width)
Now you can calculate top left point for your crop:
crop_x = face_center_x - longest_side / 2
crop_y = face_center_y - longest_side / 2
If any of the four crop corners fall outside your picture dimensions, adjust for that:
crop_x and crop_y should both be >= 0
crop_x + longest_side should be less than image width
crop_y + longest_side should be less than image height
Having calculated these, ImageMagick call gets quite straightforward:
mogrify -crop {longest_side}x{longest_side}+{crop_x}+{crop_y} -resize 60x60 image.jpg

Resources