#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#include "allegro5/allegro.h"
#include "allegro5/allegro_image.h"
#include "allegro5/internal/aintern_image.h"
#include "iio.h"
ALLEGRO_DEBUG_CHANNEL("image")
static ALLEGRO_BITMAP *really_load_image(char *buffer, int size, int flags)
{
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 dataWithBytesNoCopy:buffer length:size];
UIImage *uiimage = [UIImage imageWithData:nsdata];
int w = uiimage.size.width;
int h = uiimage.size.height;
bool premul = !(flags & ALLEGRO_NO_PREMULTIPLIED_ALPHA);
/* Now we need to draw the image into a memory buffer. */
pixels = al_malloc(w * h * 4);
CGFloat whitePoint[3] = {
1, 1, 1
};
CGFloat blackPoint[3] = {
0, 0, 0
};
CGFloat gamma[3] = {
2.2, 2.2, 2.2
};
CGFloat matrix[9] = {
1, 1, 1,
1, 1, 1,
1, 1, 1
};
/* This sets up a color space that results in identical values
* as the image data itself, which is the same as the standalone
* libpng loader
*/
CGColorSpaceRef cs =
CGColorSpaceCreateCalibratedRGB(
whitePoint, blackPoint, gamma, matrix
);
CGContextRef context = CGBitmapContextCreate(pixels, w, h, 8, w * 4,
cs, kCGImageAlphaPremultipliedLast);
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, (CGFloat)w, (CGFloat)h),
uiimage.CGImage);
CGContextRelease(context);
CGColorSpaceRelease(cs);
/* Then create a bitmap out of the memory buffer. */
bmp = al_create_bitmap(w, h);
if (!bmp) goto done;
ALLEGRO_LOCKED_REGION *lock = al_lock_bitmap(bmp,
ALLEGRO_PIXEL_FORMAT_ABGR_8888, ALLEGRO_LOCK_WRITEONLY);
if (!premul) {
for (int i = 0; i < h; i++) {
unsigned char *src_ptr = (unsigned char *)pixels + w * 4 * i;
unsigned char *dest_ptr = (unsigned char *)lock->data +
lock->pitch * i;
for (int x = 0; x < w; x++) {
unsigned char r, g, b, a;
r = *src_ptr++;
g = *src_ptr++;
b = *src_ptr++;
a = *src_ptr++;
// NOTE: avoid divide by zero by adding a fraction
float alpha_mul = 255.0f / (a+0.001f);
r *= alpha_mul;
g *= alpha_mul;
b *= alpha_mul;
*dest_ptr++ = r;
*dest_ptr++ = g;
*dest_ptr++ = b;
*dest_ptr++ = a;
}
}
}
else {
for (int i = 0; i < h; i++) {
memcpy(lock->data + lock->pitch * i, pixels + w * 4 * i, w * 4);
}
}
al_unlock_bitmap(bmp);
done:
al_free(pixels);
[pool release];
return bmp;
}
ALLEGRO_BITMAP *_al_iphone_load_image_f(ALLEGRO_FILE *f, int flags)
{
ALLEGRO_BITMAP *bmp;
ALLEGRO_ASSERT(f);
int64_t size = al_fsize(f);
if (size <= 0) {
// TODO: Read from stream until we have the whole image
ALLEGRO_ERROR("Unable to determine file size.\n");
return NULL;
}
/* Note: This *MUST* be the Apple malloc and not any wrapper, as the
* buffer will be owned and freed by the NSData object not us.
*/
void *buffer = al_malloc(size);
al_fread(f, buffer, size);
/* Really load the image now. */
bmp = really_load_image(buffer, size, flags);
return bmp;
}
ALLEGRO_BITMAP *_al_iphone_load_image(const char *filename, int flags)
{
ALLEGRO_FILE *fp;
ALLEGRO_BITMAP *bmp;
ALLEGRO_ASSERT(filename);
fp = al_fopen(filename, "rb");
if (!fp) {
ALLEGRO_ERROR("Unable to open %s for reading.\n", filename);
return NULL;
}
bmp = _al_iphone_load_image_f(fp, flags);
al_fclose(fp);
return bmp;
}