Upscaling a few pixels linearly (color math) [SOLVED]

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
atnbueno
Posts: 4
Joined: 2012-11-27T11:50:08-07:00
Authentication code: 6789

Upscaling a few pixels linearly (color math) [SOLVED]

Post by atnbueno » 2012-11-27T12:47:36-07:00

Hello, everyone.

I'm playing with very small images and it seems I'm missing something because I'm not getting what I expect. What follows is a simplified example.

I have the following 3-pixel image as a text file (primary.txt):

Code: Select all

# ImageMagick pixel enumeration: 3,1,255,srgb
0,0: (255,  0,  0)  #FF0000  red
1,0: (  0,255,  0)  #00FF00  lime
2,0: (  0,  0,255)  #0000FF  blue
When I run convert primary.txt -scale 5x1! txt: I get this...

Code: Select all

# ImageMagick pixel enumeration: 5,1,255,srgb
0,0: (255,  0,  0)  #FF0000  red
1,0: (170, 85,  0)  #AA5500  srgb(170,85,0)
2,0: (  0,255,  0)  #00FF00  lime
3,0: (  0, 85,170)  #0055AA  srgb(0,85,170)
4,0: (  0,  0,255)  #0000FF  blue
... instead of what I expected:

Code: Select all

# ImageMagick pixel enumeration: 5,1,255,srgb
0,0: (255,  0,  0)  #FF0000  red
1,0: (128,128,  0)  #808000  olive
2,0: (  0,255,  0)  #00FF00  lime
3,0: (  0,128,128)  #008080  teal
4,0: (  0,  0,255)  #0000FF  blue
The documentation says -scale is equivalent to -filter box -resize but it's not in my case (-filter triangle -resize is actually closer to what I want).

What am I missing?

P.S. I'm doing all this with ImageMagick 6.8.0-6-Q8 via command line in a Win7 XP1 x64 box.


Thanks in advance,
Antonio
Last edited by atnbueno on 2012-11-27T14:03:27-07:00, edited 1 time in total.

User avatar
fmw42
Posts: 23824
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Upscaling a few pixels linearly (color math)

Post by fmw42 » 2012-11-27T13:20:15-07:00

I think you have to work in separate channels. This is the closest I have come:


convert -size 1x1 xc:red xc:lime xc:blue +append -separate -scale 5x1! -combine -colorspace sRGB -depth 8 txt:

# ImageMagick pixel enumeration: 5,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: (213,156, 0) #D59C00 srgb(213,156,0)
2,0: ( 0,255, 0) #00FF00 lime
3,0: ( 0,156,213) #009CD5 srgb(0,156,213)
4,0: ( 0, 0,255) #0000FF blue

P.S. It may also depend upon the virtual-pixel setting.

atnbueno
Posts: 4
Joined: 2012-11-27T11:50:08-07:00
Authentication code: 6789

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by atnbueno » 2012-11-27T14:17:07-07:00

Thanks for trying :-)

I didn't know about -virtual-pixel and although it didn't help in this issue it made me think about how much of the problem was the size of my images. So I replicated my work on bigger versions of my images and not only have I found where the numbers 170 and 85 come from...

Image

...but I also found how to do what I wanted: :-D

Image

convert primary.txt -sample 4x1! -scale 6x1! -sample 5x1! txt:

Code: Select all

# ImageMagick pixel enumeration: 5,1,255,srgb
0,0: (255,  0,  0)  #FF0000  red
1,0: (128,128,  0)  #808000  olive
2,0: (  0,255,  0)  #00FF00  lime
3,0: (  0,128,128)  #008080  teal
4,0: (  0,  0,255)  #0000FF  blue
Again, Fred, thanks for trying, and I hope this solution helps someone sometime*


Regards,
Antonio

(*) Otherwise I've lost a disproportionate amount of time with this thing

User avatar
fmw42
Posts: 23824
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by fmw42 » 2012-11-27T16:47:12-07:00

Nice solution.

Here it is broken down:


convert -size 1x1 xc:red xc:lime xc:blue +append -depth 8 -write txt: \
> -sample 4x1! -write txt: \
> -scale 6x1! -write txt: \
> -sample 5x1! -write txt: \
> null:

# ImageMagick pixel enumeration: 3,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: ( 0,255, 0) #00FF00 lime
2,0: ( 0, 0,255) #0000FF blue

# ImageMagick pixel enumeration: 4,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: ( 0,255, 0) #00FF00 lime
2,0: ( 0,255, 0) #00FF00 lime
3,0: ( 0, 0,255) #0000FF blue

# ImageMagick pixel enumeration: 6,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: (128,128, 0) #808000 srgb(128,128,0)
2,0: ( 0,255, 0) #00FF00 lime
3,0: ( 0,255, 0) #00FF00 lime
4,0: ( 0,128,128) #008080 srgb(0,128,128)
5,0: ( 0, 0,255) #0000FF blue

# ImageMagick pixel enumeration: 5,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: (128,128, 0) #808000 srgb(128,128,0)
2,0: ( 0,255, 0) #00FF00 lime
3,0: ( 0,128,128) #008080 srgb(0,128,128)
4,0: ( 0, 0,255) #0000FF blue


I still wonder if there is a simpler solution?

User avatar
fmw42
Posts: 23824
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by fmw42 » 2012-11-27T19:34:36-07:00

This seems to work also and is a bit simpler:


convert -size 1x1 xc:red xc:lime xc:blue +append -depth 8 -write txt: \
-sample 10x1! -write txt: \
-scale 5x1! -write txt: \
null:


# ImageMagick pixel enumeration: 3,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: ( 0,255, 0) #00FF00 lime
2,0: ( 0, 0,255) #0000FF blue

# ImageMagick pixel enumeration: 10,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: (255, 0, 0) #FF0000 red
2,0: (255, 0, 0) #FF0000 red
3,0: ( 0,255, 0) #00FF00 lime
4,0: ( 0,255, 0) #00FF00 lime
5,0: ( 0,255, 0) #00FF00 lime
6,0: ( 0,255, 0) #00FF00 lime
7,0: ( 0, 0,255) #0000FF blue
8,0: ( 0, 0,255) #0000FF blue
9,0: ( 0, 0,255) #0000FF blue

# ImageMagick pixel enumeration: 5,1,255,srgb
0,0: (255, 0, 0) #FF0000 red
1,0: (128,128, 0) #808000 srgb(128,128,0)
2,0: ( 0,255, 0) #00FF00 lime
3,0: ( 0,128,128) #008080 srgb(0,128,128)
4,0: ( 0, 0,255) #0000FF blue

atnbueno
Posts: 4
Joined: 2012-11-27T11:50:08-07:00
Authentication code: 6789

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by atnbueno » 2012-11-29T11:15:54-07:00

Indeed. And easier to explain :-)


Thanks,
Antonio

User avatar
anthony
Posts: 8871
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by anthony » 2012-12-02T21:39:59-07:00

atnbueno wrote: I replicated my work on bigger versions of my images and not only have I found where the numbers 170 and 85 come from...

Image
This IS correct scaling results.

As Nicholas can attest, there is two ways of resizing images. One that when mapping from old to new images, you map the positions of the actual image edge (that is to say pixels have area), and one where you map the center or positions of the edge pixels (pixels as single 'sample' points without area).

The former is what IM uses and is generally accepted as the correct solution.

It is is the equivalent distortion operation....

Code: Select all

         -distort affine  '0,0 0,0     3,1 5,1'  -crop 5x1+0+0
It means the full area of an edge pixels will cover the same area as a pixel in the center of the image. As such when expanding 3 pixels to 5 pixels (width wise only), each pixel will be 5/3 or 1 and 2/3 pixels in size. That is what you get. The result is then merged into the actual pixel colors for a box filter.

The later method (edge pixel centers are mapped from old to new) is equivalent to

Code: Select all

         -distort affine '0.5,0.5  0.5,0.5    2.5,0.5  4.5,0.5  -crop 5x1+0+0
This has the effect that some of area covered by edge pixels will become clipped (that is they overflow) the final size of the resulting image. The result is you get 1 and 1/2 pixel area on the edge and a 3 pixel size for middle pixels, which is then merged.

The other effect is that mapping edge pixel centers causes the size used for scaling factors to be 1 pixel less. As such the first (image edge map) scales by a factor of 5/3 (or 1.6666), while the second (edge pixel center mapping) scales by a factor 4/2 (or 2.0). That is to say the image is also enlarged slightly more than the sizes indicate, but edge pixels are clipped to fit the requested bounds.

WARNING: -distort uses a 2-d cylindrical filters while -resize uses a faster and more common 2-pass 1-d filters technique. For more exact detail see... Resize Images using Distort
http://www.imagemagick.org/Usage/distorts/#resize
And... Distort vs Resize
http://www.imagemagick.org/Usage/resize/#distort_resize
And the forum topic...
viewtopic.php?p=68362#p68362

Note the Nicholas raised the point that perhaps IM should allow resizing by either method (scaling so as to map: edges or edge pixel centers). This has so far been deemed to not be worth the effort at this time.

To summerize: The resize resizes pixel by area (or using image edges), not by edge pixel centers as you have assumed.

Pixels have area, and area is what matters when distorting (resizing) images.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
http://www.imagemagick.org/Usage/

User avatar
anthony
Posts: 8871
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by anthony » 2012-12-04T21:31:13-07:00

Apologies are in order.

I did not realise it was as compare of -scale and Box filtered -resize, and they were actually producing different results.

I thought atnbueno was saying that -resize is not working as it is expected it to work.

I'll have to study the -scale implementation algorithm to see how it actually works, as you are right it is not acting like it is generating the expected box filtered result except in specific special cases.

Very good pickup by atnbueno
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
http://www.imagemagick.org/Usage/

atnbueno
Posts: 4
Joined: 2012-11-27T11:50:08-07:00
Authentication code: 6789

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by atnbueno » 2012-12-05T11:07:25-07:00

No apology necessary. To be fair, it was a bit of both. I re-discovered by myself the "pixels have area" idea, and I only arrived to the scale/resize issue when trying to solve the average colour issue Fred helped me with.

BTW, let me take the opportunity to thank you for your work in /Usage. I've just recently joined this board but I've been reading you for ages :-)


Regards,
Antonio

User avatar
anthony
Posts: 8871
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Upscaling a few pixels linearly (color math) [SOLVED]

Post by anthony » 2012-12-09T23:31:58-07:00

I have uploaded (though it may be a few hours to appear), a summery of the above differences between Scale and a Box Filtered resize, that I added to IM examples...

Scale Internals (pixel mixing)...
http://www.imagemagick.org/Usage/resize/#pixel_mixing

A more dramatic example (though less colorful) of the difference in results (based on a Box filter example) is also shown.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
http://www.imagemagick.org/Usage/

Post Reply