Programing

iOS에서 프로그래밍 방식으로 이미지에 색조를 지정하려면 어떻게해야합니까?

lottogame 2020. 9. 11. 19:24
반응형

iOS에서 프로그래밍 방식으로 이미지에 색조를 지정하려면 어떻게해야합니까?


색상 참조로 이미지에 색조를 지정하고 싶습니다. 결과는 Photoshop의 Multiply 블렌딩 모드와 비슷해야합니다. 여기서 흰색색조 로 대체됩니다 .

대체 텍스트

계속해서 색상 값을 변경하겠습니다.

후속 조치 : ImageView의 drawRect : 메서드에이 작업을 수행하는 코드를 넣을 것입니다.

항상 그렇듯이 코드 조각 은 링크가 아닌 내 이해에 크게 도움이 될 것입니다.

업데이트 : Ramin이 제안한 코드로 UIImageView를 서브 클래 싱합니다 .

내 뷰 컨트롤러의 viewDidLoad :에 넣습니다.

[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];

이미지는 보이지만 착색되지 않습니다. 또한 다른 이미지를로드하고, IB에서 이미지를 설정하고, 뷰 컨트롤러에서 setNeedsDisplay : 호출을 시도했습니다.

업데이트 : drawRect : 호출되지 않습니다.

최종 업데이트 : 저는 Ramin의 코드를 테스트 할 수 있도록 imageView가 제대로 설정된 오래된 프로젝트를 찾았습니다.

최종, 최종 업데이트 :

Core Graphics에 대해 방금 배우는 사람들을 위해 작동 할 수있는 가장 간단한 것이 여기 있습니다.

서브 클래 싱 된 UIView에서 :

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColor(context, CGColorGetComponents([UIColor colorWithRed:0.5 green:0.5 blue:0 alpha:1].CGColor)); // don't make color too saturated

    CGContextFillRect(context, rect); // draw base

    [[UIImage imageNamed:@"someImage.png"] drawInRect: rect blendMode:kCGBlendModeOverlay alpha:1.0]; // draw image
}

먼저 UIImageView를 하위 클래스로 만들고 drawRect 메서드를 재정의해야합니다. 클래스에는 블렌드 색상을 유지하기위한 UIColor 속성 (overlayColor라고합시다)과 색상이 변경 될 때 다시 그리기를 강제하는 사용자 지정 setter가 필요합니다. 이 같은:

- (void) setOverlayColor:(UIColor *)newColor {
   if (overlayColor)
     [overlayColor release];

   overlayColor = [newColor retain];
   [self setNeedsDisplay]; // fires off drawRect each time color changes
}

drawRect 메서드에서 먼저 이미지를 그린 다음 적절한 블렌딩 모드와 함께 원하는 색상으로 채워진 사각형을 다음과 같이 오버레이합니다.

- (void) drawRect:(CGRect)area
{
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSaveGState(context);

  // Draw picture first
  //
  CGContextDrawImage(context, self.frame, self.image.CGImage);

  // Blend mode could be any of CGBlendMode values. Now draw filled rectangle
  // over top of image.
  //
  CGContextSetBlendMode (context, kCGBlendModeMultiply);
  CGContextSetFillColor(context, CGColorGetComponents(self.overlayColor.CGColor));      
  CGContextFillRect (context, self.bounds);
  CGContextRestoreGState(context);
}

일반적으로 드로잉을 최적화하려면 실제 드로잉을 drawRect로 전달 된 영역으로 만 제한하지만 배경 이미지는 색상이 변경 될 때마다 다시 그려야하므로 전체를 새로 고쳐야 할 가능성이 높습니다.

이를 사용하려면 개체의 인스턴스를 만든 다음 image속성 (UIImageView에서 상 속됨)을 그림과 overlayColorUIColor 값으로 설정합니다 (배달 한 색상의 알파 값을 변경하여 블렌드 수준을 조정할 수 있음).


iOS7에서는 UIImageView에 tintColor 속성을, UIImage에 renderingMode를 도입했습니다. iOS7에서 UIImage에 색조를 지정하려면 다음과 같이하면됩니다.

UIImageView* imageView = …
UIImage* originalImage = …
UIImage* imageForRendering = [originalImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.image = imageForRendering;
imageView.tintColor = [UIColor redColor]; // or any color you want to tint it with

알파로 이미지에 색을 입히고 싶었고 다음 클래스를 만들었습니다. 문제가 있으면 알려주세요.

내 클래스의 이름을 지정 했으며 이전 답변에서 언급했듯이 메서드를 호출하지 않기 때문에 CSTintedImageView상속됩니다 . 클래스 에서 찾은 것과 유사한 지정된 이니셜 라이저를 설정했습니다 .UIViewUIImageViewdrawRect:UIImageView

용법:

CSTintedImageView * imageView = [[CSTintedImageView alloc] initWithImage:[UIImage imageNamed:@"image"]];
imageView.tintColor = [UIColor redColor];

CSTintedImageView.h

@interface CSTintedImageView : UIView

@property (strong, nonatomic) UIImage * image;
@property (strong, nonatomic) UIColor * tintColor;

- (id)initWithImage:(UIImage *)image;

@end

CSTintedImageView.m

#import "CSTintedImageView.h"

@implementation CSTintedImageView

@synthesize image=_image;
@synthesize tintColor=_tintColor;

- (id)initWithImage:(UIImage *)image
{
    self = [super initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];

    if(self)
    {
        self.image = image;

        //set the view to opaque
        self.opaque = NO;
    }

    return self;
}

- (void)setTintColor:(UIColor *)color
{
    _tintColor = color;

    //update every time the tint color is set
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();    

    //resolve CG/iOS coordinate mismatch
    CGContextScaleCTM(context, 1, -1);
    CGContextTranslateCTM(context, 0, -rect.size.height);

    //set the clipping area to the image
    CGContextClipToMask(context, rect, _image.CGImage);

    //set the fill color
    CGContextSetFillColor(context, CGColorGetComponents(_tintColor.CGColor));
    CGContextFillRect(context, rect);    

    //blend mode overlay
    CGContextSetBlendMode(context, kCGBlendModeOverlay);

    //draw the image
    CGContextDrawImage(context, rect, _image.CGImage);    
}

@end

간단히 설명합니다 (이 주제에 대한 몇 가지 조사 후). 여기 의 Apple 문서는 다음과 같이 명확하게 설명합니다.

UIImageView클래스는 디스플레이에 이미지를 그리는 데 최적화되어 있습니다. 하위 클래스 UIImageViewdrawRect:메서드를 호출하지 않습니다 . 하위 클래스에 사용자 정의 그리기 코드가 포함되어야하는 경우 UIView대신 클래스를 하위 클래스로 만들어야 합니다.

so don't even waste any time attempting to override that method in a UIImageView subclass. Start with UIView instead.


This could be very useful: PhotoshopFramework is one powerful library to manipulate images on Objective-C. This was developed to bring the same functionalities that Adobe Photoshop users are familiar. Examples: Set colors using RGB 0-255, apply blend filers, transformations...

Is open source, here is the project link: https://sourceforge.net/projects/photoshopframew/


UIImage * image = mySourceImage;
UIColor * color = [UIColor yellowColor];  
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height) blendMode:kCGBlendModeNormal alpha:1];
UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, image.size.width, image.size.height)];
[color setFill];
[path fillWithBlendMode:kCGBlendModeMultiply alpha:1]; //look up blending modes for your needs
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//use newImage for something

Here is another way to implement image tinting, especially if you are already using QuartzCore for something else. This was my answer for a similar question.

Import QuartzCore:

#import <QuartzCore/QuartzCore.h>

Create transparent CALayer and add it as a sublayer for the image you want to tint:

CALayer *sublayer = [CALayer layer];
[sublayer setBackgroundColor:[UIColor whiteColor].CGColor];
[sublayer setOpacity:0.3];
[sublayer setFrame:toBeTintedImage.frame];
[toBeTintedImage.layer addSublayer:sublayer];

Add QuartzCore to your projects Framework list (if it isn't already there), otherwise you'll get compiler errors like this:

Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"

For those of you who try to subclass an UIImageView class and get stuck at "drawRect: is not being called", note that you should subclass an UIView class instead, because for UIImageView classes, the "drawRect:" method is not called. Read more here: drawRect not being called in my subclass of UIImageView


For Swift 2.0,

    let image: UIImage! = UIGraphicsGetImageFromCurrentImageContext()

    imgView.image = imgView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)

    imgView.tintColor = UIColor(red: 51/255.0, green: 51/255.0, blue: 

51/255.0, alpha: 1.0)

The only thing I can think of would be to create a rectangular mostly transparent view with the desired color and lay it over your image view by adding it as a subview. I'm not sure if this will really tint the image in the way you imagine though, I'm not sure how you would hack into an image and selectively replace certain colors with others... sounds pretty ambitious to me.

For example:

UIImageView *yourPicture = (however you grab the image);
UIView *colorBlock = [[UIView alloc] initWithFrame:yourPicture.frame];
//Replace R G B and A with values from 0 - 1 based on your color and transparency
colorBlock.backgroundColor = [UIColor colorWithRed:R green:G blue:B alpha:A];
[yourPicture addSubView:colorBlock];

Documentation for UIColor:

colorWithRed:green:blue:alpha:

Creates and returns a color object using the specified opacity and RGB component values.

+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha

Parameters

red    - The red component of the color object, specified as a value from 0.0 to 1.0.

green  - The green component of the color object, specified as a value from 0.0 to 1.0.

blue   - The blue component of the color object, specified as a value from 0.0 to 1.0.



alpha  - The opacity value of the color object, specified as a value from 0.0 to 1.0.

Return Value

The color object. The color information represented by this object is in the device RGB colorspace. 

Also you might want to consider caching the composited image for performance and just rendering it in drawRect:, then updated it if a dirty flag is indeed dirty. While you might be changing it often, there may be cases where draws are coming in and you're not dirty, so you can simply refresh from the cache. If memory is more of an issue than performance, you can ignore this :)


나는 이것을 위해 오픈 소스 라이브러리가 있습니다 : ios-image-filters


이 목적을 위해 매크로를 만들었습니다.

#define removeTint(view) \
if ([((NSNumber *)[view.layer valueForKey:@"__hasTint"]) boolValue]) {\
for (CALayer *layer in [view.layer sublayers]) {\
if ([((NSNumber *)[layer valueForKey:@"__isTintLayer"]) boolValue]) {\
[layer removeFromSuperlayer];\
break;\
}\
}\
}

#define setTint(view, tintColor) \
{\
if ([((NSNumber *)[view.layer valueForKey:@"__hasTint"]) boolValue]) {\
removeTint(view);\
}\
[view.layer setValue:@(YES) forKey:@"__hasTint"];\
CALayer *tintLayer = [CALayer new];\
tintLayer.frame = view.bounds;\
tintLayer.backgroundColor = [tintColor CGColor];\
[tintLayer setValue:@(YES) forKey:@"__isTintLayer"];\
[view.layer addSublayer:tintLayer];\
}

사용하려면 다음으로 전화하십시오.

setTint(yourView, yourUIColor);
//Note: include opacity of tint in your UIColor using the alpha channel (RGBA), e.g. [UIColor colorWithRed:0.5f green:0.0 blue:0.0 alpha:0.25f];

색조를 제거 할 때 다음을 호출하십시오.

removeTint(yourView);

참고 URL : https://stackoverflow.com/questions/1117211/how-would-i-tint-an-image-programmatically-on-ios

반응형