1

CGContextClipToMaskマスク画像のグレースケール値を無視して、単純な白黒のように動作させることは可能ですか?

グレースケール イメージがあり、それをマスク グレー色として使用すると、アルファ チャネルとして解釈されます。透明でないピクセルを完全にマスクする必要がある点を除いて、これは問題ありません。

短い例:

UIImage *mask = [self prepareMaskImage];
UIGraphicsBeginImageContextWithOptions(mask.size, NO, mask.scale); {
  // Custom code
  CGContextClipToMask(UIGraphicsGetCurrentContext(), mask.size, mask.CGImage);
  // Custom code
}

私の目標を達成するためにこのコードを適応させることは可能ですか?

簡単に言うと、透明なグレースケール画像を元の場所で透明にし、無地の場所で完全に黒くする必要があります。

4

3 に答える 3

1

面白い問題! 簡単なサンプル プロジェクトで必要と思われることを実行するコードを次に示します。上記と同様ですが、スケールを適切に処理します。必要に応じて、マスク イメージにアルファを保持するオプションもあります。動作するように見えるクイック ハッキング テスト。

于 2013-02-07T15:54:58.883 に答える
1

私の大まかなアイデアは次のとおりです。

  1. 入力画像をグレー + アルファ形式の読み取り可能なバイト データに変換します。iOS の制限により、代わりに RGBA を実行する必要があるかもしれません。
  2. 所定の値を変更してバイト データを反復処理します。

アクセスを簡素化するには、

typedef struct RGBA {
    UInt8 red;
    UInt8 green;
    UInt8 blue;
    UInt8 alpha;
} RGBA;

image入力マスクを仮定しましょう。

// First step, using RGBA (because I know it works and does not harm, just writes/consumes twice the amount of memory)
CGImageRef imageRef = image.CGImage;
NSInteger rawWidth = CGImageGetWidth(imageRef);
NSInteger rawHeight = CGImageGetHeight(imageRef);
NSInteger rawBitsPerComponent = 8;
NSInteger rawBytesPerPixel = 4;
NSInteger rawBytesPerRow = rawBytesPerPixel * rawWidth;
CGRect rawRect = CGRectMake(0, 0, rawWidth, rawHeight);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 *rawImage = (UInt8 *)malloc(rawHeight * rawWidth * rawBytesPerPixel);
CGContextRef rawContext = CGBitmapContextCreate(rawImage,
                                                rawWidth,
                                                rawHeight,
                                                rawBitsPerComponent,
                                                rawBytesPerRow,
                                                colorSpace,
                                                kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);

// At this point, rawContext is ready for drawing, everything drawn will be in rawImage's byte array.
CGContextDrawImage(rawContext, rawRect, imageRef);

// Second step, crawl the byte array and do the evil work:
for (NSInteger y = 0; y < rawHeight; ++y) {
    for (NSInteger x = 0; x < rawWidth; ++x) {
        UInt8 *address = rawImage + x * rawBytesPerPixel + y * rawBytesPerRow;
        RGBA *pixel = (RGBA *)address;
        // If it is a grey input image, it does not matter what RGB channel to use - they shall all be the same
        if (0 != pixel->red) {
            pixel->alpha = 0;
        } else {
            pixel->alpha = UINT8_MAX;
        }
        pixel->red = 0;
        pixel->green = 0;
        pixel->blue = 0;
        // I am still not sure if this is the transformation you are searching for, but it may give you the idea.
    }
}

// Third: rawContext is ready, transformation is done. Get the image out of it
CGImageRef outputImage1 = CGBitmapContextCreateImage(rawContext);
UIImage *outputImage2 = [UIImage imageWithCGImage:outputImage1];
CGImageRelease(outputImage1);

わかりました...出力はRGBAですが、グレースケール+アルファコンテキストを作成し、そこに画像をブリットして変換することができます.

于 2013-02-05T12:22:17.897 に答える
0

このコードは、画像の不透明な領域に色相を適用するのに役立ちました。

- (UIImage*)imageWithImage:(UIImageView*)source colorValue:(CGFloat)hue {
    CGSize imageSize = [source.image size];
    CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

    // Create a context containing the image.
    UIGraphicsBeginImageContext(imageSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [source.image drawAtPoint:CGPointMake(0, 0)];

    // Setup a clip region using the image
    CGContextSaveGState(context);
    CGContextClipToMask(context, source.bounds, source.image.CGImage);

    self.imageColor = [UIColor colorWithHue:hue saturation:1.0 brightness:1 alpha:1.0];
    [self.imageColor set];
    CGContextFillRect(context, source.bounds);

    // Draw the hue on top of the image.
    CGContextSetBlendMode(context, kCGBlendModeHue);
    [self.imageColor set];

    UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
    [imagePath fill];

    CGContextRestoreGState(context); // remove clip region

    // Retrieve the new image.
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}
于 2015-09-11T14:00:26.483 に答える