Chciałbym zabarwić obraz za pomocą odniesienia koloru. Rezultat powinien wyglądać jak tryb mieszania Pomnóż w Photoshopie, w którym biel zostałaby zastąpiona odcieniem :
Będę zmieniać wartość koloru w sposób ciągły.
Kontynuacja: umieściłbym kod, aby to zrobić w metodzie drawRect: mojego ImageView, prawda?
Jak zawsze fragment kodu znacznie pomógłby mi w zrozumieniu, w przeciwieństwie do linku.
Aktualizacja: podklasa UIImageView z kodem sugerowanym przez Ramin .
Umieściłem to w viewDidLoad: mojego kontrolera widoku:
[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];
Widzę obraz, ale nie jest zabarwiony. Próbowałem też załadować inne obrazy, ustawić obraz w IB i wywołać setNeedsDisplay: w moim kontrolerze widoku.
Aktualizacja : drawRect: nie jest wywoływany.
Ostatnia aktualizacja: znalazłem stary projekt, który miał poprawnie skonfigurowany imageView, więc mogłem przetestować kod Ramina i działa jak urok!
Ostateczna, ostateczna aktualizacja:
Dla tych, którzy dopiero uczą się o Core Graphics, oto najprostsza rzecz, która może zadziałać.
W Twojej podklasie 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
}
źródło
Odpowiedzi:
Najpierw będziesz chciał podklasę UIImageView i nadpisać metodę drawRect. Twoja klasa potrzebuje właściwości UIColor (nazwijmy ją overlayColor), aby przechowywać kolor mieszania i niestandardową metodę ustawiającą, która wymusza przerysowanie po zmianie koloru. Coś takiego:
- (void) setOverlayColor:(UIColor *)newColor { if (overlayColor) [overlayColor release]; overlayColor = [newColor retain]; [self setNeedsDisplay]; // fires off drawRect each time color changes }
W metodzie drawRect będziesz chciał najpierw narysować obraz, a następnie nałożyć na niego prostokąt wypełniony wybranym kolorem wraz z odpowiednim trybem mieszania, coś takiego:
- (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); }
Zwykle, aby zoptymalizować rysunek, ograniczyłbyś rzeczywisty rysunek tylko do obszaru przekazanego do drawRect, ale ponieważ obraz tła musi być przerysowywany za każdym razem, gdy zmienia się kolor, prawdopodobnie całość będzie wymagała odświeżenia.
Aby go użyć, utwórz instancję obiektu, a następnie ustaw
image
właściwość (odziedziczoną z UIImageView) na obraz ioverlayColor
na wartość UIColor (poziomy mieszania można regulować, zmieniając wartość alfa przekazywanego koloru).źródło
W iOS7 wprowadzili właściwość tintColor na UIImageView i renderingMode na UIImage. Aby zabarwić UIImage na iOS7, wszystko, co musisz zrobić, to:
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
źródło
Chciałem zabarwić obraz za pomocą alfa i utworzyłem następującą klasę. Daj mi znać, jeśli napotkasz jakieś problemy.
Nazwałam swoją klasę
CSTintedImageView
i dziedziczy po niej,UIView
ponieważUIImageView
nie wywołujedrawRect:
metody, jak wspomniano w poprzednich odpowiedziach. Ustawiłem wyznaczony inicjator podobny do tego, który można znaleźć wUIImageView
klasie.Stosowanie:
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
źródło
Tylko krótkie wyjaśnienie (po kilku badaniach na ten temat). Apple doc tutaj wyraźnie stwierdza, że:
więc nawet nie trać czasu na próby przesłonięcia tej metody w
UIImageView
podklasie.UIView
Zamiast tego zacznij od .źródło
Może to być bardzo przydatne: PhotoshopFramework to potężna biblioteka do manipulowania obrazami w Objective-C. Został on opracowany, aby zapewnić te same funkcje, które znają użytkownicy Adobe Photoshop. Przykłady: Ustaw kolory za pomocą RGB 0-255, zastosuj filtry mieszające, transformacje ...
Jest open source, tutaj jest link do projektu: https://sourceforge.net/projects/photoshopframew/
źródło
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
źródło
Oto inny sposób na zaimplementowanie barwienia obrazu, zwłaszcza jeśli używasz już QuartzCore do czegoś innego. To była moja odpowiedź na podobne pytanie .
Importuj QuartzCore:
#import <QuartzCore/QuartzCore.h>
Utwórz przezroczystą warstwę CAL i dodaj ją jako podwarstwę dla obrazu, który chcesz odcień:
CALayer *sublayer = [CALayer layer]; [sublayer setBackgroundColor:[UIColor whiteColor].CGColor]; [sublayer setOpacity:0.3]; [sublayer setFrame:toBeTintedImage.frame]; [toBeTintedImage.layer addSublayer:sublayer];
Dodaj QuartzCore do swojej listy projektów Framework (jeśli jeszcze go tam nie ma), w przeciwnym razie otrzymasz takie błędy kompilatora:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"
źródło
Dla tych z Was, którzy próbują podklasować klasę UIImageView i utkną w „drawRect: nie jest wywoływana”, powinniście zauważyć, że zamiast tego powinniście utworzyć podklasę klasy UIView, ponieważ w przypadku klas UIImageView metoda „drawRect:” nie jest wywoływana. Przeczytaj więcej tutaj: drawRect nie jest wywoływany w mojej podklasie UIImageView
źródło
Jedyną rzeczą, o której mogę pomyśleć, byłoby utworzenie prostokątnego, przeważnie przezroczystego widoku o pożądanym kolorze i nałożenie go na widok obrazu, dodając go jako podwidok. Nie jestem pewien, czy to naprawdę zabarwi obraz w sposób, w jaki sobie wyobrażasz, nie jestem pewien, jak włamać się do obrazu i selektywnie zastąpić niektóre kolory innymi ... brzmi dla mnie dość ambitnie.
Na przykład:
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];
Dokumentacja dla 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.
źródło
Możesz także rozważyć buforowanie skomponowanego obrazu dla wydajności i po prostu renderowanie go w drawRect :, a następnie zaktualizować go, jeśli brudna flaga jest rzeczywiście brudna. Chociaż możesz to często zmieniać, mogą wystąpić przypadki, w których nadchodzą losowania i nie jesteś brudny, więc możesz po prostu odświeżyć się z pamięci podręcznej. Jeśli pamięć jest większym problemem niż wydajnością, możesz to zignorować :)
źródło
Mam bibliotekę, którą otworzyłem w tym celu: filtry obrazu ios
źródło
Dla 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)
źródło
W tym celu zrobiłem makra:
#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];\ }
Aby skorzystać, wystarczy zadzwonić:
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];
Aby usunąć odcień wystarczy zadzwonić:
removeTint(yourView);
źródło