You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

366 line
9.7 KiB

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