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 package com.sun.javafx.iio.ios; 27 28 import com.sun.glass.utils.NativeLibLoader; 29 import com.sun.javafx.iio.common.*; 30 import com.sun.javafx.iio.ImageFrame; 31 import com.sun.javafx.iio.ImageMetadata; 32 import com.sun.javafx.iio.ImageStorage.ImageType; 33 import com.sun.javafx.iio.common.ImageLoaderImpl; 34 import com.sun.javafx.iio.common.ImageTools; 35 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.nio.ByteBuffer; 39 import java.security.AccessController; 40 import java.security.PrivilegedAction; 41 42 import java.util.Map; 43 import java.util.HashMap; 44 45 import java.net.URL; 46 import java.net.MalformedURLException; 47 48 /** 49 * A loader for images on iOS platform. 50 */ 51 public class IosImageLoader extends ImageLoaderImpl { 52 53 /** These constants must match with those in native */ 54 public static final int GRAY = 0; 55 public static final int GRAY_ALPHA = 1; 56 public static final int GRAY_ALPHA_PRE = 2; 57 public static final int PALETTE = 3; 58 public static final int PALETTE_ALPHA = 4; 59 public static final int PALETTE_ALPHA_PRE = 5; 60 public static final int PALETTE_TRANS = 6; 61 public static final int RGB = 7; 62 public static final int RGBA = 8; 63 public static final int RGBA_PRE = 9; 64 65 private static final Map<Integer, ImageType> colorSpaceMapping = new HashMap<Integer, ImageType>(); 66 67 /** Pointer to the native loader */ 68 private long structPointer; 69 70 /** Set by native code */ 71 private int inWidth; 72 private int inHeight; 73 private int nImages; 74 75 private boolean isDisposed = false; 76 77 private int delayTime; // applicable to animated images only 78 private int loopCount; // applicable to animated images only 79 80 /***************************** Native Loader methods ******************************************/ 81 82 /** Set up static method IDs for calls back to Java. */ 83 private static native void initNativeLoading(); 84 85 /** Create a loader and buffer data from the InputStream. Report progress if requested. */ 86 private native long loadImage(final InputStream stream, boolean reportProgress) throws IOException; 87 88 /** Create a loader for the given URL. Report progress if requested. */ 89 private native long loadImageFromURL(final String url, boolean reportProgress) throws IOException; 90 91 /** Set native image size */ 92 private native void resizeImage(long structPointer, int width, int height); 93 94 /** Return a buffer with decompressed image data */ 95 private native byte[] getImageBuffer(long structPointer, int imageIndex); 96 97 /** Return the number of color components */ 98 private native int getNumberOfComponents(long structPointer); 99 100 /** Return image color space model code */ 101 private native int getColorSpaceCode(long structPointer); 102 103 /** Return image duration for animated images */ 104 private native int getDelayTime(long structPointer); 105 106 /** Destroy a loader. */ 107 private static native void disposeLoader(long structPointer); 108 109 /*************************** End of Native Loader methods ***************************************/ 110 111 112 static { 113 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 114 NativeLibLoader.loadLibrary("nativeiio"); 115 return null; 116 }); 117 118 colorSpaceMapping.put(GRAY, ImageType.GRAY); 119 colorSpaceMapping.put(GRAY_ALPHA, ImageType.GRAY_ALPHA); 120 colorSpaceMapping.put(GRAY_ALPHA_PRE, ImageType.GRAY_ALPHA_PRE); 121 colorSpaceMapping.put(PALETTE, ImageType.PALETTE); 122 colorSpaceMapping.put(PALETTE_ALPHA, ImageType.PALETTE_ALPHA); 123 colorSpaceMapping.put(PALETTE_ALPHA_PRE, ImageType.PALETTE_ALPHA_PRE); 124 colorSpaceMapping.put(PALETTE_TRANS, ImageType.PALETTE_TRANS); 125 colorSpaceMapping.put(RGB, ImageType.RGB); 126 colorSpaceMapping.put(RGBA, ImageType.RGBA); 127 colorSpaceMapping.put(RGBA_PRE, ImageType.RGBA_PRE); 128 129 initNativeLoading(); 130 } 131 132 /** Called by the native code when input parameters are known. */ 133 private void setInputParameters( 134 int width, 135 int height, 136 int imageCount, 137 int loopCount) { 138 139 inWidth = width; 140 inHeight = height; 141 nImages = imageCount; 142 this.loopCount = loopCount; 143 } 144 145 private void updateProgress(float progressPercentage) { 146 updateImageProgress(progressPercentage); 147 } 148 149 private boolean shouldReportProgress() { 150 return listeners != null && !listeners.isEmpty(); 151 } 152 153 private void checkNativePointer() throws IOException { 154 if (structPointer == 0L) { 155 throw new IOException("Unable to initialize image native loader!"); 156 } 157 } 158 159 private void retrieveDelayTime() { 160 if (nImages > 1) { 161 delayTime = getDelayTime(structPointer); 162 } 163 } 164 165 public IosImageLoader(final String urlString, final ImageDescriptor desc) throws IOException { 166 super(desc); 167 168 // see if the given URL is valid 169 try { 170 final URL url = new URL(urlString); 171 } 172 catch (MalformedURLException mue) { 173 throw new IllegalArgumentException("Image loader: Malformed URL!"); 174 } 175 176 try { 177 structPointer = loadImageFromURL(urlString, shouldReportProgress()); 178 } catch (IOException e) { 179 dispose(); 180 throw e; 181 } 182 183 checkNativePointer(); 184 retrieveDelayTime(); 185 } 186 187 public IosImageLoader(final InputStream inputStream, final ImageDescriptor desc) throws IOException { 188 super(desc); 189 if (inputStream == null) { 190 throw new IllegalArgumentException("Image loader: input stream == null"); 191 } 192 193 try { 194 structPointer = loadImage(inputStream, shouldReportProgress()); 195 } catch (IOException e) { 196 dispose(); 197 throw e; 198 } 199 200 checkNativePointer(); 201 retrieveDelayTime(); 202 } 203 204 /** 205 * @inheritDoc 206 */ 207 public synchronized void dispose() { 208 if (!isDisposed && structPointer != 0L) { 209 isDisposed = true; 210 IosImageLoader.disposeLoader(structPointer); 211 structPointer = 0L; 212 } 213 } 214 215 protected void finalize() { 216 dispose(); 217 } 218 219 /** 220 * @inheritDoc 221 */ 222 public ImageFrame load(int imageIndex, int width, int height, boolean preserveAspectRatio, boolean smooth) 223 throws IOException { 224 225 if (imageIndex >= nImages) { 226 dispose(); 227 return null; 228 } 229 230 // Determine output image dimensions. 231 int[] widthHeight = ImageTools.computeDimensions(inWidth, inHeight, width, height, preserveAspectRatio); 232 width = widthHeight[0]; 233 height = widthHeight[1]; 234 235 final ImageMetadata md = new ImageMetadata( 236 null, // gamma 237 true, // whether smaller values represent darker shades 238 null, // a palette index to use as background 239 null, // background color 240 null, // a palette index to be used as transparency 241 delayTime == 0 ? null : delayTime, // the amount of time to pause at the current image (milliseconds). 242 nImages > 1 ? loopCount : null, // number of loops 243 inWidth, // source width 244 inHeight, // source height 245 null, // image left offset 246 null, // image top offset 247 null); // disposal method 248 249 updateImageMetadata(md); 250 251 resizeImage(structPointer, width, height); 252 253 // the color model and the number of components can change when resizing 254 final int nComponents = getNumberOfComponents(structPointer); 255 final int colorSpaceCode = getColorSpaceCode(structPointer); 256 final ImageType imageType = colorSpaceMapping.get(colorSpaceCode); 257 258 final byte[] pixels = getImageBuffer(structPointer, imageIndex); 259 260 return new ImageFrame(imageType, 261 ByteBuffer.wrap(pixels), 262 width, 263 height, 264 width * nComponents, 265 null, 266 md); 267 } 268 }