JeffThompson
JeffThompson

Reputation: 1600

Get X/Y position of pixel in PNG file

After stripping off header bytes and de-compressing the pixel values, a PNG file leaves us with a set of rows (a horizontal strip of the image one pixel high).

Each row starts with a single byte specifying the filter used, followed by RGB values:

+-----+-----+-----+-----+-----+-----+-----+
| 0:F | 1:R | 2:G | 3:B | 4:R | 5:G | 6:B |    // end of first row in image
+-----+-----+-----+-----+-----+-----+-----+
| 7:F | 8:R | 9:G |10:B |11:R |12:G |13:B |    // end of second row
+-----+-----+-----+-----+-----+-----+-----+

In an image without the filter byte, I could just divide the index by 3 (since there are three values per RGB pixel), then use these formulas to get the x/y position of that pixel:

x = index % width
y = index / width

But the filter byte is throwing me off! How do I get the x/y position of a pixel, given a red pixel's byte index? (Say at byte 4 or at byte 11, as shown above.)

I've tried all kinds of permutations but I think there must be an elegant solution!

Upvotes: 0

Views: 1687

Answers (1)

JeffThompson
JeffThompson

Reputation: 1600

Based on comments from @usr2564301, I think this works correctly:

y = ((index-1) / 3) / width
x = ((index-y) / 3) % width

Where width is the width of the image in pixels, not the width of the row of bytes.

We subtract y from the index because each row has a single filter byte and we need to remove them all to get the x position.

Alternatively, y can be calculated using:

y = index / row_width

Where row_width is the number of bytes per row: three for RGB and one filter byte times the width of the image.

Upvotes: 1

Related Questions