NSBitmapImageRepをちょっと拡張
NSBitmapImageRepをちょっと拡張したもの。
現在、NSBitmapImageRepでは、bitmapDataメソッドで画像のピクセルデータが取得できますが、RGB, CMYKかは利用者が判断しなければなりません。
ので、getRGB(), getCMYK()というメソッドをカテゴリクラスとして実装して取得する、と言うものを書きました。
ちなみに、RGBからCMYKの変換は色が薄くなり、CMYKからRGBの変換がまだバグ持ちと云う者ですが・・・
使用例はこちら。
第一引数にbitmapファイルをしていすると、bitmapファイルをCMYKに変換してそれをHex表記し、第二引数のファイルに書き出すコマンドラインプログラム。
ちなみに書き出したファイルのサイズは、元ファイルの3倍になります。
#include <CoreFoundation/CoreFoundation.h> #include "myBitmapImageRep.h" int main (int argc, const char * argv[]) { NSString *bitmapPath, *outputPath; if (argc <= 2) { fprintf(stderr, "%s [bitmap file] [output file]", argv[0]); exit(1); } NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; bitmapPath = [NSString stringWithUTF8String:argv[1]]; outputPath = [NSString stringWithUTF8String:argv[2]]; NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithContentsOfFile:bitmapPath]; NSString *cmyk = [[rep getCMYK] description]; NSError *err = [NSError errorWithDomain:@"RGBCMYK_BitmapImageRep.a-yasui.info" code:0 userInfo:nil]; if ([cmyk writeToFile:outputPath atomically:YES encoding:NSASCIIStringEncoding error:&err]) { fprintf(stdout,"write out to %s", argv[2]); } else { fprintf(stderr,"write error. sorry."); } [pool release]; exit(0); }
ソース
@interface NSBitmapImageRep (NSBitmapImageRep) - (NSData *) getRGB; - (NSData *) getRGBA; - (NSData *) getCMYK; - (NSData *) getCMYKA; @end
@implementation NSBitmapImageRep (NSBitmapImageRep) #define _min(x,y) ((x)>(y))?(y):(x) #define _max(x,y) ((x)>(y))?(x):(y) #define _C cmyk[0] #define _M cmyk[1] #define _Y cmyk[2] #define _K cmyk[3] #define _CMYKA cmyk[4] #define _R rgb[0] #define _G rgb[1] #define _B rgb[2] #define _RGBA rgb[3] - (NSData *) getRGB { // ex, http://image-d.isp.jp/commentary/color_cformula/CMYK.html // RGB => CMYK (any range (0..1.0) // // k = _min(1-R, 1-G, 1-B) // C = (1 - R - K)/(1-K) // M = (1 - G - K)/(1-K) // Y = (1 - B - K)/(1-K) NSMutableData *data = nil; if (([[self colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace]) || ([[self colorSpaceName] isEqualToString:NSDeviceRGBColorSpace])) { // RGB NSLog(@"getRGB : RGB"); unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned int spp = [self samplesPerPixel]; unsigned int noAlphaSpp = ([self hasAlpha])?spp-1:spp; unsigned long imageSize = size * noAlphaSpp; unsigned char *imageBytes = [self bitmapData]; unsigned long i = 0, j = 0; // swap NSLog(@"getRGB : imageSize => %ld", imageSize); unsigned char *buff = (unsigned char*)malloc((imageSize+1)*sizeof(unsigned char)); if (buff == NULL) { NSLog(@"getRGB Malloc Error"); return nil; } if (spp == noAlphaSpp) { memcpy(buff, imageBytes,imageSize); } else { for (i = 0, j = 0; i < size*spp; i+=spp, j+=noAlphaSpp) { buff[j] = imageBytes[i]; buff[j+1] = imageBytes[i+1]; buff[j+2] = imageBytes[i+2]; } } data = [NSData dataWithBytes:buff length:imageSize]; free(buff); } else if ([[self colorSpaceName] isEqualToString:NSDeviceCMYKColorSpace]) { // CMYK => RGB NSLog(@"getRGB : CMYK -> RGB"); unsigned int spp = [self samplesPerPixel]; unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned long i = 0; unsigned char *imageBytes = [self bitmapData]; char *buff = NULL; data = [NSMutableData dataWithCapacity:size*3]; buff = (char*)malloc(size*3*sizeof(char)); if (buff == NULL) { NSLog(@"Malloc error"); return data; } for (i = 0; i < size*spp; i+=spp) { unsigned char *char_cmyk = (imageBytes + i); unsigned char rgb[4]; unsigned char cmyk[5] = { char_cmyk[0], char_cmyk[1], char_cmyk[2], char_cmyk[3], char_cmyk[4] }; _R = 255 - _min(255, ((255 - _K)*_C + 255*_K)/255); _G = 255 - _min(255, ((255 - _K)*_M + 255*_K)/255); _B = 255 - _min(255, ((255 - _K)*_Y + 255*_K)/255); _RGBA = _CMYKA; [data appendBytes:rgb length:3]; } free(buff); } else { // cannot } return data; } - (NSData *) getRGBA { // ex, http://image-d.isp.jp/commentary/color_cformula/CMYK.html // RGB => CMYK (any range (0..1.0) // // k = _min(1-R, 1-G, 1-B) // C = (1 - R - K)/(1-K) // M = (1 - G - K)/(1-K) // Y = (1 - B - K)/(1-K) NSMutableData *data = nil; if (([[self colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace]) || ([[self colorSpaceName] isEqualToString:NSDeviceRGBColorSpace])) { // RGB NSLog(@"getRGB : RGB"); unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned int spp = [self samplesPerPixel]; unsigned int hasAlphaSpp = ([self hasAlpha])?spp:spp+1; unsigned long imageSize = size * hasAlphaSpp; unsigned char *imageBytes = [self bitmapData]; unsigned long i = 0, j = 0; BOOL hasAlpha = [self hasAlpha]; // swap unsigned char *buff = (unsigned char*)malloc((imageSize+1)*sizeof(unsigned char)); if (buff == NULL) { NSLog(@"getRGB Malloc Error"); return nil; } for (i = 0, j = 0; i < size*spp; i+=spp, j+=hasAlphaSpp) { buff[j] = imageBytes[i]; buff[j+1] = imageBytes[i+1]; buff[j+2] = imageBytes[i+2]; buff[j+3] = (hasAlpha)?imageBytes[i+3]:1.0; } data = [NSData dataWithBytes:buff length:imageSize]; free(buff); } else if ([[self colorSpaceName] isEqualToString:NSDeviceCMYKColorSpace]) { // CMYK => RGB NSLog(@"getRGB : CMYK -> RGB"); unsigned int spp = [self samplesPerPixel]; unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned long i = 0; unsigned char *imageBytes = [self bitmapData]; char *buff = NULL; data = [NSMutableData dataWithCapacity:size*3]; buff = (char*)malloc(size*3*sizeof(char)); if (buff == NULL) { NSLog(@"Malloc error"); return data; } for (i = 0; i < size*spp; i+=spp) { unsigned char char_rgb[3] = "\0"; unsigned char *char_cmyk = (imageBytes + i); unsigned char rgb[4]; unsigned char cmyk[5] = { char_cmyk[0], char_cmyk[1], char_cmyk[2], char_cmyk[3], char_cmyk[4] }; _R = 255 - _min(255, ((255 - _K)*_C + 255*_K)/255); _G = 255 - _min(255, ((255 - _K)*_M + 255*_K)/255); _B = 255 - _min(255, ((255 - _K)*_Y + 255*_K)/255); _RGBA = _CMYKA; [data appendBytes:char_rgb length:4]; } free(buff); } else { // cannot } return data; } - (NSData *) getCMYK { // ex, http://image-d.isp.jp/commentary/color_cformula/CMYK.html // CMYK => RGB (any range (0..1.0)) // // R = 1 - _min(1, C*(1-K)+k) // G = 1 - _min(1, M*(1-K)+k) // B = 1 - _min(1, Y*(1-K)+k) NSMutableData *data = nil; if (([[self colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace]) || ([[self colorSpaceName] isEqualToString:NSDeviceRGBColorSpace])) { // RGB => CMYK NSLog(@"getRGB : RGB => CMYK"); unsigned int spp = [self samplesPerPixel]; unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned long i = 0; unsigned char *imageBytes = [self bitmapData]; data = [NSMutableData dataWithCapacity:size*4]; unsigned char * buff = (unsigned char*)malloc(size*4*sizeof(unsigned char)); if (buff == NULL) { NSLog(@"Malloc error"); return data; } for (i = 0; i < size*spp; i+=spp) { unsigned char *char_rgb = (imageBytes + i); unsigned char rgb[3] = { 255 - char_rgb[0], 255 - char_rgb[1], 255 - char_rgb[2] }; unsigned char cmyk[4]; _K = _min(_R, _min(_G, _B)); if (_K == 255) { _C = 0; _M = 0; _Y = 0; } else { _C = (_R - _K)*255/(255 - _K); _M = (_G - _K)*255/(255 - _K); _Y = (_B - _K)*255/(255 - _K); } [data appendBytes:cmyk length:4]; } free(buff); } else if ([[self colorSpaceName] isEqualToString:NSDeviceCMYKColorSpace]) { // CMYK NSLog(@"getRGB : CMYK"); unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned int spp = [self samplesPerPixel]; unsigned int noAlphaSpp = ([self hasAlpha])?spp-1:spp; unsigned long imageSize = size * noAlphaSpp; unsigned char *imageBytes = [self bitmapData]; unsigned long i = 0, j = 0; // swap unsigned char* buff = (unsigned char*)malloc((imageSize+1)*sizeof(unsigned char)); if (buff == NULL) { NSLog(@"getRGB Malloc Error"); return nil; } for (i = 0, j = 0; i < size*spp; i+=spp, j+=noAlphaSpp) { buff[j] = imageBytes[i]; buff[j+1] = imageBytes[i+1]; buff[j+2] = imageBytes[i+2]; buff[j+3] = imageBytes[i+3]; } data = [NSData dataWithBytes:buff length:imageSize]; free(buff); } else { // cannot } return data; } - (NSData *) getCMYKA { // ex, http://image-d.isp.jp/commentary/color_cformula/CMYK.html // CMYK => RGB (any range (0..1.0)) // // R = 1 - _min(1, C*(1-K)+k) // G = 1 - _min(1, M*(1-K)+k) // B = 1 - _min(1, Y*(1-K)+k) NSMutableData *data = nil; if (([[self colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace]) || ([[self colorSpaceName] isEqualToString:NSDeviceRGBColorSpace])) { // RGB => CMYK NSLog(@"getRGB : RGB => CMYK"); unsigned int spp = [self samplesPerPixel]; unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned long i = 0; unsigned char *imageBytes = [self bitmapData]; BOOL alpha = [self hasAlpha]; data = [NSMutableData dataWithCapacity:size*4]; unsigned char * buff = (unsigned char*)malloc(size*4*sizeof(unsigned char)); if (buff == NULL) { NSLog(@"Malloc error"); return data; } for (i = 0; i < size*spp; i+=spp) { unsigned char *char_rgb = (imageBytes + i); unsigned char rgb[3] = { 255 - char_rgb[0], 255 - char_rgb[1], 255 - char_rgb[2] }; unsigned char cmyk[4]; _K = _min(_R, _min(_G, _B)); if (_K == 255) { _C = 0; _M = 0; _Y = 0; } else { _C = (_R - _K)*255/(255 - _K); _M = (_G - _K)*255/(255 - _K); _Y = (_B - _K)*255/(255 - _K); } _CMYKA = (alpha) ? _RGBA : 1.0; [data appendBytes:cmyk length:4]; } free(buff); } else if ([[self colorSpaceName] isEqualToString:NSDeviceCMYKColorSpace]) { // CMYK NSLog(@"getRGB : CMYK"); unsigned long size = [self pixelsWide] * [self pixelsHigh]; unsigned int spp = [self samplesPerPixel]; unsigned int hasAlphaSpp = ([self hasAlpha])?spp:spp+1; unsigned long imageSize = size * hasAlphaSpp; unsigned char *imageBytes = [self bitmapData]; unsigned long i = 0, j = 0; BOOL hasAlpha = [self hasAlpha]; // swap unsigned char *buff = (unsigned char*)malloc((imageSize+1)*sizeof(unsigned char)); if (buff == NULL) { NSLog(@"getCMYKA Malloc Error"); return nil; } for (i = 0, j = 0; i < size*spp; i+=spp, j+=hasAlphaSpp) { buff[j] = imageBytes[i]; buff[j+1] = imageBytes[i+1]; buff[j+2] = imageBytes[i+2]; buff[j+3] = imageBytes[i+3]; buff[j+4] = (hasAlpha)?imageBytes[i+4]:1.0; } data = [NSData dataWithBytes:buff length:imageSize]; free(buff); } else { // cannot } return data; } @end
ちなみに、getCYMKAは不要な物だよねぇ。勢い?で作ってしまったんだよね・・・
後、この長いのをどうにかしたいなぁ・・・