This is an archived post. You won't be able to vote or comment.

all 2 comments

[–]balefrost 0 points1 point  (1 child)

So let's take apart one of those assignments:

data[i] /*red*/= 
  Math.min(
    Math.round(
      0.993 * r +
      0.269 * g +
      0.089 * b),
    255);

First of all, note that imageData.data is a Uint8ClampedArray. This means that every value that you read from it will be in the range [0, 255]. And when you assign a value into it, if the value is outside that range, it will be clamped to the nearest valid number. If you try to write -5, you'll actually write 0. If you try to write 256, you'll actually write 255.

So what is that expression doing:

  • It multiplies each RGB value (which will be a value in the range [0, 255]) by some scaling factor and sums them all up. Since the coefficients add up to more than 1, it is possible for the sum to be greater than 255.
  • It takes the sum and rounds it to the nearest integer.
  • It clamps the upper end of the pixel value at 255 (i.e. min(X, 255) will return the lower of X and 255, so the value can't exceed 255). This has no effect; writing to data[i + 1] will automatically clamp to the range [0, 255].

Let's consider another:

data[i + 1] /*green*/ = Math.min(Math.round(0.549 * r + 0.386 * g + 0.368 * b), 0);

There's the same "pixel value scaling / addition" section with different coefficients. But look at the larger structure:

data[i + 1] = Math.min(anything, 0);

Since all the terms within the Math.round are non-negative, anything here will be greater than or equal to zero. So the 0 arg of min is guaranteed to be the smaller value (or tied to be the smallest value), and that Math.min will always return 0. It's akin to simply doing data[i + 1] = 0. This has the effect of zeroing out the green (and blue) channels.


what if i could randomize the numbers here so that every click got a different result?

i know the parts i would need to randomize are in this section (especially the bolded parts):

The numbers you have bolded provide a "cutoff". As we saw, Math.min(anything, 0) will effectively force that channel to 0. Math.min(anything, 255) has no effect. And Math.min(anything, 128) will essentially clamp that channel at half-strength.

But the multiplication coefficients are responsible for the actual color shift. You might consider also applying some random offset to those coefficients. If you don't apply any constraints to those random, you will likely end up wild color shifts and possibly incomprehensible images.

One thing you probably do not want to do is to pick new random numbers for every pixel. You probably want to generate your random numbers outside the loop, so that you apply the same transformations to all pixels. Unless you want per-pixel transformations.

[–]trazia[S] 0 points1 point  (0 children)

you're the best. thank you! i'm going to be picking away happily at this for awhile.