iOS 中的石英掩模——它们还会导致崩溃吗?

发布于 2024-11-03 11:03:04 字数 477 浏览 6 评论 0原文

根据 2008 年的这个问题,使用石英掩模可能会导致崩溃!现在还是这样吗?

基本上,我想做的是在固定背景上绘制不同颜色的骰子,为每个骰子形状使用一个 png(有很多),并以某种方式在代码中添加颜色。

编辑:澄清一下,例如我想使用一个 png 文件来制作以下所有内容:

Red die蓝色骰子白色骰子

基本上, 我想要将图像的红色、绿色和蓝色分量乘以三个独立的常数,同时保持 alpha 不变。

According to this question from 2008, using quartz masks can cause crashes! Is that still the case?

Basically, what I want to do is to draw dice of different colors on a fixed background, using one png for each die shape (there are a lot of them), and somehow add the colors in code.

EDIT: to clarify, for example I want to use one png file to make all of the following:

Red dieBlue dieWhite die

Basically, I want to multiply the red, green, and blue components of my image by three independent constants, while leaving the alpha unchanged.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨光如昨 2024-11-10 11:03:04

这是一个镜头。经测试,无泄漏。没有崩溃。

.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

我用两个 UIImageView 和一个 UIButton 设置了 xib。顶部的 UIImageView 已通过 Interface Builder 预加载了图像。触摸文本按钮,图像将被处理并设置到第二个 UIImageView。

顺便说一句,我在从帖子中复制你的图标时遇到了一些麻烦。由于某种原因,透明度效果不佳。我使用了我自己在 Photoshop 中创建的带有或不带有透明度的新鲜 PNG 测试图像,一切都如广告所示。

当然,您在循环内所做的事情是根据您的需要进行修改的。

注意字节顺序,它真的会把事情搞砸!

Here's a shot. Tested, no leaks. No crashes.

.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

I setup the xib with two UIImageViews and one UIButton. The top UIImageView was pre-loaded with an image with Interface Builder. Touch the text button and the image is processed and set to the second UIImageView.

BTW, I had a little trouble with your icons copied right off your post. The transparency didn't work very well for some reason. I used fresh PNG test images of my own created in Photoshop with and without transparency and it all worked as advertised.

What you do inside the loop is to be modified per your needs, of course.

Watch endianess, it can really mess things up!

踏雪无痕 2024-11-10 11:03:04

我最近在 iPhone 应用程序中相当广泛地使用了蒙版,没有发生崩溃。该链接中的代码似乎甚至没有使用遮罩,只是进行了剪辑;唯一提到面具的是他尝试过的其他东西。更有可能的是,他是从后台线程调用的,UIGraphicsBeginImageContext 不是线程安全的。

如果不确切知道您想要达到什么效果,就很难就如何做到这一点提供建议。蒙版当然可以工作,无论是单独使用(以获得某种丝网印刷效果)还是剪辑在更真实的图像上绘制的覆盖颜色。我可能会使用遮罩或路径来设置剪切,然后绘制模具图像(使用 kCBGlendModeNormal 或 kCBGlendModeCopy),然后在其上绘制适当的纯色使用kCGBlendModeColor。

I've used masks fairly extensively recently in an iPhone app with no crashes. The code in that link doesn't even seem to be using masks, just clipping; the only mention of masks was as something else he tried. More likely he was calling that from a background thread, UIGraphicsBeginImageContext isn't thread safe.

Without knowing exactly what effect you're trying to get, it's hard to give advice on how to do it. A mask certainly could work, either alone (to get a sort of silkscreened effect) or to clip an overlay color drawn on a more realistic image. I'd probably use a mask or a path to set the clipping, then draw the die image (using kCBGlendModeNormal or kCBGlendModeCopy), and then paint the appropriate solid color over it using kCGBlendModeColor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文