Page 1 of 1

Finding first and last line and column with non-transparent pixels?

Posted: 2017-05-14T06:59:49-07:00
by myxal
Hi all.
I have many png files which are used as textures in a game and thus have their dimensions in a power of 2, even when the image itself is smaller. Is there a script for $(SUBJ)? All the transparent pixels are 0,0,0,0 RGBA. In the end, I need to convert the line/column numbers to floats between 0 and 1, proportional to texture size:

Code: Select all

<Element name="freezer_open.tex" u1="0.09765625" u2="0.7990234375" v1="0.109765625" v2="0.69934375" />

Re: Finding first and last line and column with non-transparent pixels?

Posted: 2017-05-14T07:33:07-07:00
by snibgo
Please say what version IM you use, on what platform, and link to an example image.

How large are the images?

A possible algorithm is:

1. Extract the alpha. Change non-black to white. Now the image is black and white only, and the task is to find the first and last columns with white pixels.

2. Crop into lines (so we have HH images, each WWx1 pixels), and evaluate-sequence max. Now we have one image, WWx1 pixels, and the task is to find the first and last white pixel.

3. Add a 1-pixel black border.

4. Use "format %@" to find the left-most white pixel, and width to the right-most white pixel.

5. Simple arithmetic converts the previous two numbers into coordinates.

Re: Finding first and last line and column with non-transparent pixels?

Posted: 2017-05-14T07:48:54-07:00
by myxal
Hi.
Regarding version - 6.9.8-5 from brew (macOS 10.12.4).

I was googling around in the meantime, and

Code: Select all

convert ... -trim 
is able to output info on where it would trim the image. I'll see if I can make a shell script to do the work with that. So far it seems to be able to do exactly what I'm looking for, but it turns out the mod I'm trying to fix doesn't have a clean texture image to begin with. :roll:

Re: Finding first and last line and column with non-transparent pixels?

Posted: 2017-05-14T08:18:13-07:00
by myxal
Right, this should do it:

Code: Select all

#!/bin/bash
# set -x
set -e
_scale=8

while (($#)); do
  FILE="$1"
  bounds=( $(convert "$FILE" -trim info:- | cut -d ' ' -f 3,4) )
  echo "File: " $FILE
  echo "Size: " ${bounds[0]}
  _new_x=${bounds[0]%%x*}
  _new_y=${bounds[0]##*x}
  echo "Geometry: " ${bounds[1]}
  _orig_x=${bounds[1]%%x*}
  _orig_y=${bounds[1]%%+*}
  _orig_y=${_orig_y##*x}
  _offset_x=${bounds[1]#*+}
  _offset_x=${_offset_x%%+*}
  _offset_y=${bounds[1]##*+}
  # u1 - left edge distance from left
  # u2 - right edge distance from left
  # v1 - bottom edge distance from bottom
  # v2 - top edge distance from bottom
  echo u1 = "$(bc -l <<< "scale=$_scale; $_offset_x/$_orig_x")"
  echo u2 = "$(bc -l <<< "scale=$_scale; ($_offset_x + $_new_x)/$_orig_x")"
  echo v1 = "$(bc -l <<< "scale=$_scale; 1 - ($_offset_y + $_new_y)/$_orig_x")"
  echo v2 = "$(bc -l <<< "scale=$_scale; 1 - $_offset_y/$_orig_x")"
  shift
done
Caveats:
  • Files with spaces aren't handled.