2009-05-27 6 views
1

J'ai donc essayé d'utiliser la fonction Quartz CGImageCreateWithMaskingColors, mais le seul problème est qu'il masque la gamme de couleurs que vous sélectionnez.En 2D Quartz, est-il possible de masquer une image en supprimant tout sauf le canal de couleur que vous voulez?

Je veux masquer tout sauf la gamme de couleurs que je sélectionne. Par exemple, je veux montrer toutes les couleurs rouges dans une image mais enlever les autres canaux (vert et bleu).

Je fais cela en Objective-C et je suis un noob donc s'il vous plaît me donner des exemples :)

Toute aide est grandement appréciée.

Répondre

0

utilise ces méthodes.i les trouve dans l'un des messages SO.

-(void)changeColor 
{ 
    UIImage *temp23=Image;//Pass your image here 
    CGImageRef ref1=[self createMask:temp23]; 
    const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0}; 
    CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking); 
    UIImage *resultedimage=[UIImage imageWithCGImage:New]; 
    EditImageView.image = resultedimage; 
    [EditImageView setNeedsDisplay]; 
} 

-(CGImageRef)createMask:(UIImage*)temp 
{ 


    CGImageRef ref=temp.CGImage; 
    int mWidth=CGImageGetWidth(ref); 
    int mHeight=CGImageGetHeight(ref); 
    int count=mWidth*mHeight*4; 
    void *bufferdata=malloc(count); 

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst); 

    CGRect rect = {0,0,mWidth,mHeight}; 
    CGContextDrawImage(cgctx, rect, ref); 
    bufferdata = CGBitmapContextGetData (cgctx); 

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferdata, mWidth*mHeight*4, NULL); 
    CGImageRef savedimageref = CGImageCreate(mWidth,mHeight, 8, 32, mWidth*4, colorSpaceRef, bitmapInfo,provider , NULL, NO, renderingIntent); 
    CFRelease(colorSpaceRef); 
    return savedimageref; 
} 

puis appeler la méthode de changeColor sur un bouton cliquez sur l'événement et voir le résultat

0

J'ai trouvé la réponse à mon problème ci-dessus, suivez le code ci-dessus Rahul avec quelques modifications pour définir votre propre couleur,

-(void)changeColor 
{ 
    UIImage *temp23=Image;//Pass your image here 
    CGImageRef ref1=[self createMask:temp23]; 
    const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0}; 
    CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking); 
    UIImage *resultedimage=[UIImage imageWithCGImage:New]; 
    EditImageView.image = resultedimage; 
    [EditImageView setNeedsDisplay]; 
} 

-(CGImageRef)createMask:(UIImage*)temp 
{ 
    CGImageRef ref=temp.CGImage; 
    int mWidth=CGImageGetWidth(ref); 
    int mHeight=CGImageGetHeight(ref); 
    int count=mWidth*mHeight*4; 
    void *bufferdata=malloc(count); 

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4,colorSpaceRef, kCGImageAlphaPremultipliedLast); 
    CGRect rect = {0,0,mWidth,mHeight}; 
    CGContextDrawImage(cgctx, rect, ref); 
    CGContextSaveGState(cgctx); 
    CGContextSetBlendMode(cgctx, kCGBlendModeColor); 
    CGContextSetRGBFillColor (cgctx, 1.0, 0.0, 0.0, 1.0); 
    CGContextFillRect(cgctx, rect); 


    bufferdata = CGBitmapContextGetData (cgctx); 
    const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0}; 
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferdata, mWidth*mHeight*4, NULL); 
    CGImageRef savedimageref = CGImageCreate(mWidth,mHeight, 8, 32, mWidth*4, colorSpaceRef, bitmapInfo,provider , NULL, NO, renderingIntent); 
    CFRelease(colorSpaceRef); 
    return savedimageref; 
} 
0

Hmmm ...

je manquer quelque chose, mais je ne crois pas que les réponses fournies appliquent à la question. La deuxième réponse se rapproche de la marque, mais elle contient un code erroné qui a peu à voir avec la solution.

La méthode createMask fait une copie de l'image originale en supposant alpha en position LSB. ChangeColor effectue un appel de masquage qui ne va pas faire beaucoup à une image RVB - en fait, seul le noir va être masqué (c'est-à-dire, triplets RGB dans la gamme/combinaisons de (1,1,2) à (3, 2,1)).

Je suppose que le décalage vers le rouge qui est observée est due au paramètre

kCGImageAlphaPremultipliedFirst

dans la ligne

CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst); 

en raison d'un mauvais traitement de la couche alpha. Si la méthode changeColor vous modifiez le bloc

CGImageRef ref1=[self createMask:temp23]; 
const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0}; 
CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking); 
UIImage *resultedimage=[UIImage imageWithCGImage:New]; 
EditImageView.image = resultedimage; 

être

CGImageRef ref1=[self createMask:temp23]; 
UIImage *resultedimage=[UIImage imageWithCGImage:ref]; 
EditImageView.image = resultedimage; 

vous verrez aucune différence dans l'affichage. La modification de la constante CGBitmapInfo en kCGImageAlphaPremultipliedLast doit afficher l'image correctement en utilisant l'un des blocs de code ci-dessus.

La réponse suivante se rapproche un peu plus de ce que l'OP demande, mais c'est en termes d'effet visuel, pas de données réelles. Voici le code pertinent dans createMask est

CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4,colorSpaceRef, kCGImageAlphaPremultipliedLast); 

qui affiche l'image correctement, suivie par

CGContextSetBlendMode(cgctx, kCGBlendModeColor); 
CGContextSetRGBFillColor (cgctx, 1.0, 0.0, 0.0, 1.0); 
CGContextFillRect(cgctx, rect); 

et la logique pour la construction de l'image.La logique de fusion recouvre une teinte rouge sur l'image originale, obtenant un effet similaire à celui du canal alpha égaré dans la réponse d'origine. Ce n'est toujours pas ce que l'OP demande, c'est-à-dire masquer un ou plusieurs canaux, pas mélanger les couleurs.

Cela revient à régler les valeurs de canal pour les couleurs qui ne sont pas souhaitées à zéro. Voici un exemple pour renvoyer juste le canal rouge comme les demandes OP; l'hypothèse est que le format du pixel est ABGR:

- (CGImageRef) redChannel:(CGImageRef)image 
{ 
    CGDataProviderRef provider = CGImageGetDataProvider(image); 
    NSMutableData* data = (id)CGDataProviderCopyData(provider); 

    int width = CGImageGetWidth(image); 
    int height = CGImageGetHeight(image); 

    [data autorelease]; 

    // get a mutable reference to the image data 
    uint32_t* dwords = [data mutableBytes]; 

    for (size_t idx = 0; idx < width*height; idx++) { 
     uint32_t* pixel = &dwords[idx]; 
     // perform a logical AND of the pixel with a mask that zeroes out green and blue pixels 
     *pixel &= 0x000000ff; 
    } 

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    // now create a new image using the masked original data 
    CGDataProviderRef iprovider = CGDataProviderCreateWithData(NULL, dwords, width*height*4, NULL); 
    CGImageRef savedimageref = CGImageCreate(width, height, 8, 32, width*4, colorSpaceRef, bitmapInfo, iprovider, NULL, NO, renderingIntent); 
    CGColorSpaceRelease(colorSpaceRef); 
    CGDataProviderRelease(iprovider); 

    return savedimageref; 
} 

Un bon résumé des opérations binaires se trouve here.

Comme indiqué here, vous devrez peut-être modifier la structure du masque en fonction de l'ordre LSB/MSB des bits dans le pixel. Cet exemple suppose des pixels de 32 bits à partir d'un PNG iPhone standard.