From c196fe292eb28d20e2d21d639651bbafc78373f2 Mon Sep 17 00:00:00 2001 From: Peter Hull Date: Sat, 17 Feb 2024 13:36:48 +0000 Subject: [PATCH] Load images with CoreImage --- addons/image/macosx.m | 129 +++++++++++++----------------------------- 1 file changed, 40 insertions(+), 89 deletions(-) diff --git a/addons/image/macosx.m b/addons/image/macosx.m index 4a83408b07..8d5e0938b4 100644 --- a/addons/image/macosx.m +++ b/addons/image/macosx.m @@ -1,6 +1,6 @@ #import -#import -#import +#import +#import #include "allegro5/allegro.h" #include "allegro5/fshook.h" @@ -23,108 +23,60 @@ { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; ALLEGRO_BITMAP *bmp = NULL; - void *pixels = NULL; /* Note: buffer is now owned (and later freed) by the data object. */ - NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:buffer length:size]; - NSImage *image = [[NSImage alloc] initWithData:nsdata]; - [nsdata release]; - bool premul = !(flags & ALLEGRO_NO_PREMULTIPLIED_ALPHA); + NSData *nsdata = [NSData dataWithBytesNoCopy:buffer length:size]; + CIImage* image = [CIImage imageWithData:nsdata]; - if (!image) - goto done; - - /* Get the image representations */ - NSArray *reps = [image representations]; - NSImageRep *image_rep = [reps objectAtIndex: 0]; + BOOL premul = (flags & ALLEGRO_NO_PREMULTIPLIED_ALPHA) ? NO : YES; - if (!image_rep) { - [image release]; + if (!image) goto done; - } + NSNumber* value = [NSNumber numberWithBool:premul]; + NSDictionary* options = [NSDictionary dictionaryWithObject: value + forKey:kCIContextOutputPremultiplied]; + CIContext* context = [CIContext contextWithOptions:options]; /* Get the actual size in pixels from the representation */ - unsigned char *data[5]; - // TODO: We should check it really is a bitmap representation. - NSBitmapImageRep *bitmap_rep = (NSBitmapImageRep *)image_rep; - [bitmap_rep getBitmapDataPlanes:data]; - pixels = data[0]; - int w = [image_rep pixelsWide]; - int h = [image_rep pixelsHigh]; - int bits = [bitmap_rep bitsPerPixel]; - int samples = bits / 8; - ALLEGRO_DEBUG("Read image of size %dx%dx%d\n", w, h, bits); + + int w = [image extent].size.width; + int h = [image extent].size.height; + + ALLEGRO_DEBUG("Read image of size %dx%d\n", w, h); + uint8_t* surf = al_calloc(w*h*4, sizeof(uint8_t)); + [context render:image + toBitmap:surf + rowBytes:w*4 + bounds:CGRectMake(0,0,w,h) + format:kCIFormatRGBA8 colorSpace:nil]; /* Then create a bitmap out of the memory buffer. */ bmp = al_create_bitmap(w, h); if (bmp) { ALLEGRO_LOCKED_REGION *lock = al_lock_bitmap(bmp, - ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE, ALLEGRO_LOCK_WRITEONLY); - int i, j; - { - for (i = 0; i < h; i++) { - uint8_t *data_row = (uint8_t *) lock->data + lock->pitch * i; - uint8_t *source_row = (uint8_t *) pixels + w * samples * i; - if (samples == 4) { - if (premul) { - for (j = 0; j < w; j++) { - int r, g, b, a; - r = source_row[j * 4 + 0]; - g = source_row[j * 4 + 1]; - b = source_row[j * 4 + 2]; - a = source_row[j * 4 + 3]; - data_row[j * 4 + 0] = r * a / 255; - data_row[j * 4 + 1] = g * a / 255; - data_row[j * 4 + 2] = b * a / 255; - data_row[j * 4 + 3] = a; - } - } - else - memcpy(data_row, source_row, w * 4); - } - else if (samples == 3) { - for (j = 0; j < w; j++) { - data_row[j * 4 + 0] = source_row[j * 3 + 0]; - data_row[j * 4 + 1] = source_row[j * 3 + 1]; - data_row[j * 4 + 2] = source_row[j * 3 + 2]; - data_row[j * 4 + 3] = 255; - } - } - else if (samples == 2) { - for (j = 0; j < w; j++) { - int a = data_row[j * 4 + 3] = source_row[j * 2 + 1]; - if (!premul) - a = 255; - data_row[j * 4 + 0] = source_row[j * 2 + 0] * a / 255; - data_row[j * 4 + 1] = source_row[j * 2 + 0] * a / 255; - data_row[j * 4 + 2] = source_row[j * 2 + 0] * a / 255; - - } - } - else if (samples == 1) { - for (j = 0; j < w; j++) { - data_row[j * 4 + 0] = source_row[j]; - data_row[j * 4 + 1] = source_row[j]; - data_row[j * 4 + 2] = source_row[j]; - data_row[j * 4 + 3] = 255; - } - } - } + ALLEGRO_PIXEL_FORMAT_ABGR_8888, ALLEGRO_LOCK_WRITEONLY); + int j; + uint8_t* dest = (uint8_t*) lock->data; + uint8_t* src = surf; + for (j=0; jpitch; + src += w*4; } + al_unlock_bitmap(bmp); } + al_free(surf); - [image release]; done: [pool drain]; return bmp; } - static ALLEGRO_BITMAP *_al_osx_load_image_f(ALLEGRO_FILE *f, int flags) { ALLEGRO_BITMAP *bmp; ASSERT(f); - + int64_t size = al_fsize(f); if (size <= 0) { // TODO: Read from stream until we have the whole image @@ -170,7 +122,7 @@ bool _al_osx_save_image_f(ALLEGRO_FILE *f, const char *ident, ALLEGRO_BITMAP *bmp) { NSBitmapImageFileType type; - + if (!strcmp(ident, ".bmp")) { type = NSBMPFileType; } @@ -192,18 +144,18 @@ bool _al_osx_save_image_f(ALLEGRO_FILE *f, const char *ident, ALLEGRO_BITMAP *bm } NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - + NSImage *image = NSImageFromAllegroBitmap(bmp); NSArray *reps = [image representations]; NSData *nsdata = [NSBitmapImageRep representationOfImageRepsInArray: reps usingType: type properties: [NSDictionary dictionary]]; - + size_t size = (size_t)[nsdata length]; bool ret = al_fwrite(f, [nsdata bytes], size) == size; - + [image release]; [pool drain]; - + return ret; } @@ -280,9 +232,9 @@ bool _al_osx_register_image_loader(void) success |= al_register_bitmap_loader(s, _al_osx_load_image); success |= al_register_bitmap_loader_f(s, _al_osx_load_image_f); } - + char const *extensions[] = { ".tif", ".tiff", ".gif", ".png", ".jpg", ".jpeg", NULL }; - + for (i = 0; extensions[i]; i++) { ALLEGRO_DEBUG("Registering native saver for bitmap type %s\n", extensions[i]); success |= al_register_bitmap_saver(extensions[i], _al_osx_save_image); @@ -294,9 +246,8 @@ bool _al_osx_register_image_loader(void) success |= al_register_bitmap_saver_f(".png", _al_osx_save_png_f); success |= al_register_bitmap_saver_f(".jpg", _al_osx_save_jpg_f); success |= al_register_bitmap_saver_f(".jpeg", _al_osx_save_jpg_f); - + [pool drain]; return success; } -