Replace a Particular Color Inside an Image with Another Color

Replace a particular color inside an image with another color

  1. You have to iterate through each pixel in the image and take its rgb
    values
  2. Check its rgb values matches your fromColor rgb values, if yes
    change the pixel value to your toColor rgb values.If not, just leave
    that pixel and go to next one..

Wrote a function from memory..errors possible..correct yourself

-(UIImage*)changeColor:(UIImage*)myImage fromColor:(UIColor*)fromColor toColor:(UIColor*)toColor{
CGImageRef originalImage = [myImage CGImage];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext =
CGBitmapContextCreate(NULL,CGImageGetWidth(originalImage),CGImageGetHeight(originalImage),
8,CGImageGetWidth(originalImage)*4,colorSpace,kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(bitmapContext, CGRectMake(0, 0,
CGBitmapContextGetWidth(bitmapContext),CGBitmapContextGetHeight(bitmapContext)),
originalImage);
UInt8 *data = CGBitmapContextGetData(bitmapContext);
int numComponents = 4;
int bytesInContext = CGBitmapContextGetHeight(bitmapContext) *
CGBitmapContextGetBytesPerRow(bitmapContext);
double redIn, greenIn, blueIn,alphaIn;
CGFloat fromRed,fromGreen,fromBlue,fromAlpha;
CGFloat toRed,toGreen,toBlue,toAlpha;

//Get RGB values of fromColor
int fromCountComponents = CGColorGetNumberOfComponents([fromColor CGColor]);
if (fromCountComponents == 4) {
const CGFloat *_components = CGColorGetComponents([fromColor CGColor]);
fromRed = _components[0];
fromGreen = _components[1];
fromBlue = _components[2];
fromAlpha = _components[3];
}

//Get RGB values for toColor
int toCountComponents = CGColorGetNumberOfComponents([toColor CGColor]);
if (toCountComponents == 4) {
const CGFloat *_components = CGColorGetComponents([toColor CGColor]);
toRed = _components[0];
toGreen = _components[1];
toBlue = _components[2];
toAlpha = _components[3];
}

//Now iterate through each pixel in the image..
for (int i = 0; i < bytesInContext; i += numComponents) {
//rgba value of current pixel..
redIn = (double)data[i]/255.0;
greenIn = (double)data[i+1]/255.0;
blueIn = (double)data[i+2]/255.0;
alphaIn = (double)data[i+3]/255.0;

//now you got current pixel rgb values...check it curresponds with your fromColor
if( redIn == fromRed && greenIn == fromGreen && blueIn == fromBlue ){
//image color matches fromColor, then change current pixel color to toColor
data[i] = toRed;
data[i+1] = toGreen;
data[i+2] = toBlue;
data[i+3] = toAlpha;
}
}
CGImageRef outImage = CGBitmapContextCreateImage(bitmapContext);
myImage = [UIImage imageWithCGImage:outImage];
CGImageRelease(outImage);
return myImage;
}

I hope you are not calling this function every time...It is a bit processor heavy..And if I was your processor, I wouldn't be happy with you..:)

Replace color in numpy image with another color

As far as I can tell your code replaces color A with color B. You should see a change in images, but not a swap of colors: color A should be gone and color B should appear in its place.

To swap two colors you can try, for example, the following. Create a sample image:

import numpy as np
import matplotlib.pyplot as plt

img = np.zeros((12, 12, 3))
col1 = [1, 0, 0]
col2 = [0, 1, 0]
col3 = [0, 0, 0]
img[:] = col1
img[3:9, 3:9] = col3
img[4:8, 4:8] = col2
plt.imshow(img)

This gives:

image

Swap col1 with col2 (i.e. red with green):

mask = [(img == c).all(axis=-1)[..., None] for c in [col1, col2]]
new_img = np.select(mask, [col2, col1], img)
plt.imshow(new_img)

Result:

image with swapped colors

How to replace one color in a image with another one?

Your image has an alpha channel, so you need:

gm convert input.png -fill "#9ea09a" -opaque "#687a40ff" result.png

How to replace a given color with another on an opaque UIImage

I couldn't see any answers on the 'duplicates' (this question shouldn't have been flagged as a duplicate) that will let you replace a given color with another color and work on an opaque image, so I decided to add one that would.


I created a UIImage category to do this, it basically works by looping through each pixel and detecting how close it is to a given colour, and blends it with your replacement colour if it is.

This will work for images with both transparency and opaque backgrounds.

@implementation UIImage (UIImageColorReplacement)

-(UIImage*) imageByReplacingColor:(UIColor*)sourceColor withMinTolerance:(CGFloat)minTolerance withMaxTolerance:(CGFloat)maxTolerance withColor:(UIColor*)destinationColor {

// components of the source color
const CGFloat* sourceComponents = CGColorGetComponents(sourceColor.CGColor);
UInt8* source255Components = malloc(sizeof(UInt8)*4);
for (int i = 0; i < 4; i++) source255Components[i] = (UInt8)round(sourceComponents[i]*255.0);

// components of the destination color
const CGFloat* destinationComponents = CGColorGetComponents(destinationColor.CGColor);
UInt8* destination255Components = malloc(sizeof(UInt8)*4);
for (int i = 0; i < 4; i++) destination255Components[i] = (UInt8)round(destinationComponents[i]*255.0);

// raw image reference
CGImageRef rawImage = self.CGImage;

// image attributes
size_t width = CGImageGetWidth(rawImage);
size_t height = CGImageGetHeight(rawImage);
CGRect rect = {CGPointZero, {width, height}};

// bitmap format
size_t bitsPerComponent = 8;
size_t bytesPerRow = width*4;
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;

// data pointer
UInt8* data = calloc(bytesPerRow, height);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// create bitmap context
CGContextRef ctx = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);
CGContextDrawImage(ctx, rect, rawImage);

// loop through each pixel's components
for (int byte = 0; byte < bytesPerRow*height; byte += 4) {

UInt8 r = data[byte];
UInt8 g = data[byte+1];
UInt8 b = data[byte+2];

// delta components
UInt8 dr = abs(r-source255Components[0]);
UInt8 dg = abs(g-source255Components[1]);
UInt8 db = abs(b-source255Components[2]);

// ratio of 'how far away' each component is from the source color
CGFloat ratio = (dr+dg+db)/(255.0*3.0);
if (ratio > maxTolerance) ratio = 1; // if ratio is too far away, set it to max.
if (ratio < minTolerance) ratio = 0; // if ratio isn't far enough away, set it to min.

// blend color components
data[byte] = (UInt8)round(ratio*r)+(UInt8)round((1.0-ratio)*destination255Components[0]);
data[byte+1] = (UInt8)round(ratio*g)+(UInt8)round((1.0-ratio)*destination255Components[1]);
data[byte+2] = (UInt8)round(ratio*b)+(UInt8)round((1.0-ratio)*destination255Components[2]);

}

// get image from context
CGImageRef img = CGBitmapContextCreateImage(ctx);

// clean up
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(data);
free(source255Components);
free(destination255Components);

UIImage* returnImage = [UIImage imageWithCGImage:img];
CGImageRelease(img);

return returnImage;
}

@end

Usage:

UIImage* colaImage = [UIImage imageNamed:@"cola1.png"];
UIImage* blackColaImage = [colaImage imageByReplacingColor:[UIColor colorWithRed:1 green:0 blue:0 alpha:1] withMinTolerance:0.5 withMaxTolerance:0.6 withColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1]];

The minTolerance is the point at which pixels will start to blend with the replacement colour (rather than being replaced). The maxTolerance is the point at which the pixels will stop being blended.

Before:

enter image description here

After:

enter image description here

The result is a little aliased, but bear in mind that your original image was fairly small. This will work much better with a higher resolution image. You can also play about with the tolerances to get even better results!

Replace a color with another color in an image with PHP

EDIT 2 :
You might need to optimize something and change hueAbsoluteError to suit your needs, but hue is the way to enlightenment and sharper picture quality (functions taken from https://gist.github.com/brandonheyer/5254516):

<?php
function RGBtoHSL( $r, $g, $b ) {
$r /= 255;
$g /= 255;
$b /= 255;
$max = max( $r, $g, $b );
$min = min( $r, $g, $b );
$l = ( $max + $min ) / 2;
$d = $max - $min;
if( $d == 0 ){
$h = $s = 0;
} else {
$s = $d / ( 1 - abs( 2 * $l - 1 ) );
switch( $max ){
case $r:
$h = 60 * fmod( ( ( $g - $b ) / $d ), 6 );
if ($b > $g) {
$h += 360;
}
break;
case $g:
$h = 60 * ( ( $b - $r ) / $d + 2 );
break;
case $b:
$h = 60 * ( ( $r - $g ) / $d + 4 );
break;
}
}
return array( round( $h, 2 ), round( $s, 2 ), round( $l, 2 ) );
}

function HSLtoRGB( $h, $s, $l ){
$c = ( 1 - abs( 2 * $l - 1 ) ) * $s;
$x = $c * ( 1 - abs( fmod( ( $h / 60 ), 2 ) - 1 ) );
$m = $l - ( $c / 2 );
if ( $h < 60 ) {
$r = $c;
$g = $x;
$b = 0;
} else if ( $h < 120 ) {
$r = $x;
$g = $c;
$b = 0;
} else if ( $h < 180 ) {
$r = 0;
$g = $c;
$b = $x;
} else if ( $h < 240 ) {
$r = 0;
$g = $x;
$b = $c;
} else if ( $h < 300 ) {
$r = $x;
$g = 0;
$b = $c;
} else {
$r = $c;
$g = 0;
$b = $x;
}
$r = ( $r + $m ) * 255;
$g = ( $g + $m ) * 255;
$b = ( $b + $m ) * 255;
return array( floor( $r ), floor( $g ), floor( $b ) );
}

/* ---------------CHANGE THESE------------------- */
$colorToReplace = RGBtoHSL(255, 0, 255);
$hueAbsoluteError = 0.4;
$replacementColor = RGBtoHSL(0, 192, 239);
/* ---------------------------------------------- */

$filename = 'img/Mascots_Aviators_General-copy.png';
$im = imagecreatefrompng($filename);
$out = imagecreatetruecolor(imagesx($im), imagesy($im));
$transColor = imagecolorallocatealpha($out, 254, 254, 254, 127);
imagefill($out, 0, 0, $transColor);

for ($x = 0; $x < imagesx($im); $x++) {
for ($y = 0; $y < imagesy($im); $y++) {
$pixel = imagecolorat($im, $x, $y);

$red = ($pixel >> 16) & 0xFF;
$green = ($pixel >> 8) & 0xFF;
$blue = $pixel & 0xFF;
$alpha = ($pixel & 0x7F000000) >> 24;

$colorHSL = RGBtoHSL($red, $green, $blue);

if ((($colorHSL[0] >= $colorToReplace[0] - $hueAbsoluteError) && ($colorToReplace[0] + $hueAbsoluteError) >= $colorHSL[0])){
$color = HSLtoRGB($replacementColor[0], $replacementColor[1], $colorHSL[2]);
$red = $color[0];
$green= $color[1];
$blue = $color[2];
}

if ($alpha == 127) {
imagesetpixel($out, $x, $y, $transColor);
}
else {
imagesetpixel($out, $x, $y, imagecolorallocatealpha($out, $red, $green, $blue, $alpha));
}
}
}
imagecolortransparent($out, $transColor);
imagesavealpha($out, TRUE);
header('Content-type: image/png');
imagepng($out);

enter image description here

EDIT :
Better solution - determine if color needs replacement (using this method). Determine replaced color's hue (I have no idea if it's correct term, what I mean is lightness and darkness). Apply it to replacement color to give it a shade or AA feeling.


So, as I have said in my comment, you need to determine if this color is really ping (dark, light, etc.). Easiest solution is to apply absolute error method for specific color channels. There may be (there definitely is) better universal method, but I hope this will do:

$color = [255, 0, 255];
$colorAbsoluteError = [150, 0, 150];
$replacementColor = [0, 192, 239];
$filename = 'img/Mascots_Aviators_General-copy.png';
$im = imagecreatefrompng($filename);
$out = imagecreatetruecolor(imagesx($im), imagesy($im));
$transColor = imagecolorallocatealpha($out, 254, 254, 254, 127);
imagefill($out, 0, 0, $transColor);

for ($x = 0; $x < imagesx($im); $x++) {
for ($y = 0; $y < imagesy($im); $y++) {
$pixel = imagecolorat($im, $x, $y);

$red = ($pixel >> 16) & 0xFF;
$green = ($pixel >> 8) & 0xFF;
$blue = $pixel & 0xFF;
$alpha = ($pixel & 0x7F000000) >> 24;

if ((($red >= $color[0] - $colorAbsoluteError[0]) && ($color[0] + $colorAbsoluteError[0]) >= $red) &&
(($green >= $color[1] - $colorAbsoluteError[1]) && ($color[1] + $colorAbsoluteError[1]) >= $green) &&
(($blue >= $color[2] - $colorAbsoluteError[2]) && ($color[2] + $colorAbsoluteError[2]) >= $blue)){
$red = $replacementColor[0];
$green= $replacementColor[1];
$blue = $replacementColor[2];
}

if ($alpha == 127) {
imagesetpixel($out, $x, $y, $transColor);
}
else {
imagesetpixel($out, $x, $y, imagecolorallocatealpha($out, $red, $green, $blue, $alpha));
}
}
}
imagecolortransparent($out, $transColor);
imagesavealpha($out, TRUE);
header('Content-type: image/png');
imagepng($out);

enter image description here



Related Topics



Leave a reply



Submit