turbojpeg-jni.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. * Copyright (C)2011-2013 D. R. Commander. All Rights Reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * - Redistributions of source code must retain the above copyright notice,
  8. * this list of conditions and the following disclaimer.
  9. * - Redistributions in binary form must reproduce the above copyright notice,
  10. * this list of conditions and the following disclaimer in the documentation
  11. * and/or other materials provided with the distribution.
  12. * - Neither the name of the libjpeg-turbo Project nor the names of its
  13. * contributors may be used to endorse or promote products derived from this
  14. * software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  20. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. * POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "turbojpeg.h"
  31. #ifdef WIN32
  32. #include "tjutil.h"
  33. #endif
  34. #include <jni.h>
  35. #include "java/org_libjpegturbo_turbojpeg_TJCompressor.h"
  36. #include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h"
  37. #include "java/org_libjpegturbo_turbojpeg_TJ.h"
  38. #define _throw(msg) { \
  39. jclass _exccls=(*env)->FindClass(env, "java/lang/Exception"); \
  40. if(!_exccls) goto bailout; \
  41. (*env)->ThrowNew(env, _exccls, msg); \
  42. goto bailout; \
  43. }
  44. #define bailif0(f) {if(!(f)) { \
  45. char temps[80]; \
  46. snprintf(temps, 80, "Unexpected NULL condition in line %d", __LINE__); \
  47. _throw(temps); \
  48. }}
  49. #define gethandle() \
  50. jclass _cls=(*env)->GetObjectClass(env, obj); \
  51. jfieldID _fid; \
  52. if(!_cls) goto bailout; \
  53. bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J")); \
  54. handle=(tjhandle)(jlong)(*env)->GetLongField(env, obj, _fid); \
  55. JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
  56. (JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
  57. {
  58. jint retval=(jint)tjBufSize(width, height, jpegSubsamp);
  59. if(retval==-1) _throw(tjGetErrorStr());
  60. bailout:
  61. return retval;
  62. }
  63. JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV
  64. (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
  65. {
  66. jint retval=(jint)tjBufSizeYUV(width, height, subsamp);
  67. if(retval==-1) _throw(tjGetErrorStr());
  68. bailout:
  69. return retval;
  70. }
  71. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
  72. (JNIEnv *env, jobject obj)
  73. {
  74. jclass cls;
  75. jfieldID fid;
  76. tjhandle handle;
  77. if((handle=tjInitCompress())==NULL)
  78. _throw(tjGetErrorStr());
  79. bailif0(cls=(*env)->GetObjectClass(env, obj));
  80. bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
  81. (*env)->SetLongField(env, obj, fid, (jlong)handle);
  82. bailout:
  83. return;
  84. }
  85. JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII
  86. (JNIEnv *env, jobject obj, jbyteArray src, jint x, jint y, jint width,
  87. jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
  88. jint jpegQual, jint flags)
  89. {
  90. tjhandle handle=0;
  91. unsigned long jpegSize=0;
  92. jsize arraySize=0, actualPitch;
  93. unsigned char *srcBuf=NULL, *jpegBuf=NULL;
  94. gethandle();
  95. if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
  96. || pitch<0)
  97. _throw("Invalid argument in compress()");
  98. if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
  99. _throw("Mismatch between Java and C API");
  100. actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
  101. arraySize=(y+height-1)*actualPitch + x+width;
  102. if((*env)->GetArrayLength(env, src)<arraySize)
  103. _throw("Source buffer is not large enough");
  104. jpegSize=tjBufSize(width, height, jpegSubsamp);
  105. if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
  106. _throw("Destination buffer is not large enough");
  107. bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  108. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  109. if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width,
  110. pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual,
  111. flags|TJFLAG_NOREALLOC)==-1)
  112. {
  113. (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
  114. (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  115. jpegBuf=srcBuf=NULL;
  116. _throw(tjGetErrorStr());
  117. }
  118. bailout:
  119. if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
  120. if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  121. return (jint)jpegSize;
  122. }
  123. JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
  124. (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
  125. jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
  126. jint flags)
  127. {
  128. return Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIIIII_3BIII(
  129. env, obj, src, 0, 0, width, pitch, height, pf, dst, jpegSubsamp, jpegQual,
  130. flags);
  131. }
  132. JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII
  133. (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width,
  134. jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp,
  135. jint jpegQual, jint flags)
  136. {
  137. tjhandle handle=0;
  138. unsigned long jpegSize=0;
  139. jsize arraySize=0, actualStride;
  140. unsigned char *srcBuf=NULL, *jpegBuf=NULL;
  141. gethandle();
  142. if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
  143. || stride<0)
  144. _throw("Invalid argument in compress()");
  145. if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
  146. _throw("Mismatch between Java and C API");
  147. if(tjPixelSize[pf]!=sizeof(jint))
  148. _throw("Pixel format must be 32-bit when compressing from an integer buffer.");
  149. actualStride=(stride==0)? width:stride;
  150. arraySize=(y+height-1)*actualStride + x+width;
  151. if((*env)->GetArrayLength(env, src)<arraySize)
  152. _throw("Source buffer is not large enough");
  153. jpegSize=tjBufSize(width, height, jpegSubsamp);
  154. if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize)
  155. _throw("Destination buffer is not large enough");
  156. bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  157. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  158. if(tjCompress2(handle, &srcBuf[(y*actualStride + x)*sizeof(int)], width,
  159. stride*sizeof(jint), height, pf, &jpegBuf, &jpegSize, jpegSubsamp,
  160. jpegQual, flags|TJFLAG_NOREALLOC)==-1)
  161. {
  162. (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
  163. (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  164. jpegBuf=srcBuf=NULL;
  165. _throw(tjGetErrorStr());
  166. }
  167. bailout:
  168. if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0);
  169. if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  170. return (jint)jpegSize;
  171. }
  172. JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
  173. (JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch,
  174. jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual,
  175. jint flags)
  176. {
  177. return Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII(
  178. env, obj, src, 0, 0, width, pitch, height, pf, dst, jpegSubsamp, jpegQual,
  179. flags);
  180. }
  181. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
  182. (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
  183. jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
  184. {
  185. tjhandle handle=0;
  186. jsize arraySize=0;
  187. unsigned char *srcBuf=NULL, *dstBuf=NULL;
  188. gethandle();
  189. if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
  190. || pitch<0)
  191. _throw("Invalid argument in encodeYUV()");
  192. if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
  193. _throw("Mismatch between Java and C API");
  194. arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height;
  195. if((*env)->GetArrayLength(env, src)<arraySize)
  196. _throw("Source buffer is not large enough");
  197. if((*env)->GetArrayLength(env, dst)
  198. <(jsize)tjBufSizeYUV(width, height, subsamp))
  199. _throw("Destination buffer is not large enough");
  200. bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  201. bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  202. if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp,
  203. flags)==-1)
  204. {
  205. (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  206. (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  207. dstBuf=srcBuf=NULL;
  208. _throw(tjGetErrorStr());
  209. }
  210. bailout:
  211. if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  212. if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  213. return;
  214. }
  215. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
  216. (JNIEnv *env, jobject obj, jintArray src, jint width, jint stride,
  217. jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
  218. {
  219. tjhandle handle=0;
  220. jsize arraySize=0;
  221. unsigned char *srcBuf=NULL, *dstBuf=NULL;
  222. gethandle();
  223. if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
  224. || stride<0)
  225. _throw("Invalid argument in encodeYUV()");
  226. if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
  227. _throw("Mismatch between Java and C API");
  228. if(tjPixelSize[pf]!=sizeof(jint))
  229. _throw("Pixel format must be 32-bit when encoding from an integer buffer.");
  230. arraySize=(stride==0)? width*height:stride*height;
  231. if((*env)->GetArrayLength(env, src)<arraySize)
  232. _throw("Source buffer is not large enough");
  233. if((*env)->GetArrayLength(env, dst)
  234. <(jsize)tjBufSizeYUV(width, height, subsamp))
  235. _throw("Destination buffer is not large enough");
  236. bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  237. bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  238. if(tjEncodeYUV2(handle, srcBuf, width, stride*sizeof(jint), height, pf,
  239. dstBuf, subsamp, flags)==-1)
  240. {
  241. (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  242. (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  243. dstBuf=srcBuf=NULL;
  244. _throw(tjGetErrorStr());
  245. }
  246. bailout:
  247. if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  248. if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0);
  249. return;
  250. }
  251. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
  252. (JNIEnv *env, jobject obj)
  253. {
  254. tjhandle handle=0;
  255. gethandle();
  256. if(tjDestroy(handle)==-1) _throw(tjGetErrorStr());
  257. (*env)->SetLongField(env, obj, _fid, 0);
  258. bailout:
  259. return;
  260. }
  261. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
  262. (JNIEnv *env, jobject obj)
  263. {
  264. jclass cls;
  265. jfieldID fid;
  266. tjhandle handle;
  267. if((handle=tjInitDecompress())==NULL) _throw(tjGetErrorStr());
  268. bailif0(cls=(*env)->GetObjectClass(env, obj));
  269. bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
  270. (*env)->SetLongField(env, obj, fid, (jlong)handle);
  271. bailout:
  272. return;
  273. }
  274. JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
  275. (JNIEnv *env, jclass cls)
  276. {
  277. jclass sfcls=NULL; jfieldID fid=0;
  278. tjscalingfactor *sf=NULL; int n=0, i;
  279. jobject sfobj=NULL;
  280. jobjectArray sfjava=NULL;
  281. if((sf=tjGetScalingFactors(&n))==NULL || n==0)
  282. _throw(tjGetErrorStr());
  283. bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor"));
  284. bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
  285. for(i=0; i<n; i++)
  286. {
  287. bailif0(sfobj=(*env)->AllocObject(env, sfcls));
  288. bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
  289. (*env)->SetIntField(env, sfobj, fid, sf[i].num);
  290. bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
  291. (*env)->SetIntField(env, sfobj, fid, sf[i].denom);
  292. (*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
  293. }
  294. bailout:
  295. return sfjava;
  296. }
  297. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
  298. (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize)
  299. {
  300. tjhandle handle=0;
  301. unsigned char *jpegBuf=NULL;
  302. int width=0, height=0, jpegSubsamp=-1;
  303. gethandle();
  304. if((*env)->GetArrayLength(env, src)<jpegSize)
  305. _throw("Source buffer is not large enough");
  306. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  307. if(tjDecompressHeader2(handle, jpegBuf, (unsigned long)jpegSize,
  308. &width, &height, &jpegSubsamp)==-1)
  309. {
  310. (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  311. _throw(tjGetErrorStr());
  312. }
  313. (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); jpegBuf=NULL;
  314. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
  315. (*env)->SetIntField(env, obj, _fid, jpegSubsamp);
  316. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
  317. (*env)->SetIntField(env, obj, _fid, width);
  318. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
  319. (*env)->SetIntField(env, obj, _fid, height);
  320. bailout:
  321. return;
  322. }
  323. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
  324. (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
  325. jint x, jint y, jint width, jint pitch, jint height, jint pf, jint flags)
  326. {
  327. tjhandle handle=0;
  328. jsize arraySize=0, actualPitch;
  329. unsigned char *jpegBuf=NULL, *dstBuf=NULL;
  330. gethandle();
  331. if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
  332. _throw("Invalid argument in decompress()");
  333. if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
  334. _throw("Mismatch between Java and C API");
  335. if((*env)->GetArrayLength(env, src)<jpegSize)
  336. _throw("Source buffer is not large enough");
  337. actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
  338. arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
  339. if((*env)->GetArrayLength(env, dst)<arraySize)
  340. _throw("Destination buffer is not large enough");
  341. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  342. bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  343. if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
  344. &dstBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf,
  345. flags)==-1)
  346. {
  347. (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  348. (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  349. dstBuf=jpegBuf=NULL;
  350. _throw(tjGetErrorStr());
  351. }
  352. bailout:
  353. if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  354. if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  355. return;
  356. }
  357. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
  358. (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
  359. jint width, jint pitch, jint height, jint pf, jint flags)
  360. {
  361. Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIIIII
  362. (env, obj, src, jpegSize, dst, 0, 0, width, pitch, height, pf, flags);
  363. }
  364. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
  365. (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
  366. jint x, jint y, jint width, jint stride, jint height, jint pf, jint flags)
  367. {
  368. tjhandle handle=0;
  369. jsize arraySize=0, actualStride;
  370. unsigned char *jpegBuf=NULL, *dstBuf=NULL;
  371. gethandle();
  372. if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
  373. _throw("Invalid argument in decompress()");
  374. if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
  375. _throw("Mismatch between Java and C API");
  376. if(tjPixelSize[pf]!=sizeof(jint))
  377. _throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
  378. if((*env)->GetArrayLength(env, src)<jpegSize)
  379. _throw("Source buffer is not large enough");
  380. actualStride=(stride==0)? width:stride;
  381. arraySize=(y+height-1)*actualStride + x+width;
  382. if((*env)->GetArrayLength(env, dst)<arraySize)
  383. _throw("Destination buffer is not large enough");
  384. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  385. bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  386. if(tjDecompress2(handle, jpegBuf, (unsigned long)jpegSize,
  387. &dstBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint),
  388. height, pf, flags)==-1)
  389. {
  390. (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  391. (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  392. dstBuf=jpegBuf=NULL;
  393. _throw(tjGetErrorStr());
  394. }
  395. bailout:
  396. if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  397. if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  398. return;
  399. }
  400. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
  401. (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jintArray dst,
  402. jint width, jint stride, jint height, jint pf, jint flags)
  403. {
  404. Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIIIII
  405. (env, obj, src, jpegSize, dst, 0, 0, width, stride, height, pf, flags);
  406. }
  407. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV
  408. (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst,
  409. jint flags)
  410. {
  411. tjhandle handle=0;
  412. unsigned char *jpegBuf=NULL, *dstBuf=NULL;
  413. int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
  414. gethandle();
  415. if((*env)->GetArrayLength(env, src)<jpegSize)
  416. _throw("Source buffer is not large enough");
  417. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
  418. jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
  419. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
  420. jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
  421. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
  422. jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
  423. if((*env)->GetArrayLength(env, dst)
  424. <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp))
  425. _throw("Destination buffer is not large enough");
  426. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
  427. bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
  428. if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf,
  429. flags)==-1)
  430. {
  431. (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  432. (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  433. dstBuf=jpegBuf=NULL;
  434. _throw(tjGetErrorStr());
  435. }
  436. bailout:
  437. if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0);
  438. if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0);
  439. return;
  440. }
  441. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
  442. (JNIEnv *env, jobject obj)
  443. {
  444. jclass cls;
  445. jfieldID fid;
  446. tjhandle handle;
  447. if((handle=tjInitTransform())==NULL) _throw(tjGetErrorStr());
  448. bailif0(cls=(*env)->GetObjectClass(env, obj));
  449. bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
  450. (*env)->SetLongField(env, obj, fid, (jlong)handle);
  451. bailout:
  452. return;
  453. }
  454. typedef struct _JNICustomFilterParams
  455. {
  456. JNIEnv *env;
  457. jobject tobj;
  458. jobject cfobj;
  459. } JNICustomFilterParams;
  460. static int JNICustomFilter(short *coeffs, tjregion arrayRegion,
  461. tjregion planeRegion, int componentIndex, int transformIndex,
  462. tjtransform *transform)
  463. {
  464. JNICustomFilterParams *params=(JNICustomFilterParams *)transform->data;
  465. JNIEnv *env=params->env;
  466. jobject tobj=params->tobj, cfobj=params->cfobj;
  467. jobject arrayRegionObj, planeRegionObj, bufobj, borobj;
  468. jclass cls; jmethodID mid; jfieldID fid;
  469. bailif0(bufobj=(*env)->NewDirectByteBuffer(env, coeffs,
  470. sizeof(short)*arrayRegion.w*arrayRegion.h));
  471. bailif0(cls=(*env)->FindClass(env, "java/nio/ByteOrder"));
  472. bailif0(mid=(*env)->GetStaticMethodID(env, cls, "nativeOrder",
  473. "()Ljava/nio/ByteOrder;"));
  474. bailif0(borobj=(*env)->CallStaticObjectMethod(env, cls, mid));
  475. bailif0(cls=(*env)->GetObjectClass(env, bufobj));
  476. bailif0(mid=(*env)->GetMethodID(env, cls, "order",
  477. "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;"));
  478. (*env)->CallObjectMethod(env, bufobj, mid, borobj);
  479. bailif0(mid=(*env)->GetMethodID(env, cls, "asShortBuffer",
  480. "()Ljava/nio/ShortBuffer;"));
  481. bailif0(bufobj=(*env)->CallObjectMethod(env, bufobj, mid));
  482. bailif0(cls=(*env)->FindClass(env, "java/awt/Rectangle"));
  483. bailif0(arrayRegionObj=(*env)->AllocObject(env, cls));
  484. bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
  485. (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.x);
  486. bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
  487. (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.y);
  488. bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
  489. (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.w);
  490. bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
  491. (*env)->SetIntField(env, arrayRegionObj, fid, arrayRegion.h);
  492. bailif0(planeRegionObj=(*env)->AllocObject(env, cls));
  493. bailif0(fid=(*env)->GetFieldID(env, cls, "x", "I"));
  494. (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.x);
  495. bailif0(fid=(*env)->GetFieldID(env, cls, "y", "I"));
  496. (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.y);
  497. bailif0(fid=(*env)->GetFieldID(env, cls, "width", "I"));
  498. (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.w);
  499. bailif0(fid=(*env)->GetFieldID(env, cls, "height", "I"));
  500. (*env)->SetIntField(env, planeRegionObj, fid, planeRegion.h);
  501. bailif0(cls=(*env)->GetObjectClass(env, cfobj));
  502. bailif0(mid=(*env)->GetMethodID(env, cls, "customFilter",
  503. "(Ljava/nio/ShortBuffer;Ljava/awt/Rectangle;Ljava/awt/Rectangle;IILorg/libjpegturbo/turbojpeg/TJTransform;)V"));
  504. (*env)->CallVoidMethod(env, cfobj, mid, bufobj, arrayRegionObj,
  505. planeRegionObj, componentIndex, transformIndex, tobj);
  506. return 0;
  507. bailout:
  508. return -1;
  509. }
  510. JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
  511. (JNIEnv *env, jobject obj, jbyteArray jsrcBuf, jint jpegSize,
  512. jobjectArray dstobjs, jobjectArray tobjs, jint flags)
  513. {
  514. tjhandle handle=0; int i;
  515. unsigned char *jpegBuf=NULL, **dstBufs=NULL; jsize n=0;
  516. unsigned long *dstSizes=NULL; tjtransform *t=NULL;
  517. jbyteArray *jdstBufs=NULL;
  518. int jpegWidth=0, jpegHeight=0, jpegSubsamp;
  519. jintArray jdstSizes=0; jint *dstSizesi=NULL;
  520. JNICustomFilterParams *params=NULL;
  521. gethandle();
  522. if((*env)->GetArrayLength(env, jsrcBuf)<jpegSize)
  523. _throw("Source buffer is not large enough");
  524. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
  525. jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
  526. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
  527. jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
  528. bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
  529. jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
  530. n=(*env)->GetArrayLength(env, dstobjs);
  531. if(n!=(*env)->GetArrayLength(env, tobjs))
  532. _throw("Mismatch between size of transforms array and destination buffers array");
  533. if((dstBufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
  534. _throw("Memory allocation failure");
  535. if((jdstBufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
  536. _throw("Memory allocation failure");
  537. if((dstSizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
  538. _throw("Memory allocation failure");
  539. if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
  540. _throw("Memory allocation failure");
  541. if((params=(JNICustomFilterParams *)malloc(sizeof(JNICustomFilterParams)*n))
  542. ==NULL)
  543. _throw("Memory allocation failure");
  544. for(i=0; i<n; i++)
  545. {
  546. dstBufs[i]=NULL; jdstBufs[i]=NULL; dstSizes[i]=0;
  547. memset(&t[i], 0, sizeof(tjtransform));
  548. memset(&params[i], 0, sizeof(JNICustomFilterParams));
  549. }
  550. for(i=0; i<n; i++)
  551. {
  552. jobject tobj, cfobj;
  553. bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i));
  554. bailif0(_cls=(*env)->GetObjectClass(env, tobj));
  555. bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I"));
  556. t[i].op=(*env)->GetIntField(env, tobj, _fid);
  557. bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I"));
  558. t[i].options=(*env)->GetIntField(env, tobj, _fid);
  559. bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I"));
  560. t[i].r.x=(*env)->GetIntField(env, tobj, _fid);
  561. bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I"));
  562. t[i].r.y=(*env)->GetIntField(env, tobj, _fid);
  563. bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I"));
  564. t[i].r.w=(*env)->GetIntField(env, tobj, _fid);
  565. bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I"));
  566. t[i].r.h=(*env)->GetIntField(env, tobj, _fid);
  567. bailif0(_fid=(*env)->GetFieldID(env, _cls, "cf",
  568. "Lorg/libjpegturbo/turbojpeg/TJCustomFilter;"));
  569. cfobj=(*env)->GetObjectField(env, tobj, _fid);
  570. if(cfobj)
  571. {
  572. params[i].env=env;
  573. params[i].tobj=tobj;
  574. params[i].cfobj=cfobj;
  575. t[i].customFilter=JNICustomFilter;
  576. t[i].data=(void *)&params[i];
  577. }
  578. }
  579. bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, jsrcBuf, 0));
  580. for(i=0; i<n; i++)
  581. {
  582. int w=jpegWidth, h=jpegHeight;
  583. if(t[i].r.w!=0) w=t[i].r.w;
  584. if(t[i].r.h!=0) h=t[i].r.h;
  585. bailif0(jdstBufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
  586. if((unsigned long)(*env)->GetArrayLength(env, jdstBufs[i])
  587. <tjBufSize(w, h, jpegSubsamp))
  588. _throw("Destination buffer is not large enough");
  589. bailif0(dstBufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstBufs[i], 0));
  590. }
  591. if(tjTransform(handle, jpegBuf, jpegSize, n, dstBufs, dstSizes, t,
  592. flags|TJFLAG_NOREALLOC)==-1)
  593. {
  594. (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
  595. jpegBuf=NULL;
  596. for(i=0; i<n; i++)
  597. {
  598. (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
  599. dstBufs[i]=NULL;
  600. }
  601. _throw(tjGetErrorStr());
  602. }
  603. jdstSizes=(*env)->NewIntArray(env, n);
  604. bailif0(dstSizesi=(*env)->GetIntArrayElements(env, jdstSizes, 0));
  605. for(i=0; i<n; i++) dstSizesi[i]=(int)dstSizes[i];
  606. bailout:
  607. if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcBuf, jpegBuf, 0);
  608. if(dstBufs)
  609. {
  610. for(i=0; i<n; i++)
  611. {
  612. if(dstBufs[i] && jdstBufs && jdstBufs[i])
  613. (*env)->ReleasePrimitiveArrayCritical(env, jdstBufs[i], dstBufs[i], 0);
  614. }
  615. free(dstBufs);
  616. }
  617. if(jdstBufs) free(jdstBufs);
  618. if(dstSizes) free(dstSizes);
  619. if(dstSizesi) (*env)->ReleaseIntArrayElements(env, jdstSizes, dstSizesi, 0);
  620. if(t) free(t);
  621. return jdstSizes;
  622. }
  623. JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
  624. (JNIEnv *env, jobject obj)
  625. {
  626. Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
  627. }