Saya ingin mewarnai gambar dengan referensi warna. Hasilnya akan terlihat seperti mode pencampuran Multiply di Photoshop, di mana warna putih akan diganti dengan warna :
Saya akan mengubah nilai warna terus menerus.
Tindak lanjut: Saya akan meletakkan kode untuk melakukan ini di metode drawRect: ImageView saya, bukan?
Seperti biasa, potongan kode akan sangat membantu pemahaman saya, bukan tautan.
Pembaruan: Subclassing UIImageView dengan kode yang disarankan Ramin .
Saya meletakkan ini di viewDidLoad: dari pengontrol tampilan saya:
[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];
Saya melihat gambarnya, tetapi gambar itu tidak diwarnai. Saya juga mencoba memuat gambar lain, mengatur gambar di IB, dan memanggil setNeedsDisplay: di pengontrol tampilan saya.
Pembaruan : drawRect: tidak dipanggil.
Pembaruan terakhir: Saya menemukan proyek lama yang memiliki imageView diatur dengan benar sehingga saya dapat menguji kode Ramin dan bekerja seperti pesona!
Pembaruan terakhir, pembaruan terakhir:
Bagi Anda yang baru belajar tentang Core Graphics, berikut adalah hal paling sederhana yang mungkin bisa berfungsi.
Di subclass UIView Anda:
- (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
}
sumber
Jawaban:
Pertama, Anda ingin membuat subkelas UIImageView dan mengganti metode drawRect. Kelas Anda membutuhkan properti UIColor (sebut saja overlayColor) untuk menahan warna campuran dan penyetel kustom yang memaksa menggambar ulang saat warna berubah. Sesuatu seperti ini:
- (void) setOverlayColor:(UIColor *)newColor { if (overlayColor) [overlayColor release]; overlayColor = [newColor retain]; [self setNeedsDisplay]; // fires off drawRect each time color changes }
Dalam metode drawRect Anda ingin menggambar gambar terlebih dahulu kemudian melapisinya dengan persegi panjang yang diisi dengan warna yang Anda inginkan bersama dengan mode pencampuran yang tepat, seperti ini:
- (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); }
Biasanya untuk mengoptimalkan gambar, Anda akan membatasi gambar sebenarnya hanya ke area yang diteruskan ke drawRect, tetapi karena gambar latar belakang harus digambar ulang setiap kali warna berubah, sepertinya semuanya perlu disegarkan.
Untuk menggunakannya, buat instance objek lalu setel
image
properti (diwarisi dari UIImageView) ke gambar danoverlayColor
ke nilai UIColor (tingkat campuran dapat disesuaikan dengan mengubah nilai alpha dari warna yang Anda turunkan).sumber
Di iOS7, mereka telah memperkenalkan properti tintColor di UIImageView dan renderingMode di UIImage. Untuk mewarnai UIImage di iOS7, yang harus Anda lakukan adalah:
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
sumber
Saya ingin mewarnai gambar dengan alfa dan saya membuat kelas berikut. Tolong beri tahu saya jika Anda menemukan masalah dengan itu.
Saya telah menamai kelas saya
CSTintedImageView
dan itu mewarisiUIView
sejakUIImageView
tidak memanggildrawRect:
metode, seperti yang disebutkan dalam balasan sebelumnya. Saya telah menetapkan penginisialisasi yang ditunjuk mirip dengan yang ditemukan diUIImageView
kelas.Pemakaian:
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
sumber
Hanya klarifikasi singkat (setelah beberapa penelitian tentang topik ini). Dokumen Apple di sini dengan jelas menyatakan bahwa:
jadi jangan buang waktu untuk mencoba menimpa metode itu dalam
UIImageView
subclass. Mulailah denganUIView
sebagai gantinya.sumber
Ini bisa sangat berguna: PhotoshopFramework adalah salah satu pustaka yang ampuh untuk memanipulasi gambar di Objective-C. Ini dikembangkan untuk menghadirkan fungsionalitas yang sama dengan yang dikenal oleh pengguna Adobe Photoshop. Contoh: Atur warna menggunakan RGB 0-255, terapkan filter campuran, transformasi ...
Apakah open source, ini tautan proyek: https://sourceforge.net/projects/photoshopframew/
sumber
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
sumber
Berikut adalah cara lain untuk menerapkan pewarnaan gambar, terutama jika Anda sudah menggunakan QuartzCore untuk hal lain. Ini adalah jawaban saya untuk pertanyaan serupa .
Impor QuartzCore:
#import <QuartzCore/QuartzCore.h>
Buat CALayer transparan dan tambahkan sebagai sublayer untuk gambar yang ingin Anda warnai:
CALayer *sublayer = [CALayer layer]; [sublayer setBackgroundColor:[UIColor whiteColor].CGColor]; [sublayer setOpacity:0.3]; [sublayer setFrame:toBeTintedImage.frame]; [toBeTintedImage.layer addSublayer:sublayer];
Tambahkan QuartzCore ke daftar Kerangka proyek Anda (jika belum ada), jika tidak, Anda akan mendapatkan kesalahan kompiler seperti ini:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"
sumber
Bagi Anda yang mencoba membuat subkelas kelas UIImageView dan terjebak di "drawRect: tidak dipanggil", perhatikan bahwa Anda harus membuat subkelas kelas UIView sebagai gantinya, karena untuk kelas UIImageView, metode "drawRect:" tidak dipanggil. Baca lebih lanjut di sini: drawRect tidak dipanggil di subclass UIImageView saya
sumber
Satu-satunya hal yang dapat saya pikirkan adalah membuat tampilan persegi panjang yang sebagian besar transparan dengan warna yang diinginkan dan meletakkannya di atas tampilan gambar Anda dengan menambahkannya sebagai subview. Saya tidak yakin apakah ini benar-benar akan mewarnai gambar seperti yang Anda bayangkan, saya tidak yakin bagaimana Anda akan meretas gambar dan secara selektif mengganti warna tertentu dengan yang lain ... kedengarannya cukup ambisius bagi saya.
Sebagai contoh:
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];
Dokumentasi untuk 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.
sumber
Anda juga mungkin ingin mempertimbangkan untuk menyimpan gambar gabungan untuk kinerja dan hanya merendernya di drawRect :, lalu memperbaruinya jika bendera kotor memang kotor. Meskipun Anda mungkin sering mengubahnya, mungkin ada kasus di mana hasil imbang masuk dan Anda tidak kotor, jadi Anda dapat menyegarkan dari cache. Jika memori lebih merupakan masalah daripada kinerja, Anda dapat mengabaikan ini :)
sumber
Saya memiliki perpustakaan yang saya buka bersumber untuk ini: ios-image-filter
sumber
Untuk 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)
sumber
Saya membuat makro untuk tujuan ini:
#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];\ }
Untuk menggunakan, cukup panggil:
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];
Saat menghapus tint cukup panggil:
removeTint(yourView);
sumber