HELP
HELP

Reputation: 14575

PHP imagefilter parameter question

for the filtertype parameter value IMG_FILTER_CONTRAST what number values can it range from.

Upvotes: 1

Views: 282

Answers (3)

mdfst13
mdfst13

Reputation: 900

The range is rather obviously intended to be 0 to 100. At 100, every pixel is 7F7F7F. At 0, every pixel is the same as the original. That's sensible behavior. It means that at 0, there's the maximum difference between each original color that can be maintained with all the colors.

At 101, the result is the same as at 99. At 200, the same as at 0. So there's no need to go above 100. That just duplicates things from the range 0 to 100. 6

It's tempting to think that the range might extend into the negative. But if someone was attempting that, they didn't create a symmetrical range. At -100, the effect is to push the colors away from the middle of the range. 7F would become 7D. 80 would become 82. 7E would become 79. 81 to 86. 9F to FC. Everything A0 and above becomes FF. Everything 5F and below becomes 00. Yes, colors from 5F to A0 differ by 4. But 0 to 5F and A0 to FF do not differ at all. Their contrast actually disappears. And that effect continues.

The key point is that -100 is not the mirror image of 100. -100 matches with 300. A more natural endpoint of the range would be the point where 7F and 80 become 0 and FF. That's -2159. Here's the math for 80 (128):

(100 - -1497) / 100.0 = 15.97  
15.97 * 15.97 = 249.3241  
128 / 255 - .5 = .00196...

Multiply the last two results together and you get a number just over .5. Change the -1497 to -1496 and you end up with a number just under .5. If you repeat the exercise with 7F (127), you get the same result in the opposite direction. The next step is to add .5, then multiple by 255 and truncate the result to the nearest integer (255 or 0).

The meaningful range is actually -1497 to 100. Or symmetrically, from 100 to 1697. Numbers smaller than -1497 or larger than 1697 will have the same effect as the endpoints of the range. And remember, there are actually three interesting points in each range. 100 has minimal contrast, every pixel changing to 7F7F7F. 0 (or 200) just returns the original image. -1497 (or 1697) returns a two color image. Everything is white or black.

This answer already linked the source if you want to review the algorithm.

This seems like a weird result. 100 is minimum contrast. 0 is a type of maximum contrast. -1497 is a different type of maximum contrast. Meanwhile, without the subtract from 100 step, 0 would be minimum contrast; 100 would be one kind of maximum contrast; and 1597 would be a different type of maximum contrast. As is, it measures similarity rather than contrast. It's backwards.

Upvotes: 0

Dave Houlbrooke
Dave Houlbrooke

Reputation: 428

Even though the documentation states -255 to +255, it's not! It's supposed to be -100 to +100. But, there's a deeper issue:

PHP doesn't limit the number to 100. It's passed straight through to the underlying lib-gd with whatever number you specify. lib-gd also doesn't limit the range to 100, so whatever number you use has a direct effect on the pixels.

In lib-gd, the following formula is used to calculate the contrast:

(100.0-contrast)/100.0

You can see this for yourself here: https://bitbucket.org/libgd/gd-libgd/src/cdea9eb0ad01/src/gd_filter.c

This formula is supposed to turn the contrast you've requested in PHP (between 0 and 100) into a number between 0 and 1.

Problem is, because the range is never getting checked, it has a mathmatically weird effect on numbers outside the range.

If you enter 90 in PHP, lib-GD translates that to 0.9, and applies a contrast algorithm using that number. Makes sense. HOWEVER, if you enter 2000, lib-gd is now using -19 in its contrast algorithm, which is wildly different.

Firstly, you'll note any value above 100 or below -100 has the same effect of increasing the contrast, because of the maths.

To achieve an 'absolute' contrast effect, i.e. moving all pixels in the picture to either 0 or 255, 25600 is the number you want. A pixel with a value of 127 will become 0, and a pixel with a value of 128 will become 255.

This can be useful if you want to make an image completely flat colour (especially if you apply a greyscale filter first, you'll get full black and white).

I wouldn't rely on this behaviour though, because either PHP or lib-gd could start limiting the range in new releases.

So, in effect:

  • The range of IMG_FILTER_CONTRAST is -25600 to +25600
  • Numbers above and below won't be rejected, but can't affect the pixels further.
  • Numbers below -100 become positive again, i.e. -100 === +100
  • As numbers get into the thousands, visual differences are minor as the pixels are so very exponentially close to their maximum.

Upvotes: 3

Adnan
Adnan

Reputation: 26350

Between -255 and 255

MG_FILTER_CONTRAST filter allows you to change the contrast of the image, and takes just one parameter for a contrast value between -255 and 255. Lower values increase the contrast of the picture, essentially reducing the number of colours so that they are more separate and obvious to the eye. Using positive values brings the colours closer together by mixing them with grey, until at 255 you have a full-grey picture.

Source

Upvotes: 2

Related Questions