Changeset 955


Ignore:
Timestamp:
Sep 18, 2011, 9:13:56 PM (11 years ago)
Author:
sam
Message:

core: implement dynamic registration of image loaders.

Location:
trunk/src
Files:
7 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/Makefile.am

    r912 r955  
    2525    shader/shader.cpp shader/shader.h \
    2626    \
    27     image/image.cpp image/image.h \
     27    image/image.cpp image/image.h image/image-private.h \
     28    image/codec/android-image.cpp \
     29    image/codec/ios-image.cpp \
     30    image/codec/sdl-image.cpp \
     31    image/codec/ps3-image.cpp \
     32    image/codec/dummy-image.cpp \
    2833    \
    2934    loldebug.h \
  • trunk/src/image/image.cpp

    r950 r955  
    1515#include <cmath>
    1616
    17 #if defined __APPLE__ && defined __MACH__
    18 #   import <UIKit/UIKit.h>
    19 #elif defined USE_SDL_IMAGE
    20 #   include <SDL.h>
    21 #   include <SDL_image.h>
    22 #elif defined __ANDROID__
    23 #   include <jni.h>
    24 #   include <android/log.h>
    25 #elif defined __CELLOS_LV2__
    26 #   include <cell/sysmodule.h>
    27 #   include <cell/codec/pngdec.h>
    28 #endif
    29 
    3017#include "core.h"
     18#include "image-private.h"
    3119
    3220using namespace std;
     
    3523{
    3624
     25bool ImageLoader::RegisterAllLoaders()
     26{
    3727#if defined __ANDROID__
    38 extern JavaVM *g_vm;
    39 extern jobject g_activity;
     28    REGISTER_IMAGE_LOADER(AndroidImageData)
     29#endif
     30    REGISTER_IMAGE_LOADER(DummyImageData)
     31#if defined __APPLE__ && defined __MACH__
     32    REGISTER_IMAGE_LOADER(IosImageData)
     33#endif
     34#if defined __CELLOS_LV2__
     35    REGISTER_IMAGE_LOADER(Ps3ImageData)
     36#endif
     37#if defined USE_SDL_IMAGE
     38    REGISTER_IMAGE_LOADER(SdlImageData)
    4039#endif
    4140
    42 /*
    43  * Image implementation class
    44  */
    45 
    46 class ImageData
    47 {
    48     friend class Image;
    49 
    50 private:
    51     ivec2 size;
    52     Image::format_t format;
    53 
    54 #if defined __APPLE__ && defined __MACH__
    55     uint8_t *pixels;
    56 #elif defined USE_SDL_IMAGE
    57     SDL_Surface *img;
    58 #elif defined __ANDROID__
    59     jobject bmp;
    60     jintArray array;
    61     jint *pixels;
    62 #elif defined __CELLOS_LV2__
    63     static void* Malloc(uint32_t size, void* data) { return malloc(size); };
    64     static int32_t Free(void* ptr, void* data) { free(ptr); return 0; };
    65     uint8_t *pixels;
    66 #else
    67     uint8_t *pixels;
    68 #endif
    69 };
     41    return true;
     42}
    7043
    7144/*
     
    7447
    7548Image::Image(char const *path)
    76   : data(new ImageData())
    7749{
    78 #if defined __APPLE__ && defined __MACH__
    79     NSString *fullpath = [NSString stringWithUTF8String:path];
    80     NSArray *chunks = [fullpath componentsSeparatedByString: @"/"];
    81     NSString *filename = [chunks objectAtIndex: [chunks count] - 1];
    82     chunks = [filename componentsSeparatedByString: @"."];
    83     NSString *prefix = [chunks objectAtIndex: 0];
    84     NSString *mypath = [[NSBundle mainBundle] pathForResource:prefix ofType:@"png"];
    85     NSData *pngdata = [[NSData alloc] initWithContentsOfFile:mypath];
    86     UIImage *image = [[UIImage alloc] initWithData:pngdata];
    87     if (!image)
    88     {
    89 #if !LOL_RELEASE
    90         Log::Error("could not load %s\n", path);
    91 #endif
    92         exit(1);
    93     }
     50    static bool unused = ImageLoader::RegisterAllLoaders();
    9451
    95     int w = CGImageGetWidth(image.CGImage);
    96     int h = CGImageGetHeight(image.CGImage);
    97     data->size = ivec2(w, h);
    98     data->format = FORMAT_RGBA;
    99 
    100     CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
    101     data->pixels = (uint8_t *)malloc(w * h * 4);
    102     CGContextRef ctx =
    103             CGBitmapContextCreate(data->pixels, w, h, 8, 4 * w, cspace,
    104                     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    105     CGColorSpaceRelease(cspace);
    106     CGContextClearRect(ctx, CGRectMake(0, 0, w, h));
    107     CGContextTranslateCTM(ctx, 0, h - h);
    108     CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), image.CGImage);
    109     CGContextRelease(ctx);
    110     [image release];
    111     [pngdata release];
    112 #elif defined USE_SDL_IMAGE
    113     for (char const *name = path; *name; name++)
    114         if ((data->img = IMG_Load(name)))
    115             break;
    116 
    117     if (!data->img)
    118     {
    119 #if !LOL_RELEASE
    120         Log::Error("could not load %s\n", path);
    121 #endif
    122         SDL_Quit();
    123         exit(1);
    124     }
    125 
    126     data->size = ivec2(data->img->w, data->img->h);
    127     data->format = data->img->format->Amask ? FORMAT_RGBA : FORMAT_RGB;
    128 #elif defined __ANDROID__
    129     JNIEnv *env;
    130     jint res = g_vm->GetEnv((void **)&env, JNI_VERSION_1_2);
    131     if (res < 0)
    132     {
    133 #if !LOL_RELEASE
    134         Log::Error("could not get JVM environment\n");
    135 #endif
    136         exit(1);
    137     }
    138     jclass cls = env->GetObjectClass(g_activity);
    139     jmethodID mid;
    140 
    141     mid = env->GetMethodID(cls, "openImage",
    142                            "(Ljava/lang/String;)Landroid/graphics/Bitmap;");
    143     jstring name = env->NewStringUTF(path);
    144     data->bmp = env->CallObjectMethod(g_activity, mid, name);
    145     env->DeleteLocalRef(name);
    146     if (!data->bmp)
    147     {
    148 #if !LOL_RELEASE
    149         Log::Error("could not load %s\n", path);
    150 #endif
    151         exit(1);
    152     }
    153     env->NewGlobalRef(data->bmp);
    154 
    155     /* Get image dimensions */
    156     mid = env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
    157     data->size.x = env->CallIntMethod(g_activity, mid, data->bmp);
    158     mid = env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I");
    159     data->size.y = env->CallIntMethod(g_activity, mid, data->bmp);
    160 
    161     /* Get pixels */
    162     data->array = env->NewIntArray(data->size.x * data->size.y);
    163     env->NewGlobalRef(data->array);
    164     mid = env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V");
    165     env->CallVoidMethod(g_activity, mid, data->bmp, data->array);
    166 
    167     data->pixels = env->GetIntArrayElements(data->array, 0);
    168     for (int n = 0; n < data->size.x * data->size.y; n++)
    169     {
    170         uint32_t u = data->pixels[n];
    171         u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16);
    172         data->pixels[n] = u;
    173     }
    174     data->format = FORMAT_RGBA;
    175 #elif defined __CELLOS_LV2__
    176     int32_t err;
    177 
    178     /* Initialise decoding library */
    179     CellPngDecMainHandle hmain;
    180 
    181     err = cellSysmoduleLoadModule(CELL_SYSMODULE_FS);
    182     if (err != CELL_OK)
    183     {
    184 #if !LOL_RELEASE
    185         Log::Error("could not open Fs sysmodule\n");
    186 #endif
    187         exit(1);
    188     }
    189 
    190     err = cellSysmoduleLoadModule(CELL_SYSMODULE_PNGDEC);
    191     if (err != CELL_OK)
    192     {
    193 #if !LOL_RELEASE
    194         Log::Error("could not open PngDec sysmodule\n");
    195 #endif
    196         exit(1);
    197     }
    198 
    199     CellPngDecThreadInParam in_param;
    200     in_param.spuThreadEnable = CELL_PNGDEC_SPU_THREAD_ENABLE;
    201     in_param.ppuThreadPriority = 1000;
    202     in_param.spuThreadPriority = 200;
    203     in_param.cbCtrlMallocFunc = ImageData::Malloc;
    204     in_param.cbCtrlMallocArg = NULL;
    205     in_param.cbCtrlFreeFunc = ImageData::Free;
    206     in_param.cbCtrlFreeArg = NULL;
    207     CellPngDecThreadOutParam out_param;
    208     err = cellPngDecCreate(&hmain, &in_param, &out_param);
    209     if (err != CELL_OK)
    210     {
    211 #if !LOL_RELEASE
    212         Log::Error("could not create PngDec library\n");
    213 #endif
    214         exit(1);
    215     }
    216 
    217     /* Create decoder */
    218     CellPngDecSubHandle hsub;
    219 
    220     char file[1024];
    221     sprintf(file, "/app_home/c:/Users/s.hocevar/lolengine/%s", path);
    222 
    223     CellPngDecSrc dec_src;
    224     dec_src.srcSelect = CELL_PNGDEC_FILE;
    225     dec_src.fileName = file;
    226     dec_src.fileOffset = 0;
    227     dec_src.fileSize = 0;
    228     dec_src.streamPtr = NULL;
    229     dec_src.streamSize = 0;
    230     dec_src.spuThreadEnable  = CELL_PNGDEC_SPU_THREAD_ENABLE;
    231     CellPngDecOpnInfo open_info;
    232     err = cellPngDecOpen(hmain, &hsub, &dec_src, &open_info);
    233     if (err != CELL_OK)
    234     {
    235 #if !LOL_RELEASE
    236         Log::Error("could not open %s for decoding\n", file);
    237 #endif
    238         exit(1);
    239     }
    240 
    241     CellPngDecInfo info;
    242     err = cellPngDecReadHeader(hmain, hsub, &info);
    243     if (err != CELL_OK)
    244     {
    245 #if !LOL_RELEASE
    246         Log::Error("could not read image header\n");
    247 #endif
    248         exit(1);
    249     }
    250 
    251     CellPngDecInParam in_dec_param;
    252     in_dec_param.commandPtr = NULL;
    253     in_dec_param.outputMode = CELL_PNGDEC_TOP_TO_BOTTOM;
    254     in_dec_param.outputColorSpace = CELL_PNGDEC_RGBA;
    255     in_dec_param.outputBitDepth = 8;
    256     in_dec_param.outputPackFlag = CELL_PNGDEC_1BYTE_PER_1PIXEL;
    257     in_dec_param.outputAlphaSelect = CELL_PNGDEC_STREAM_ALPHA;
    258     in_dec_param.outputColorAlpha = 0xff;
    259     CellPngDecOutParam out_dec_param;
    260     err = cellPngDecSetParameter(hmain, hsub, &in_dec_param, &out_dec_param);
    261     if (err != CELL_OK)
    262     {
    263 #if !LOL_RELEASE
    264         Log::Error("could not configure PngDec decoder\n");
    265 #endif
    266         exit(1);
    267     }
    268 
    269     /* Decode image */
    270     data->size = ivec2(info.imageWidth, info.imageHeight);
    271     data->format = FORMAT_RGBA;
    272     data->pixels = (uint8_t *)malloc(info.imageWidth * 4 * info.imageHeight);
    273     CellPngDecDataCtrlParam data_ctrl_param;
    274     data_ctrl_param.outputBytesPerLine = info.imageWidth * 4;
    275     CellPngDecDataOutInfo data_out_info;
    276     err = cellPngDecDecodeData(hmain, hsub, data->pixels,
    277                                &data_ctrl_param, &data_out_info);
    278     if (err != CELL_OK)
    279     {
    280 #if !LOL_RELEASE
    281         Log::Error("could not run PngDec decoder\n");
    282 #endif
    283         exit(1);
    284     }
    285 
    286     /* Close decoder */
    287     err = cellPngDecClose(hmain, hsub);
    288     if (err != CELL_OK)
    289     {
    290 #if !LOL_RELEASE
    291         Log::Error("could not close PngDec decoder\n");
    292 #endif
    293         exit(1);
    294     }
    295 
    296     /* Deinitialise library */
    297     err = cellPngDecDestroy(hmain);
    298     if (err != CELL_OK)
    299     {
    300 #if !LOL_RELEASE
    301         Log::Error("could not destroy PngDec decoder\n");
    302 #endif
    303         exit(1);
    304     }
    305     err = cellSysmoduleUnloadModule(CELL_SYSMODULE_PNGDEC);
    306     err = cellSysmoduleUnloadModule(CELL_SYSMODULE_FS);
    307 #else
    308     data->size = 256;
    309     data->format = FORMAT_RGBA;
    310     data->pixels = (uint8_t *)malloc(256 * 256 * 4 * sizeof(*data->pixels));
    311     uint8_t *parser = data->pixels;
    312     for (int j = 0; j < 256; j++)
    313         for (int i = 0; i < 256; i++)
    314         {
    315             *parser++ = ((i ^ j) & 1) * 0xff;
    316             *parser++ = (uint8_t)i;
    317             *parser++ = (uint8_t)j;
    318             *parser++ = (((i >> 4) ^ (j >> 4)) & 1) * 0xff;
    319         }
    320 #endif
     52    data = ImageLoader::Load(path);
    32153}
    32254
     
    33365void * Image::GetData() const
    33466{
    335 #if defined __APPLE__ && defined __MACH__
    336     return data->pixels;
    337 #elif defined USE_SDL_IMAGE
    338     return data->img->pixels;
    339 #elif defined __ANDROID__
    340     return data->pixels;
    341 #elif defined __CELLOS_LV2__
    342     return data->pixels;
    343 #else
    344     return data->pixels;
    345 #endif
     67    return data->GetData();
    34668}
    34769
    34870Image::~Image()
    34971{
    350 #if defined __APPLE__ && defined __MACH__
    351     free(data->pixels);
    352 #elif defined USE_SDL_IMAGE
    353     SDL_FreeSurface(data->img);
    354 #elif defined __ANDROID__
    355     JNIEnv *env;
    356     jint res = g_vm->GetEnv((void **)&env, JNI_VERSION_1_2);
    357     if (res < 0)
    358     {
    359 #if !LOL_RELEASE
    360         Log::Error("could not get JVM environment\n");
    361 #endif
    362         exit(1);
    363     }
    364     jclass cls = env->GetObjectClass(g_activity);
    365     jmethodID mid;
    366 
    367     env->ReleaseIntArrayElements(data->array, data->pixels, 0);
    368     env->DeleteGlobalRef(data->array);
    369 
    370     /* Free image */
    371     mid = env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V");
    372     env->CallVoidMethod(g_activity, mid, data->bmp);
    373     env->DeleteGlobalRef(data->bmp);
    374 #elif defined __CELLOS_LV2__
    375     free(data->pixels);
    376 #else
    377     free(data->pixels);
    378 #endif
     72    data->Close();
    37973    delete data;
    38074}
Note: See TracChangeset for help on using the changeset viewer.