30

Pixel Test

Embed Size (px)

DESCRIPTION

Pixel Test. 朱中華 2010/11/25. CreateARGBBitmapContext. CGContextRef CreateARGBBitmapContext (CGImageRef inImage, CGSize size) { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; - PowerPoint PPT Presentation

Citation preview

Page 1: Pixel Test
Page 2: Pixel Test

CGContextRef CreateARGBBitmapContext (CGImageRef inImage, CGSize size) { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; size_t pixelsWide = size.width; size_t pixelsHigh = size.height; bitmapBytesPerRow = (pixelsWide * 4); bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); colorSpace = CGColorSpaceCreateDeviceRGB(); if (colorSpace == NULL) { fprintf(stderr, "Error allocating color space\n"); return NULL; }

Page 3: Pixel Test

// allocate the bitmap & create context bitmapData = malloc( bitmapByteCount ); if (bitmapData == NULL) { fprintf (stderr, "Memory not allocated!"); CGColorSpaceRelease( colorSpace ); return NULL; } context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8,

bitmapBytesPerRow, colorSpace,

kCGImageAlphaPremultipliedFirst); if (context == NULL) { free (bitmapData); fprintf (stderr, "Context not created!"); }

CGColorSpaceRelease( colorSpace ); return context; }

Page 4: Pixel Test

// Return a C-based bitmap of the image data inside an image unsigned char *RequestImagePixelData(UIImage *inImage) { CGImageRef img = [inImage CGImage]; CGSize size = [inImage size]; CGContextRef cgctx = CreateARGBBitmapContext(img, size); if (cgctx == NULL) return NULL;

CGRect rect = {{0,0},{size.width, size.height}}; CGContextDrawImage(cgctx, rect, img); unsigned char *data = CGBitmapContextGetData (cgctx); CGContextRelease(cgctx);

return data; }

Page 5: Pixel Test

@interface CrossHairView : UIView @end @implementation CrossHairView - (void) drawRect: (CGRect) aRect { // Create a new path CGContextRef context =

UIGraphicsGetCurrentContext(); CGMutablePathRef path = CGPathCreateMutable(); // Set up the stroke characteristics CGContextSetLineWidth(context, 3.0f); CGFloat gray[4] = {0.75f, 0.75f, 0.75f, 1.0f}; CGContextSetStrokeColor(context, gray);

Page 6: Pixel Test

// Add circle to path CGRect limits = CGRectMake(2.0f, 2.0f, SIDELENGTH - 4.0f, SIDELENGTH - 4.0f); CGPathAddEllipseInRect(path, NULL, limits); CGContextAddPath(context, path);

// Add cross to path, leaving an inspection point in the middle CGContextMoveToPoint(context, 0.0f, SIDELENGTH/2.0f); CGContextAddLineToPoint(context, (SIDELENGTH/2.0f) - 2.0f, SIDELENGTH/2.0f); CGContextMoveToPoint(context, (SIDELENGTH /2.0f) + 2.0f, SIDELENGTH/2.0f); CGContextAddLineToPoint(context, SIDELENGTH, SIDELENGTH/2.0f); CGContextMoveToPoint(context, SIDELENGTH/2.0f, 0.0f); CGContextAddLineToPoint(context, SIDELENGTH/2.0f, (SIDELENGTH / 2.0f) - 2.0f); CGContextMoveToPoint(context, SIDELENGTH/2.0f, SIDELENGTH); CGContextAddLineToPoint(context, SIDELENGTH/2.0f, (SIDELENGTH / 2.0f) + 2.0f);

CGContextStrokePath(context); CFRelease(path); } @end

Page 7: Pixel Test

• // Create an Image View that stores a copy of its image as an addressable bitmap

• @interface BitMapView : UIImageView• {• unsigned char *bitmap;• CGSize size;• }• @end

Page 8: Pixel Test

- (id) initWithFrame: (CGRect) aFrame { if (!(self = [super initWithFrame: aFrame])) return NULL;

// initialize by adding the cross-hair CrossHairView *crossHair = [[CrossHairView alloc]

initWithFrame:CGRectMake(0.0f, 0.0f, SIDELENGTH, SIDELENGTH)];

crossHair.tag = CROSSHAIR_TAG; crossHair.backgroundColor = [UIColor clearColor]; crossHair.center = CGPointMake(160.0f, 240.0f); [self addSubview:crossHair]; [crossHair release]; return self; }

Page 9: Pixel Test

• (BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event

• {• long startByte = (int)((point.y *

size.width) + point.x) * 4;• int alpha = (unsigned char)

bitmap[startByte];• return (alpha > 0.5);• }

Page 10: Pixel Test

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { CGPoint pt = [[touches anyObject] locationInView:self]; long startByte = (int)((pt.y * size.width) + pt.x) * 4;

// Note these points are slightly off in the simulator [self viewWithTag:CROSSHAIR_TAG].center = pt;

// Output RGB values. The alpha value has offset 0 /* printf("[%3d, %3d] %3dR %3dG %3dB\n", (int)pt.x, (int)pt.y, (unsigned char) bitmap[startByte+1], (unsigned char) bitmap[startByte+2], (unsigned char) bitmap[startByte+3]); */

[self viewWithTag:COLOR_VIEW_TAG].backgroundColor = [UIColor colorWithRed: (float) (bitmap[startByte+1]/255.0f) green: (float) (bitmap[startByte+2]/255.0f) blue: (float) (bitmap[startByte+3]/255.0f) alpha: 1.0f]; }

Page 11: Pixel Test

-(void) setImage:(UIImage *) anImage { [super setImage:anImage]; bitmap = RequestImagePixelData(anImage); size = [anImage size]; UIView *colorView = [[UIView alloc]

initWithFrame:CGRectMake(0.0f, 400.0f, 320.0f, 80.0f)]; colorView.userInteractionEnabled = NO; colorView.backgroundColor = [UIColor blueColor]; colorView.tag = COLOR_VIEW_TAG; [self addSubview:colorView]; [colorView release]; }

Page 12: Pixel Test

@interface HelloController : UIViewController @end @implementation HelloController - (void)loadView { BitMapView *contentView = [[BitMapView alloc]

initWithFrame:[[UIScreen mainScreen] bounds]]; [contentView setImage:[UIImage

imageNamed:@"image2.jpg"]]; [contentView setUserInteractionEnabled:YES]; self.view = contentView; [contentView release]; } @end

Page 13: Pixel Test

@interface SampleAppDelegate : NSObject <UIApplicationDelegate>

@end @implementation SampleAppDelegate - (void)applicationDidFinishLaunching:(UIApplication

*)application { UIWindow *window = [[UIWindow alloc] initWithFrame:

[[UIScreen mainScreen] bounds]]; HelloController *hello = [[HelloController alloc] init]; [window addSubview:hello.view]; [window makeKeyAndVisible]; [application setStatusBarHidden:YES]; } @end

Page 14: Pixel Test

int main(int argc, char *argv[]) { NSAutoreleasePool * pool =

[[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc,

argv, nil, @"SampleAppDelegate"); [pool release]; return retVal; }

Page 15: Pixel Test
Page 16: Pixel Test

• 這個程式會在 iPhone 螢幕上顯示一個image(image 在 image2.jpg 內 ) ,並放一個圓形的 pixel tester 在 image 之上,一開始, image下方顯示一條藍色 bar ,一旦移動該 pixel tester ,中心 pixel 的顏色會立即顯示在下方 bar 上,見下圖,任何時候,隨著 pixel tester 移動,其中心所在位置的顏色會顯示在下方 bar 。最左邊的圖是剛開始, image 下方顯示一條藍色 bar , pixel tester 在螢幕中間,中間是的圖是 pixel tester 移至上方,右邊的圖是 pixel tester 移到魚上,在不同的位置,下方 bar 顯示出 image 內某 pixel 的顏色。 pixel tester 在程式中是以 crossHair class來表示:

Page 17: Pixel Test

[window addSubview:hello.view]; 跳入hello 所在的 HelloController class 的loadSubView 。

Page 18: Pixel Test

• BitMapView *contentView = [[BitMapView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 這一行呼叫 initWithFrame 開啟一個 BitMapView object -- contentView ,在 initWithFrame 內,

• CrossHairView *crossHair = [[CrossHairView alloc] initWithFrame:CGReckMake(0.0f, 0.0f, SIDELENGTH, SIDELENGTH)]; // 將 ( SIDELENGTH, SIDELENGTH ) 這 ( 40 x 40 ) 的 pixel tester 加入 BitMapView object 內

• [contentView setImage:[UIImage imageNamed:@"image2.jpg"]]; 這一行呼叫contentView 所屬的 BitMapView class 中的setImage 。

Page 19: Pixel Test

下面這一行是 call RequestImagePixelData ,把 anImage(image2.jpg) 放入 bitmap 這個array 內,每個 pixel 4 個 byte 。 › bitmap = RequestImagePixelData(anImage);

下面這一行是 call CreateARGBBitmapContext ,產生一個CGContextRef ,以便準備放下 image2.jpg 的所有 pixel 。› CreateARGBBitmapContext(img, size)

Page 20: Pixel Test

Color Space 就是用來表現顏色的方式,例如 RGB 、 CMYK 等。

CGColorSpaceCreateDeviceRGB› Create 一個 device dependent RGB device

color space , return value 為CGColorSpaceRef object 。

Page 21: Pixel Test

在 CGBitmapContext reference 裡,把 bitmap 所需的 memory 、 width 、 height 、 bytesPerRow...等七個 parameter 放入 type 為 CGContextRef 的context ,回傳 context ,這七個 parameter 是:› void *data :一塊 memory ,至少 bytesPerRow * height 。

這一塊 memory, 用 c 的 malloc 得到,由這個程式放入context 內。

› size_t width : bitmap 的 width in pixel 。› size_t height : bitmap 的 height in pixel 。 › size_t bitsPerComponent : 32-bit pixel format 的 RGB ,

8 bits per component 。 › size_t bytesPerRow :一個 row 多少 bytes 。

Page 22: Pixel Test

• 這個程式將 inImage 這 file load 進 memory ,並return pointer points to the memory 。 注意,這一塊 memory 是由 CreateARGBBitmapContext 的malloc 來的。

• CGContextDrawImage ( cgctx, rect, img ); 將image 畫上螢幕。

• unsign char *data = CGBitmapContextGetData (cgctx); 會將 cgctx 內的 bitmap image data 傳回,讓 data 這個 pointer 指向這塊 bitmap image data ,也就是 CreateARGBBitmapContext 的 malloc 來的memory ,並由 [UIImage imageNamed:@"image2.jpg"]load image2.jpg 進memory 。

Page 23: Pixel Test

BitMapView *contentView = .... , call initWithFrame ,將 crossHair subView 放上。

[contentView setImage:[UIImage imageNamed:@"image2.jpg"]]; :拿contentView 的資訊,由 [UIImage imageNamed:@"image2.jpg"]load image2.jpg 進 memory 。

Page 24: Pixel Test

• pointInside : click pixel tester crossHair 時,會跳入,如果 alpha 值 >0.5 ,則系統會繼續。若 alpha 值 <= 0.5 ,則系統不會繼續。

• touchesMoved :當 click 及 drag 時,且如果 alpha 值 > 0.5 則跳入

• [self viewWithTag:COLOR_VIEW_TAG].backgroundColor – 將該位置顏色顯示於下方 bar 。若 alpha 值 < =

0.5 ,即使 click 及 drag 仍不會跳入。

Page 25: Pixel Test

• 畫出一個圓,中間一個十字的 pixel tester(crossHair class) ,在 loadView 執行完後,系統會 call drawRect :

• 行先產生 context 及 path 兩個 CGContext 需用的object 。

• CGContextSetStrokeColor(context, gray);– 設定筆畫 (stroke) 相關資訊, 76 行設定筆畫的寬度為

3pixel( 可試試改為 1 個 pixel 或 5 個 pixel) , 77~78 行設定筆畫的顏色及透明度, 77 行 gray[4] 有四個值,依次為 RGBA ,

– RGB 為 1 是表示全部 0 表示沒有,例如:– R=1 G=0 B=0 表示全紅。– A 值 1 表示不透明, 0 表示全透明。所以若 A=0 ,就完全

看不到這個 pixel tester 。

Page 26: Pixel Test

設定的方塊內畫一個圓 ( 畫一個圓 ) , 2.0f, 20.f 表示內縮 2.0 ,因此 size 少了 4.0 ,所以 SIDELENGTH - 4.0f ,從 (2.0, 2.0) 開始,直徑 SIDELENGTH - 4.0f 。› CGRect limits = CGRectMake(2.0f, 2.0f,

SIDELENGTH - 4.0f, SIDELENGTH - 4.0f);› CGPathAddEllipseInRect(path, NULL,

limits);› CGContextAddPath(context, path);

Page 27: Pixel Test

CGContextMoveToPoint(context, 0.0f, SIDELENGTH/2.0f);CGContextAddLineToPoint(context, (SIDELENGTH/2.0f) - 2.0f,

SIDELENGTH/2.0f);CGContextMoveToPoint(context, (SIDELENGTH /2.0f) + 2.0f,

SIDELENGTH/2.0f);CGContextAddLineToPoint(context, SIDELENGTH,

SIDELENGTH/2.0f);CGContextMoveToPoint(context, SIDELENGTH/2.0f, 0.0f);CGContextAddLineToPoint(context, SIDELENGTH/2.0f,

(SIDELENGTH / 2.0f) - 2.0f);CGContextMoveToPoint(context, SIDELENGTH/2.0f,

SIDELENGTH);CGContextAddLineToPoint(context, SIDELENGTH/2.0f,

(SIDELENGTH / 2.0f) + 2.0f);

CGContextStrokePath(context);CFRelease(path);

Page 28: Pixel Test

CGContextMoveToPoint :在 CGContext 內, 指定一點為 (0, SIDELENGTH/2.0f) = ( 0, 20 )

CGContextAddLineToPoint :在 CGContext 內,從前一點 (0, 20) 畫一條線到 ( ( SIDELENGTH/2.0f ) - 2.0f, SIDELENGTH/2.0f ) = (18, 20) 。

CGContextMoveToPoint : 指定一點為( (SIDELENGTH/2.0f) + 2.0f, SIDELENGTH/2.0f )= ( 22 , 20 ) 。也就是離上面 (18, 20) 向右四個點,如此中間留了一個 4 點的空間。

CGContextAddLineToPoint :在 CGContext 內,從前一點 (22, 20) 畫一條線到 ( ( SIDELENGTH, SIDELENGTH/2.0f ) = (40, 20) 。至此, pixel tester crossHair的中間橫線畫好了。

Page 29: Pixel Test

Show color space in R, G, and B Hand in: due 2010/12/02, 00:00 [email protected] 以組別學號姓名為檔名來繳報告

Page 30: Pixel Test