은행권에서 요구가 있어 24bitBMP를 만들 일이 있었다.
원래 우리가 사진을 찍으면 RGBA 각각 8bit씩 32bit의 사진이 나온다.
여기에서 A값만 날리면 24bit RGB데이터가 나오고
여기 위에다가 BMP헤더만 붙이면 되는 아주 간단한(?) 일이 었다.
간단하긴 개뿔 내가 무슨 BMP헤더를 잘 아나 이미지를 많이 다뤄봤나...
그래서 만듬
작업하면서 계속 안돼길래
16진수로 계속 확인했던건 안비밀
typedef struct s_bitmap_header {
// Bitmap file header
UInt16 fileType;
UInt32 fileSize;
UInt16 reserved1;
UInt16 reserved2;
UInt32 bitmapOffset;
// DIB Header
UInt32 headerSize;
UInt32 width;
UInt32 height;
UInt16 colorPlanes;
UInt16 bitsPerPixel;
UInt32 compression;
UInt32 bitmapSize;
UInt32 horizontalResolution;
UInt32 verticalResolution;
UInt32 colorsUsed;
UInt32 colorsImportant;
} t_bitmap_header;
// 함수 사용
+ (NSMutableData *)convertTo24BMPWithImage:(UIImage *)image {
if (image == nil || image.size.width <= 0 || image.size.height <= 0) {
return nil;
}
NSData *pixelData = (__bridge_transfer NSData *)CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
unsigned char *pixelBytes = (unsigned char *)[pixelData bytes]; //이미지의 byte수
int width = (int)CGImageGetWidth(image.CGImage);
int height = (int)CGImageGetHeight(image.CGImage);
// 24 bit RGB변환
int rgb24DataLen = width * height * 3;
Byte *rgb24Data = malloc(rgb24DataLen * sizeof(Byte));
if (rgb24Data == NULL)
return nil;
for (int j = 0; j < height; ++j) {
unsigned char * src = pixelBytes + j * width * 4;
unsigned char * dst = rgb24Data + j * width * 3;
for (int i = 0; i< width; ++i) {
*(dst) = *(src+2);
*(dst+1) = *(src+1);
*(dst+2) = *(src);
dst+=3;
src+=4;
}
}
pixelBytes = nil;
// 이미지 패딩 값 계산
Byte *dummyBytesPerRow = nil;
BOOL hasDummy = NO;
int BYTE_PER_PIXEL = 3;
int BMP_WIDTH_OF_TIMES = 4;
int rowWidthInBytes = BYTE_PER_PIXEL * width;
int byteLength = (BMP_WIDTH_OF_TIMES - (rowWidthInBytes % BMP_WIDTH_OF_TIMES));
if(rowWidthInBytes % BMP_WIDTH_OF_TIMES > 0) {
hasDummy = YES;
dummyBytesPerRow = malloc(byteLength * sizeof(Byte));
for(int i=0;i<byteLength; i++) {
dummyBytesPerRow[i] = (Byte)0xFF;
}
}
// BMP 헤더 작성 (해당 내용은 위키의 bmp파일 포멧 참조)
t_bitmap_header header;
int imageSize = (rowWidthInBytes+(hasDummy?byteLength:0)) * height;
int imageDataOffset = 0x36;
int fileSize = imageSize + imageDataOffset;
header.fileType = 0x4D42; // BM
header.fileSize = fileSize;
header.reserved1 = 0x0000;
header.reserved2 = 0x0000;
header.bitmapOffset = 0x00000036;
header.headerSize = 0x00000028;
header.width = (hasDummy?(byteLength==3?1:0):0)+width;
header.height = height;
header.colorPlanes = 0x0001;
header.bitsPerPixel = 0x0018;
header.compression = 0x00000000;
header.bitmapSize = imageSize;
header.horizontalResolution = 0x00000000;
header.verticalResolution = 0x00000000;
header.colorsUsed = 0x00000000;
header.colorsImportant = 0x00000000;
// Data에 BMP 헤더 작성하기
NSMutableData* bmpData = [[NSMutableData alloc] init];
[bmpData appendBytes:&(header.fileType) length:sizeof(UInt16)];
[bmpData appendBytes:&(header.fileSize) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.reserved1) length:sizeof(UInt16)];
[bmpData appendBytes:&(header.reserved2) length:sizeof(UInt16)];
[bmpData appendBytes:&(header.bitmapOffset) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.headerSize) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.width) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.height) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.colorPlanes) length:sizeof(UInt16)];
[bmpData appendBytes:&(header.bitsPerPixel) length:sizeof(UInt16)];
[bmpData appendBytes:&(header.compression) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.bitmapSize) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.horizontalResolution) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.verticalResolution) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.colorsUsed) length:sizeof(UInt32)];
[bmpData appendBytes:&(header.colorsImportant) length:sizeof(UInt32)];
// 24bit RGB값에 패딩 값 추가하기
Byte *pData = malloc(fileSize * sizeof(Byte));
Byte *pRawData = rgb24Data;
unsigned long dwLine=((((width * 24) + 31) &~ 31) >> 3);
if (pData) {
int i=0;
long lCount=3*width*height;
for(lCount-=width*3; lCount > 0; lCount-=width*3) {
memcpy(&pData[i], &pRawData[lCount], width*3);
if (hasDummy) {
memcpy(&pData[i], dummyBytesPerRow, byteLength);
}
i+=(long)dwLine;
}
}
// 패딩 값이 추가된 24bit RGB데이터를 NSData로
NSData *rawData = [[NSData alloc] initWithBytes:pData length:imageSize];
[bmpData appendData:rawData]; // 헤더 데이터에 24bit RGB 데이터 추가하기
if (hasDummy)
free(dummyBytesPerRow);
free(rgb24Data);
free(pData);
return bmpData;
}
'프로그래밍 > iOS' 카테고리의 다른 글
[iOS] 시스템 루트 키체인을 수정할 수 없습니다. (0) | 2015.10.26 |
---|---|
[iOS] 현재 시뮬레이터인지 단말인지 확인하는 코드 (0) | 2015.10.21 |
[iOS] 설정화면으로 바로 가기 (0) | 2015.10.16 |
[iOS] 엔터프라이즈 배포 (0) | 2015.09.30 |
[iOS] UIImage Resize (0) | 2015.09.14 |