How to create CGDataProviderRef from RGB

Discussion in 'Mac Programming' started by dearvivekkumar, Jan 7, 2011.

  1. dearvivekkumar macrumors newbie

    Joined:
    Jan 3, 2011
    Location:
    New Delhi, India
    #1
    Code:
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, [COLOR="Red"]quadBytes[/COLOR], rowBytes * height, NULL);
    I am not getting how to create DataProvide if I have RBG value. RGB value is in structure like below. As i am porting from window os to mac.

    Code:
    typedef struct tagRGBQUAD { 
    	unsigned char  rgbBlue;
    	unsigned char  rgbGreen;
    	unsigned char  rgbRed;
    	unsigned char  rgbReserved;
    } RGBQUAD;
    
    please guide me. Any clue will be highly appreciated.

    Thanks.
     
  2. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #2
    I've never used that function, but I suspect it is looking for an array based on the next argument to the size.

    So the struct is close, (although the last byte should probably be alpha) and may compile with a size of 1.
     
  3. dearvivekkumar thread starter macrumors newbie

    Joined:
    Jan 3, 2011
    Location:
    New Delhi, India
    #3
    Thanks for your reply

    Yeah i am passing quadBytes which is containg the channel pixel data is that what required or something else. If yes, then how would i arrange my pixel data for passing to the CGDataProvider.
     
  4. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    I've never done this, but I don't think you'll be able get a data provider for raw bitmap data like this. As I understand it, one of things CGDataProviderCreateWithData is going to do is analyse the data to try to determine it's format (JPEG, PNG, TIFF, etc.).

    Again I've never done this, but it sounds to me you might need to create a custom data provider via CGDataProviderCreateDirect or CGDataProviderCreateSequential. Or perhaps you could wrap your raw data in an image container format first (TIFF would probably be the easiest) and then use CGDataProviderCreateWithData.

    The Quartz 2D Programming Guide in the documentation as chapters on data management and bitmap images. Perhaps these might shed some light.

    However if your ultimate goal is just to display the bitmap, perhaps a custom view which draw the bitmap might be the easiest approach.
     
  5. dearvivekkumar thread starter macrumors newbie

    Joined:
    Jan 3, 2011
    Location:
    New Delhi, India
    #5
    @jiminaus

    Actually i am very new to image graphics type programming. I am trying to create a photoshop plug-in, which i have to export every layers in a corresponding image file.
    For that I have gathered the layer data in structure I have posted in my earlier post and that is working well and nice in win os as i had first tried in win os.
    Now i am doing the same for mac os using carbon framework and definitely Quartz, so as for now i have the layer data which is RGB and alpha components for which i wants to create a image for that i need to create a pixel in that image.
    I have read the quartz 2d programming documentation, i that i have to provide the color spaces for data i need to provide the data which i created through the data provider and as it to opaque i am not getting how the pixel data(ie the RGB layer components and the alpha components) is created with the data provider.

    so here i am stuck how would i provide the data which i have collected in the structure (named rgbQuard which i have mentioned in my earlier post) form???
    If am wrong somewhere is my process of creating the data advice will be greatly appreciated.

    Thanks​
     
  6. jiminaus, Jan 9, 2011
    Last edited: Jan 9, 2011

    jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #6
    The code below creates a CGImage from your raw layer data and then outputs it to an uncompressed TIFF file.

    You can specify many options for the output file. Have a look at the Image I/O programming guide and the CGImageProperties reference.

    You can output to a different type of file by changing the image type in the call to CGImageDestinationCreateWithURL. A list of pre-declared UTI's is in the Uniform Type Identifiers reference.

    Code:
    #include <CoreFoundation/CoreFoundation.h>
    #include <ApplicationServices/ApplicationServices.h>
    #include <assert.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct tagRGBQUAD {
    	unsigned char rgbBlue;
    	unsigned char rgbGreen;
    	unsigned char rgbRed;
    	unsigned char rgbReserved;
    } RGBQUAD;
    
    RGBQUAD *makeLayer(size_t xSize, size_t ySize) {
    	assert(ySize % 3 == 0);        /* This code only works when ySize is a multiple of 3 */
    	assert(sizeof(RGBQUAD) == 4);  /* And when sizeof(RGBQUAD) is 4 */
    	RGBQUAD *layer = malloc(sizeof(RGBQUAD) * xSize * ySize);
    	const size_t rowSize = sizeof(RGBQUAD) * xSize;
    	RGBQUAD *row = malloc(rowSize);
    	const size_t bandSize = ySize / 3;
    	size_t y = 0;
    	/* Make a band of blue */
    	memset(row, 0, sizeof(RGBQUAD));
    	row->rgbBlue = 255;
    	memset_pattern4(row + 1, row, rowSize - sizeof(RGBQUAD));
    	for (; y < bandSize; ++y) {
    		memcpy(layer + (y * xSize), row, sizeof(RGBQUAD) * xSize);
    	}
    	/* Make a band of green */
    	memset(row, 0, sizeof(RGBQUAD));
    	row->rgbGreen = 255;
    	memset_pattern4(row + 1, row, rowSize - sizeof(RGBQUAD));
    	for (; y < bandSize * 2; ++y) {
    		memcpy(layer + (y * xSize), row, sizeof(RGBQUAD) * xSize);
    	}
    	/* Make a band of red */
    	memset(row, 0, sizeof(RGBQUAD));
    	row->rgbRed = 255;
    	memset_pattern4(row + 1, row, rowSize - sizeof(RGBQUAD));
    	for (; y < ySize; ++y) {
    		memcpy(layer + (y * xSize), row, sizeof(RGBQUAD) * xSize);
    	}	
    	free(row);
    	return layer;
    }
    
    CGImageRef makeImageFromLayer(RGBQUAD *layer, size_t xSize, size_t ySize) {
    	CGDataProviderRef provider =
    		CGDataProviderCreateWithData(NULL, layer, sizeof(RGBQUAD) * xSize * ySize, NULL);
    	CGColorSpaceRef colorSpace = 
    		CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    	CGImageRef image =
    		CGImageCreate(xSize, ySize, 8, 32, sizeof(RGBQUAD) * xSize,
                                  colorSpace, kCGBitmapByteOrderDefault, provider,
                                  NULL, FALSE, kCGRenderingIntentDefault);
    	CFRelease(provider);
    	CFRelease(colorSpace);
    	return image;
    }
    
    void writeImageToPath(CGImageRef layerImage, const char* path) {
    	CFStringRef pathString =
    		CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
    	CFURLRef url =
    		CFURLCreateWithFileSystemPath(NULL, pathString, kCFURLPOSIXPathStyle, false);	
    
    	CFDictionaryRef options =
    		CFDictionaryCreate(NULL, NULL, NULL, 0, NULL, NULL);
    	
    	CGImageDestinationRef imageDest =
    		CGImageDestinationCreateWithURL(url, kUTTypeTIFF, 1, NULL);
    	CGImageDestinationAddImage(imageDest, layerImage, options);
    	CGImageDestinationFinalize(imageDest);
    	
    	CFRelease(imageDest);
    	CFRelease(options);
    	CFRelease(url);
    	CFRelease(pathString);
    }
    
    int main (int argc, const char *argv[]) {	
    	const size_t xSize = 96;
    	const size_t ySize = 96;
    	const char *outputPath = "/tmp/a.tiff";
    	RGBQUAD *layer = makeLayer(xSize, ySize);
    	CGImageRef layerImage = makeImageFromLayer(layer, xSize, ySize);
    	writeImageToPath(layerImage, outputPath);
    	CFRelease(layerImage);
    	free(layer);
        return 0;	
    }
    
     
  7. dearvivekkumar thread starter macrumors newbie

    Joined:
    Jan 3, 2011
    Location:
    New Delhi, India

Share This Page