From c882ec13df2d45af555091793034e4f43c978f27 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Nov 2009 07:39:07 +0000 Subject: [PATCH] Simplified image conversion code even more. The alpha channel is a goner... --- IMG_ImageIO.c | 83 +++++++++++++++++++++++---------------------------- IMG_UIImage.m | 83 +++++++++++++++++++++++---------------------------- 2 files changed, 76 insertions(+), 90 deletions(-) diff --git a/IMG_ImageIO.c b/IMG_ImageIO.c index 6423127a..2b2c5c41 100644 --- a/IMG_ImageIO.c +++ b/IMG_ImageIO.c @@ -227,70 +227,63 @@ static SDL_Surface* Create_SDL_Surface_From_CGImage(CGImageRef image_ref) * All this code should be scrutinized. */ - size_t the_width = CGImageGetWidth(image_ref); - size_t the_height = CGImageGetHeight(image_ref); - CGRect the_rect = {{0, 0}, {the_width, the_height}}; + size_t w = CGImageGetWidth(image_ref); + size_t h = CGImageGetHeight(image_ref); + CGRect rect = {{0, 0}, {w, h}}; + CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image_ref); size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); size_t bits_per_component = 8; - SDL_Surface* sdl_surface = NULL; + SDL_Surface* surface; + Uint32 Amask; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; - Uint32 Amask; - CGContextRef bitmap_context = NULL; - CGColorSpaceRef color_space = NULL; - CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); - - switch (bits_per_pixel) - { - case 32: - { - color_space = CGColorSpaceCreateDeviceRGB(); - //bitmap_info = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; /* ARGB */ - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; /* ARGB */ - - Amask = 0xFF000000; - Rmask = 0x00FF0000; - Gmask = 0x0000FF00; - Bmask = 0x000000FF; - - sdl_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, the_width, the_height, 32, Rmask, Gmask, Bmask, Amask); - break; - } - default: - { - color_space = CGColorSpaceCreateDeviceRGB(); - bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; /* XRGB */ - Amask = 0x00000000; - Rmask = 0x00FF0000; - Gmask = 0x0000FF00; - Bmask = 0x000000FF; - - sdl_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, the_width, the_height, 32, Rmask, Gmask, Bmask, Amask); - break; - } + CGContextRef bitmap_context; + CGBitmapInfo bitmap_info; + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + + if (alpha == kCGImageAlphaNone || + alpha == kCGImageAlphaNoneSkipFirst || + alpha == kCGImageAlphaNoneSkipLast) { + bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; /* XRGB */ + Amask = 0x00000000; + } else { + /* kCGImageAlphaFirst isn't supported */ + //bitmap_info = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; /* ARGB */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; /* ARGB */ + Amask = 0xFF000000; } - if (sdl_surface) + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, Rmask, Gmask, Bmask, Amask); + if (surface) { - // Sets up a context to be drawn to with sdl_surface->pixels as the area to be drawn to + // Sets up a context to be drawn to with surface->pixels as the area to be drawn to bitmap_context = CGBitmapContextCreate( - sdl_surface->pixels, - the_width, - the_height, + surface->pixels, + surface->w, + surface->h, bits_per_component, - sdl_surface->pitch, + surface->pitch, color_space, bitmap_info ); // Draws the image into the context's image_data - CGContextDrawImage(bitmap_context, the_rect, image_ref); + CGContextDrawImage(bitmap_context, rect, image_ref); CGContextRelease(bitmap_context); + + // FIXME: Reverse the premultiplied alpha + if ((bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst) { + // Errr, alpha premultiplication is lossy... + } } if (color_space) @@ -298,7 +291,7 @@ static SDL_Surface* Create_SDL_Surface_From_CGImage(CGImageRef image_ref) CGColorSpaceRelease(color_space); } - return sdl_surface; + return surface; } diff --git a/IMG_UIImage.m b/IMG_UIImage.m index b63ca827..40299249 100644 --- a/IMG_UIImage.m +++ b/IMG_UIImage.m @@ -22,70 +22,63 @@ * All this code should be scrutinized. */ - size_t the_width = CGImageGetWidth(image_ref); - size_t the_height = CGImageGetHeight(image_ref); - CGRect the_rect = {{0, 0}, {the_width, the_height}}; + size_t w = CGImageGetWidth(image_ref); + size_t h = CGImageGetHeight(image_ref); + CGRect rect = {{0, 0}, {w, h}}; + CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image_ref); size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); size_t bits_per_component = 8; - SDL_Surface* sdl_surface = NULL; + SDL_Surface* surface; + Uint32 Amask; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; - Uint32 Amask; - CGContextRef bitmap_context = NULL; - CGColorSpaceRef color_space = NULL; - CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); - - switch (bits_per_pixel) - { - case 32: - { - color_space = CGColorSpaceCreateDeviceRGB(); - //bitmap_info = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; /* ARGB */ - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; /* ARGB */ - - Amask = 0xFF000000; - Rmask = 0x00FF0000; - Gmask = 0x0000FF00; - Bmask = 0x000000FF; - - sdl_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, the_width, the_height, 32, Rmask, Gmask, Bmask, Amask); - break; - } - default: - { - color_space = CGColorSpaceCreateDeviceRGB(); - bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; /* XRGB */ - Amask = 0x00000000; - Rmask = 0x00FF0000; - Gmask = 0x0000FF00; - Bmask = 0x000000FF; - - sdl_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, the_width, the_height, 32, Rmask, Gmask, Bmask, Amask); - break; - } + CGContextRef bitmap_context; + CGBitmapInfo bitmap_info; + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + + if (alpha == kCGImageAlphaNone || + alpha == kCGImageAlphaNoneSkipFirst || + alpha == kCGImageAlphaNoneSkipLast) { + bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; /* XRGB */ + Amask = 0x00000000; + } else { + /* kCGImageAlphaFirst isn't supported */ + //bitmap_info = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; /* ARGB */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; /* ARGB */ + Amask = 0xFF000000; } - if (sdl_surface) + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, Rmask, Gmask, Bmask, Amask); + if (surface) { - // Sets up a context to be drawn to with sdl_surface->pixels as the area to be drawn to + // Sets up a context to be drawn to with surface->pixels as the area to be drawn to bitmap_context = CGBitmapContextCreate( - sdl_surface->pixels, - the_width, - the_height, + surface->pixels, + surface->w, + surface->h, bits_per_component, - sdl_surface->pitch, + surface->pitch, color_space, bitmap_info ); // Draws the image into the context's image_data - CGContextDrawImage(bitmap_context, the_rect, image_ref); + CGContextDrawImage(bitmap_context, rect, image_ref); CGContextRelease(bitmap_context); + + // FIXME: Reverse the premultiplied alpha + if ((bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst) { + // Errr, alpha premultiplication is lossy... + } } if (color_space) @@ -93,7 +86,7 @@ CGColorSpaceRelease(color_space); } - return sdl_surface; + return surface; } static SDL_Surface* LoadImageFromRWops(SDL_RWops* rw_ops, CFStringRef uti_string_hint)