そこで、Quartz CGImageCreateWithMaskingColors 関数を使用しようとしましたが、唯一の問題は、選択している色の範囲をマスクすることです。
選択している色の範囲以外をすべてマスクしたい。たとえば、画像内のすべての赤色を表示し、他のチャネル (緑と青) を削除したいとします。
私はObjective-Cでこれを行っています。私は初心者なので、例を教えてください:)
どんな助けでも大歓迎です。
そこで、Quartz CGImageCreateWithMaskingColors 関数を使用しようとしましたが、唯一の問題は、選択している色の範囲をマスクすることです。
選択している色の範囲以外をすべてマスクしたい。たとえば、画像内のすべての赤色を表示し、他のチャネル (緑と青) を削除したいとします。
私はObjective-Cでこれを行っています。私は初心者なので、例を教えてください:)
どんな助けでも大歓迎です。
上記の問題の答えを見つけました.Rahulの上記のコードに従って、独自の色を設定するためにいくつかの変更を加えてください.
-(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;
}
うーん...
何かが足りないかもしれませんが、提供された回答が質問に当てはまるとは思いません。2 番目の応答は目標に近づいていますが、ソリューションとはほとんど関係のない偽のコードが含まれています。
このcreateMask
メソッドは、LSB 位置にアルファがあると仮定して、元のイメージのコピーを作成します。changeColor は、RGB 画像にはあまり影響を与えないマスキング呼び出しを実行します。基本的には、黒のみがマスクされます (つまり、(1,1,2) から (3, 2,1))。
観察されている赤方偏移は、パラメーターによるものだと推測しています
kCGImageAlphaPremultipliedFirst
ラインで
CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst);
アルファ チャネルの不適切な処理が原因です。changeColor
メソッドでブロックを変更する場合
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;
することが
CGImageRef ref1=[self createMask:temp23];
UIImage *resultedimage=[UIImage imageWithCGImage:ref];
EditImageView.image = resultedimage;
表示に違いはありません。CGBitmapInfo 定数を に変更するkCGImageAlphaPremultipliedLast
と、上記のコード ブロックのいずれかを使用して画像が正しく表示されます。
次の応答は、OP が要求するものに少し近づきますが、実際のデータではなく、視覚効果に関してです。ここで関連するコードcreateMask
は
CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4,colorSpaceRef, kCGImageAlphaPremultipliedLast);
これにより、画像が正しく表示され、その後に
CGContextSetBlendMode(cgctx, kCGBlendModeColor);
CGContextSetRGBFillColor (cgctx, 1.0, 0.0, 0.0, 1.0);
CGContextFillRect(cgctx, rect);
次に、イメージを構築するためのロジックです。ブレンド ロジックは、元の画像に赤い色合いを重ねて、元の応答で誤って配置されたアルファ チャネルと同様の効果を実現します。これはまだ、OP が要求するものではありません。これは、色をブレンドするのではなく、1 つまたは複数のチャネルをマスクすることです。
これは実際には、望ましくない色のチャネル値をゼロに設定することになります。OP の要求に応じて赤のチャネルのみを返す例を次に示します。ピクセルのフォーマットが 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;
}
ビット演算の概要については、こちらを参照してください。
ここで指摘されているように、ピクセル内のビットの LSB/MSB の順序に応じて、マスクの構造を変更する必要がある場合があります。この例では、標準の iPhone PNG の 32 ビット ピクセルを想定しています。
SO投稿の1つでそれらを見つけました。
-(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;
}
次に、ボタンのクリック イベントで changecolor メソッドを呼び出し、結果を確認します。