Question

How can I swap two colors using a color matrix? For instance swapping red and blue is easy. The matrix would look like:

0 0 1 0 0
0 1 0 0 0
1 0 0 0 0
0 0 0 1 0
0 0 0 0 1

So how can I swap any two colors in general? For example, there is Color1 with R1, G1, B1 and Color2 with R2, G2, B2.

EDIT: By swap I mean Color1 will translate into color2 and color2 will translate into color1. Looks like I need a reflection transformation. How to calculate it?

GIMP reference removed. Sorry for confusion.

Was it helpful?

Solution 2

I solved it by creating a reflection matrix via D3DXMatrixReflect using a plane that's perpendicular to the vector AB and intersects the midpoint of the AB.

  1. D3DXVECTOR3 AB( colorA.r-colorB.r, colorA.g-colorB.g, colorA.b-colorB.b );

  2. D3DXPLANE plane( AB.x, AB.y, AB.z, -AB.x*midpoint.x-AB.y*midpoint.y-AB.z*midpoint.z );

  3. D3DXMatrixReflect

OTHER TIPS

This appears to be the section of the color-exchange.c file in the GIMP source that cycles through all the pixels and if a pixel meets the chosen criteria(which can be a range of colors), swaps it with the chosen color:

  for (y = y1; y < y2; y++)
    {
      gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, width);

      for (x = 0; x < width; x++)
        {
          guchar pixel_red, pixel_green, pixel_blue;
          guchar new_red, new_green, new_blue;
          guint  idx;

          /* get current pixel-values */
          pixel_red   = src_row[x * bpp];
          pixel_green = src_row[x * bpp + 1];
          pixel_blue  = src_row[x * bpp + 2];

          idx = x * bpp;

          /* want this pixel? */
          if (pixel_red >= min_red &&
              pixel_red <= max_red &&
              pixel_green >= min_green &&
              pixel_green <= max_green &&
              pixel_blue >= min_blue &&
              pixel_blue <= max_blue)
            {
              guchar red_delta, green_delta, blue_delta;

              red_delta   = pixel_red > from_red ?
                pixel_red - from_red : from_red - pixel_red;
              green_delta = pixel_green > from_green ?
                pixel_green - from_green : from_green - pixel_green;
              blue_delta  = pixel_blue > from_blue ?
                pixel_blue - from_blue : from_blue - pixel_blue;

              new_red   = CLAMP (to_red   + red_delta,   0, 255);
              new_green = CLAMP (to_green + green_delta, 0, 255);
              new_blue  = CLAMP (to_blue  + blue_delta,  0, 255);
            }
          else
            {
              new_red   = pixel_red;
              new_green = pixel_green;
              new_blue  = pixel_blue;
            }

          /* fill buffer */
          dest_row[idx + 0] = new_red;
          dest_row[idx + 1] = new_green;
          dest_row[idx + 2] = new_blue;

          /* copy alpha-channel */
          if (has_alpha)
            dest_row[idx + 3] = src_row[x * bpp + 3];
        }
      /* store the dest */
      gimp_pixel_rgn_set_row (&destPR, dest_row, x1, y, width);

      /* and tell the user what we're doing */
      if (!preview && (y % 10) == 0)
        gimp_progress_update ((gdouble) y / (gdouble) height);
    }

GIMP_Image

EDIT/ADDITION

Another way you could have transformed red to blue would be with this matrix:

1   0   0   0   0
0   1   0   0   0
0   0   1   0   0
0   0   0   1   0
-1  0   1   0   1

The only values that really matter are the bottom ones in this matrix.

This would be the same as saying subtract 255 from red, keep green the same, and then add 255 to blue. You could cut the alpha in half like so as well like so:

-1  0   1   -0.5    1

So (just like the gimp source) you just need to find the difference between your current color and your target color, for each channel, and then apply the difference. Instead of channel values from 0 to 255 you would use values from 0 to 1.

You could have changed it from red to green like so:

-1  1   0   0   1

See here for some good info:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms533875%28v=vs.85%29.aspx

Good luck.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top