아이폰 어플리케이션에서 그림을 그리려면 UIView 객체를 설정하고 drawRect: 메서드를 구현해야 한다. view 객체는 drawRect: 메서드를 호출하기 전에 드로잉 환경을 자동으로 구성해 놓는다. 따라서 아이폰에서는 바로 그리기를 시작할 수 있다. 자동으로 만들어진 그래픽스 컨텍스트를 얻기 위해서 UIKit 함수인 UIGraphicsGetCurrentContext 함수를 호출한다. 얻은 그래픽스 컨텍스트의 상태를 저장하고 복귀하는 것도 UIGraphicsPushContext / UIGraphicsPopContext 함수로 가능하다.
뷰 이외에 다른 곳에 그림을 그리고자 할 때 커스텀 그래픽스 컨텍스트 객체를 생성할 수 있다. 컨텍스트를 생성하기 위해서 CGBitmapContextCreate 또는 CGPDFContextCreate 류의 함수를 사용한다. 컨텍스트를 생성한 후에는 컨텍스트를 드로잉 함수에 전달하여 그리기를 할 수 있다.
아이폰에서 주의할 것은 커스텀 컨텍스트를 생성했을 때 이 컨텍스트의 좌표계가 아이폰OS에서 사용하는 기본 좌표계와 다르다는 것이다. 좌표계의 원점이 좌상측이 아니라 좌하측이며 y 좌표는 위쪽이 + 값이 된다. 따라서 y값을 뒤집어야 하는 변환(플립핑)이 필요하다. 이 것은 CTM의 y축 값에 -1 을 곱하고 원점을 좌하측에서 좌상측으로 이동해야 한다.
만 약 CGImageRef 를 감싸고 있는 UIImage를 사용한다면 원점 변환을 할 필요는 없다. UIImage 가 내부에서 수행한다.
박스그리기
- (void)drawRect:(CGRect)rect
{
//컨텍스트 얻기
CGContextRef context = UIGraphicsGetCurrentContext();
//박스 그리기
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake(0, 0, 200, 100));
CGContextSetRGBFillColor(context, 0, 0, 1, 0.5);
CGContextFillRect(context, CGRectMake(0, 0, 100, 200));
}
{
//컨텍스트 얻기
CGContextRef context = UIGraphicsGetCurrentContext();
//박스 그리기
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake(0, 0, 200, 100));
CGContextSetRGBFillColor(context, 0, 0, 1, 0.5);
CGContextFillRect(context, CGRectMake(0, 0, 100, 200));
}
좌표계 변경
- (void)drawRect:(CGRect)rect
{
//컨텍스트 얻기
CGContextRef context = UIGraphicsGetCurrentContext();
//원점 좌표계 이동
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//박스 그리기
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake(0, 0, 200, 100));
CGContextSetRGBFillColor(context, 0, 0, 1, 0.5);
CGContextFillRect(context, CGRectMake(0, 0, 100, 200));
}
{
//컨텍스트 얻기
CGContextRef context = UIGraphicsGetCurrentContext();
//원점 좌표계 이동
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//박스 그리기
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake(0, 0, 200, 100));
CGContextSetRGBFillColor(context, 0, 0, 1, 0.5);
CGContextFillRect(context, CGRectMake(0, 0, 100, 200));
}
비트맵컨텍스트 만들기
/**
너비와 높이를 갖는 비트맵컨텍스트를 만들어 반환한다.
*/
CGContextRef createBitmapContext(int pixelsWide, int pixelsHigh)
{
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void *bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (pixelsWide * 4); //RGBA8
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
//CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
//은 아이폰에서 사용 불가
colorSpace = CGColorSpaceCreateDeviceRGB();
bitmapData = malloc(bitmapByteCount);
if(bitmapData == NULL)
{
NSLog(@"Memory not allocated!");
return NULL;
}
context = CGBitmapContextCreate(
bitmapData,
pixelsWide,
pixelsHigh,
8, //bits per color component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
if(context == NULL)
{
free(bitmapData);
NSLog(@"Context not created!");
return NULL;
}
CGColorSpaceRelease(colorSpace);
return context;
}
- (void)drawRect:(CGRect)rect
{
//비트맵 컨텍스트 얻기
CGContextRef bitmapContext = createBitmapContext(320, 460);
//원점 좌표계 이동
CGContextTranslateCTM(bitmapContext, 0, self.bounds.size.height);
CGContextScaleCTM(bitmapContext, 1.0, -1.0);
//박스 그리기
CGContextSetRGBFillColor(bitmapContext, 1, 0, 0, 1);
CGContextFillRect(bitmapContext, CGRectMake(0, 0, 200, 100));
CGContextSetRGBFillColor(bitmapContext, 0, 0, 1, 0.5);
CGContextFillRect(bitmapContext, CGRectMake(0, 0, 100, 200));
//비트맵을 이미지로 변경(렌더링)하기
CGImageRef bitmapImage = CGBitmapContextCreateImage(bitmapContext);
//이미지를 뷰에 그리기
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, CGRectMake(0, 0, 320, 460), bitmapImage);
//자원메모리 해지하기
char *bitmapData = CGBitmapContextGetData(bitmapContext);
if(bitmapData)
free(bitmapData);
CGContextRelease(bitmapContext);
CGImageRelease(bitmapImage);
}
너비와 높이를 갖는 비트맵컨텍스트를 만들어 반환한다.
*/
CGContextRef createBitmapContext(int pixelsWide, int pixelsHigh)
{
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void *bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (pixelsWide * 4); //RGBA8
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
//CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
//은 아이폰에서 사용 불가
colorSpace = CGColorSpaceCreateDeviceRGB();
bitmapData = malloc(bitmapByteCount);
if(bitmapData == NULL)
{
NSLog(@"Memory not allocated!");
return NULL;
}
context = CGBitmapContextCreate(
bitmapData,
pixelsWide,
pixelsHigh,
8, //bits per color component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
if(context == NULL)
{
free(bitmapData);
NSLog(@"Context not created!");
return NULL;
}
CGColorSpaceRelease(colorSpace);
return context;
}
- (void)drawRect:(CGRect)rect
{
//비트맵 컨텍스트 얻기
CGContextRef bitmapContext = createBitmapContext(320, 460);
//원점 좌표계 이동
CGContextTranslateCTM(bitmapContext, 0, self.bounds.size.height);
CGContextScaleCTM(bitmapContext, 1.0, -1.0);
//박스 그리기
CGContextSetRGBFillColor(bitmapContext, 1, 0, 0, 1);
CGContextFillRect(bitmapContext, CGRectMake(0, 0, 200, 100));
CGContextSetRGBFillColor(bitmapContext, 0, 0, 1, 0.5);
CGContextFillRect(bitmapContext, CGRectMake(0, 0, 100, 200));
//비트맵을 이미지로 변경(렌더링)하기
CGImageRef bitmapImage = CGBitmapContextCreateImage(bitmapContext);
//이미지를 뷰에 그리기
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, CGRectMake(0, 0, 320, 460), bitmapImage);
//자원메모리 해지하기
char *bitmapData = CGBitmapContextGetData(bitmapContext);
if(bitmapData)
free(bitmapData);
CGContextRelease(bitmapContext);
CGImageRelease(bitmapImage);
}
안티앨리어싱
컨텍스트의 그래픽스 상태로 CGContextSetShouldAntialias(context, true or false); 함수로 설정을 켜거나 끈다.
'iOS개발팁' 카테고리의 다른 글
SIO2와 Blender를 만나다. (2) | 2010.06.14 |
---|---|
아이폰, 사용가능한 장치 확인하기. (2) | 2010.06.14 |
쿼츠2D 튜토리얼...1 (0) | 2010.05.18 |
맥에서 화면 캡쳐하기 (0) | 2010.05.12 |
테두리가 둥근 UITextView 만들기. (0) | 2010.05.10 |