PageRenderTime 39ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/ARViewerAndroid/jni/yuv420sp2rgb/yuv420sp2rgb.c

http://android-ar-base.googlecode.com/
C | 256 lines | 162 code | 32 blank | 62 comment | 10 complexity | 3b7fcf232fc00af63f66d328f07ea3ad MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /*
  2. * PROJECT: NyARToolkit for Android SDK
  3. * --------------------------------------------------------------------------------
  4. * This work is based on the original ARToolKit developed by
  5. * Hirokazu Kato
  6. * Mark Billinghurst
  7. * HITLab, University of Washington, Seattle
  8. * http://www.hitl.washington.edu/artoolkit/
  9. *
  10. * NyARToolkit for Android SDK
  11. * Copyright (C)2010 NyARToolkit for Android team
  12. * Copyright (C)2010 R.Iizuka(nyatla)
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation, either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. *
  27. * For further information please contact.
  28. * http://sourceforge.jp/projects/nyartoolkit-and/
  29. *
  30. * This work is based on the NyARToolKit developed by
  31. * R.Iizuka (nyatla)
  32. * http://nyatla.jp/nyatoolkit/
  33. *
  34. * contributor(s)
  35. * Atsuo Igarashi
  36. */
  37. #include <jni.h>
  38. #include <android/log.h>
  39. #define LOG_TAG "libyuv420sp2rgb"
  40. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  41. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
  42. /*
  43. * derived from development/tools/yuv420sp2rgb/yuv420sp2rgb.c
  44. */
  45. #include <unistd.h>
  46. #ifndef max
  47. #define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; })
  48. #define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; })
  49. #endif
  50. #define CONVERT_TYPE_PPM 0
  51. #define CONVERT_TYPE_RGB 1
  52. #define CONVERT_TYPE_ARGB 2
  53. /*
  54. YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved
  55. U/V plane containing 8 bit 2x2 subsampled chroma samples.
  56. except the interleave order of U and V is reversed.
  57. H V
  58. Y Sample Period 1 1
  59. U (Cb) Sample Period 2 2
  60. V (Cr) Sample Period 2 2
  61. */
  62. typedef struct rgb_context {
  63. unsigned char *buffer;
  64. int width;
  65. int height;
  66. int rotate;
  67. int i;
  68. int j;
  69. int size; /* for debugging */
  70. } rgb_context;
  71. typedef void (*rgb_cb)(
  72. unsigned char r,
  73. unsigned char g,
  74. unsigned char b,
  75. rgb_context *ctx);
  76. const int bytes_per_pixel = 2;
  77. static void color_convert_common(
  78. unsigned char *pY, unsigned char *pUV,
  79. int width, int height,
  80. unsigned char *buffer,
  81. int size, /* buffer size in bytes */
  82. int gray,
  83. int rotate,
  84. rgb_cb cb)
  85. {
  86. int i, j;
  87. int nR, nG, nB;
  88. int nY, nU, nV;
  89. rgb_context ctx;
  90. ctx.buffer = buffer;
  91. ctx.size = size; /* debug */
  92. ctx.width = width;
  93. ctx.height = height;
  94. ctx.rotate = rotate;
  95. if (gray) {
  96. for (i = 0; i < height; i++) {
  97. for (j = 0; j < width; j++) {
  98. nB = *(pY + i * width + j);
  99. ctx.i = i;
  100. ctx.j = j;
  101. cb(nB, nB, nB, &ctx);
  102. }
  103. }
  104. } else {
  105. // YUV 4:2:0
  106. for (i = 0; i < height; i++) {
  107. for (j = 0; j < width; j++) {
  108. nY = *(pY + i * width + j);
  109. nV = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
  110. nU = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
  111. // Yuv Convert
  112. nY -= 16;
  113. nU -= 128;
  114. nV -= 128;
  115. if (nY < 0)
  116. nY = 0;
  117. // nR = (int)(1.164 * nY + 2.018 * nU);
  118. // nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU);
  119. // nB = (int)(1.164 * nY + 1.596 * nV);
  120. nB = (int)(1192 * nY + 2066 * nU);
  121. nG = (int)(1192 * nY - 833 * nV - 400 * nU);
  122. nR = (int)(1192 * nY + 1634 * nV);
  123. nR = min(262143, max(0, nR));
  124. nG = min(262143, max(0, nG));
  125. nB = min(262143, max(0, nB));
  126. nR >>= 10; nR &= 0xff;
  127. nG >>= 10; nG &= 0xff;
  128. nB >>= 10; nB &= 0xff;
  129. ctx.i = i;
  130. ctx.j = j;
  131. cb(nR, nG, nB, &ctx);
  132. }
  133. }
  134. }
  135. }
  136. static void common_rgb_cb(
  137. unsigned char r,
  138. unsigned char g,
  139. unsigned char b,
  140. rgb_context *ctx,
  141. int alpha)
  142. {
  143. unsigned char *out = ctx->buffer;
  144. int offset = 0;
  145. int bpp;
  146. int i = 0;
  147. switch(ctx->rotate) {
  148. case 0: /* no rotation */
  149. offset = ctx->i * ctx->width + ctx->j;
  150. break;
  151. case 1: /* 90 degrees */
  152. offset = ctx->height * (ctx->j + 1) - ctx->i;
  153. break;
  154. case 2: /* 180 degrees */
  155. offset = (ctx->height - 1 - ctx->i) * ctx->width + ctx->j;
  156. break;
  157. case 3: /* 270 degrees */
  158. offset = (ctx->width - 1 - ctx->j) * ctx->height + ctx->i;
  159. break;
  160. default:
  161. //FAILIF(1, "Unexpected roation value %d!\n", ctx->rotate);
  162. break;
  163. }
  164. bpp = 3 + !!alpha;
  165. offset *= bpp;
  166. /*FAILIF(offset < 0, "point (%d, %d) generates a negative offset.\n", ctx->i, ctx->j);
  167. FAILIF(offset + bpp > ctx->size, "point (%d, %d) at offset %d exceeds the size %d of the buffer.\n",
  168. ctx->i, ctx->j,
  169. offset,
  170. ctx->size);*/
  171. out += offset;
  172. if (alpha) out[i++] = 0xff;
  173. out[i++] = r;
  174. out[i++] = g;
  175. out[i] = b;
  176. }
  177. static void rgb24_cb(
  178. unsigned char r,
  179. unsigned char g,
  180. unsigned char b,
  181. rgb_context *ctx)
  182. {
  183. return common_rgb_cb(r,g,b,ctx,0);
  184. }
  185. static void argb_cb(
  186. unsigned char r,
  187. unsigned char g,
  188. unsigned char b,
  189. rgb_context *ctx)
  190. {
  191. return common_rgb_cb(r,g,b,ctx,1);
  192. }
  193. JNIEXPORT void JNICALL Java_jp_androidgroup_nyartoolkit_ARToolkitDrawer_decodeYUV420SP(JNIEnv * env, jobject obj, jintArray rgb, jbyteArray yuv420sp, jint width, jint height, jint type)
  194. {
  195. void *in, *out;
  196. int psz = getpagesize();
  197. int header_size;
  198. size_t outsize;
  199. int bpp = 3;
  200. switch (type) {
  201. case CONVERT_TYPE_RGB:
  202. header_size = 0;
  203. break;
  204. case CONVERT_TYPE_ARGB:
  205. header_size = 0;
  206. bpp = 4;
  207. break;
  208. }
  209. outsize = header_size + width * height * bpp;
  210. outsize = (outsize + psz - 1) & ~(psz - 1);
  211. jboolean isCopyIn, isCopyOut;
  212. in = (*env)->GetByteArrayElements(env, yuv420sp, &isCopyIn);
  213. out = (*env)->GetIntArrayElements(env, rgb, &isCopyOut);
  214. color_convert_common(in, in + width * height,
  215. width, height,
  216. out + header_size, outsize - header_size,
  217. 0, 0,
  218. type == CONVERT_TYPE_ARGB ? argb_cb : rgb24_cb);
  219. //if (isCopyIn == JNI_TRUE)
  220. (*env)->ReleaseByteArrayElements(env, yuv420sp, in, 0);
  221. //if (isCopyOut == JNI_TRUE)
  222. (*env)->ReleaseIntArrayElements(env, rgb, out, 0);
  223. }