Example #1
0
void computeMD5HashStringForContext(CGContextRef bitmapContext, char hashString[33])
{
    ASSERT(CGBitmapContextGetBitsPerPixel(bitmapContext) == 32); // ImageDiff assumes 32 bit RGBA, we must as well.
    size_t pixelsHigh = CGBitmapContextGetHeight(bitmapContext);
    size_t pixelsWide = CGBitmapContextGetWidth(bitmapContext);
    size_t bytesPerRow = CGBitmapContextGetBytesPerRow(bitmapContext);
    
    // We need to swap the bytes to ensure consistent hashes independently of endianness
    MD5 md5;
    unsigned char* bitmapData = static_cast<unsigned char*>(CGBitmapContextGetData(bitmapContext));
#if PLATFORM(MAC)
    if ((CGBitmapContextGetBitmapInfo(bitmapContext) & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Big) {
        for (unsigned row = 0; row < pixelsHigh; row++) {
            Vector<uint8_t> buffer(4 * pixelsWide);
            for (unsigned column = 0; column < pixelsWide; column++)
                buffer[column] = OSReadLittleInt32(bitmapData, 4 * column);
            md5.addBytes(buffer);
            bitmapData += bytesPerRow;
        }
    } else
#endif
    {
        for (unsigned row = 0; row < pixelsHigh; row++) {
            md5.addBytes(bitmapData, 4 * pixelsWide);
            bitmapData += bytesPerRow;
        }
    }

    Vector<uint8_t, 16> hash;
    md5.checksum(hash);
    
    hashString[0] = '\0';
    for (int i = 0; i < 16; i++)
        snprintf(hashString, 33, "%s%02x", hashString, hash[i]);
}
Example #2
0
static void getMD5HashStringForBitmap(CGContextRef bitmap, char string[33])
{
    MD5_CTX md5Context;
    unsigned char hash[16];

    size_t bitsPerPixel = CGBitmapContextGetBitsPerPixel(bitmap);
    ASSERT(bitsPerPixel == 32); // ImageDiff assumes 32 bit RGBA, we must as well.
    size_t bytesPerPixel = bitsPerPixel / 8;
    size_t pixelsHigh = CGBitmapContextGetHeight(bitmap);
    size_t pixelsWide = CGBitmapContextGetWidth(bitmap);
    size_t bytesPerRow = CGBitmapContextGetBytesPerRow(bitmap);
    ASSERT(bytesPerRow >= (pixelsWide * bytesPerPixel));

    MD5_Init(&md5Context);
    unsigned char* bitmapData = static_cast<unsigned char*>(CGBitmapContextGetData(bitmap));
    for (unsigned row = 0; row < pixelsHigh; row++) {
        MD5_Update(&md5Context, bitmapData, static_cast<unsigned>(pixelsWide * bytesPerPixel));
        bitmapData += bytesPerRow;
    }
    MD5_Final(hash, &md5Context);

    string[0] = '\0';
    for (int i = 0; i < 16; i++)
        snprintf(string, 33, "%s%02x", string, hash[i]);
}
/*	createMaskFromAlphaOnlyContext creates a CGImageRef
	from an alpha-only bitmap context. Calling this routine
	transfers 'ownership' of the raster data in the bitmap 
	context, to the image. If the image can't be created, this 
	routine frees the memory associated with the raster. 
*/
static CGImageRef createMaskFromAlphaOnlyContext(CGContextRef alphaContext)
{
    CGImageRef mask;
	unsigned char *rasterData = CGBitmapContextGetData(alphaContext);
    size_t imageDataSize = CGBitmapContextGetBytesPerRow(alphaContext)*
								CGBitmapContextGetHeight(alphaContext);
    float invertDecode[] = { 1. , 0. };
        
	if(rasterData == NULL){
		fprintf(stderr, "Context is not a bitmap context!\n");
		return NULL;
	}

    // Create the data provider from the image data.
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, 
					    rasterData,
					    imageDataSize,
					    releaseBitmapContextImageData);

    if(dataProvider == NULL){
		// Must free the memory if the data provider couldn't be created
		// since this routine now owns it.
		free(rasterData);
		fprintf(stderr, "Couldn't create data provider!\n");
		return NULL;
    }
    mask = CGImageMaskCreate(CGBitmapContextGetWidth(alphaContext), 
			  CGBitmapContextGetHeight(alphaContext), 
			  CGBitmapContextGetBitsPerComponent(alphaContext), 
			  CGBitmapContextGetBitsPerPixel(alphaContext), 
			  CGBitmapContextGetBytesPerRow(alphaContext), 
			  dataProvider,
	// The decode is an inverted decode since a mask has the opposite
	// sense than alpha, i.e. 0 in a mask paints 100% and 1 in a mask
	// paints nothing.
			  invertDecode,
			  true);

    // Release the data provider since the mask retains it.
    CGDataProviderRelease(dataProvider);

    if(mask == NULL){
		fprintf(stderr, "Couldn't create image mask!\n");
		return NULL;
    }
    return mask;
}
/*	createImageFromBitmapContext creates a CGImageRef
	from a bitmap context. Calling this routine
	transfers 'ownership' of the raster data
	in the bitmap context, to the image. If the
	image can't be created, this routine frees
	the memory associated with the raster. 
*/
CGImageRef createImageFromBitmapContext(CGContextRef c)
{
    CGImageRef image;
	unsigned char *rasterData = CGBitmapContextGetData(c);
    size_t imageDataSize = 
		CGBitmapContextGetBytesPerRow(c)*CGBitmapContextGetHeight(c);
	
	if(rasterData == NULL){
		fprintf(stderr, "Context is not a bitmap context!\n");
		return NULL;
	}
	
    // Create the data provider from the image data, using
	// the image releaser function releaseBitmapContextImageData.
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL,
					    rasterData,
					    imageDataSize,
					    releaseBitmapContextImageData);
    if(dataProvider == NULL){
		// Since this routine owns the raster memory, it must
		// free it if it can't create the data provider.
		free(rasterData);
		fprintf(stderr, "Couldn't create data provider!\n");
		return NULL;
    }
	// Now create the image. The parameters for the image closely match
	// the parameters of the bitmap context. This code uses a NULL
	// decode array and shouldInterpolate is true.
    image = CGImageCreate(CGBitmapContextGetWidth(c), 
			  CGBitmapContextGetHeight(c), 
			  CGBitmapContextGetBitsPerComponent(c), 
			  CGBitmapContextGetBitsPerPixel(c), 
			  CGBitmapContextGetBytesPerRow(c), 
			  CGBitmapContextGetColorSpace(c),
			  myCGContextGetBitmapInfo(c),
			  dataProvider,
			  NULL,
			  true,
			  kCGRenderingIntentDefault);
    // Release the data provider since the image retains it.
    CGDataProviderRelease(dataProvider);
    if(image == NULL){
		fprintf(stderr, "Couldn't create image!\n");
		return NULL;
    }
    return image;
}