210 行
5.3 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. #include <cstdio>
  15. #if defined __APPLE__ && defined __MACH__
  16. #
  17. #elif defined USE_SDL
  18. # include <SDL.h>
  19. # include <SDL_image.h>
  20. #elif defined ANDROID_NDK
  21. # include <jni.h>
  22. # include <android/log.h>
  23. #endif
  24. #include "core.h"
  25. namespace lol
  26. {
  27. #if defined ANDROID_NDK
  28. extern JNIEnv *g_env;
  29. extern jobject g_ctx;
  30. #endif
  31. /*
  32. * Image implementation class
  33. */
  34. class ImageData
  35. {
  36. friend class Image;
  37. private:
  38. vec2i size;
  39. Image::format_t format;
  40. #if defined __APPLE__ && defined __MACH__
  41. uint8_t *pixels;
  42. #elif defined USE_SDL
  43. SDL_Surface *img;
  44. #elif defined ANDROID_NDK
  45. jobject bmp;
  46. jintArray array;
  47. jint *pixels;
  48. #else
  49. uint8_t *pixels;
  50. #endif
  51. };
  52. /*
  53. * Public Image class
  54. */
  55. Image::Image(char const *path)
  56. : data(new ImageData())
  57. {
  58. #if defined __APPLE__ && defined __MACH__
  59. NSString *path = [[NSBundle mainBundle] pathForResource:@"ascii" ofType:@"png"];
  60. NSData *pngdata = [[NSData alloc] initWithContentsOfFile:path];
  61. UIImage *image = [[UIImage alloc] initWithData:pngdata];
  62. if (!image)
  63. {
  64. #if !LOL_RELEASE
  65. fprintf(stderr, "ERROR: could not load %s\n", path);
  66. #endif
  67. exit(1);
  68. }
  69. int w = CGImageGetWidth(image.CGImage);
  70. int h = CGImageGetHeight(image.CGImage);
  71. data->size = vec2i(w, h);
  72. data->format = FORMAT_RGBA;
  73. CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
  74. data->pixels = (uint8_t *)malloc(w * h * 4);
  75. CGContextRef ctx =
  76. CGBitmapContextCreate(data->pixels, w, h, 8, 4 * w, cspace,
  77. kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
  78. CGColorSpaceRelease(cspace);
  79. CGContextClearRect(ctx, CGRectMake(0, 0, w, h));
  80. CGContextTranslateCTM(ctx, 0, h - h);
  81. CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), image.CGImage);
  82. CGContextRelease(ctx);
  83. [image release];
  84. [pngdata release];
  85. #elif defined USE_SDL
  86. for (char const *name = path; *name; name++)
  87. if ((data->img = IMG_Load(name)))
  88. break;
  89. if (!data->img)
  90. {
  91. #if !LOL_RELEASE
  92. fprintf(stderr, "ERROR: could not load %s\n", path);
  93. #endif
  94. SDL_Quit();
  95. exit(1);
  96. }
  97. data->size = vec2i(data->img->w, data->img->h);
  98. data->format = data->img->format->Amask ? FORMAT_RGBA : FORMAT_RGB;
  99. #elif defined ANDROID_NDK
  100. jclass cls = g_env->GetObjectClass(g_ctx);
  101. jmethodID mid;
  102. mid = g_env->GetMethodID(cls, "openImage",
  103. "(Ljava/lang/String;)Landroid/graphics/Bitmap;");
  104. jstring name = g_env->NewStringUTF(path);
  105. data->bmp = g_env->CallObjectMethod(g_ctx, mid, name);
  106. g_env->DeleteLocalRef(name);
  107. g_env->NewGlobalRef(data->bmp);
  108. /* Get image dimensions */
  109. mid = g_env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
  110. data->size.x = g_env->CallIntMethod(g_ctx, mid, data->bmp);
  111. mid = g_env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I");
  112. data->size.y = g_env->CallIntMethod(g_ctx, mid, data->bmp);
  113. /* Get pixels */
  114. data->array = g_env->NewIntArray(data->size.x * data->size.y);
  115. g_env->NewGlobalRef(data->array);
  116. mid = g_env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V");
  117. g_env->CallVoidMethod(g_ctx, mid, data->bmp, data->array);
  118. data->pixels = g_env->GetIntArrayElements(data->array, 0);
  119. for (int n = 0; n < data->size.x * data->size.y; n++)
  120. {
  121. uint32_t u = data->pixels[n];
  122. u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16);
  123. data->pixels[n] = u;
  124. }
  125. data->format = FORMAT_RGBA;
  126. #else
  127. data->size = 256;
  128. data->format = FORMAT_RGBA;
  129. data->pixels = (uint8_t *)malloc(256 * 256 * 4 * sizeof(*data->pixels));
  130. uint8_t *parser = data->pixels;
  131. for (int j = 0; j < 256; j++)
  132. for (int i = 0; i < 256; i++)
  133. {
  134. *parser++ = ((i ^ j) & 1) * 0xff;
  135. *parser++ = (uint8_t)i;
  136. *parser++ = (uint8_t)j;
  137. *parser++ = (((i >> 4) ^ (j >> 4)) & 1) * 0xff;
  138. }
  139. #endif
  140. }
  141. vec2i Image::GetSize() const
  142. {
  143. return data->size;
  144. }
  145. Image::format_t Image::GetFormat() const
  146. {
  147. return data->format;
  148. }
  149. void * Image::GetData() const
  150. {
  151. #if defined __APPLE__ && defined __MACH__
  152. return data->pixels;
  153. #elif defined USE_SDL
  154. return data->img->pixels;
  155. #elif defined ANDROID_NDK
  156. return data->pixels;
  157. #else
  158. return data->pixels;
  159. #endif
  160. }
  161. Image::~Image()
  162. {
  163. #if defined __APPLE__ && defined __MACH__
  164. free(data->pixels);
  165. #elif defined USE_SDL
  166. SDL_FreeSurface(data->img);
  167. #elif defined ANDROID_NDK
  168. jclass cls = g_env->GetObjectClass(g_ctx);
  169. jmethodID mid;
  170. g_env->ReleaseIntArrayElements(data->array, data->pixels, 0);
  171. g_env->DeleteGlobalRef(data->array);
  172. /* Free image */
  173. mid = g_env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V");
  174. g_env->CallVoidMethod(g_ctx, mid, data->bmp);
  175. g_env->DeleteGlobalRef(data->bmp);
  176. #else
  177. free(data->pixels);
  178. #endif
  179. delete data;
  180. }
  181. } /* namespace lol */