2012-03-13 11 views

risposta

3

cosa significa sottrarre un'immagine? l'immagine di esempio mostrata mostra più di una operazione! rosso. diciamo che per sottrarre l'immagine a dall'immagine b significa impostare ogni pixel in b che intersechi un pixel in a trasparente. per eseguire la sottrazione, ciò che stiamo facendo è mascherare l'immagine b all'inverso dell'immagine a. quindi, un buon approccio sarebbe quello di creare una maschera immagine dal canale alfa dell'immagine a, quindi applicarla a b. per creare la maschera si dovrebbe fare qualcosa di simile:

// get access to the image bytes 
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage)); 

// create a buffer to hold the mask values 
size_t width = CGImageGetWidth(image.CGImage); 
size_t height = CGImageGetHeight(image.CGImage);  
uint8_t *maskData = malloc(width * height); 

// iterate over the pixel data, reading the alpha value 
uint8_t *alpha = (uint8_t *)CFDataGetBytePtr(pixelData) + 3; 
uint8_t *mask = maskData; 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     *mask = *alpha; 
     mask++;  
     alpha += 4; // skip to the next pixel 
    } 
} 

// create the mask image from the buffer 
CGDataProviderRef maskProvider = CGDataProviderCreateWithData(NULL, maskData, width * height, NULL); 
CGImageRef maskImage = CGImageMaskCreate(width, height, 8, 8, width, maskProvider, NULL, false); 

// cleanup 
CFRelease(pixelData); 
CFRelease(maskProvider); 
free(maskData); 

whew. quindi, per mascherare l'immagine b, tutto ciò che devi fare è:

CGImageRef subtractedImage = CGImageCreateWithMask(b.CGImage, maskImage); 

hey presto.

+0

buon esempio: questo è lavoro per me. Grazie! –

3

Per ottenere questi risultati, utilizzare la seconda immagine come maschera quando si disegna la prima immagine. Per questo tipo di disegno, è necessario utilizzare Core Graphics, a.k.a. Quartz 2D. La guida di programmazione 2D al quarzo , ha una sezione chiamata Bitmap Images and Image Masks che dovrebbe dirti tutto quello che devi sapere.

Stai chiedendo informazioni sugli oggetti UIImage, ma per utilizzare Core Graphics avrai bisogno di CGImages. Non c'è problema: UIImage fornisce una proprietà CGImage che ti consente di ottenere facilmente i dati che ti servono.

13

Credo che sia possibile farlo utilizzando la modalità di miscelazione kCGBlendModeDestinationOut. Crea un nuovo contesto, disegna la tua immagine di sfondo, quindi disegna l'immagine in primo piano con questa modalità di fusione.

UIGraphicsBeginImageContextWithOptions(sourceImage.size, NO, sourceImage.scale) 
[sourceImage drawAtPoint:CGPointZero]; 
[maskImage drawAtPoint:CGPointZero blendMode:kCGBlendModeDestinationOut alpha:1.0f]; 
UIImage *result = UIGraphicsGetImageFromCurrentImageContext() 
UIGraphicsEndImageContext(); 
+0

+1: consiglierei di andare per questo. Molto più pulito e semplice della risposta accettata. – sjwarner

+0

Anch'io, molto carino. – Tark

+1

Sì, questa dovrebbe essere la risposta accettata. –

0

La soluzione di Kevin Ballard ha funzionato per me! In Swift 3.x:

func subtract(source: UIImage, mask: UIImage) -> UIImage? { 
    UIGraphicsBeginImageContextWithOptions(source.size, false, source.scale) 
    source.draw(at: CGPoint.zero) 
    mask.draw(at: CGPoint.zero, blendMode: .destinationOut, alpha: 1.0) 
    let result = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
    return result 
}