1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "jni_utils.h" 27 #include "com_sun_javafx_iio_ios_IosImageLoader.h" 28 29 #import "ImageLoader.h" 30 31 #include "debug.h" 32 33 #define BUFFER_SIZE 8 * 1024 34 35 36 // NOTE: 37 // It seems to be inefficient to decode the stream progressively. 38 // Thus we download the input stream to memory at once and decompress it then. 39 40 // Maybe we could get motivated here: 41 //http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/ 42 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 static jmethodID InputStream_readID; 49 static jmethodID InputStream_skipID; 50 static jmethodID IosImageLoader_setInputParametersID; 51 static jmethodID IosImageLoader_updateImageProgressID; 52 53 JNIEXPORT jint JNICALL 54 JNI_OnLoad_nativeiio(JavaVM *vm, void *reserved) { 55 #ifdef JNI_VERSION_1_8 56 //min. returned JNI_VERSION required by JDK8 for builtin libraries 57 JNIEnv *env; 58 if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_8) != JNI_OK) { 59 return JNI_VERSION_1_2; 60 } 61 return JNI_VERSION_1_8; 62 #else 63 return JNI_VERSION_1_2; 64 #endif 65 } 66 67 68 /* 69 * Class: com_sun_javafx_iio_ios_IosImageLoader 70 * Method: initNativeLoading 71 * Signature: ()V 72 */ 73 JNIEXPORT void JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_initNativeLoading 74 (JNIEnv *env, jclass klazz) { 75 76 IIOLog(@"IosImageLoader_initNativeLoading"); 77 78 jclass cls_InputStream = (*env)->FindClass(env, "java/io/InputStream"); 79 if (cls_InputStream == NULL) { 80 81 throwException(env, 82 "java/lang/ClassNotFoundException", 83 "Cannot find class java.io.InputStream"); 84 85 return; 86 } 87 88 InputStream_readID = (*env)->GetMethodID(env, 89 cls_InputStream, 90 "read", 91 "([BII)I"); 92 InputStream_skipID = (*env)->GetMethodID(env, 93 cls_InputStream, 94 "skip", 95 "(J)J"); 96 97 IosImageLoader_setInputParametersID = (*env)->GetMethodID(env, 98 klazz, 99 "setInputParameters", 100 "(IIII)V"); 101 IosImageLoader_updateImageProgressID = (*env)->GetMethodID(env, 102 klazz, 103 "updateProgress", 104 "(F)V"); 105 106 (*env)->DeleteLocalRef(env, cls_InputStream); 107 } 108 109 /* 110 * Class: com_sun_javafx_iio_ios_IosImageLoader 111 * Method: loadImage 112 * Signature: (Ljava/lang/String;Z)J 113 */ 114 JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_loadImageFromURL 115 (JNIEnv *env, jobject obj, jstring jStringURL, jboolean reportProgress) { 116 117 IIOLog(@"IosImageLoader_loadImageFromURL"); 118 119 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 120 121 ImageLoader *loader = [[ImageLoader alloc] init]; 122 123 const char *urlNativeString = (*env)->GetStringUTFChars(env, jStringURL, 0); 124 NSString *url = [NSString stringWithCString : urlNativeString 125 encoding : NSUTF8StringEncoding]; 126 (*env)->ReleaseStringUTFChars(env, jStringURL, urlNativeString); 127 128 IIOLog(@"Image URL: %@", url); 129 130 BOOL isLoaded = [loader loadFromURL : url 131 JNIEnv : env]; 132 133 if (!isLoaded) { 134 [pool release]; 135 return 0L; 136 } 137 138 (*env)->CallVoidMethod(env, 139 obj, 140 IosImageLoader_setInputParametersID, 141 (jint) [loader width], 142 (jint) [loader height], 143 (jint) [loader nImages], 144 (jint) [loader loopCount]); 145 146 (*env)->CallVoidMethod(env, 147 obj, 148 IosImageLoader_updateImageProgressID, 149 100.0f); 150 151 [pool release]; 152 153 return ptr_to_jlong(loader); 154 155 } 156 157 /* 158 * Class: com_sun_javafx_iio_ios_IosImageLoader 159 * Method: loadImage 160 * Signature: (Ljava/io/InputStream;Z)J 161 */ 162 JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_loadImage 163 (JNIEnv *env, jobject obj, jobject inputStream, jboolean reportProgress) { 164 165 IIOLog(@"IosImageLoader_loadImage"); 166 167 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 168 169 jbyteArray buffer = (*env)->NewByteArray(env, BUFFER_SIZE); 170 if (buffer == NULL) { 171 throwException(env, 172 "java/lang/OutOfMemoryError", 173 "Cannot initilialize memory buffer for native image loader"); 174 175 [pool release]; 176 return 0L; 177 } 178 179 ImageLoader *loader = [[ImageLoader alloc] init]; 180 181 int bytesRead = 0; 182 jboolean iscopy = FALSE; 183 jbyte *primitiveArray = (*env)->GetPrimitiveArrayCritical(env, buffer, &iscopy); 184 185 do { 186 bytesRead = (*env)->CallIntMethod(env, 187 inputStream, 188 InputStream_readID, 189 buffer, 190 0, 191 (jint) BUFFER_SIZE); 192 if (bytesRead != -1) { 193 [loader addToBuffer : (const unsigned char *) primitiveArray 194 length : bytesRead]; 195 } 196 } while (bytesRead != -1); 197 198 BOOL isLoaded = [loader loadFromBuffer : env]; 199 200 (*env)->ReleasePrimitiveArrayCritical(env, buffer, primitiveArray, JNI_ABORT); 201 202 if (!isLoaded) { 203 [pool release]; 204 return 0L; 205 } 206 207 (*env)->CallVoidMethod(env, 208 obj, 209 IosImageLoader_setInputParametersID, 210 (jint) [loader width], 211 (jint) [loader height], 212 (jint) [loader nImages], 213 (jint) [loader loopCount]); 214 215 (*env)->CallVoidMethod(env, 216 obj, 217 IosImageLoader_updateImageProgressID, 218 100.0f); 219 220 [pool release]; 221 222 return ptr_to_jlong(loader); 223 } 224 225 226 /* 227 * Class: com_sun_javafx_iio_ios_IosImageLoader 228 * Method: resizeImage 229 * Signature: (JII)V 230 */ 231 JNIEXPORT void JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_resizeImage 232 (JNIEnv *env, jobject obj, jlong loaderRef, jint width, jint height) { 233 234 IIOLog(@"IosImageLoader_resizeImage"); 235 236 ImageLoader *loader = (ImageLoader *) jlong_to_ptr(loaderRef); 237 238 [loader resize : (int) width 239 : (int) height]; 240 } 241 242 /* 243 * Class: com_sun_javafx_iio_ios_IosImageLoader 244 * Method: getImageBuffer 245 * Signature: (JI)[B 246 */ 247 JNIEXPORT jbyteArray JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_getImageBuffer 248 (JNIEnv *env, jobject obj, jlong loaderRef, jint imageIndex) { 249 250 IIOLog(@"IosImageLoader_getImageBuffer for image number %ld", imageIndex); 251 252 ImageLoader *loader = (ImageLoader *) jlong_to_ptr(loaderRef); 253 254 return [loader getDecompressedBuffer : env 255 imageIndex : imageIndex]; 256 257 } 258 259 /* 260 * Class: com_sun_javafx_iio_ios_IosImageLoader 261 * Method: getNumberOfComponents 262 * Signature: (J)I 263 */ 264 JNIEXPORT jint JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_getNumberOfComponents 265 (JNIEnv *env, jobject obj, jlong loaderRef) { 266 267 IIOLog(@"IosImageLoader_getNumberOfComponents"); 268 269 ImageLoader *loader = (ImageLoader *) jlong_to_ptr(loaderRef); 270 271 return (jint) [loader nComponents]; 272 } 273 274 /* 275 * Class: com_sun_javafx_iio_ios_IosImageLoader 276 * Method: getColorSpaceCode 277 * Signature: (J)I 278 */ 279 JNIEXPORT jint JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_getColorSpaceCode 280 (JNIEnv *env, jobject obj, jlong loaderRef) { 281 282 IIOLog(@"IosImageLoader_getColorSpaceCode"); 283 284 ImageLoader *loader = (ImageLoader *) jlong_to_ptr(loaderRef); 285 286 return (jint) [loader colorSpace]; 287 } 288 289 /* 290 * Class: com_sun_javafx_iio_ios_IosImageLoader 291 * Method: getDelayTime 292 * Signature: (J)I 293 */ 294 JNIEXPORT jint JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_getDelayTime 295 (JNIEnv *env, jobject obj, jlong loaderRef) { 296 297 IIOLog(@"IosImageLoader_getDelayTime"); 298 299 ImageLoader *loader = (ImageLoader *) jlong_to_ptr(loaderRef); 300 301 return (jint) [loader delayTime]; 302 } 303 304 /* 305 * Class: com_sun_javafx_iio_ios_IosImageLoader 306 * Method: disposeLoader 307 * Signature: (J)V 308 */ 309 JNIEXPORT void JNICALL Java_com_sun_javafx_iio_ios_IosImageLoader_disposeLoader 310 (JNIEnv *env, jclass klazz, jlong loaderRef) { 311 312 IIOLog(@"IosImageLoader_disposeLoader"); 313 314 ImageLoader *loader = (ImageLoader *) jlong_to_ptr(loaderRef); 315 316 [loader release]; 317 } 318 319 #ifdef __cplusplus 320 } 321 #endif