我試圖用libtiff寫一個UIImage作爲tiff。問題是,儘管我將它寫爲每像素1位,但當我預計更像100k或更少的內容時,這些文件仍在2-5MB範圍內出現。如何在iOS上使用libtiff編寫1bpp tiff?
這是我得到的。
- (void) convertUIImage:(UIImage *)uiImage toTiff:(NSString *)file withThreshold:(float)threshold {
TIFF *tiff;
if ((tiff = TIFFOpen([file UTF8String], "w")) == NULL) {
[[[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Unable to write to file %@.", file] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show];
return;
}
CGImageRef image = [uiImage CGImage];
CGDataProviderRef provider = CGImageGetDataProvider(image);
CFDataRef pixelData = CGDataProviderCopyData(provider);
unsigned char *buffer = (unsigned char *)CFDataGetBytePtr(pixelData);
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(image);
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image);
size_t compBits = CGImageGetBitsPerComponent(image);
size_t pixelBits = CGImageGetBitsPerPixel(image);
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
NSLog(@"bitmapInfo=%d, alphaInfo=%d, pixelBits=%lu, compBits=%lu, width=%lu, height=%lu", bitmapInfo, alphaInfo, pixelBits, compBits, width, height);
TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
TIFFSetField(tiff, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tiff, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tiff, TIFFTAG_XRESOLUTION, 200.0);
TIFFSetField(tiff, TIFFTAG_YRESOLUTION, 200.0);
TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
unsigned char red, green, blue, gray, bite;
unsigned char *line = (unsigned char *)_TIFFmalloc(width/8);
unsigned long pos;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pos = y * width * 4 + x * 4; // multiplying by four because each pixel is represented by four bytes
red = buffer[ pos ];
green = buffer[ pos + 1 ];
blue = buffer[ pos + 2 ];
gray = .3 * red + .59 * green + .11 * blue; // http://answers.yahoo.com/question/index?qid=20100608031814AAeBHPU
bite = line[x/8];
bite = bite << 1;
if (gray > threshold) bite = bite | 1;
// NSLog(@"y=%d, x=%d, byte=%d, red=%d, green=%d, blue=%d, gray=%d, before=%@, after=%@", y, x, x/8, red, green, blue, gray, [self bitStringForChar:line[x/8]], [self bitStringForChar:bite]);
line[x/8] = bite;
}
TIFFWriteEncodedStrip(tiff, y, line, width);
}
// Close the file and free buffer
TIFFClose(tiff);
if (line) _TIFFfree(line);
if (pixelData) CFRelease(pixelData);
}
第一的NSLog行說:
bitmapInfo=5, alphaInfo=5, pixelBits=32, compBits=8, width=3264, height=2448
我也有一個版本,這個項目使用GPUImage代替。通過這個,我可以將相同的圖像下載到大約13萬像素的8位PNG。如果我將該PNG發送到PNG優化器網站,他們可以將其降至25k左右。如果有人能告訴我如何編寫從我的GPUImage過濾器生成的1位PNG,我會放棄tiff。
謝謝!
哇,謝謝。明天我會試試這個。我目前使用GPUImage的自適應閾值過濾器。它的工作正常,但圖像的純黑色區域變爲白色。我會在TIFF上回復你。 – bmauter
@bmauter事實上,我用定製的自適應閾值算法進行雙色調轉換。我使用OpenCV來操縱圖像。一旦我有了雙色調圖像,我在將圖像上傳到服務器之前使用tiff轉換。這裏的關鍵是轉換爲雙色調,並且沒有自適應閾值算法,結果可能很差。讓我知道TIFF算法是否適合您。 –
@bmauter您是否嘗試過我建議的TIFF解決方案? –