On Thu, 2006-03-30 at 19:49 -0700, Tom Tromey wrote:
> >>>>> "Tom" == Thomas Fitzsimmons <[EMAIL PROTECTED]> writes:
>
> Tom> + public static final JPEGQTable K1Luminance = new JPEGQTable(new int[]
> Tom> + {
>
> For these it would be mildly better to have a private constructor
> which doesn't copy the argument.
>
> Tom> + int[] tableCopy = new int[table.length];
> Tom> + System.arraycopy(table, 0, tableCopy, 0, table.length);
> Tom> + return tableCopy;
>
> This is: return (int[]) table.clone();
>
> Tom> + public JPEGQTable getScaledInstance(float scaleFactor,
> Tom> + boolean forceBaseline)
> Tom> + {
> Tom> + int[] scaledTable = getTable();
>
> Somehow this should also be able to make a single copy of the table.
> Right now it makes 2 -- one here and one in the constructor.
Thanks for the comments. They're all fixed by the attached patch, which
I've committed.
Tom
2006-03-31 Thomas Fitzsimmons <[EMAIL PROTECTED]>
* javax/imageio/plugins/jpeg/JPEGHuffmanTable.java: Eliminate
unnecessary copying.
* javax/imageio/plugins/jpeg/JPEGQTable.java: Likewise.
Index: javax/imageio/plugins/jpeg/JPEGHuffmanTable.java
===================================================================
RCS file: /sources/classpath/classpath/javax/imageio/plugins/jpeg/JPEGHuffmanTable.java,v
retrieving revision 1.2
diff -u -r1.2 JPEGHuffmanTable.java
--- javax/imageio/plugins/jpeg/JPEGHuffmanTable.java 31 Mar 2006 02:07:31 -0000 1.2
+++ javax/imageio/plugins/jpeg/JPEGHuffmanTable.java 31 Mar 2006 21:50:01 -0000
@@ -55,6 +55,8 @@
*/
private short[] values;
+ // The private constructors are used for these final fields to avoid
+ // unnecessary copying.
/**
* The standard JPEG AC chrominance Huffman table.
*/
@@ -93,7 +95,7 @@
0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xf2, 0xf3,
0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa });
+ 0xf9, 0xfa }, false);
/**
* The standard JPEG AC luminance Huffman table.
@@ -133,7 +135,7 @@
0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
0xe9, 0xea, 0xf1, 0xf2, 0xf3,
0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa });
+ 0xf9, 0xfa }, false);
/**
* The standard JPEG DC chrominance Huffman table.
@@ -142,7 +144,7 @@
new JPEGHuffmanTable(new short[] { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0 },
new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11 });
+ 10, 11 }, false);
/**
* The standard JPEG DC luminance Huffman table.
@@ -151,7 +153,7 @@
new JPEGHuffmanTable(new short[] { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0 },
new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11 });
+ 10, 11 }, false);
/**
* Construct and initialize a Huffman table. Copies are created of
@@ -168,9 +170,28 @@
*/
public JPEGHuffmanTable(short[] lengths, short[] values)
{
- if (lengths == null || values == null || lengths.length > 16
- || values.length > 256)
- throw new IllegalArgumentException("invalid length or values array");
+ // Create copies of the lengths and values arguments.
+ this(checkLengths(lengths), checkValues(values, lengths), true);
+ }
+
+ /**
+ * Private constructor that avoids unnecessary copying and argument
+ * checking.
+ *
+ * @param lengths an array of Huffman code lengths
+ * @param values a sorted array of Huffman values
+ * @param copy true if copies should be created of the given arrays
+ */
+ private JPEGHuffmanTable(short[] lengths, short[] values, boolean copy)
+ {
+ this.lengths = copy ? (short[]) lengths.clone() : lengths;
+ this.values = copy ? (short[]) values.clone() : values;
+ }
+
+ private static short[] checkLengths(short[] lengths)
+ {
+ if (lengths == null || lengths.length > 16)
+ throw new IllegalArgumentException("invalid length array");
for (int i = 0; i < lengths.length; i++)
{
@@ -178,12 +199,6 @@
throw new IllegalArgumentException("negative length");
}
- for (int i = 0; i < values.length; i++)
- {
- if (values[i] < 0)
- throw new IllegalArgumentException("negative value");
- }
-
int sum = 0;
for (int i = 0; i < lengths.length; i++)
{
@@ -192,15 +207,30 @@
+ " for code length " + (i + 1));
sum += lengths[i];
}
+
+ return lengths;
+ }
+
+ private static short[] checkValues(short[] values, short[] lengths)
+ {
+ if (values == null || values.length > 256)
+ throw new IllegalArgumentException("invalid values array");
+
+ for (int i = 0; i < values.length; i++)
+ {
+ if (values[i] < 0)
+ throw new IllegalArgumentException("negative value");
+ }
+ // lengths is known-valid by this point.
+ int sum = 0;
+ for (int i = 0; i < lengths.length; i++)
+ sum += lengths[i];
+
if (values.length != sum)
throw new IllegalArgumentException("invalid number of values"
+ " for number of codes");
- this.lengths = new short[lengths.length];
- System.arraycopy(lengths, 0, this.lengths, 0, lengths.length);
-
- this.values = new short[values.length];
- System.arraycopy(values, 0, this.values, 0, values.length);
+ return values;
}
/**
@@ -212,9 +242,7 @@
*/
public short[] getLengths()
{
- short[] lengthsCopy = new short[lengths.length];
- System.arraycopy(lengths, 0, lengthsCopy, 0, lengths.length);
- return lengthsCopy;
+ return (short[]) lengths.clone();
}
/**
@@ -225,9 +253,7 @@
*/
public short[] getValues()
{
- short[] valuesCopy = new short[values.length];
- System.arraycopy(values, 0, valuesCopy, 0, values.length);
- return valuesCopy;
+ return (short[]) values.clone();
}
/**
Index: javax/imageio/plugins/jpeg/JPEGQTable.java
===================================================================
RCS file: /sources/classpath/classpath/javax/imageio/plugins/jpeg/JPEGQTable.java,v
retrieving revision 1.1
diff -u -r1.1 JPEGQTable.java
--- javax/imageio/plugins/jpeg/JPEGQTable.java 31 Mar 2006 02:07:31 -0000 1.1
+++ javax/imageio/plugins/jpeg/JPEGQTable.java 31 Mar 2006 21:50:01 -0000
@@ -66,7 +66,7 @@
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
- });
+ }, false);
/**
* The standard JPEG luminance quantization table, scaled by
@@ -89,7 +89,7 @@
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
- });
+ }, false);
/**
* The standard JPEG chrominance quantization table, scaled by
@@ -99,20 +99,37 @@
K2Chrominance.getScaledInstance(0.5f, true);
/**
- * Construct a new JPEG quantization table.
+ * Construct a new JPEG quantization table. A copy is created of
+ * the table argument.
*
- * @param table the 64-element value table, stored in natural order.
+ * @param table the 64-element value table, stored in natural order
*
* @throws IllegalArgumentException if the table is null or if
* table's length is not equal to 64.
*/
public JPEGQTable(int[] table)
{
+ this(checkTable(table), true);
+ }
+
+ /**
+ * Private constructor that avoids unnecessary copying and argument
+ * checking.
+ *
+ * @param table the 64-element value table, stored in natural order
+ * @param copy true if a copy should be created of the given table
+ */
+ private JPEGQTable(int[] table, boolean copy)
+ {
+ this.table = copy ? (int[]) table.clone() : table;
+ }
+
+ private static int[] checkTable(int[] table)
+ {
if (table == null || table.length != 64)
throw new IllegalArgumentException("invalid JPEG quantization table");
- this.table = new int[table.length];
- System.arraycopy(table, 0, this.table, 0, table.length);
+ return table;
}
/**
@@ -122,9 +139,7 @@
*/
public int[] getTable()
{
- int[] tableCopy = new int[table.length];
- System.arraycopy(table, 0, tableCopy, 0, table.length);
- return tableCopy;
+ return (int[]) table.clone();
}
/**
@@ -153,7 +168,9 @@
scaledTable[i] = max;
}
- return new JPEGQTable(scaledTable);
+ // Do not copy scaledTable. It is already a copy because we used
+ // getTable to retrieve it.
+ return new JPEGQTable(scaledTable, false);
}
/**