16-bit to 8-bit image conversion

Discussion in 'Mac Programming' started by madart9, Nov 3, 2009.

  1. macrumors newbie

    Nov 3, 2009
    I'm trying to make a scientific program that works with 16-bit tiff directories (of images) but displays the images as 8-bit. I also want to allow for the adjusting of the white and black levels. As of now, I'm reading in the 16-bit tiff, getting out the data, editing it, and then loading it into a new image. However, I can't figure out how to set the IKImageView settings correctly. It displays my 16-bit tiff as two (almost) duplicate versions in the top left quadrant and top right quadrant with black in the bottom quadrants. I suspect this is a problem with the number of bytes per row and bits per component in my ikimageview output, but I can't figure out how to edit the NSDictionary metadata.

    		if ([[(NSDictionary *)imageProperties valueForKey:(NSString *)kCGImagePropertyDepth] intValue] == 16) {
    			CGImageRef imR = CGImageSourceCreateImageAtIndex(imageSource, index, NULL);
    			CFDataRef pixData = CGDataProviderCopyData(CGImageGetDataProvider(imR));
    			UInt16 * pixels = (UInt16 *) CFDataGetBytePtr(pixData);
    			UInt8 * eightPix = (UInt8 *) CFDataGetBytePtr(pixData);
    			int plen = CFDataGetLength(pixData);
    			int i;
    			for (i = 0; i < heightInPixels*widthInPixels; i++) {
    				eightPix[i] = (UInt8) pixels[i];
    			CGContextRef imcont = CGBitmapContextCreate(pixels, CGImageGetWidth(imR), CGImageGetHeight(imR), CGImageGetBitsPerComponent(imR), CGImageGetBytesPerRow(imR), CGImageGetColorSpace(imR), CGImageGetBitmapInfo(imR));
    						CGImageRef outR = CGBitmapContextCreateImage(imcont);
    			CFMutableDictionaryRef outProperties = CFDictionaryCreateMutableCopy(NULL, 0, imageProperties);
    //			const UInt8 * outVal;
    //			outVal = 8;
    //			NSString * outVal = (NSString *) 8;
    //			CFDictionarySetValue(outProperties, kCGImagePropertyDepth, outVal);
    //			outVal = (NSString *) CGImageGetWidth(imR);
    //			CFDictionarySetValue(outProperties, kCGImagePropertyDepth, outVal);
    			[imageView setImage: outR imageProperties: (NSDictionary *)outProperties];
  2. macrumors 65816


    Apr 19, 2007
    I don't know about what you're doing (over my head :p). The simplest way I can think of to load and convert images is through SDL/SDL_image. Load the image using Load_IMG() into an SDL surface, then convert it to the format you want. There are tutorials around the interwebs for converting an SDL_surface into something OpenGL can read, for instance.
  3. macrumors regular

    Oct 13, 2008
    Achewood, CA
    Use CGContextDrawImage() to draw your 16-bit-per-channel image into an 8-bit-per-channel CGBitmapContext. It should handle the conversion automatically.

    Core Image might help as well.

    Don't go mucking about with SDL. The functionality you need is in the OS.
  4. macrumors 6502

    Apr 24, 2008
    Wait, your "pixels" and "eightPix" are pointing to the same memory - you are trying to convert the image data in-place. That won't work. Also, converting 16-bit images to 8-bit images can't be done with a simple cast for each pixel. Instead, you divide each 16-bit pixel value by 257. (Someone will try to correct me here and say it should be 256, but it's not a typo.)

    But perhaps you don't really need to do this conversion at all (like autorelease said), since I believe you can display 16-bit TIFF images just fine on MacOS X. Why exactly do you want to convert it to 8-bit yourself?

Share This Page