кварцевые маски в iOS - они все еще вызывают сбои? - PullRequest
0 голосов
/ 26 апреля 2011

Согласно этому вопросу от 2008 , использование кварцевых масок может вызвать сбои! Это все еще так?

По сути, я хочу нарисовать кости разных цветов на фиксированном фоне, используя один png для каждой фигуры (их много), и каким-то образом добавить цвета в код.

РЕДАКТИРОВАТЬ: чтобы уточнить, например, я хочу использовать один файл PNG, чтобы сделать все следующее:

Red dieBlue dieWhite die

По сути, я хочу умножить красные, зеленые и синие компоненты моего изображения на три независимых константы, оставив при этом альфа-значение без изменений.

Ответы [ 2 ]

1 голос
/ 04 мая 2011

Вот выстрел.Проверено, нет утечек.Без сбоев.

.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

Я установил XIB с двумя UIImageViews и одним UIButton.Верхний UIImageView был предварительно загружен изображением с Интерфейсным Разработчиком.Нажмите текстовую кнопку, и изображение будет обработано и настроено на второй UIImageView.

Кстати, у меня возникли небольшие проблемы с вашими иконками, скопированными прямо с вашего поста.По какой-то причине прозрачность не сработала.Я использовал свежие собственные тестовые изображения PNG, созданные в Photoshop с прозрачностью и без нее, и все это работало так, как рекламировалось.

То, что вы делаете внутри цикла, должно быть изменено в соответствии с вашими потребностями, конечно.

Наблюдайте за порядком, это действительно может испортить!

1 голос
/ 01 мая 2011

В последнее время я довольно широко использовал маски в приложении для iPhone без сбоев.Код в этой ссылке, кажется, даже не использует маски, а просто обрезает;единственное упоминание масок было как-то еще, что он пытался.Скорее всего, он звонил из фонового потока: UIGraphicsBeginImageContext не является потокобезопасным.

Не зная точно, какой эффект вы пытаетесь получить, сложно дать совет, как это сделать.Маска, безусловно, может сработать, либо одна (чтобы получить эффект шелкографии), либо обрезать цвет наложения, нарисованный на более реалистичном изображении.Я бы, вероятно, использовал маску или путь, чтобы установить отсечение, затем нарисовал изображение штампа (используя kCBGlendModeNormal или kCBGlendModeCopy), а затем закрасил его соответствующим сплошным цветом, используя kCGBlendModeColor.

...