Home | History | Annotate | Download | only in jpegstream
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.gallery3d.jpegstream;
     18 
     19 import java.io.FilterOutputStream;
     20 import java.io.IOException;
     21 import java.io.OutputStream;
     22 public class JPEGOutputStream extends FilterOutputStream {
     23     private long JNIPointer = 0; // Used by JNI code. Don't touch.
     24 
     25     private byte[] mTmpBuffer = new byte[1];
     26     private int mWidth = 0;
     27     private int mHeight = 0;
     28     private int mQuality = 0;
     29     private int mFormat = -1;
     30     private boolean mValidConfig = false;
     31     private boolean mConfigChanged = false;
     32 
     33     public JPEGOutputStream(OutputStream out) {
     34         super(out);
     35     }
     36 
     37     public JPEGOutputStream(OutputStream out, int width, int height, int quality,
     38             int format) {
     39         super(out);
     40         setConfig(width, height, quality, format);
     41     }
     42 
     43     public boolean setConfig(int width, int height, int quality, int format) {
     44         // Clamp quality to range (0, 100]
     45         quality = Math.max(Math.min(quality, 100), 1);
     46 
     47         // Make sure format is valid
     48         switch (format) {
     49             case JpegConfig.FORMAT_GRAYSCALE:
     50             case JpegConfig.FORMAT_RGB:
     51             case JpegConfig.FORMAT_ABGR:
     52             case JpegConfig.FORMAT_RGBA:
     53                 break;
     54             default:
     55                 return false;
     56         }
     57 
     58         // If valid, set configuration
     59         if (width > 0 && height > 0) {
     60             mWidth = width;
     61             mHeight = height;
     62             mFormat = format;
     63             mQuality = quality;
     64             mValidConfig = true;
     65             mConfigChanged = true;
     66         } else {
     67             return false;
     68         }
     69 
     70         return mValidConfig;
     71     }
     72 
     73     @Override
     74     public void close() throws IOException {
     75         cleanup();
     76         super.close();
     77     }
     78 
     79     @Override
     80     public void write(byte[] buffer, int offset, int length) throws IOException {
     81         if (offset < 0 || length < 0 || (offset + length) > buffer.length) {
     82             throw new ArrayIndexOutOfBoundsException(String.format(
     83                     " buffer length %d, offset %d, length %d",
     84                     buffer.length, offset, length));
     85         }
     86         if (!mValidConfig) {
     87             return;
     88         }
     89         if (mConfigChanged) {
     90             cleanup();
     91             int flag = setup(out, mWidth, mHeight, mFormat, mQuality);
     92             switch(flag) {
     93                 case JpegConfig.J_SUCCESS:
     94                     break; // allow setup to continue
     95                 case JpegConfig.J_ERROR_BAD_ARGS:
     96                     throw new IllegalArgumentException("Bad arguments to write");
     97                 default:
     98                     throw new IOException("Error to writing jpeg headers.");
     99             }
    100             mConfigChanged = false;
    101         }
    102         int returnCode = JpegConfig.J_ERROR_FATAL;
    103         try {
    104             returnCode = writeInputBytes(buffer, offset, length);
    105         } finally {
    106             if (returnCode < 0) {
    107                 cleanup();
    108             }
    109         }
    110         if (returnCode < 0) {
    111             throw new IOException("Error writing jpeg stream");
    112         }
    113     }
    114 
    115     @Override
    116     public void write(byte[] buffer) throws IOException {
    117         write(buffer, 0, buffer.length);
    118     }
    119 
    120     @Override
    121     public void write(int oneByte) throws IOException {
    122         mTmpBuffer[0] = (byte) oneByte;
    123         write(mTmpBuffer);
    124     }
    125 
    126     @Override
    127     protected void finalize() throws Throwable {
    128         try {
    129             cleanup();
    130         } finally {
    131             super.finalize();
    132         }
    133     }
    134 
    135     native private int setup(OutputStream out, int width, int height, int format, int quality);
    136 
    137     native private void cleanup();
    138 
    139     native private int writeInputBytes(byte[] inBuffer, int offset, int inCount);
    140 
    141     static {
    142         System.loadLibrary("jni_jpegstream");
    143     }
    144 }
    145