Подтвердить что ты не робот

Изменение цвета UIImage?

Как я могу изменить цвет UIImage с помощью программирования, любая помощь, пожалуйста? Если я отправлю UIImage, его цвет должен изменить любую помощь, пожалуйста? Если я изменил цвет RGB с помощью битмафлинга, это не сработает.

4b9b3361

Ответ 1

Если вам нужно только выглядеть иначе, просто используйте imageView.tintColor (iOS 7+). Catch, установка tintColor по умолчанию не делает:

Why isn't my image blue?  I'm setting tintColor...

Чтобы сделать работу, используйте imageWithRenderingMode:

var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)

let imageView = ...
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)
imageView.image = image

И теперь он будет работать:

Now the image is orange!

Ссылка на документацию


Производительность

Настройка изображения после настройки UIImageView позволяет избежать дорогостоящих операций:

// Good usage
let imageView = ...
imageView.tintColor = yourTintColor
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
imageView.image = image        // Expensive

// Bad usage
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
let imageView = ...
imageView.image = image        // Expensive
imageView.frame = ...          // Expensive
imageView.tintColor = yourTint // Expensive

Получение и настройка изображения асинхронно уменьшает прокрутку и задержку анимации (особенно при тонировании изображения внутри UICollectionViewCell или UITableViewCell):

let imageView = cell.yourImageView
imageView.image = nil // Clear out old image
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)

// Setting the image asynchronously reduces stuttering 
// while scrolling.  Remember, the image should be set as
// late as possible to avoid repeating expensive operations
// unnecessarily.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
    var image = UIImage(named: "stackoverflow")!
    image = image.imageWithRenderingMode(.AlwaysTemplate)
    imageView.image = image
})

Ответ 2

Один из способов добиться этого - обесцветить изображение и добавить оттенок поверх этого изображения с желаемым цветом.

Desaturate

-(UIImage *) getImageWithUnsaturatedPixelsOfImage:(UIImage *)image {
    const int RED = 1, GREEN = 2, BLUE = 3;

    CGRect imageRect = CGRectMake(0, 0, image.size.width*2, image.size.height*2);

    int width = imageRect.size.width, height = imageRect.size.height;

    uint32_t * pixels = (uint32_t *) malloc(width*height*sizeof(uint32_t));
    memset(pixels, 0, width * height * sizeof(uint32_t));

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]);

    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            uint8_t * rgbaPixel = (uint8_t *) &pixels[y*width+x];
            uint32_t gray = (0.3*rgbaPixel[RED]+0.59*rgbaPixel[GREEN]+0.11*rgbaPixel[BLUE]);

            rgbaPixel[RED] = gray;
            rgbaPixel[GREEN] = gray;
            rgbaPixel[BLUE] = gray;
        }
    }

    CGImageRef newImage = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);

    UIImage * resultUIImage = [UIImage imageWithCGImage:newImage scale:2 orientation:0];
    CGImageRelease(newImage);

    return resultUIImage;
}

Наложение с цветом

-(UIImage *) getImageWithTintedColor:(UIImage *)image withTint:(UIColor *)color withIntensity:(float)alpha {
    CGSize size = image.size;

    UIGraphicsBeginImageContextWithOptions(size, FALSE, 2);
    CGContextRef context = UIGraphicsGetCurrentContext();

    [image drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:1.0];

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextSetBlendMode(context, kCGBlendModeOverlay);
    CGContextSetAlpha(context, alpha);

    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(CGPointZero.x, CGPointZero.y, image.size.width, image.size.height));

    UIImage * tintedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return tintedImage;
}

How-To

//For a UIImageView
yourImageView.image = [self getImageWithUnsaturatedPixelsOfImage:yourImageView.image];
yourImageView.image = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];

//For a UIImage
yourImage = [self getImageWithUnsaturatedPixelsOfImage:yourImage];
yourImage = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];

Вы можете изменить цвет оттенка так, как хотите.

Ответ 3

Отправляй сообщение (в основном просто код для ремикса).

Изменить. Этот код в основном создает новый CGContext, накладывает на него слой с новым цветом и возвращает из него новый UIImage. Некоторое время я не углублялся в этот код, но он просто рисует UIImage с той же формой, что и оригинал, так что предел (теряет любую деталь на изображении).

Ответ 4

Там отличный пост об этом здесь: http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage

Одно из предостережений, которое у меня есть с текущим кодом, заключается в том, что использование его на изображениях сетчатки приведет к потере более высокого разрешения для этих изображений. В настоящее время я ищу решение для этого...

Ответ 5

Если вам нужна высокая производительность, я настоятельно рекомендую вам использовать GPUImage. Вы можете загрузить его на https://github.com/BradLarson/GPUImage

Ответ 6

Данные RGB, на которых вы работаете, - это просто копия. После того, как вы закончите внесение изменений, вам нужно вернуть данные обратно в изображение.

Сначала создаю новое растровое изображение:

CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
ctx = CGBitmapContextCreate( malloc(dataSize), width, height,
                                8, //   CGImageGetBitsPerComponent(cgImage),
                                bytesPerRow, //CGImageGetBytesPerRow(cgImage),
                                space,
                                //kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big );
                                kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
                                //kCGImageAlphaPremultipliedFirst  | kCGBitmapByteOrder32Little);

    CGColorSpaceRelease( space );

// now draw the image into the context
CGRect rect = CGRectMake( 0, 0, CGImageGetWidth(cgImage), CGImageGetHeight(cgImage) );
CGContextDrawImage( ctx, rect, cgImage );

И получить пиксели:

pixels = CGBitmapContextGetData( ctx );

Предполагая, что ваши пиксельные данные поступают из pixels = CGBitmapContextGetData( ctx );, затем возьмите этот контекст и создайте из него новое изображение:

CGImageRef newImg = CGBitmapContextCreateImage(ctx);
[[UIImage imageWithCGImage:newImg] drawInRect:rect];
CGImageRelease(newImg);

Ответ 7

Я думаю, вы можете создать другой контекст с настройкой цвета контекста на RGB, который вы хотите покрасить. Затем нарисуйте UIImage в этом контексте и используйте этот контекст вместо того, чтобы напрямую использовать вашу фотографию. Это концепция. Таким образом вы создаете экранный буфер с цветным изображением. Я не пробовал это в cocoa, только в углероде, но я полагаю, что он будет работать одинаково.

Ответ 8

Hmmm - это не порядок байтов, который должен быть RGBA? Вы устанавливаете их как ARGB...

Ответ 9

попробуйте это

- (UIImage *)imageWithOverlayColor:(UIColor *)color
{
    CGRect rect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);

    if (UIGraphicsBeginImageContextWithOptions) {
        CGFloat imageScale = 1.0f;
        if ([self respondsToSelector:@selector(scale)])  // The scale property is new with iOS4.
            imageScale = self.scale;
        UIGraphicsBeginImageContextWithOptions(self.size, NO, imageScale);
    }
    else {
        UIGraphicsBeginImageContext(self.size);
    }

    [self drawInRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(context, kCGBlendModeSourceIn);

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Ответ 10

Отличная статья, упомянутая пользователем576924, отлично поработала для меня: iPhone: как динамически окрашивать UIImage

и быстро:

extension UIImage {

    func imageWithColor( color : UIColor ) -> UIImage {

       // begin a new image context, to draw our colored image onto
       UIGraphicsBeginImageContext(self.size)

       // get a reference to that context we created
       let context = UIGraphicsGetCurrentContext();

       // set the fill color
       color.setFill()

       // translate/flip the graphics context (for transforming from CG* coords to UI* coords
       CGContextTranslateCTM(context, 0, self.size.height)
       CGContextScaleCTM(context, 1.0, -1.0)

       // set the blend mode to color burn, and the original image
       CGContextSetBlendMode(context, kCGBlendModeColor)
       let rect = CGRect(origin: CGPointZero, size: self.size)
       CGContextDrawImage(context, rect, self.CGImage)

       // set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
       CGContextClipToMask(context, rect, self.CGImage)
       CGContextAddRect(context, rect)
       CGContextDrawPath(context,kCGPathFill)

       // generate a new UIImage from the graphics context we drew onto
       let coloredImg = UIGraphicsGetImageFromCurrentImageContext()
       UIGraphicsEndImageContext()

       //return the color-burned image
       return coloredImg
   }

}

Обратите внимание, что я также изменил "kCGBlendModeColorBurn" на "kCGBlendModeColor", как указано в разделе комментариев для комментариев.

Ответ 11

Для меня это сработало:

extension UIImage {
    class func image(image: UIImage, withColor color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height), false, image.scale)
        let context = UIGraphicsGetCurrentContext()
        color.set()
        CGContextTranslateCTM(context, 0, image.size.height)
        CGContextScaleCTM(context, 1, -1)
        let rect = CGRectMake(0, 0, image.size.width, image.size.height)
        CGContextClipToMask(context, rect, image.CGImage)
        CGContextFillRect(context, rect)
        let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return coloredImage
    }
}