根据this question from 2008,使用石英面罩会导致崩溃!还是这样吗?
基本上,我想做的是在固定背景上绘制不同颜色的骰子,为每个骰子形状使用一个 png(有很多),并以某种方式在代码中添加颜色。
编辑:澄清一下,例如,我想使用一个 png 文件来制作以下所有内容:
基本上,我想将图像的红色、绿色和蓝色分量乘以三个独立的常数,同时保持 alpha 不变。
根据this question from 2008,使用石英面罩会导致崩溃!还是这样吗?
基本上,我想做的是在固定背景上绘制不同颜色的骰子,为每个骰子形状使用一个 png(有很多),并以某种方式在代码中添加颜色。
编辑:澄清一下,例如,我想使用一个 png 文件来制作以下所有内容:
基本上,我想将图像的红色、绿色和蓝色分量乘以三个独立的常数,同时保持 alpha 不变。
我最近在一个没有崩溃的 iPhone 应用程序中广泛使用了掩码。该链接中的代码似乎甚至没有使用蒙版,只是剪裁;唯一提到面具是他尝试过的其他东西。他更有可能是从后台线程调用它,这UIGraphicsBeginImageContext
不是线程安全的。
在不确切知道您想要获得什么效果的情况下,很难就如何做到这一点给出建议。遮罩当然可以单独工作(以获得一种丝网印刷效果),也可以剪裁在更逼真的图像上绘制的覆盖颜色。我可能会使用蒙版或路径来设置剪辑,然后绘制模具图像(使用kCBGlendModeNormal
or kCBGlendModeCopy
),然后使用kCGBlendModeColor
.
这是一个镜头。经测试,无泄漏。没有崩溃。
。H
#import <UIKit/UIKit.h>
@interface ImageModViewController : UIViewController {
}
@property (nonatomic, retain) IBOutlet UIButton *test_button;
@property (nonatomic, retain) IBOutlet UIImageView *source_image;
@property (nonatomic, retain) IBOutlet UIImageView *destination_image;
@property (nonatomic, assign) float kr;
@property (nonatomic, assign) float kg;
@property (nonatomic, assign) float kb;
@property (nonatomic, assign) float ka;
-(IBAction)touched_test_button:(id)sender;
-(UIImage *) MultiplyImagePixelsByRGBA:(UIImage *)source kr:(float)red_k kg:(float)green_k kb:(float)blue_k ka:(float)alpha_k;
@end
.m
#define BITS_PER_WORD 32
#define BITS_PER_CHANNEL 8
#define COLOR_CHANNELS 4
#define BYTES_PER_PIXEL BITS_PER_WORD / BITS_PER_CHANNEL
#import "ImageModViewController.h"
@implementation ImageModViewController
@synthesize test_button;
@synthesize source_image;
@synthesize destination_image;
@synthesize kr;
@synthesize kg;
@synthesize kb;
@synthesize ka;
-(IBAction)touched_test_button:(id)sender
{
// Setup coefficients
kr = 1.0;
kg = 0.0;
kb = 0.0;
ka = 1.0;
// Set UIImageView image to the result of multiplying the pixels by the coefficients
destination_image.image = [self MultiplyImagePixelsByRGBA:source_image.image kr:kr kg:kg kb:kb ka:ka];
}
-(UIImage *) MultiplyImagePixelsByRGBA:(UIImage *)source kr:(float)red_k kg:(float)green_k kb:(float)blue_k ka:(float)alpha_k
{
// Get image information
CGImageRef bitmap = [source CGImage];
int width = source.size.width;
int height = source.size.height;
int total_pixels = width * height;
// Allocate a buffer
unsigned char *buffer = malloc(total_pixels * COLOR_CHANNELS);
// Copy image data to buffer
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(buffer, width, height, BITS_PER_CHANNEL, width * BYTES_PER_PIXEL, cs, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault);
CGColorSpaceRelease(cs);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), bitmap);
CGContextRelease(context);
// Bounds limit coefficients
kr = ((((kr < 0.0) ? 0.0 : kr) > 1.0) ? 1.0 : kr);
kg = ((((kg < 0.0) ? 0.0 : kg) > 1.0) ? 1.0 : kg);
kb = ((((kb < 0.0) ? 0.0 : kb) > 1.0) ? 1.0 : kb);
ka = ((((ka < 0.0) ? 0.0 : ka) > 1.0) ? 1.0 : ka);
// Process the image in the buffer
int offset = 0; // Used to index into the buffer
for (int i = 0 ; i < total_pixels; i++)
{
buffer[offset] = (char)(buffer[offset] * red_k); offset++;
buffer[offset] = (char)(buffer[offset] * green_k); offset++;
buffer[offset] = (char)(buffer[offset] * blue_k); offset++;
buffer[offset] = (char)(buffer[offset] * alpha_k); offset++;
}
// Put the image back into a UIImage
context = CGBitmapContextCreate(buffer, width, height, BITS_PER_CHANNEL, width * BYTES_PER_PIXEL, cs, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault);
bitmap = CGBitmapContextCreateImage(context);
UIImage *output = [UIImage imageWithCGImage:bitmap];
CGContextRelease(context);
free(buffer);
return output;
}
- (void)dealloc
{
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}
*/
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end
我用两个 UIImageViews 和一个 UIButton 设置 xib。顶部 UIImageView 使用 Interface Builder 预加载了图像。触摸文本按钮,图像被处理并设置为第二个 UIImageView。
顺便说一句,我从你的帖子中复制了你的图标有点麻烦。由于某种原因,透明度效果不佳。我使用了我自己在 Photoshop 中创建的新的 PNG 测试图像,有和没有透明度,它都像宣传的那样工作。
当然,您在循环中所做的事情将根据您的需要进行修改。
注意字节序,它真的会把事情搞砸!