source: trunk/src/image.cpp @ 833

Last change on this file since 833 was 833, checked in by sam, 10 years ago

ps3: load textures using the system's PNGDEC module.

File size: 9.6 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cmath>
16
17#if defined __APPLE__ && defined __MACH__
18#   import <UIKit/UIKit.h>
19#elif defined USE_SDL
20#   include <SDL.h>
21#   include <SDL_image.h>
22#elif defined ANDROID_NDK
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
30#include "core.h"
31
32using namespace std;
33
34namespace lol
35{
36
37#if defined ANDROID_NDK
38extern JNIEnv *g_env;
39extern jobject g_ctx;
40#endif
41
42/*
43 * Image implementation class
44 */
45
46class ImageData
47{
48    friend class Image;
49
50private:
51    vec2i size;
52    Image::format_t format;
53
54#if defined __APPLE__ && defined __MACH__
55    uint8_t *pixels;
56#elif defined USE_SDL
57    SDL_Surface *img;
58#elif defined ANDROID_NDK
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};
70
71/*
72 * Public Image class
73 */
74
75Image::Image(char const *path)
76  : data(new ImageData())
77{
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    }
94
95    int w = CGImageGetWidth(image.CGImage);
96    int h = CGImageGetHeight(image.CGImage);
97    data->size = vec2i(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
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 = vec2i(data->img->w, data->img->h);
127    data->format = data->img->format->Amask ? FORMAT_RGBA : FORMAT_RGB;
128#elif defined ANDROID_NDK
129    jclass cls = g_env->GetObjectClass(g_ctx);
130    jmethodID mid;
131
132    mid = g_env->GetMethodID(cls, "openImage",
133                             "(Ljava/lang/String;)Landroid/graphics/Bitmap;");
134    jstring name = g_env->NewStringUTF(path);
135    data->bmp = g_env->CallObjectMethod(g_ctx, mid, name);
136    g_env->DeleteLocalRef(name);
137    g_env->NewGlobalRef(data->bmp);
138
139    /* Get image dimensions */
140    mid = g_env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
141    data->size.x = g_env->CallIntMethod(g_ctx, mid, data->bmp);
142    mid = g_env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I");
143    data->size.y = g_env->CallIntMethod(g_ctx, mid, data->bmp);
144
145    /* Get pixels */
146    data->array = g_env->NewIntArray(data->size.x * data->size.y);
147    g_env->NewGlobalRef(data->array);
148    mid = g_env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V");
149    g_env->CallVoidMethod(g_ctx, mid, data->bmp, data->array);
150
151    data->pixels = g_env->GetIntArrayElements(data->array, 0);
152    for (int n = 0; n < data->size.x * data->size.y; n++)
153    {
154        uint32_t u = data->pixels[n];
155        u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16);
156        data->pixels[n] = u;
157    }
158    data->format = FORMAT_RGBA;
159#elif defined __CELLOS_LV2__
160    int32_t err;
161
162    /* Initialise decoding library */
163    CellPngDecMainHandle hmain;
164
165    err = cellSysmoduleLoadModule(CELL_SYSMODULE_FS);
166    if (err != CELL_OK)
167    {
168#if !LOL_RELEASE
169        Log::Error("could not open Fs sysmodule\n");
170#endif
171        exit(1);
172    }
173
174    err = cellSysmoduleLoadModule(CELL_SYSMODULE_PNGDEC);
175    if (err != CELL_OK)
176    {
177#if !LOL_RELEASE
178        Log::Error("could not open PngDec sysmodule\n");
179#endif
180        exit(1);
181    }
182
183    CellPngDecThreadInParam in_param;
184    in_param.spuThreadEnable = CELL_PNGDEC_SPU_THREAD_ENABLE;
185    in_param.ppuThreadPriority = 1000;
186    in_param.spuThreadPriority = 200;
187    in_param.cbCtrlMallocFunc = ImageData::Malloc;
188    in_param.cbCtrlMallocArg = NULL;
189    in_param.cbCtrlFreeFunc = ImageData::Free;
190    in_param.cbCtrlFreeArg = NULL;
191    CellPngDecThreadOutParam out_param;
192    err = cellPngDecCreate(&hmain, &in_param, &out_param);
193    if (err != CELL_OK)
194    {
195#if !LOL_RELEASE
196        Log::Error("could not create PngDec library\n");
197#endif
198        exit(1);
199    }
200
201    /* Create decoder */
202    CellPngDecSubHandle hsub;
203
204    char file[1024];
205    sprintf(file, "/app_home/c:/Users/s.hocevar/lolengine/%s", path);
206
207    CellPngDecSrc dec_src;
208    dec_src.srcSelect = CELL_PNGDEC_FILE;
209    dec_src.fileName = file;
210    dec_src.fileOffset = 0;
211    dec_src.fileSize = 0;
212    dec_src.streamPtr = NULL;
213    dec_src.streamSize = 0;
214    dec_src.spuThreadEnable  = CELL_PNGDEC_SPU_THREAD_ENABLE;
215    CellPngDecOpnInfo open_info;
216    err = cellPngDecOpen(hmain, &hsub, &dec_src, &open_info);
217    if (err != CELL_OK)
218    {
219#if !LOL_RELEASE
220        Log::Error("could not open %s for decoding\n", file);
221#endif
222        exit(1);
223    }
224
225    CellPngDecInfo info;
226    err = cellPngDecReadHeader(hmain, hsub, &info);
227    if (err != CELL_OK)
228    {
229#if !LOL_RELEASE
230        Log::Error("could not read image header\n");
231#endif
232        exit(1);
233    }
234
235    CellPngDecInParam in_dec_param;
236    in_dec_param.commandPtr = NULL;
237    in_dec_param.outputMode = CELL_PNGDEC_TOP_TO_BOTTOM;
238    in_dec_param.outputColorSpace = CELL_PNGDEC_RGBA;
239    in_dec_param.outputBitDepth = 8;
240    in_dec_param.outputPackFlag = CELL_PNGDEC_1BYTE_PER_1PIXEL;
241    in_dec_param.outputAlphaSelect = CELL_PNGDEC_STREAM_ALPHA;
242    in_dec_param.outputColorAlpha = 0xff;
243    CellPngDecOutParam out_dec_param;
244    err = cellPngDecSetParameter(hmain, hsub, &in_dec_param, &out_dec_param);
245    if (err != CELL_OK)
246    {
247#if !LOL_RELEASE
248        Log::Error("could not configure PngDec decoder\n");
249#endif
250        exit(1);
251    }
252
253    /* Decode image */
254    data->size = vec2i(info.imageWidth, info.imageHeight);
255    data->format = FORMAT_RGBA;
256    data->pixels = (uint8_t *)malloc(info.imageWidth * 4 * info.imageHeight);
257    CellPngDecDataCtrlParam data_ctrl_param;
258    data_ctrl_param.outputBytesPerLine = info.imageWidth * 4;
259    CellPngDecDataOutInfo data_out_info;
260    err = cellPngDecDecodeData(hmain, hsub, data->pixels,
261                               &data_ctrl_param, &data_out_info);
262    if (err != CELL_OK)
263    {
264#if !LOL_RELEASE
265        Log::Error("could not run PngDec decoder\n");
266#endif
267        exit(1);
268    }
269
270    /* Close decoder */
271    err = cellPngDecClose(hmain, hsub);
272    if (err != CELL_OK)
273    {
274#if !LOL_RELEASE
275        Log::Error("could not close PngDec decoder\n");
276#endif
277        exit(1);
278    }
279
280    /* Deinitialise library */
281    err = cellPngDecDestroy(hmain);
282    if (err != CELL_OK)
283    {
284#if !LOL_RELEASE
285        Log::Error("could not destroy PngDec decoder\n");
286#endif
287        exit(1);
288    }
289    err = cellSysmoduleUnloadModule(CELL_SYSMODULE_PNGDEC);
290    err = cellSysmoduleUnloadModule(CELL_SYSMODULE_FS);
291#else
292    data->size = 256;
293    data->format = FORMAT_RGBA;
294    data->pixels = (uint8_t *)malloc(256 * 256 * 4 * sizeof(*data->pixels));
295    uint8_t *parser = data->pixels;
296    for (int j = 0; j < 256; j++)
297        for (int i = 0; i < 256; i++)
298        {
299            *parser++ = ((i ^ j) & 1) * 0xff;
300            *parser++ = (uint8_t)i;
301            *parser++ = (uint8_t)j;
302            *parser++ = (((i >> 4) ^ (j >> 4)) & 1) * 0xff;
303        }
304#endif
305}
306
307vec2i Image::GetSize() const
308{
309    return data->size;
310}
311
312Image::format_t Image::GetFormat() const
313{
314    return data->format;
315}
316
317void * Image::GetData() const
318{
319#if defined __APPLE__ && defined __MACH__
320    return data->pixels;
321#elif defined USE_SDL
322    return data->img->pixels;
323#elif defined ANDROID_NDK
324    return data->pixels;
325#elif defined __CELLOS_LV2__
326    return data->pixels;
327#else
328    return data->pixels;
329#endif
330}
331
332Image::~Image()
333{
334#if defined __APPLE__ && defined __MACH__
335    free(data->pixels);
336#elif defined USE_SDL
337    SDL_FreeSurface(data->img);
338#elif defined ANDROID_NDK
339    jclass cls = g_env->GetObjectClass(g_ctx);
340    jmethodID mid;
341
342    g_env->ReleaseIntArrayElements(data->array, data->pixels, 0);
343    g_env->DeleteGlobalRef(data->array);
344
345    /* Free image */
346    mid = g_env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V");
347    g_env->CallVoidMethod(g_ctx, mid, data->bmp);
348    g_env->DeleteGlobalRef(data->bmp);
349#elif defined __CELLOS_LV2__
350    free(data->pixels);
351#else
352    free(data->pixels);
353#endif
354    delete data;
355}
356
357} /* namespace lol */
358
Note: See TracBrowser for help on using the repository browser.