1 /*
   2  * Copyright (c) 1995, 2018, 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  *      Reads JPEG images from an InputStream and reports the
  27  *      image data to an InputStreamImageSource object.
  28  *
  29  * The native implementation of the JPEG image decoder was adapted from
  30  * release 6 of the free JPEG software from the Independent JPEG Group.
  31  */
  32 package sun.awt.image;
  33 
  34 import java.util.Vector;
  35 import java.util.Hashtable;
  36 import java.io.InputStream;
  37 import java.io.IOException;
  38 import java.awt.image.*;
  39 
  40 /**
  41  * JPEG Image converter
  42  *
  43  * @author Jim Graham
  44  */
  45 public class JPEGImageDecoder extends ImageDecoder {
  46     private static ColorModel RGBcolormodel;
  47     private static ColorModel ARGBcolormodel;
  48     private static ColorModel Graycolormodel;
  49 
  50     private static final Class<?> InputStreamClass = InputStream.class;
  51     private static native void initIDs(Class<?> InputStreamClass);
  52 
  53     private ColorModel colormodel;
  54 
  55     static {
  56         java.security.AccessController.doPrivileged(
  57             new java.security.PrivilegedAction<Void>() {
  58                 public Void run() {
  59                     System.loadLibrary("javajpeg");
  60                     return null;
  61                 }
  62             });
  63         initIDs(InputStreamClass);
  64         RGBcolormodel = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
  65         ARGBcolormodel = ColorModel.getRGBdefault();
  66         byte[] g = new byte[256];
  67         for (int i = 0; i < 256; i++) {
  68             g[i] = (byte) i;
  69         }
  70         Graycolormodel = new IndexColorModel(8, 256, g, g, g);
  71     }
  72 
  73     private native void readImage(InputStream is, byte[] buf)
  74         throws ImageFormatException, IOException;
  75 
  76     Hashtable<String, Object> props = new Hashtable<>();
  77 
  78     public JPEGImageDecoder(InputStreamImageSource src, InputStream is) {
  79         super(src, is);
  80     }
  81 
  82     /**
  83      * An error has occurred. Throw an exception.
  84      */
  85     private static void error(String s1) throws ImageFormatException {
  86         throw new ImageFormatException(s1);
  87     }
  88 
  89     public boolean sendHeaderInfo(int width, int height,
  90                                   boolean gray, boolean hasalpha,
  91                                   boolean multipass)
  92     {
  93         setDimensions(width, height);
  94 
  95         setProperties(props);
  96         if (gray) {
  97             colormodel = Graycolormodel;
  98         } else {
  99             if (hasalpha) {
 100                 colormodel = ARGBcolormodel;
 101             } else {
 102                 colormodel = RGBcolormodel;
 103             }
 104         }
 105 
 106         setColorModel(colormodel);
 107 
 108         int flags = hintflags;
 109         if (!multipass) {
 110             flags |= ImageConsumer.SINGLEPASS;
 111         }
 112         setHints(hintflags);
 113         headerComplete();
 114 
 115         return true;
 116     }
 117 
 118     public boolean sendPixels(int[] pixels, int y) {
 119         int count = setPixels(0, y, pixels.length, 1, colormodel,
 120                               pixels, 0, pixels.length);
 121         if (count <= 0) {
 122             aborted = true;
 123         }
 124         return !aborted;
 125     }
 126 
 127     public boolean sendPixels(byte[] pixels, int y) {
 128         int count = setPixels(0, y, pixels.length, 1, colormodel,
 129                               pixels, 0, pixels.length);
 130         if (count <= 0) {
 131             aborted = true;
 132         }
 133         return !aborted;
 134     }
 135 
 136     /**
 137      * produce an image from the stream.
 138      */
 139     public void produceImage() throws IOException, ImageFormatException {
 140         try {
 141             readImage(input, new byte[1024]);
 142             if (!aborted) {
 143                 imageComplete(ImageConsumer.STATICIMAGEDONE, true);
 144             }
 145         } catch (IOException e) {
 146             if (!aborted) {
 147                 throw e;
 148             }
 149         } finally {
 150             close();
 151         }
 152     }
 153 
 154     /**
 155      * The ImageConsumer hints flag for a JPEG image.
 156      */
 157     private static final int hintflags =
 158         ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
 159         ImageConsumer.SINGLEFRAME;
 160 }