summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/javax/imageio/jpeg
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/javax/imageio/jpeg')
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/DCT.java347
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java207
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java351
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java625
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java48
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java108
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java188
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java141
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java137
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java205
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java50
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java151
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java113
-rw-r--r--libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java520
14 files changed, 3191 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/DCT.java b/libjava/classpath/gnu/javax/imageio/jpeg/DCT.java
new file mode 100644
index 000000000..fda52e5f5
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/DCT.java
@@ -0,0 +1,347 @@
+/* DCT.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+/**
+ * Discrete Cosine Transformations.
+ */
+public class DCT
+{
+
+ /**
+ * Cosine matrix
+ */
+ public double c[][] = new double[8][8];
+
+ /**
+ * Transformed cosine matrix
+ */
+ public double cT[][] = new double[8][8];
+
+ public DCT()
+ {
+ initMatrix();
+ }
+
+ /**
+ * Figure A.3.3 IDCT, Cu Cv on A-5 of the ISO DIS 10918-1. Requirements and
+ * Guidelines.
+ *
+ * @param u
+ * @return
+ */
+ public static double C(int u)
+ {
+ return ((u == 0) ? (double) 1 / (double) Math.sqrt((double) 2)
+ : (double) 1);
+ }
+
+ /**
+ * Initialize matrix values for the fast_idct function
+ */
+ private void initMatrix()
+ {
+ for (int j = 0; j < 8; j++)
+ {
+ double nn = (double) (8);
+ c[0][j] = 1.0 / Math.sqrt(nn);
+ cT[j][0] = c[0][j];
+ }
+ for (int i = 1; i < 8; i++)
+ {
+ for (int j = 0; j < 8; j++)
+ {
+ double jj = (double) j;
+ double ii = (double) i;
+ c[i][j] =
+ Math.sqrt(2.0 / 8.0)
+ * Math.cos(((2.0 * jj + 1.0) * ii * Math.PI) / (2.0 * 8.0));
+ cT[j][i] = c[i][j];
+ }
+ }
+ }
+
+ /**
+ * slow_idct - Figure A.3.3 IDCT (informative) on A-5 of the ISO DIS
+ * 10918-1. Requirements and Guidelines. This is a slow IDCT, there are
+ * better algorithms to use, it's fairly expensive with processor speed.
+ *
+ * @param matrix
+ * @return
+ */
+ public static double[][] slow_idct(double[][] matrix)
+ {
+ double[][] output = new double[matrix.length][matrix.length];
+ for (int y = 0; y < 8; y++)
+ {
+ for (int x = 0; x < 8; x++)
+ {
+ double val = 0;
+ for (double v = 0; v < 8; v++)
+ {
+ double innerloop = 0;
+ for (double u = 0; u < 8; u++)
+ innerloop += (DCT.C((int) u) / (double) 2)
+ * matrix[(int) v][(int) u]
+ * Math.cos((2 * x + 1) * u * Math.PI / (double) 16)
+ * Math.cos((2 * y + 1) * v * Math.PI / (double) 16);
+ val += (DCT.C((int) v) / (double) 2) * innerloop;
+ }
+ output[y][x] = (val + 128);
+ }
+ }
+ return (output);
+ }
+
+ public static float[][] slow_fdct(float[][] value)
+ {
+ float[][] buffer = new float[8][8];
+
+ for (int u = 0; u < 8; u++)
+ {
+ for (int v = 0; v < 8; v++)
+ {
+ buffer[u][v] =
+ (float) (1 / 4) * (float) C((int) u) * (float) C((int) v);
+ float innerval = 0;
+ for (int x = 0; x < 8; x++)
+ {
+ for (int y = 0; y < 8; y++)
+ {
+ innerval += value[y][x]
+ * Math.cos(((2 * x + 1) * u * Math.PI) / 16)
+ * Math.cos(((2 * y + 1) * v * Math.PI) / 16);
+ }
+ }
+ buffer[u][v] *= innerval;
+ }
+ }
+ return (buffer);
+ }
+
+ public float[][] fast_fdct(float[][] input)
+ {
+ float output[][] = new float[8][8];
+ double temp[][] = new double[8][8];
+ double temp1;
+ int i;
+ int j;
+ int k;
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ temp[i][j] = 0.0;
+ for (k = 0; k < 8; k++)
+ {
+ temp[i][j] += (((int) (input[i][k]) - 128) * cT[k][j]);
+ }
+ }
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ temp1 = 0.0;
+
+ for (k = 0; k < 8; k++)
+ {
+ temp1 += (c[i][k] * temp[k][j]);
+ }
+
+ output[i][j] = (int) Math.round(temp1) * 8;
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * fast_idct - Figure A.3.3 IDCT (informative) on A-5 of the ISO DIS
+ * 10918-1. Requires and Guidelines. This is a fast IDCT, it much more
+ * effecient and only inaccurate at about 1/1000th of a percent of values
+ * analyzed. Cannot be static because initMatrix must run before any
+ * fast_idct values can be computed.
+ *
+ * @param input
+ * @return
+ */
+ public double[][] fast_idct(double[][] input)
+ {
+ double output[][] = new double[8][8];
+ double temp[][] = new double[8][8];
+ double temp1;
+ int i, j, k;
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ temp[i][j] = 0.0;
+ for (k = 0; k < 8; k++)
+ {
+ temp[i][j] += input[i][k] * c[k][j];
+ }
+ }
+ }
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ temp1 = 0.0;
+ for (k = 0; k < 8; k++)
+ temp1 += cT[i][k] * temp[k][j];
+ temp1 += 128.0;
+ if (temp1 < 0)
+ output[i][j] = 0;
+ else if (temp1 > 255)
+ output[i][j] = 255;
+ else
+ output[i][j] = (int) Math.round(temp1);
+ }
+ }
+ return output;
+ }
+
+ public double[][] idj_fast_fdct(float input[][])
+ {
+ double output[][] = new double[8][8];
+ double tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ double tmp10, tmp11, tmp12, tmp13;
+ double z1, z2, z3, z4, z5, z11, z13;
+ int i;
+ int j;
+
+ // Subtracts 128 from the input values
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ output[i][j] = ((double) input[i][j] - (double) 128.0);
+ // input[i][j] -= 128;
+
+ }
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ tmp0 = output[i][0] + output[i][7];
+ tmp7 = output[i][0] - output[i][7];
+ tmp1 = output[i][1] + output[i][6];
+ tmp6 = output[i][1] - output[i][6];
+ tmp2 = output[i][2] + output[i][5];
+ tmp5 = output[i][2] - output[i][5];
+ tmp3 = output[i][3] + output[i][4];
+ tmp4 = output[i][3] - output[i][4];
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ output[i][0] = tmp10 + tmp11;
+ output[i][4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * (double) 0.707106781;
+ output[i][2] = tmp13 + z1;
+ output[i][6] = tmp13 - z1;
+
+ tmp10 = tmp4 + tmp5;
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ z5 = (tmp10 - tmp12) * (double) 0.382683433;
+ z2 = ((double) 0.541196100) * tmp10 + z5;
+ z4 = ((double) 1.306562965) * tmp12 + z5;
+ z3 = tmp11 * ((double) 0.707106781);
+
+ z11 = tmp7 + z3;
+ z13 = tmp7 - z3;
+
+ output[i][5] = z13 + z2;
+ output[i][3] = z13 - z2;
+ output[i][1] = z11 + z4;
+ output[i][7] = z11 - z4;
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ tmp0 = output[0][i] + output[7][i];
+ tmp7 = output[0][i] - output[7][i];
+ tmp1 = output[1][i] + output[6][i];
+ tmp6 = output[1][i] - output[6][i];
+ tmp2 = output[2][i] + output[5][i];
+ tmp5 = output[2][i] - output[5][i];
+ tmp3 = output[3][i] + output[4][i];
+ tmp4 = output[3][i] - output[4][i];
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ output[0][i] = tmp10 + tmp11;
+ output[4][i] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * (double) 0.707106781;
+ output[2][i] = tmp13 + z1;
+ output[6][i] = tmp13 - z1;
+
+ tmp10 = tmp4 + tmp5;
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ z5 = (tmp10 - tmp12) * (double) 0.382683433;
+ z2 = ((double) 0.541196100) * tmp10 + z5;
+ z4 = ((double) 1.306562965) * tmp12 + z5;
+ z3 = tmp11 * ((double) 0.707106781);
+
+ z11 = tmp7 + z3;
+ z13 = tmp7 - z3;
+
+ output[5][i] = z13 + z2;
+ output[3][i] = z13 - z2;
+ output[1][i] = z11 + z4;
+ output[7][i] = z11 - z4;
+ }
+
+ return output;
+ }
+
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java b/libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java
new file mode 100644
index 000000000..78f3c1c4f
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java
@@ -0,0 +1,207 @@
+/* HuffmanTable.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.io.IOException;
+
+import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
+
+
+/**
+ * This Object construct a JPEGHuffmanTable which can be used to encode/decode
+ * a scan from a JPEG codec stream. The table must be initalized with either a
+ * BITS byte amount and a Huffman Table Value for decoding or a Huffman Size
+ * and Huffman Code table for encoding.
+ */
+public class HuffmanTable
+{
+ public final static int HUFFMAN_MAX_TABLES = 4;
+
+ private short[] huffcode = new short[256];
+ private short[] huffsize = new short[256];
+ private short[] EHUFCO;
+ private short[] EHUFSI;
+ private short[] valptr = new short[16];
+ private short[] mincode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1,-1,-1};
+ private short[] maxcode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1};
+ private short[] huffval;
+ private short[] bits;
+
+ static byte JPEG_DC_TABLE = 0;
+ static byte JPEG_AC_TABLE = 1;
+
+ private short lastk = 0;
+
+ public HuffmanTable(JPEGHuffmanTable table)
+ {
+ huffcode = table.getValues();
+ bits = table.getLengths();
+ }
+
+ /**
+ * Generated from FIGURE C.1 - Generation of table of Huffman code sizes on
+ * ISO DIS 10918-1. Requirements and Guidelines
+ */
+ private void generateSizeTable()
+ {
+ short index=0;
+ for(short i=0; i < bits.length ; i++)
+ {
+ for(short j=0; j < bits[i] ; j++)
+ {
+ huffsize[index] = (short) (i+1);
+ index++;
+ }
+ }
+ lastk = index;
+ }
+
+ /**
+ * Generated from FIGURE C.2 - Generation of table of Huffman codes on
+ * ISO DIS 10918-1. Requirements and Guidelines
+ */
+ private void generateCodeTable()
+ {
+ short k=0;
+ short si = huffsize[0];
+ short code = 0;
+ for(short i=0; i < huffsize.length ; i++)
+ {
+ while(huffsize[k]==si)
+ {
+ huffcode[k] = code;
+ code++;
+ k++;
+ }
+ code <<= 1;
+ si++;
+ }
+ }
+
+ /**
+ * Generated from FIGURE F.15 - Generation of decode table generation on
+ * ISO DIS 10918-1. Requirements and Guidelines
+ */
+ private void generateDecoderTables()
+ {
+ short bitcount = 0;
+ for(int i=0; i < 16 ; i++)
+ {
+ if(bits[i]!=0)
+ valptr[i] = bitcount;
+ for(int j=0 ; j < bits[i] ; j++)
+ {
+ if(huffcode[j+bitcount] < mincode[i] || mincode[i] == -1)
+ mincode[i] = huffcode[j+bitcount];
+
+ if(huffcode[j+bitcount] > maxcode[i])
+ maxcode[i] = huffcode[j+bitcount];
+ }
+ if(mincode[i]!=-1)
+ valptr[i] = (short) (valptr[i] - mincode[i]);
+ bitcount += bits[i];
+ }
+ }
+
+ /**
+ * Generated from FIGURE C.3 - Generation of Order Codes and tables EHUFCO
+ * and EHUFSI from the ISO DIS 10918-1. Requirements and Guidelines
+ */
+ public void orderCodes(boolean isDC)
+ {
+ EHUFCO = new short[isDC ? 15 : 255];
+ EHUFSI = new short[isDC ? 15 : 255];
+
+ for (int p=0; p < lastk ; p++)
+ {
+ int i = huffval[p];
+ if(i < 0 || i > EHUFCO.length || EHUFSI[i]!=0)
+ System.err.println("Error, bad huffman table.");
+ EHUFCO[i] = huffcode[p];
+ EHUFSI[i] = huffsize[p];
+ }
+ }
+
+ /**
+ * Generated from FIGURE F.12 - Extending the sign bit of a decoded value in on
+ * ISO DIS 10918-1. Requirements and Guidelines<p>
+ *
+ * @param diff TODO
+ * @param t TODO
+ * @return TODO
+ */
+ public static int extend(int diff, int t)
+ {
+ int Vt = (int)Math.pow(2,(t-1));
+ if(diff<Vt)
+ {
+ Vt=(-1 << t)+1;
+ diff=diff+Vt;
+ }
+ return diff;
+ }
+
+ /**
+ * Generated from FIGURE F.16 - Procedure for DECODE on
+ * ISO DIS 10918-1. Requirements and Guidelines<p>
+ *
+ * This function takes in a dynamic amount of bits and using the Huffman
+ * table returns information on how many bits must be read in to a byte in
+ * order to reconstruct said byte.
+ *
+ * @param JPEGStream the bits of the data stream.
+ */
+ public int decode(JPEGImageInputStream JPEGStream)
+ throws IOException, JPEGException
+ {
+ int i=0;
+ short code = (short) JPEGStream.readBits(1);
+ while(code > maxcode[i])
+ {
+ i++;
+ code <<= 1;
+ code |= JPEGStream.readBits(1);
+ }
+ int val = huffval[code+(valptr[i])];
+ if(val < 0)
+ val = 256 + val;
+ return val;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java
new file mode 100644
index 000000000..7be67a02a
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java
@@ -0,0 +1,351 @@
+/* JPEGComponent.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.util.ArrayList;
+import java.io.IOException;
+import java.awt.image.WritableRaster;
+
+import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
+
+/**
+ * This class holds the methods to decode and write a component information to
+ * a raster.
+ */
+public class JPEGComponent
+{
+ public byte factorH, factorV, component_id, quant_id;
+ public int width = 0, height = 0, maxV = 0, maxH = 0;
+ public HuffmanTable ACTable;
+ public HuffmanTable DCTable;
+ public int[] quantizationTable;
+ public double previousDC = 0;
+ ArrayList data = new ArrayList();
+
+ /**
+ * Initializes the component
+ *
+ * @param id
+ * @param factorHorizontal
+ * @param factorVertical
+ * @param quantizationID
+ */
+ public JPEGComponent(byte id, byte factorHorizontal, byte factorVertical,
+ byte quantizationID)
+ {
+ component_id = id;
+ factorH = factorHorizontal;
+ factorV = factorVertical;
+ quant_id = quantizationID;
+ }
+
+ /**
+ * If a restart marker is found with too little of an MCU count (i.e. our
+ * Restart Interval is 63 and we have 61 we copy the last MCU until it's
+ * full)
+ *
+ * @param index
+ * @param length
+ */
+ public void padMCU(int index, int length)
+ {
+ double[] src = (double[]) data.get(index - 1);
+ for (int i = 0; i < length; i++)
+ data.add(index, src);
+ }
+
+ /**
+ * Reset the interval by setting the previous DC value
+ */
+ public void resetInterval()
+ {
+ previousDC = 0;
+ }
+
+ /**
+ * Run the Quantization backward method on all of the block data.
+ */
+ public void quantitizeData()
+ {
+ for (int i = 0; i < data.size(); i++)
+ {
+ double[] mydata = (double[]) data.get(i);
+ for (int j = 0; j < mydata.length; j++)
+ mydata[j] *= quantizationTable[j];
+ }
+ }
+
+ public void setDCTable(JPEGHuffmanTable table)
+ {
+ DCTable = new HuffmanTable(table);
+ }
+
+ public void setACTable(JPEGHuffmanTable table)
+ {
+ ACTable = new HuffmanTable(table);
+ }
+
+ /**
+ * Run the Inverse DCT method on all of the block data
+ */
+ public void idctData(DCT myDCT)
+ {
+ for (int i = 0; i < data.size(); i++)
+ data.add(i,myDCT.fast_idct(ZigZag.decode8x8_map((double[]) data.remove(i))));
+ }
+
+ /**
+ * This scales up the component size based on the factor size. This
+ * calculates everyting up automatically so it's simply ran at the end of
+ * the frame to normalize the size of all of the components.
+ */
+ public void scaleByFactors()
+ {
+ int factorUpVertical = maxV / factorV;
+ int factorUpHorizontal = maxH / factorH;
+
+ if (factorUpVertical > 1)
+ {
+ for (int i = 0; i < data.size(); i++)
+ {
+ double[][] src = (double[][]) data.remove(i);
+ double[][] dest =
+ new double[src.length * factorUpVertical][src[0].length];
+ for (int j = 0; j < src.length; j++)
+ {
+ for (int u = 0; u < factorUpVertical; u++)
+ {
+ dest[j * factorUpVertical + u] = src[j];
+ }
+ }
+ data.add(i, dest);
+ }
+ }
+
+ if (factorUpHorizontal > 1)
+ {
+ for (int i = 0; i < data.size(); i++)
+ {
+ double[][] src = (double[][]) data.remove(i);
+ double[][] dest =
+ new double[src.length][src[0].length * factorUpHorizontal];
+ for (int j = 0; j < src.length; j++)
+ {
+ for (int u = 0; u < src[0].length; u++)
+ {
+ for (int v = 0; v < factorUpHorizontal; v++)
+ dest[j][u * factorUpHorizontal + v] = src[j][u];
+ }
+ }
+ data.add(i, dest);
+ }
+ }
+ }
+
+ /**
+ * This write the block of data to the raster throwing out anything that
+ * spills over the raster width or height.
+ *
+ * @param raster
+ * @param data
+ * @param compIndex
+ * @param x
+ * @param y
+ */
+ public void writeBlock(WritableRaster raster, double[][] data,
+ int compIndex, int x, int y)
+ {
+ for (int yIndex = 0; yIndex < data.length; yIndex++)
+ {
+ for (int xIndex = 0; xIndex < data[yIndex].length; xIndex++)
+ {
+ // The if statement is needed because blocks can spill over the
+ // frame width because they are padded to make sure we keep the
+ // height of the block the same as the width of the block
+ if (x + xIndex < raster.getWidth()
+ && y + yIndex < raster.getHeight())
+ raster.setSample(x + xIndex, y + yIndex, compIndex,
+ data[yIndex][xIndex]);
+ }
+ }
+ }
+
+ /**
+ * This writes data to a raster block, so really it's reading not writing
+ * but it writes the data to the raster block by factor size in a zig zag
+ * fashion. This has the helper function writeBlock which does the actual
+ * writing.
+ *
+ * @param raster
+ * @param componentIndex
+ */
+ public void writeData(WritableRaster raster, int componentIndex)
+ {
+ int x = 0, y = 0, lastblockheight = 0, incrementblock = 0;
+
+ // Keep looping through all of the blocks until there are no more.
+ while(data.size() > 0)
+ {
+ int blockwidth = 0;
+ int blockheight = 0;
+
+ if (x >= raster.getWidth())
+ {
+ x = 0;
+ y += incrementblock;
+ }
+
+ // Loop through the horizontal component blocks of the MCU first
+ // then for each horizontal line write out all of the vertical
+ // components
+ for (int factorVIndex = 0; factorVIndex < factorV; factorVIndex++)
+ {
+ blockwidth = 0;
+
+ for (int factorHIndex = 0; factorHIndex < factorH; factorHIndex++)
+ {
+ // Captures the width of this block so we can increment the
+ // X coordinate
+ double[][] blockdata = (double[][]) data.remove(0);
+
+ // Writes the data at the specific X and Y coordinate of
+ // this component
+ writeBlock(raster, blockdata, componentIndex, x, y);
+ blockwidth += blockdata[0].length;
+ x += blockdata[0].length;
+ blockheight = blockdata.length;
+ }
+ y += blockheight;
+ x -= blockwidth;
+ lastblockheight += blockheight;
+ }
+ y -= lastblockheight;
+ incrementblock = lastblockheight;
+ lastblockheight = 0;
+ x += blockwidth;
+ }
+ }
+
+ /**
+ * Set the quantization table for this component.
+ *
+ * @param quanttable
+ */
+ public void setQuantizationTable(int[] quanttable)
+ {
+ quantizationTable = quanttable;
+ }
+
+ /**
+ * Read in a partial MCU for this component
+ *
+ * @param stream TODO
+ * @throws JPEGException TODO
+ * @throws IOException TODO
+ */
+ public void readComponentMCU(JPEGImageInputStream stream)
+ throws JPEGException, IOException
+ {
+ for (int i = 0; i < factorH * factorV; i++)
+ {
+ double dc = decode_dc_coefficient(stream);
+ double[] datablock = decode_ac_coefficients(stream);
+ datablock[0] = dc;
+ data.add(datablock);
+ }
+ }
+
+ /**
+ * Generated from text on F-22, F.2.2.1 - Huffman decoding of DC
+ * coefficients on ISO DIS 10918-1. Requirements and Guidelines.
+ *
+ * @param JPEGStream TODO
+ *
+ * @return TODO
+ * @throws JPEGException TODO
+ * @throws IOException TODO
+ */
+ public double decode_dc_coefficient(JPEGImageInputStream JPEGStream)
+ throws JPEGException, IOException
+ {
+ int t = DCTable.decode(JPEGStream);
+ double diff = JPEGStream.readBits(t);
+ diff = HuffmanTable.extend((int) diff, t);
+ diff = (previousDC + diff);
+ previousDC = diff;
+ return diff;
+ }
+
+ /**
+ * Generated from text on F-23, F.13 - Huffman decoded of AC coefficients
+ * on ISO DIS 10918-1. Requirements and Guidelines.
+ *
+ * @param JPEGStream TODO
+ * @return TODO
+ *
+ * @throws JPEGException TODO
+ * @throws IOException TODO
+ */
+ public double[] decode_ac_coefficients(JPEGImageInputStream JPEGStream)
+ throws JPEGException, IOException
+ {
+ double[] zz = new double[64];
+
+ for (int k = 1; k < 64; k++)
+ {
+ int s = ACTable.decode(JPEGStream);
+ int r = s >> 4;
+ s &= 15;
+
+ if (s != 0)
+ {
+ k += r;
+ r = (int) JPEGStream.readBits(s);
+ s = HuffmanTable.extend(r, s);
+ zz[k] = s;
+ }
+ else
+ {
+ if (r != 15)
+ return (zz);
+ k += 15;
+ }
+ }
+ return zz;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java
new file mode 100644
index 000000000..11d547f4d
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java
@@ -0,0 +1,625 @@
+/* JPEGDecoder.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.io.IOException;
+import java.nio.ByteOrder;
+
+import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
+import javax.imageio.plugins.jpeg.JPEGQTable;
+import javax.imageio.stream.ImageInputStream;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+public class JPEGDecoder
+{
+ byte majorVersion;
+ byte minorVersion;
+ byte units;
+ short Xdensity;
+ short Ydensity;
+ byte Xthumbnail;
+ byte Ythumbnail;
+ byte[] thumbnail;
+ BufferedImage image;
+ int width;
+ int height;
+
+ byte marker;
+
+ /**
+ * This decoder expects JFIF 1.02 encoding.
+ */
+ public static final byte MAJOR_VERSION = (byte) 1;
+ public static final byte MINOR_VERSION = (byte) 2;
+
+ /**
+ * The length of the JFIF field not including thumbnail data.
+ */
+ public static final short JFIF_FIXED_LENGTH = 16;
+
+ /**
+ * The length of the JFIF extension field not including extension
+ * data.
+ */
+ public static final short JFXX_FIXED_LENGTH = 8;
+
+ private JPEGImageInputStream jpegStream;
+
+ ArrayList jpegFrames = new ArrayList();
+
+ JPEGHuffmanTable[] dcTables = new JPEGHuffmanTable[4];
+ JPEGHuffmanTable[] acTables = new JPEGHuffmanTable[4];
+ JPEGQTable[] qTables = new JPEGQTable[4];
+
+ public int getHeight()
+ {
+ return height;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+ public JPEGDecoder(ImageInputStream in)
+ throws IOException, JPEGException
+ {
+ jpegStream = new JPEGImageInputStream(in);
+ jpegStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+
+ if (jpegStream.findNextMarker() != JPEGMarker.SOI)
+ throw new JPEGException("Failed to find SOI marker.");
+
+ if (jpegStream.findNextMarker() != JPEGMarker.APP0)
+ throw new JPEGException("Failed to find APP0 marker.");
+
+ int length = jpegStream.readShort();
+ if (!(length >= JFIF_FIXED_LENGTH))
+ throw new JPEGException("Failed to find JFIF field.");
+
+ byte[] identifier = new byte[5];
+ jpegStream.read(identifier);
+ if (identifier[0] != JPEGMarker.JFIF_J
+ || identifier[1] != JPEGMarker.JFIF_F
+ || identifier[2] != JPEGMarker.JFIF_I
+ || identifier[3] != JPEGMarker.JFIF_F
+ || identifier[4] != JPEGMarker.X00)
+ throw new JPEGException("Failed to read JFIF identifier.");
+
+ majorVersion = jpegStream.readByte();
+ minorVersion = jpegStream.readByte();
+ if (majorVersion != MAJOR_VERSION
+ || (majorVersion == MAJOR_VERSION
+ && minorVersion < MINOR_VERSION))
+ throw new JPEGException("Unsupported JFIF version.");
+
+ units = jpegStream.readByte();
+ if (units > (byte) 2)
+ throw new JPEGException("Units field is out of range.");
+
+ Xdensity = jpegStream.readShort();
+ Ydensity = jpegStream.readShort();
+ Xthumbnail = jpegStream.readByte();
+ Ythumbnail = jpegStream.readByte();
+
+ // 3 * for RGB data
+ int thumbnailLength = 3 * Xthumbnail * Ythumbnail;
+ if (length > JFIF_FIXED_LENGTH
+ && thumbnailLength != length - JFIF_FIXED_LENGTH)
+ throw new JPEGException("Invalid length, Xthumbnail"
+ + " or Ythumbnail field.");
+
+ if (thumbnailLength > 0)
+ {
+ thumbnail = new byte[thumbnailLength];
+ if (jpegStream.read(thumbnail) != thumbnailLength)
+ throw new IOException("Failed to read thumbnail.");
+ }
+ }
+
+ public void decode()
+ throws IOException
+ {
+ System.out.println ("DECODE!!!");
+ // The frames in this jpeg are loaded into a list. There is
+ // usually just one frame except in heirarchial progression where
+ // there are multiple frames.
+ JPEGFrame frame = null;
+
+ // The restart interval defines how many MCU's we should have
+ // between the 8-modulo restart marker. The restart markers allow
+ // us to tell whether or not our decoding process is working
+ // correctly, also if there is corruption in the image we can
+ // recover with these restart intervals. (See RSTm DRI).
+ int resetInterval = 0;
+
+ // The JPEGDecoder constructor parses the JFIF field. At this
+ // point jpegStream points to the first byte after the JFIF field.
+
+ // Find the first marker after the JFIF field.
+ byte marker = jpegStream.findNextMarker();
+
+ // Check for a JFIF extension field directly following the JFIF
+ // header and advance the current marker to the next marker in the
+ // stream, if necessary.
+ decodeJFIFExtension();
+
+ // Loop through until there are no more markers to read in, at
+ // that point everything is loaded into the jpegFrames array and
+ // can be processed.
+ while (true)
+ {
+ switch (marker)
+ {
+ // APPn Application Reserved Information - Just throw this
+ // information away because we wont be using it.
+ case JPEGMarker.APP0:
+ case JPEGMarker.APP1:
+ case JPEGMarker.APP2:
+ case JPEGMarker.APP3:
+ case JPEGMarker.APP4:
+ case JPEGMarker.APP5:
+ case JPEGMarker.APP6:
+ case JPEGMarker.APP7:
+ case JPEGMarker.APP8:
+ case JPEGMarker.APP9:
+ case JPEGMarker.APP10:
+ case JPEGMarker.APP11:
+ case JPEGMarker.APP12:
+ case JPEGMarker.APP13:
+ case JPEGMarker.APP14:
+ case JPEGMarker.APP15:
+ jpegStream.skipBytes(jpegStream.readShort() - 2);
+ break;
+
+ case JPEGMarker.SOF0:
+ // SOFn Start of Frame Marker, Baseline DCT - This is the start
+ // of the frame header that defines certain variables that will
+ // be carried out through the rest of the encoding. Multiple
+ // frames are used in a heirarchiel system, however most JPEG's
+ // only contain a single frame.
+ jpegFrames.add(new JPEGFrame());
+ frame = (JPEGFrame) jpegFrames.get(jpegFrames.size() - 1);
+ // Skip the frame length.
+ jpegStream.readShort();
+ // Bits percision, either 8 or 12.
+ frame.setPrecision(jpegStream.readByte());
+ // Scan lines = to the height of the frame.
+ frame.setScanLines(jpegStream.readShort());
+ // Scan samples per line = to the width of the frame.
+ frame.setSamplesPerLine(jpegStream.readShort());
+ // Number of Color Components (or channels).
+ frame.setComponentCount(jpegStream.readByte());
+
+ // Set the color mode for this frame, so far only 2 color
+ // modes are supported.
+ if (frame.getComponentCount() == 1)
+ frame.setColorMode(JPEGFrame.JPEG_COLOR_GRAY);
+ else
+ frame.setColorMode(JPEGFrame.JPEG_COLOR_YCbCr);
+ // Add all of the necessary components to the frame.
+ for (int i = 0; i < frame.getComponentCount(); i++)
+ frame.addComponent(jpegStream.readByte(), jpegStream.readByte(),
+ jpegStream.readByte());
+ break;
+
+ case JPEGMarker.SOF2:
+ jpegFrames.add(new JPEGFrame());
+ frame = (JPEGFrame) jpegFrames.get(jpegFrames.size() - 1);
+ // Skip the frame length.
+ jpegStream.readShort();
+ // Bits percision, either 8 or 12.
+ frame.setPrecision(jpegStream.readByte());
+ // Scan lines = to the height of the frame.
+ frame.setScanLines(jpegStream.readShort());
+ // Scan samples per line = to the width of the frame.
+ frame.setSamplesPerLine(jpegStream.readShort());
+ // Number of Color Components (or channels).
+ frame.setComponentCount(jpegStream.readByte());
+
+ // Set the color mode for this frame, so far only 2 color
+ // modes are supported.
+ if (frame.getComponentCount() == 1)
+ frame.setColorMode(JPEGFrame.JPEG_COLOR_GRAY);
+ else
+ frame.setColorMode(JPEGFrame.JPEG_COLOR_YCbCr);
+
+ // Add all of the necessary components to the frame.
+ for (int i = 0; i < frame.getComponentCount(); i++)
+ frame.addComponent(jpegStream.readByte(), jpegStream.readByte(),
+ jpegStream.readByte());
+ break;
+
+ case JPEGMarker.DHT:
+ // DHT non-SOF Marker - Huffman Table is required for decoding
+ // the JPEG stream, when we receive a marker we load in first
+ // the table length (16 bits), the table class (4 bits), table
+ // identifier (4 bits), then we load in 16 bytes and each byte
+ // represents the count of bytes to load in for each of the 16
+ // bytes. We load this into an array to use later and move on 4
+ // huffman tables can only be used in an image.
+ int huffmanLength = (jpegStream.readShort() - 2);
+
+ // Keep looping until we are out of length.
+ int index = huffmanLength;
+
+ // Multiple tables may be defined within a DHT marker. This
+ // will keep reading until there are no tables left, most
+ // of the time there are just one tables.
+ while (index > 0)
+ {
+ // Read the identifier information and class
+ // information about the Huffman table, then read the
+ // 16 byte codelength in and read in the Huffman values
+ // and put it into table info.
+ byte huffmanInfo = jpegStream.readByte();
+ byte tableClass = (byte) (huffmanInfo >> 4);
+ byte huffmanIndex = (byte) (huffmanInfo & 0x0f);
+ short[] codeLength = new short[16];
+ jpegStream.readFully(codeLength, 0, codeLength.length);
+ int huffmanValueLen = 0;
+ for (int i = 0; i < 16; i++)
+ huffmanValueLen += codeLength[i];
+ index -= (huffmanValueLen + 17);
+ short[] huffmanVal = new short[huffmanValueLen];
+ for (int i = 0; i < huffmanVal.length; i++)
+ huffmanVal[i] = jpegStream.readByte();
+ // Assign DC Huffman Table.
+ if (tableClass == HuffmanTable.JPEG_DC_TABLE)
+ dcTables[(int) huffmanIndex] = new JPEGHuffmanTable(codeLength,
+ huffmanVal);
+ // Assign AC Huffman Table.
+ else if (tableClass == HuffmanTable.JPEG_AC_TABLE)
+ acTables[(int) huffmanIndex] = new JPEGHuffmanTable(codeLength,
+ huffmanVal);
+ }
+ break;
+ case JPEGMarker.DQT:
+ // DQT non-SOF Marker - This defines the quantization
+ // coeffecients, this allows us to figure out the quality of
+ // compression and unencode the data. The data is loaded and
+ // then stored in to an array.
+ short quantizationLength = (short) (jpegStream.readShort() - 2);
+ for (int j = 0; j < quantizationLength / 65; j++)
+ {
+ byte quantSpecs = jpegStream.readByte();
+ int[] quantData = new int[64];
+ if ((byte) (quantSpecs >> 4) == 0)
+ // Precision 8 bit.
+ {
+ for (int i = 0; i < 64; i++)
+ quantData[i] = jpegStream.readByte();
+
+ }
+ else if ((byte) (quantSpecs >> 4) == 1)
+ // Precision 16 bit.
+ {
+ for (int i = 0; i < 64; i++)
+ quantData[i] = jpegStream.readShort();
+ }
+ qTables[(int) (quantSpecs & 0x0f)] = new JPEGQTable (quantData);
+ }
+ break;
+ case JPEGMarker.SOS:
+ // SOS non-SOF Marker - Start Of Scan Marker, this is where the
+ // actual data is stored in a interlaced or non-interlaced with
+ // from 1-4 components of color data, if three components most
+ // likely a YCrCb model, this is a fairly complex process.
+
+ // Read in the scan length.
+ jpegStream.readShort();
+ // Number of components in the scan.
+ byte numberOfComponents = jpegStream.readByte();
+ byte[] componentSelector = new byte[numberOfComponents];
+ for (int i = 0; i < numberOfComponents; i++)
+ {
+ // Component ID, packed byte containing the Id for the
+ // AC table and DC table.
+ byte componentID = jpegStream.readByte();
+ byte tableInfo = jpegStream.readByte();
+ frame.setHuffmanTables(componentID,
+ acTables[(byte) (tableInfo >> 4)],
+ dcTables[(byte) (tableInfo & 0x0f)]);
+ componentSelector[i] = componentID;
+ }
+ byte startSpectralSelection = jpegStream.readByte();
+ byte endSpectralSelection = jpegStream.readByte();
+ byte successiveApproximation = jpegStream.readByte();
+
+ int mcuIndex = 0;
+ int mcuTotalIndex = 0;
+ // This loops through until a MarkerTagFound exception is
+ // found, if the marker tag is a RST (Restart Marker) it
+ // simply skips it and moves on this system does not handle
+ // corrupt data streams very well, it could be improved by
+ // handling misplaced restart markers.
+ while (true)
+ {
+ try
+ {
+ // Loop though capturing MCU, instruct each
+ // component to read in its necessary count, for
+ // scaling factors the components automatically
+ // read in how much they need
+ for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
+ {
+ JPEGComponent comp = frame.components.getComponentByID(componentSelector[compIndex]);
+ comp.readComponentMCU(jpegStream);
+ }
+ mcuIndex++;
+ mcuTotalIndex++;
+ }
+ // We've found a marker, see if the marker is a restart
+ // marker or just the next marker in the stream. If
+ // it's the next marker in the stream break out of the
+ // while loop, if it's just a restart marker skip it
+ catch (JPEGMarkerFoundException bse)
+ {
+ // Handle JPEG Restart Markers, this is where the
+ // count of MCU's per interval is compared with
+ // the count actually obtained, if it's short then
+ // pad on some MCU's ONLY for components that are
+ // greater than one. Also restart the DC prediction
+ // to zero.
+ if (marker == JPEGMarker.RST0
+ || marker == JPEGMarker.RST1
+ || marker == JPEGMarker.RST2
+ || marker == JPEGMarker.RST3
+ || marker == JPEGMarker.RST4
+ || marker == JPEGMarker.RST5
+ || marker == JPEGMarker.RST6
+ || marker == JPEGMarker.RST7)
+ {
+ for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
+ {
+ JPEGComponent comp = frame.components.getComponentByID(componentSelector[compIndex]);
+ if (compIndex > 1)
+ comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex);
+ comp.resetInterval();
+ }
+ mcuTotalIndex += (resetInterval - mcuIndex);
+ mcuIndex = 0;
+ }
+ else
+ {
+ // We're at the end of our scan, exit out.
+ break;
+ }
+ }
+ }
+ break;
+ case JPEGMarker.DRI:
+ // DRI - This defines the restart interval, if we have a
+ // restart interval when we reach our restart modulo calculate
+ // whether the count of MCU's specified in the restart
+ // interval have been reached, if they havent then pad with
+ // whatever MCU was last used, this is supposed to be a form of
+ // error recovery but it turns out that some JPEG encoders
+ // purposely cause missing MCU's on repeating MCU's to compress
+ // data even more (even though it adds an extra layer of
+ // complexity.. But since when is JPEG easy?
+ jpegStream.skipBytes(2);
+ resetInterval = jpegStream.readShort();
+ break;
+ case JPEGMarker.COM:
+ // COM - This is a comment that was inserted into the JPEG, we
+ // simply skip over the comment because it's really of no
+ // importance, usually contains a verbal description of the
+ // application or author who created the JPEG.
+ jpegStream.skipBytes(jpegStream.readShort() - 2);
+ break;
+ case JPEGMarker.DNL:
+ // DNL - This sets the height of the image. This is the Define
+ // Number Lines for the image, I'm not sure exactly why we need
+ // this but, whatever we'll abide.
+ frame.setScanLines(jpegStream.readShort());
+ break;
+ case JPEGMarker.EOI:
+ // EOI - End of Image, this processes the frames and turns the
+ // frames into a buffered image.
+
+ if (jpegFrames.size() == 0)
+ {
+ return;
+ }
+ else if (jpegFrames.size() == 1)
+ {
+ // Only one frame, JPEG Non-Heirarchial Frame.
+
+ DCT myDCT = new DCT();
+ WritableRaster raster =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ frame.width,
+ frame.height,
+ frame.getComponentCount(),
+ new Point(0, 0));
+
+ // Unencode the data.
+ for (int i = 0; i < frame.getComponentCount(); i++)
+ {
+ JPEGComponent comp = frame.components.get(i);
+ comp.setQuantizationTable(qTables[comp.quant_id].getTable());
+ comp.quantitizeData();
+ comp.idctData(myDCT);
+ }
+ // Scale the image and write the data to the raster.
+ for (int i = 0; i < frame.getComponentCount(); i++)
+ {
+ JPEGComponent comp = frame.components.get(i);
+ comp.scaleByFactors();
+ comp.writeData(raster, i);
+ // Ensure garbage collection.
+ comp = null;
+ }
+ // Grayscale Color Image (1 Component).
+ if (frame.getComponentCount() == 1)
+ {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
+ ComponentColorModel ccm =
+ new ComponentColorModel(cs, false, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ image = new BufferedImage(ccm, raster, false,
+ new Hashtable());
+ }
+ // YCbCr Color Image (3 Components).
+ else if (frame.getComponentCount() == 3)
+ {
+ ComponentColorModel ccm =
+ new ComponentColorModel(new YCbCr_ColorSpace(), false,
+ false, Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ image = new BufferedImage(ccm, raster, false,
+ new Hashtable());
+ }
+ // Possibly CMYK or RGBA ?
+ else
+ {
+ throw new JPEGException("Unsupported Color Mode: 4 "
+ + "Component Color Mode found.");
+ }
+ height = frame.height;
+ width = frame.width;
+ }
+ else
+ {
+ //JPEG Heirarchial Frame (progressive or baseline).
+ throw new JPEGException("Unsupported Codec Type:"
+ + " Hierarchial JPEG");
+ }
+ break;
+ case JPEGMarker.SOF1:
+ // ERROR - If we encounter any of the following marker codes
+ // error out with a codec exception, progressive, heirarchial,
+ // differential, arithmetic, lossless JPEG's are not supported.
+ // This is where enhancements can be made for future versions.
+ // Thankfully 99% of all JPEG's are baseline DCT.
+ throw new JPEGException("Unsupported Codec Type: Extended "
+ + "Sequential DCT JPEG's Not-Supported");
+ //case JPEGMarker.SOF2:
+ // throw new JPEGException("Unsupported Codec Type: Progressive DCT JPEG's Not-Supported");
+ case JPEGMarker.SOF3:
+ throw new JPEGException("Unsupported Codec Type:"
+ + " Lossless (sequential)");
+ case JPEGMarker.SOF5:
+ throw new JPEGException("Unsupported Codec Type:"
+ + " Differential sequential DCT");
+ case JPEGMarker.SOF6:
+ throw new JPEGException("Unsupported Codec Type:"
+ + " Differential progressive DCT");
+ case JPEGMarker.SOF7:
+ throw new JPEGException("Unsupported Codec Type:"
+ + " Differential lossless");
+ case JPEGMarker.SOF9:
+ case JPEGMarker.SOF10:
+ case JPEGMarker.SOF11:
+ case JPEGMarker.SOF13:
+ case JPEGMarker.SOF14:
+ case JPEGMarker.SOF15:
+ throw new JPEGException("Unsupported Codec Type:"
+ + " Arithmetic Coding Frame");
+ default:
+ // Unknown marker found, ignore it.
+ }
+ marker = jpegStream.findNextMarker();
+ }
+ }
+
+ // If the current marker is APP0, tries to decode a JFIF extension
+ // and advances the current marker to the next marker in the stream.
+ private void decodeJFIFExtension() throws IOException
+ {
+ if (marker == JPEGMarker.APP0)
+ {
+ int length = jpegStream.readShort();
+
+ if (length >= JFXX_FIXED_LENGTH)
+ {
+ byte[] identifier = new byte[5];
+ jpegStream.read(identifier);
+ if (identifier[0] != JPEGMarker.JFIF_J
+ || identifier[1] != JPEGMarker.JFIF_F
+ || identifier[2] != JPEGMarker.JFIF_X
+ || identifier[3] != JPEGMarker.JFIF_X
+ || identifier[4] != JPEGMarker.X00)
+ // Not a JFXX field. Ignore it and continue.
+ jpegStream.skipBytes(length - 7);
+ else
+ {
+ byte extension_code = jpegStream.readByte();
+
+ switch (extension_code)
+ {
+ case JPEGMarker.JFXX_JPEG:
+ // FIXME: add support for JFIF Extension:
+ // Thumbnail coded using JPEG.
+ jpegStream.skipBytes(length - 8);
+ case JPEGMarker.JFXX_ONE_BPP:
+ // FIXME: add support for JFIF Extension:
+ // Thumbnail stored using 1 byte/pixel.
+ jpegStream.skipBytes(length - 8);
+ case JPEGMarker.JFXX_THREE_BPP:
+ // FIXME: add support for JFIF Extension:
+ // Thumbnail stored using 3 bytes/pixel.
+ jpegStream.skipBytes(length - 8);
+ }
+ }
+ }
+ else
+ {
+ // Unknown APP0 marker. Ignore it and continue.
+ jpegStream.skipBytes(length - 2);
+ }
+ marker = jpegStream.findNextMarker();
+ }
+ }
+
+ public BufferedImage getImage()
+ {
+ return image;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java
new file mode 100644
index 000000000..a2c06e27e
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java
@@ -0,0 +1,48 @@
+/* JPEGException.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import javax.imageio.*;
+
+public class JPEGException extends IIOException
+{
+ public JPEGException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java
new file mode 100644
index 000000000..35aed728a
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java
@@ -0,0 +1,108 @@
+/* JPEGFrame.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
+
+public class JPEGFrame
+{
+ public final static byte JPEG_COLOR_GRAY = 1;
+ public final static byte JPEG_COLOR_RGB = 2;
+ public final static byte JPEG_COLOR_YCbCr = 3;
+ public final static byte JPEG_COLOR_CMYK = 4;
+
+ public byte precision = 8;
+ public byte colorMode = JPEGFrame.JPEG_COLOR_YCbCr;
+ public byte componentCount = 0;
+
+ public short width=0, height=0;
+
+ public JPEGScan components;
+
+ public JPEGFrame()
+ {
+ components = new JPEGScan();
+ }
+
+ public void addComponent(byte componentID, byte sampleFactors,
+ byte quantizationTableID)
+ {
+ byte sampleHorizontalFactor = (byte)(sampleFactors >> 4);
+ byte sampleVerticalFactor = (byte)(sampleFactors & 0x0f);
+ components.addComponent(componentID, sampleHorizontalFactor,
+ sampleVerticalFactor, quantizationTableID);
+ }
+
+ public void setPrecision(byte data)
+ {
+ precision = data;
+ }
+
+ public void setScanLines(short data)
+ {
+ height = data;
+ }
+
+ public void setSamplesPerLine(short data)
+ {
+ width = data;
+ }
+
+ public void setColorMode(byte data)
+ {
+ colorMode = data;
+ }
+
+ public void setComponentCount(byte data)
+ {
+ componentCount = data;
+ }
+
+ public byte getComponentCount()
+ {
+ return componentCount;
+ }
+
+ public void setHuffmanTables(byte componentID, JPEGHuffmanTable ACTable,
+ JPEGHuffmanTable DCTable)
+ {
+ JPEGComponent comp = components.getComponentByID(componentID);
+ comp.setACTable(ACTable);
+ comp.setDCTable(DCTable);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java
new file mode 100644
index 000000000..f2c26d9d5
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java
@@ -0,0 +1,188 @@
+/* JPEGImageInputStream.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.io.IOException;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageInputStreamImpl;
+
+public class JPEGImageInputStream
+ extends ImageInputStreamImpl
+{
+ private ImageInputStream in;
+
+ byte marker;
+
+ public JPEGImageInputStream(ImageInputStream in)
+ {
+ super();
+
+ this.in = in;
+ }
+
+ public int read()
+ throws IOException
+ {
+ setBitOffset(0);
+ return in.read();
+ }
+
+ public int read(byte[] data, int offset, int len)
+ throws IOException
+ {
+ setBitOffset(0);
+ return in.read(data, offset, len);
+ }
+
+ /**
+ * Pull a byte from the stream, this checks to see if the byte is 0xff
+ * and if the next byte isn't 0x00 (stuffed byte) it errors out. If it's
+ * 0x00 then it simply ignores the byte.
+ *
+ * @return the next byte in the buffer
+ *
+ * @throws IOException TODO
+ * @throws BitStreamException TODO
+ */
+ private byte pullByte() throws IOException, JPEGMarkerFoundException
+ {
+ byte mybyte = readByte();
+ // FIXME: handle multiple 0xff in a row
+ if(mybyte==(byte)(0xff))
+ {
+ byte secondbyte = readByte();
+ if(secondbyte != (byte)(0x00))
+ {
+ marker = secondbyte;
+ throw new JPEGMarkerFoundException();
+ }
+ }
+ return mybyte;
+ }
+
+ /**
+ * This returns the marker that was last encountered. This should only be
+ * used if removeBit() throws a MarkerTagFound exception.
+ *
+ * @return marker as byte
+ */
+ public byte getMarker()
+ {
+ return marker;
+ }
+
+ /**
+ * Removes a bit from the buffer. (Removes from the top of a queue). This
+ * also checks for markers and throws MarkerTagFound exception if it does.
+ * If MarkerTagFound is thrown you can use getMarker() method to get the
+ * marker that caused the throw.
+ *
+ * @param l specifies how many bits you want to remove and add to the
+ * integer
+ * @return the amount of bits specified by l as an integer
+ *
+ * @throws IOException TODO
+ * @throws JPEGMarkerFoundException
+ * @throws BitStreamException TODO
+ */
+ public int readBit()
+ throws IOException, JPEGMarkerFoundException
+{
+ checkClosed();
+
+ // Calc new bit offset here, readByte resets it.
+ int newOffset = (bitOffset + 1) & 0x7;
+
+ byte data = pullByte();
+
+ if (bitOffset != 0)
+ {
+ seek(getStreamPosition() - 1);
+ data = (byte) (data >> (8 - newOffset));
+ }
+
+ bitOffset = newOffset;
+ return data & 0x1;
+}
+
+
+ /**
+ * This method skips over the the data and finds the next position
+ * in the bit sequence with a X'FF' X'??' sequence. Multiple X'FF
+ * bytes in sequence are considered padding and interpreted as one
+ * X'FF byte.
+ *
+ * @return the next marker byte in the stream
+ * @throws IOException if the end of the stream is reached
+ * unexpectedly
+ */
+ public byte findNextMarker()
+ throws IOException
+ {
+ boolean marked0xff = false;
+ byte byteinfo = JPEGMarker.X00;
+
+ setBitOffset(0);
+ while (true)
+ {
+ byteinfo = readByte();
+ if (!marked0xff)
+ {
+ if (byteinfo == JPEGMarker.XFF)
+ marked0xff = true;
+ }
+ else
+ {
+ if (byteinfo == JPEGMarker.XFF)
+ // Ignore the value 0xff when it is immediately
+ // followed by another 0xff byte.
+ continue;
+ else if (byteinfo == JPEGMarker.X00)
+ // The sequence 0xff 0x00 is used to encode the
+ // actual value 0xff. So restart our search for a
+ // marker.
+ marked0xff = false;
+ else
+ // One or more 0xff values were follwed by a
+ // non-0x00, non-0xff value so return this as the
+ // marker byte.
+ return byteinfo;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java
new file mode 100644
index 000000000..5ecbe0f8c
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java
@@ -0,0 +1,141 @@
+/* JPEGImageReader.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.io.IOException;
+import javax.imageio.*;
+import javax.imageio.spi.*;
+import javax.imageio.metadata.*;
+import javax.imageio.stream.ImageInputStream;
+import java.util.Iterator;
+import java.awt.image.BufferedImage;
+
+public class JPEGImageReader extends ImageReader
+{
+ JPEGDecoder decoder;
+
+ protected JPEGImageReader(ImageReaderSpi originatingProvider)
+ {
+ super(originatingProvider);
+ System.out.println("JPEGIMAGEREADER!!!");
+ }
+
+ // Abstract ImageReader methods.
+ public int getHeight(int imageIndex)
+ throws IOException
+ {
+ checkIndex(imageIndex);
+ decodeStream();
+ return decoder.getHeight();
+ }
+
+ public IIOMetadata getImageMetadata(int imageIndex)
+ throws IOException
+ {
+ // FIXME: handle metadata
+ checkIndex(imageIndex);
+ return null;
+ }
+
+ public Iterator getImageTypes(int imageIndex)
+ throws IOException
+ {
+ return null;
+ }
+
+ public int getNumImages(boolean allowSearch)
+ throws IOException
+ {
+ return 1;
+ }
+
+ public IIOMetadata getStreamMetadata()
+ throws IOException
+ {
+ // FIXME: handle metadata
+ return null;
+ }
+
+ public int getWidth(int imageIndex)
+ throws IOException
+ {
+ checkIndex(imageIndex);
+ decodeStream();
+ return decoder.getWidth();
+ }
+
+ public BufferedImage read(int imageIndex, ImageReadParam param)
+ throws IOException
+ {
+ checkIndex(imageIndex);
+ decodeStream();
+ return decoder.getImage();
+ }
+
+ // private helper methods
+ private void checkIndex(int imageIndex)
+ throws IndexOutOfBoundsException
+ {
+ if (imageIndex != 0)
+ throw new IndexOutOfBoundsException();
+ }
+
+ private void checkStream() throws IOException
+ {
+ if (!(input instanceof ImageInputStream))
+ throw new IllegalStateException("Input not an ImageInputStream.");
+ if(input == null)
+ throw new IllegalStateException("No input stream.");
+ }
+
+ private void decodeStream()
+ throws IOException, IIOException
+ {
+ System.out.println("DECONDING 1");
+ if (decoder != null)
+ return;
+
+ System.out.println("DECONDING 2");
+ checkStream();
+
+ System.out.println("DECONDING 3");
+ decoder = new JPEGDecoder((ImageInputStream)input);
+ System.out.println("DECONDING 4");
+ decoder.decode();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java
new file mode 100644
index 000000000..c45b818c7
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java
@@ -0,0 +1,137 @@
+/* JPEGImageReaderSpi.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.io.IOException;
+import java.util.Locale;
+import javax.imageio.ImageReader;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.stream.ImageInputStream;
+
+public class JPEGImageReaderSpi extends ImageReaderSpi
+{
+ static final String vendorName = "GNU";
+ static final String version = "0.1";
+ static final String readerClassName =
+ "gnu.javax.imageio.jpeg.JPEGImageReader";
+ static final String[] names = { "JPEG" };
+ static final String[] suffixes = { ".jpeg", ".jpg", ".jpe" };
+ static final String[] MIMETypes = { "image/jpeg" };
+ static final String[] writerSpiNames =
+ { "gnu.javax.imageio.jpeg.JPEGImageWriterSpi" };
+
+ static final boolean supportsStandardStreamMetadataFormat = false;
+ static final String nativeStreamMetadataFormatName = null;
+ static final String nativeStreamMetadataFormatClassName = null;
+ static final String[] extraStreamMetadataFormatNames = null;
+ static final String[] extraStreamMetadataFormatClassNames = null;
+ static final boolean supportsStandardImageMetadataFormat = false;
+ static final String nativeImageMetadataFormatName = null;
+ static final String nativeImageMetadataFormatClassName = null;
+ static final String[] extraImageMetadataFormatNames = null;
+ static final String[] extraImageMetadataFormatClassNames = null;
+
+ private static JPEGImageReaderSpi readerSpi;
+
+ public JPEGImageReaderSpi()
+ {
+ super(vendorName, version,
+ names, suffixes, MIMETypes,
+ readerClassName,
+ STANDARD_INPUT_TYPE, // Accept ImageInputStreams
+ writerSpiNames,
+ supportsStandardStreamMetadataFormat,
+ nativeStreamMetadataFormatName,
+ nativeStreamMetadataFormatClassName,
+ extraStreamMetadataFormatNames,
+ extraStreamMetadataFormatClassNames,
+ supportsStandardImageMetadataFormat,
+ nativeImageMetadataFormatName,
+ nativeImageMetadataFormatClassName,
+ extraImageMetadataFormatNames,
+ extraImageMetadataFormatClassNames);
+ System.out.println ("JPEGImageReaderSPI!!!");
+ }
+
+ public String getDescription(Locale locale)
+ {
+ return "JPEG ISO 10918-1, JFIF V1.02";
+ }
+
+ public boolean canDecodeInput(Object input)
+ throws IOException
+ {
+ if (!(input instanceof ImageInputStream))
+ return false;
+
+ ImageInputStream in = (ImageInputStream) input;
+ boolean retval;
+
+ in.mark();
+ try
+ {
+ new JPEGDecoder(in);
+ retval = true;
+ }
+ catch(JPEGException e)
+ {
+ retval = false;
+ }
+ in.reset();
+
+ return retval;
+ }
+
+ public ImageReader createReaderInstance(Object extension)
+ {
+ return new JPEGImageReader(this);
+ }
+
+ public static void registerSpis(IIORegistry reg)
+ {
+ reg.registerServiceProvider(getReaderSpi(), ImageReaderSpi.class);
+ }
+
+ public static synchronized JPEGImageReaderSpi getReaderSpi()
+ {
+ if (readerSpi == null)
+ readerSpi = new JPEGImageReaderSpi();
+ return readerSpi;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java
new file mode 100644
index 000000000..bc6350fbc
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java
@@ -0,0 +1,205 @@
+/* JPEGMarker.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+public class JPEGMarker
+{
+ /**
+ * JFIF identifiers.
+ */
+ public final static byte JFIF_J = (byte) 0x4a;
+ public final static byte JFIF_F = (byte) 0x46;
+ public final static byte JFIF_I = (byte) 0x49;
+ public final static byte JFIF_X = (byte) 0x46;
+
+ /**
+ * JFIF extension codes.
+ */
+ public final static byte JFXX_JPEG = (byte) 0x10;
+ public final static byte JFXX_ONE_BPP = (byte) 0x11;
+ public final static byte JFXX_THREE_BPP = (byte) 0x13;
+
+ /**
+ * Marker prefix byte.
+ */
+ public final static byte XFF = (byte) 0xff;
+
+ /**
+ * Marker byte that represents a literal 0xff.
+ */
+ public final static byte X00 = (byte) 0x00;
+
+ /**
+ * Application Reserved Keyword.
+ */
+ public final static byte APP0 = (byte) 0xe0;
+
+ public final static byte APP1 = (byte) 0xe1;
+ public final static byte APP2 = (byte) 0xe2;
+ public final static byte APP3 = (byte) 0xe3;
+ public final static byte APP4 = (byte) 0xe4;
+ public final static byte APP5 = (byte) 0xe5;
+ public final static byte APP6 = (byte) 0xe6;
+ public final static byte APP7 = (byte) 0xe7;
+ public final static byte APP8 = (byte) 0xe8;
+ public final static byte APP9 = (byte) 0xe9;
+ public final static byte APP10 = (byte) 0xea;
+ public final static byte APP11 = (byte) 0xeb;
+ public final static byte APP12 = (byte) 0xec;
+ public final static byte APP13 = (byte) 0xed;
+ public final static byte APP14 = (byte) 0xee;
+ public final static byte APP15 = (byte) 0xef;
+
+ /**
+ * Modulo Restart Interval.
+ */
+ public final static byte RST0 = (byte) 0xd0;
+
+ public final static byte RST1 = (byte) 0xd1;
+ public final static byte RST2 = (byte) 0xd2;
+ public final static byte RST3 = (byte) 0xd3;
+ public final static byte RST4 = (byte) 0xd4;
+ public final static byte RST5 = (byte) 0xd5;
+ public final static byte RST6 = (byte) 0xd6;
+ public final static byte RST7 = (byte) 0xd7;
+
+ /**
+ * Nondifferential Huffman-coding frame (baseline dct).
+ */
+ public final static byte SOF0 = (byte) 0xc0;
+
+ /**
+ * Nondifferential Huffman-coding frame (extended dct).
+ */
+ public final static byte SOF1 = (byte) 0xc1;
+
+ /**
+ * Nondifferential Huffman-coding frame (progressive dct).
+ */
+ public final static byte SOF2 = (byte) 0xc2;
+
+ /**
+ * Nondifferential Huffman-coding frame Lossless (Sequential).
+ */
+ public final static byte SOF3 = (byte) 0xc3;
+
+ /**
+ * Differential Huffman-coding frame Sequential DCT.
+ */
+ public final static byte SOF5 = (byte) 0xc5;
+
+ /**
+ * Differential Huffman-coding frame Progressive DCT.
+ */
+ public final static byte SOF6 = (byte) 0xc6;
+
+ /**
+ * Differential Huffman-coding frame lossless.
+ */
+ public final static byte SOF7 = (byte) 0xc7;
+
+ /**
+ * Nondifferential Arithmetic-coding frame (extended dct).
+ */
+ public final static byte SOF9 = (byte) 0xc9;
+
+ /**
+ * Nondifferential Arithmetic-coding frame (progressive dct).
+ */
+ public final static byte SOF10 = (byte) 0xca;
+
+ /**
+ * Nondifferential Arithmetic-coding frame (lossless).
+ */
+ public final static byte SOF11 = (byte) 0xcb;
+
+ /**
+ * Differential Arithmetic-coding frame (sequential dct).
+ */
+ public final static byte SOF13 = (byte) 0xcd;
+
+ /**
+ * Differential Arithmetic-coding frame (progressive dct).
+ */
+ public final static byte SOF14 = (byte) 0xce;
+
+ /**
+ * Differential Arithmetic-coding frame (lossless).
+ */
+ public final static byte SOF15 = (byte) 0xcf;
+
+ /**
+ * Huffman Table.
+ */
+ public final static byte DHT = (byte) 0xc4;
+
+ /**
+ * Quantization Table.
+ */
+ public final static byte DQT = (byte) 0xdb;
+
+ /**
+ * Start of Scan.
+ */
+ public final static byte SOS = (byte) 0xda;
+
+ /**
+ * Defined Restart Interval.
+ */
+ public final static byte DRI = (byte) 0xdd;
+
+ /**
+ * Comment in JPEG.
+ */
+ public final static byte COM = (byte) 0xfe;
+
+ /**
+ * Start of Image.
+ */
+ public final static byte SOI = (byte) 0xd8;
+
+ /**
+ * End of Image.
+ */
+ public final static byte EOI = (byte) 0xd9;
+
+ /**
+ * Define Number of Lines.
+ */
+ public final static byte DNL = (byte) 0xdc;
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java
new file mode 100644
index 000000000..2e72d495b
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java
@@ -0,0 +1,50 @@
+/* JPEGMarkerFoundException.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.imageio.jpeg;
+
+import java.io.IOException;
+
+public class JPEGMarkerFoundException
+ extends IOException
+{
+ public JPEGMarkerFoundException()
+ {
+ super("");
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java
new file mode 100644
index 000000000..e07251021
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java
@@ -0,0 +1,151 @@
+/* JPEGScan.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.util.ArrayList;
+
+public class JPEGScan
+{
+ private int maxHeight = 0, maxWidth = 0, maxV = 0, maxH = 0;
+ private int numOfComponents = 0, numOfComponentBlocks = 0;
+ private ArrayList components = new ArrayList();
+
+ public JPEGScan()
+ {
+ // Nothing to do here.
+ }
+
+ public JPEGScan(int h, int w)
+ {
+ maxHeight=h;
+ maxWidth=w;
+ }
+
+ private void recalculateDimensions()
+ {
+ JPEGComponent comp;
+
+ // Compute the maximum H, maximum V factors defined in Annex A of the ISO
+ // DIS 10918-1.
+ for(int i=0; i < components.size() ; i++)
+ {
+ comp = (JPEGComponent)components.get(i);
+ if(comp.factorH > maxH)
+ maxH=comp.factorH;
+ if(comp.factorV > maxV)
+ maxV=comp.factorV;
+ }
+
+ for(int i=0; i < components.size() ; i++)
+ {
+ comp = (JPEGComponent)components.get(i);
+ comp.maxH = maxH;
+ comp.maxV = maxV;
+ }
+
+ }
+
+ public void addComponent(byte id, byte factorHorizontal, byte factorVertical,
+ byte quantizationID)
+ {
+ JPEGComponent component = new JPEGComponent(id, factorHorizontal, factorVertical, quantizationID);
+ components.add((Object)component);
+ recalculateDimensions();
+ numOfComponents++;
+ numOfComponentBlocks += factorHorizontal*factorVertical;
+ }
+
+ public JPEGComponent getComponentByID(byte id)
+ {
+ JPEGComponent comp = (JPEGComponent)components.get(0);
+ for(int i=0; i < components.size() ; i++)
+ {
+ comp=(JPEGComponent)components.get(i);
+ if(comp.component_id==id)
+ break;
+ }
+ return(comp);
+ }
+
+ public JPEGComponent get(int id)
+ {
+ return((JPEGComponent)components.get(id));
+ }
+
+ public int getX(byte id)
+ {
+ JPEGComponent comp = getComponentByID(id);
+ return(comp.width);
+ }
+
+ public int getY(byte id)
+ {
+ JPEGComponent comp = getComponentByID(id);
+ return(comp.height);
+ }
+
+ public int getMaxV()
+ {
+ return(maxV);
+ }
+
+ public int getMaxH()
+ {
+ return(maxH);
+ }
+
+ public void setWidth(int w)
+ {
+ maxWidth=w;
+ }
+
+ public void setHeight(int h)
+ {
+ maxHeight=h;
+ }
+
+ public int size()
+ {
+ return(numOfComponents);
+ }
+
+ public int sizeComponentBlocks()
+ {
+ return(numOfComponentBlocks);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java b/libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java
new file mode 100644
index 000000000..a3970b7fa
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java
@@ -0,0 +1,113 @@
+/* YCbCr_ColorSpace.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+import java.awt.color.ColorSpace;
+
+public class YCbCr_ColorSpace extends ColorSpace {
+ public YCbCr_ColorSpace() {
+ super(ColorSpace.TYPE_YCbCr, 3);
+ }
+
+ public float[] fromCIEXYZ(float[] data) {
+ return(new float[data.length]);
+ }
+
+ public float[] toCIEXYZ(float[] data) {
+ return(new float[data.length]);
+ }
+
+ public float[] fromRGB(float[] data) {
+ return(new float[data.length]);
+ }
+
+ /* YCbCr to RGB range 0 to 1 */
+ public float[] toRGB(float[] data) {
+ float[] dest = new float[3];
+
+ data[0] *= 255;
+ data[1] *= 255;
+ data[2] *= 255;
+
+ dest[0] = (float)data[0] + (float)1.402*((float)data[2]-(float)128);
+ dest[1] = (float)data[0] - (float)0.34414*((float)data[1]-(float)128) - (float)0.71414*((float)data[2]-(float)128);
+ dest[2] = (float)data[0] + (float)1.772*((float)data[1]-(float)128);
+
+ dest[0] /= 255;
+ dest[1] /= 255;
+ dest[2] /= 255;
+
+ //dest[0] = ((float)1.164*((float)data[0]*(float)255 - (float)16) + (float)1.596*((float)data[2]*(float)255 - (float)128))/(float)255;
+ //dest[1] = ((float)1.164*((float)data[0]*(float)255 - (float)16) - (float)0.813*((float)data[2]*(float)255 - (float)128) - (float)0.392*(data[1]*255 - 128))/(float)255;
+ //dest[2] = ((float)1.164*((float)data[0]*(float)255 - (float)16) + (float)2.017*((float)data[1]*(float)255 - (float)128))/(float)255;
+
+ //System.err.println("toRGB values received: 0: "+data[0]+" 1: "+data[1]+" 2: "+data[2]+" sent: 0: "+dest[0]+" 1: "+dest[1]+" 2: "+dest[2]);
+ if(dest[0] < (float)0)
+ dest[0] = 0;
+ if(dest[1] < (float)0)
+ dest[1] = 0;
+ if(dest[2] < (float)0)
+ dest[2] = 0;
+
+ if(dest[0] > (float)1)
+ dest[0] = 1;
+ if(dest[1] > (float)1)
+ dest[1] = 1;
+ if(dest[2] > (float)1)
+ dest[2] = 1;
+
+
+ return(dest);
+ }
+
+ /* RGB to YCbCr range 0-255 */
+ public static float[] toYCbCr(float[] data) {
+ float[] dest = new float[3];
+ //dest[0] = (float)0.257*data[0] + (float)0.504*data[1] + (float)0.098*data[2] + 16;
+ //dest[1] = (float)-0.148*data[0] - (float)0.291*data[1] + (float)0.439*data[2] + 128;
+ //dest[2] = (float)0.439*data[0] - (float)0.368*data[1] - (float)0.071*data[2] + 128;
+
+ dest[0] = (float)((0.299 * (float)data[0] + 0.587 * (float)data[1] + 0.114 * (float)data[2]));
+ dest[1] = 128 + (float)((-0.16874 * (float)data[0] - 0.33126 * (float)data[1] + 0.5 * (float)data[2]));
+ dest[2] = 128 + (float)((0.5 * (float)data[0] - 0.41869 * (float)data[1] - 0.08131 * (float)data[2]));
+
+
+ return(dest);
+
+ }
+}
diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java b/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java
new file mode 100644
index 000000000..9aac0df40
--- /dev/null
+++ b/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java
@@ -0,0 +1,520 @@
+/* ZigZag.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.jpeg;
+
+/**
+ * This class implements the Zig Zag Algorithm on any array with
+ * the same amount of rows and columns. It takes a matrix and in turn builds an
+ * encoded byte array (or double array) from it. The adverse is also true, this
+ * will take a byte or double array and build a matrix based on the zig zag
+ * algorithm.
+ * <p>This is used exclusively in the JPEG DCT encoding.</p>
+ */
+public class ZigZag
+{
+ public final static boolean ZIGZAG_FORWARD = true;
+ public final static boolean ZIGZAG_BACKWARD = false;
+ public final static int ZIGZAG_8X8_MAP[] =
+ {
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+ };
+
+ /**
+ * Encodes a matrix of equal width and height to a byte array.
+ *
+ * @param matrix
+ *
+ * @return
+ */
+ public static byte[] encode(byte[][] matrix)
+ {
+ byte[] buffer = new byte[matrix.length ^ 2];
+ boolean direction = ZigZag.ZIGZAG_FORWARD;
+ int x = 0, y = 0, index = 0;
+ for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1);
+ zigIndex++, direction = !direction)
+ {
+ if (direction == ZigZag.ZIGZAG_FORWARD)
+ {
+ while (x >= 0 && y != matrix.length)
+ {
+ if (x == matrix.length)
+ {
+ x--;
+ y++;
+ }
+ buffer[index] = matrix[x][y];
+ y++;
+ x--;
+ index++;
+ }
+ x++;
+ }
+ else
+ {
+ while (y >= 0 && x != matrix.length)
+ {
+ if (y == matrix.length)
+ {
+ y--;
+ x++;
+ }
+ buffer[index] = matrix[x][y];
+ y--;
+ x++;
+ index++;
+ }
+ y++;
+ }
+ }
+ return (buffer);
+ }
+
+ /**
+ * Encodes a matrix of equal width and height to a double array
+ *
+ * @param matrix
+ *
+ * @return
+ */
+ public static double[] encode(double[][] matrix)
+ {
+ double[] buffer = new double[matrix.length * matrix.length];
+ boolean direction = ZigZag.ZIGZAG_FORWARD;
+ int x = 0, y = 0, index = 0;
+ for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1);
+ zigIndex++, direction = !direction)
+ {
+ if (direction == ZigZag.ZIGZAG_FORWARD)
+ {
+ while (x >= 0 && y != matrix.length)
+ {
+ if (x == matrix.length)
+ {
+ x--;
+ y++;
+ }
+ buffer[index] = matrix[x][y];
+ y++;
+ x--;
+ index++;
+ }
+ x++;
+ }
+ else
+ {
+ while (y >= 0 && x != matrix.length)
+ {
+ if (y == matrix.length)
+ {
+ y--;
+ x++;
+ }
+ buffer[index] = matrix[x][y];
+ y--;
+ x++;
+ index++;
+ }
+ y++;
+ }
+ }
+ return (buffer);
+ }
+
+ /**
+ * Encodes a matrix of equal width and height to a float array
+ *
+ * @param matrix
+ *
+ * @return
+ */
+ public static float[] encode(float[][] matrix)
+ {
+ float[] buffer = new float[matrix.length * matrix.length];
+ boolean direction = ZigZag.ZIGZAG_FORWARD;
+ int x = 0, y = 0, index = 0;
+ for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1);
+ zigIndex++, direction = !direction)
+ {
+ if (direction == ZigZag.ZIGZAG_FORWARD)
+ {
+ while (x >= 0 && y != matrix.length)
+ {
+ if (x == matrix.length)
+ {
+ x--;
+ y++;
+ }
+ buffer[index] = matrix[x][y];
+ y++;
+ x--;
+ index++;
+ }
+ x++;
+ }
+ else
+ {
+ while (y >= 0 && x != matrix.length)
+ {
+ if (y == matrix.length)
+ {
+ y--;
+ x++;
+ }
+ buffer[index] = matrix[x][y];
+ y--;
+ x++;
+ index++;
+ }
+ y++;
+ }
+ }
+ return (buffer);
+ }
+
+ /**
+ * Encodes a matrix of equal width and height to a float array
+ *
+ * @param matrix
+ *
+ * @return
+ */
+ public static short[] encode(short[][] matrix)
+ {
+ short[] buffer = new short[matrix.length * matrix.length];
+ boolean direction = ZigZag.ZIGZAG_FORWARD;
+ int x = 0, y = 0, index = 0;
+ for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1);
+ zigIndex++, direction = !direction)
+ {
+ if (direction == ZigZag.ZIGZAG_FORWARD)
+ {
+ while (x >= 0 && y != matrix.length)
+ {
+ if (x == matrix.length)
+ {
+ x--;
+ y++;
+ }
+ buffer[index] = matrix[x][y];
+ y++;
+ x--;
+ index++;
+ }
+ x++;
+ }
+ else
+ {
+ while (y >= 0 && x != matrix.length)
+ {
+ if (y == matrix.length)
+ {
+ y--;
+ x++;
+ }
+ buffer[index] = matrix[x][y];
+ y--;
+ x++;
+ index++;
+ }
+ y++;
+ }
+ }
+ return (buffer);
+ }
+
+ /**
+ * Convert a double array into a matrix with the same amount of columns and
+ * rows with length sqrt(double array length)
+ *
+ * @param data
+ *
+ * @return
+ */
+ public static double[][] decode(double[] data)
+ {
+ return decode(data, (int) Math.sqrt(data.length),
+ (int) Math.sqrt(data.length));
+ }
+
+ /**
+ * Convert a byte array into a matrix with the same amount of columns and
+ * rows with length sqrt(double array length)
+ *
+ * @param data
+ *
+ * @return
+ */
+ public static byte[][] decode(byte[] data)
+ {
+ return decode(data, (int) Math.sqrt(data.length),
+ (int) Math.sqrt(data.length));
+ }
+
+ public static int[][] decode(int[] data)
+ {
+ return decode(data, (int) Math.sqrt(data.length),
+ (int) Math.sqrt(data.length));
+ }
+
+ public static byte[][] decode(byte[] data, int width, int height)
+ {
+ byte[][] buffer = new byte[height][width];
+
+ for (int v = 0; v < height; v++)
+ for (int z = 0; z < width; z++)
+ buffer[v][z] = 11;
+
+ boolean dir = ZigZag.ZIGZAG_FORWARD;
+ int xindex = 0, yindex = 0, dataindex = 0;
+
+ while (xindex < width && yindex < height && dataindex < data.length)
+ {
+ buffer[yindex][xindex] = data[dataindex];
+ dataindex++;
+
+ if (dir == ZigZag.ZIGZAG_FORWARD)
+ {
+ if (yindex == 0 || xindex == (width - 1))
+ {
+ dir = ZigZag.ZIGZAG_BACKWARD;
+ if (xindex == (width - 1))
+ yindex++;
+ else
+ xindex++;
+ }
+ else
+ {
+ yindex--;
+ xindex++;
+ }
+ }
+ else
+ { /* Backwards */
+ if (xindex == 0 || yindex == (height - 1))
+ {
+ dir = ZigZag.ZIGZAG_FORWARD;
+ if (yindex == (height - 1))
+ xindex++;
+ else
+ yindex++;
+ }
+ else
+ {
+ yindex++;
+ xindex--;
+ }
+ }
+ }
+ return (buffer);
+ }
+
+ public static double[][] decode(double[] data, int width, int height)
+ {
+ double[][] buffer = new double[height][width];
+
+ for (int v = 0; v < height; v++)
+ for (int z = 0; z < width; z++)
+ buffer[v][z] = 11;
+
+ boolean dir = ZigZag.ZIGZAG_FORWARD;
+ int xindex = 0, yindex = 0, dataindex = 0;
+
+ while (xindex < width && yindex < height && dataindex < data.length)
+ {
+ buffer[yindex][xindex] = data[dataindex];
+ dataindex++;
+ System.err.println("Setting " + dataindex + " to row: " + yindex
+ + " column: " + xindex + " yourval:"
+ + (yindex*8+xindex));
+ if (dir == ZigZag.ZIGZAG_FORWARD)
+ {
+ if (yindex == 0 || xindex == (width - 1))
+ {
+ dir = ZigZag.ZIGZAG_BACKWARD;
+ if (xindex == (width - 1))
+ yindex++;
+ else
+ xindex++;
+ }
+ else
+ {
+ yindex--;
+ xindex++;
+ }
+ }
+ else
+ { /* Backwards */
+ if (xindex == 0 || yindex == (height - 1))
+ {
+ dir = ZigZag.ZIGZAG_FORWARD;
+ if (yindex == (height - 1))
+ xindex++;
+ else
+ yindex++;
+ }
+ else
+ {
+ yindex++;
+ xindex--;
+ }
+ }
+ }
+ return (buffer);
+ }
+
+ public static float[][] decode(float[] data, int width, int height)
+ {
+ float[][] buffer = new float[height][width];
+
+ for (int v = 0; v < height; v++)
+ for (int z = 0; z < width; z++)
+ buffer[v][z] = 11;
+
+ boolean dir = ZigZag.ZIGZAG_FORWARD;
+ int xindex = 0, yindex = 0, dataindex = 0;
+
+ while (xindex < width && yindex < height && dataindex < data.length)
+ {
+ buffer[yindex][xindex] = data[dataindex];
+ dataindex++;
+
+ if (dir == ZigZag.ZIGZAG_FORWARD)
+ {
+ if (yindex == 0 || xindex == (width - 1))
+ {
+ dir = ZigZag.ZIGZAG_BACKWARD;
+ if (xindex == (width - 1))
+ yindex++;
+ else
+ xindex++;
+ }
+ else
+ {
+ yindex--;
+ xindex++;
+ }
+ }
+ else
+ { /* Backwards */
+ if (xindex == 0 || yindex == (height - 1))
+ {
+ dir = ZigZag.ZIGZAG_FORWARD;
+ if (yindex == (height - 1))
+ xindex++;
+ else
+ yindex++;
+ }
+ else
+ {
+ yindex++;
+ xindex--;
+ }
+ }
+ }
+ return (buffer);
+ }
+
+ public static int[][] decode(int[] data, int width, int height)
+ {
+ int[][] buffer = new int[height][width];
+
+ for (int v = 0; v < height; v++)
+ for (int z = 0; z < width; z++)
+ buffer[v][z] = 11;
+
+ boolean dir = ZigZag.ZIGZAG_FORWARD;
+ int xindex = 0, yindex = 0, dataindex = 0;
+
+ while (xindex < width && yindex < height && dataindex < data.length)
+ {
+ buffer[yindex][xindex] = data[dataindex];
+ dataindex++;
+
+ if (dir == ZigZag.ZIGZAG_FORWARD)
+ {
+ if (yindex == 0 || xindex == (width - 1))
+ {
+ dir = ZigZag.ZIGZAG_BACKWARD;
+ if (xindex == (width - 1))
+ yindex++;
+ else
+ xindex++;
+ }
+ else
+ {
+ yindex--;
+ xindex++;
+ }
+ }
+ else
+ { /* Backwards */
+ if (xindex == 0 || yindex == (height - 1))
+ {
+ dir = ZigZag.ZIGZAG_FORWARD;
+ if (yindex == (height - 1))
+ xindex++;
+ else
+ yindex++;
+ }
+ else
+ {
+ yindex++;
+ xindex--;
+ }
+ }
+ }
+ return (buffer);
+ }
+
+ public static double[][] decode8x8_map(double input[])
+ {
+ double[][] output = new double[8][8];
+ for(int i=0; i < 64 ; i++)
+ output[ZIGZAG_8X8_MAP[i]/8][ZIGZAG_8X8_MAP[i]%8] = input[i];
+ return (output);
+ }
+
+}