15

NSImage を NSBitmapImageRep に変換するには? 私はコードを持っています:

- (NSBitmapImageRep *)bitmapImageRepresentation
{
    NSBitmapImageRep *ret = (NSBitmapImageRep *)[self representations];

    if(![ret isKindOfClass:[NSBitmapImageRep class]])
    {
        ret = nil;
        for(NSBitmapImageRep *rep in [self representations])
            if([rep isKindOfClass:[NSBitmapImageRep class]])
            {
                ret = rep;
                break;
            }
    }

    if(ret == nil)
    {
        NSSize size = [self size];

        size_t width         = size.width;
        size_t height        = size.height;
        size_t bitsPerComp   = 32;
        size_t bytesPerPixel = (bitsPerComp / CHAR_BIT) * 4;
        size_t bytesPerRow   = bytesPerPixel * width;
        size_t totalBytes    = height * bytesPerRow;

        NSMutableData *data = [NSMutableData dataWithBytesNoCopy:calloc(totalBytes, 1) length:totalBytes freeWhenDone:YES];

        CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);

        CGContextRef ctx = CGBitmapContextCreate([data mutableBytes], width, height, bitsPerComp, bytesPerRow, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), kCGBitmapFloatComponents | kCGImageAlphaPremultipliedLast);

        if(ctx != NULL)
        {
            [NSGraphicsContext saveGraphicsState];
            [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[self isFlipped]]];

            [self drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];

            [NSGraphicsContext restoreGraphicsState];

            CGImageRef img = CGBitmapContextCreateImage(ctx);

            ret = [[NSBitmapImageRep alloc] initWithCGImage:img];
            [self addRepresentation:ret];

            CFRelease(img);
            CFRelease(space);

            CGContextRelease(ctx);
        }
    }


    return ret;
}

動作しますが、メモリ リークが発生します。少なくともARCで使用している場合。それを使用initWithData:[nsimagename TIFFRepresentation]すると正しく動作しません。一部の画像の表現は適切ではありません。画像のフォーマットと色空間に依存すると思います。それを達成する他の方法はありますか?


mrwalkerが推奨する解決策の結果:

元の画像:
ここに画像の説明を入力

bitmapimagerep に変換し、画像に 1 回戻す:
ここに画像の説明を入力

bitmapimagerep に変換し、画像に 3 回戻します。
ここに画像の説明を入力

ご覧のとおり、NSBitmapImageRepに変換した後、画像は毎回暗くなります

4

3 に答える 3

15

@Julius: コードが複雑すぎて、いくつかのバグが含まれています。最初の行のみを修正します。

- (NSBitmapImageRep *)bitmapImageRepresentation
{
   for( NSImageRep *rep in [self representations] )
      if( [rep isKindOfClass:[NSBitmapImageRep class]] ) return rep;
   return nil;
}

これは、表現のメンバーである場合は最初のものを抽出し、NSBitmapImageRep存在しない場合は nil を返しNSBitmapImageRepます。NSImageReps表現にあるものに関係なく常に機能する別のソリューションを提供NSBitmapImageRepNSPDFImageRepますNSCGImageSnapshotRep

- (NSBitmapImageRep *)bitmapImageRepresentation
{
   CGImageRef CGImage = [self CGImageForProposedRect:nil context:nil hints:nil];
   return [[[NSBitmapImageRep alloc] initWithCGImage:CGImage] autorelease];
}

または、NSImage のサブクラス化を避けるために、次のように記述できます。

NSImage *img = [[[NSImage alloc] initWithContentsOfFile:filename] autorelease];
CGImageRef CGImage = [img CGImageForProposedRect:nil context:nil hints:nil];
NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithCGImage:CGImage] autorelease];

NSBitmapImageRepこれは、イメージに複数の表現 ( NSBitmapImageRepTIFF ファイルからの多数の など)が含まれている場合、十分ではない可能性がある単一の値のみを返します。ただし、コードを追加するのは簡単です。

于 2012-10-16T09:20:19.950 に答える
13

この方法は、Mike Ash の「画像データの取得と解釈」のブログ投稿を参考にして試すことができます。

- (NSBitmapImageRep *)bitmapImageRepresentation {
  int width = [self size].width;
  int height = [self size].height;

  if(width < 1 || height < 1)
      return nil;

  NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
                           initWithBitmapDataPlanes: NULL
                           pixelsWide: width
                           pixelsHigh: height
                           bitsPerSample: 8
                           samplesPerPixel: 4
                           hasAlpha: YES
                           isPlanar: NO
                           colorSpaceName: NSDeviceRGBColorSpace
                           bytesPerRow: width * 4
                           bitsPerPixel: 32];

  NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep: rep];
  [NSGraphicsContext saveGraphicsState];
  [NSGraphicsContext setCurrentContext: ctx];  
  [self drawAtPoint: NSZeroPoint fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1.0];
  [ctx flushGraphics];
  [NSGraphicsContext restoreGraphicsState];

  return [rep autorelease];
}
于 2012-10-15T14:18:44.950 に答える