CoreImage CIHueAdjust filter giving wrong colors

I am working with the code from the Dondragmer example "Rotated Hue" from this question: How to programmatically change the hue of a UIImage?

However, I get very different results than I expect. I expect that changing the hue will give similar results for changing the hue in Photoshop, but the changes are completely different.

To illustrate using this source image:

source image

Rotating pi / 4 in Photoshop yields the following:

45 degrees rotation of Photoshop

Using the Dondragmer code, I get:

45 degree rotation CIHueAdjust

Similarly, a 180 degree rotation in Photoshop gives the following:

180 degree rotation of Photoshop

But the CIHueAdjust filter produces:

180 degree rotation CIHueAdjust

My code is:

- (CGImageRef)changeHueOfImage(CGImageRef)source By:(NSInteger)angle
{
    CIImage *image = [CIImage imageWithCGImage:source];

    // Convert degrees to radians
    CGFloat angleRadians = GLKMathDegreesToRadians(angle);

    // Use the Core Image CIHueAdjust filter to change the hue
    CIFilter *hueFilter = [CIFilter filterWithName:@"CIHueAdjust"];
    [hueFilter setDefaults];
    [hueFilter setValue:image forKey:@"inputImage"];
    [hueFilter setValue:[NSNumber numberWithFloat:angleRadians] forKey:@"inputAngle"];
    image = [hueFilter outputImage];

    // Save the modified image
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef result = [context createCGImage:image fromRect:[image extent]];

    return result;
}

My questions:

  • Don't understand what the CIHueAdjust filter does?
  • Do I need to consider how the coefficient of brightness and saturation of the filter?
  • How to reproduce Photoshop behavior
  • , ?
+4
2

CIImage. , CoreImage RGB, , HSV.

, , . , , UIColor RGB , HSV , , , UIColor RGB .

CGImageRef imageRef = [img CGImage];
uint width = CGImageGetWidth(imageRef);
uint height = CGImageGetHeight(imageRef);
unsigned char *pixels = malloc(height*width*4); //1d array with size for every pixel. Each pixel has the components: Red,Green,Blue,Alpha

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, 4*width, colorSpaceRef, kCGImageAlphaPremultipliedLast); //our quartz2d drawing env
CGColorSpaceRelease(colorSpaceRef);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

for (int y=0;y<height;++y){
    for (int x=0;x<width;++x){
        int idx = (width*y+x)*4; //the index of pixel(x,y) in the 1d array pixels

        //Pixel manipulation here

        //red = pixels[idx]
        //green = piexls[idx+1]
        //blue = pixels[idx+2]
        //alpha = pixels[idx+3]

        //pixels[idx] = NEW_RED_VALUE

        //Please note that this assumes an image format with alpha stored in the least significant bit.
        //See kCGImageAlphaPremultipliedLast for more info. 
        //Change if needed and also update bitmapInfo provided to CGBitmapContextCreate
    }
}


imageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
free(pixels);

//load our new image
UIImage* newImg = [UIImage imageWithCGImage:imageRef];

: , . bjorndagerman @github

, RGB -> HSV -> RGB, , , , , HSV CoreImage.

: @dfd, , ​​ , , , Google, RGB HSV .

+3

: CIHueAdjust . , :

#define Mask8(x) ( (x) & 0xFF )
#define R(x) ( Mask8(x) )
#define G(x) ( Mask8(x >> 8 ) )
#define B(x) ( Mask8(x >> 16) )
#define A(x) ( Mask8(x >> 24) )
#define RGBAMake(r, g, b, a) ( Mask8(r) | Mask8(g) << 8 | Mask8(b) << 16 | Mask8(a) << 24 )

- (CGImageRef)changeHueForImage:(CGImageRef)image by:(NSInteger)angle
{
    // Get size and allocate array of UIColors
    NSInteger width = CGImageGetWidth(image);
    NSInteger height = CGImageGetHeight(image);
    NSInteger count = width * height;

    // Draw image into pixel buffer
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    NSInteger bytesPerPixel = 4;
    NSInteger bitsPerComponent = 8;

    NSInteger bytesPerRow = bytesPerPixel * width;

    UInt32 *bitmapPixels = (UInt32 *)calloc(count, sizeof(UInt32));

    CGContextRef context = CGBitmapContextCreate(bitmapPixels, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);

    // Shift hue of every pixel
    for (int i = 0; i < count; i++) {
        // Get pixel
        UInt32 pixel = bitmapPixels[i];

        // Convert to HSBA
        UIColor *color = [UIColor colorWithRed:R(pixel)/255.0 green:G(pixel)/255.0 blue:B(pixel)/255.0 alpha:A(pixel)/255.0];
        CGFloat h, s, br, a;
        [color getHue:&h saturation:&s brightness:&br alpha:&a];

        // Shift by angle
        CGFloat angleRadians = GLKMathDegreesToRadians(angle);
        angleRadians /= 2.0f*M_PI;
        h += angleRadians;
        if (h > 1.0f || h < 0.0f) {
            h -= floor(h);
        }

        // Make new color
        UIColor *newColor = [UIColor colorWithHue:h saturation:s brightness:br alpha:a];

        // Convert back to RGBA
        CGFloat r, g, b;
        [newColor getRed:&r green:&g blue:&b alpha:&a];

        // Set pixel
        bitmapPixels[i] = RGBAMake((UInt32)(r * 255.0), (UInt32)(g * 255.0), (UInt32)(b * 255.0), (UInt32)(a * 255.0));
    }

    // Create the new image and clean up
    CGImageRef newImg = CGBitmapContextCreateImage(context);
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    free(bitmapPixels);

    return newImg;
 }

; , - , UIColor . , .

0

Source: https://habr.com/ru/post/1691150/


All Articles