1 7 8 package com.sun.imageio.plugins.jpeg; 9 10 import javax.imageio.IIOException ; 11 import javax.imageio.metadata.IIOInvalidTreeException ; 12 import javax.imageio.metadata.IIOMetadataNode ; 13 import javax.imageio.stream.ImageOutputStream ; 14 import javax.imageio.plugins.jpeg.JPEGQTable ; 15 16 import java.io.IOException ; 17 import java.util.List ; 18 import java.util.ArrayList ; 19 import java.util.Iterator ; 20 21 import org.w3c.dom.Node ; 22 import org.w3c.dom.NodeList ; 23 import org.w3c.dom.NamedNodeMap ; 24 25 28 class DQTMarkerSegment extends MarkerSegment { 29 List tables = new ArrayList (); 31 DQTMarkerSegment(float quality, boolean needTwo) { 32 super(JPEG.DQT); 33 tables.add(new Qtable(true, quality)); 34 if (needTwo) { 35 tables.add(new Qtable(false, quality)); 36 } 37 } 38 39 DQTMarkerSegment(JPEGBuffer buffer) throws IOException { 40 super(buffer); 41 int count = length; 42 while (count > 0) { 43 Qtable newGuy = new Qtable(buffer); 44 tables.add(newGuy); 45 count -= newGuy.data.length+1; 46 } 47 buffer.bufAvail -= length; 48 } 49 50 DQTMarkerSegment(JPEGQTable [] qtables) { 51 super(JPEG.DQT); 52 for (int i = 0; i < qtables.length; i++) { 53 tables.add(new Qtable(qtables[i], i)); 54 } 55 } 56 57 DQTMarkerSegment(Node node) throws IIOInvalidTreeException { 58 super(JPEG.DQT); 59 NodeList children = node.getChildNodes(); 60 int size = children.getLength(); 61 if ((size < 1) || (size > 4)) { 62 throw new IIOInvalidTreeException ("Invalid DQT node", node); 63 } 64 for (int i = 0; i < size; i++) { 65 tables.add(new Qtable(children.item(i))); 66 } 67 } 68 69 protected Object clone() { 70 DQTMarkerSegment newGuy = (DQTMarkerSegment) super.clone(); 71 newGuy.tables = new ArrayList (tables.size()); 72 Iterator iter = tables.iterator(); 73 while (iter.hasNext()) { 74 Qtable table = (Qtable) iter.next(); 75 newGuy.tables.add(table.clone()); 76 } 77 return newGuy; 78 } 79 80 IIOMetadataNode getNativeNode() { 81 IIOMetadataNode node = new IIOMetadataNode ("dqt"); 82 for (int i= 0; i<tables.size(); i++) { 83 Qtable table = (Qtable) tables.get(i); 84 node.appendChild(table.getNativeNode()); 85 } 86 return node; 87 } 88 89 93 void write(ImageOutputStream ios) throws IOException { 94 } 96 97 void print() { 98 printTag("DQT"); 99 System.out.println("Num tables: " 100 + Integer.toString(tables.size())); 101 for (int i= 0; i<tables.size(); i++) { 102 Qtable table = (Qtable) tables.get(i); 103 table.print(); 104 } 105 System.out.println(); 106 } 107 108 113 Qtable getChromaForLuma(Qtable luma) { 114 Qtable newGuy = null; 115 boolean allSame = true; 118 for (int i = 1; i < luma.QTABLE_SIZE; i++) { 119 if (luma.data[i] != luma.data[i-1]) { 120 allSame = false; 121 break; 122 } 123 } 124 if (allSame) { 125 newGuy = (Qtable) luma.clone(); 126 newGuy.tableID = 1; 127 } else { 128 int largestPos = 0; 131 for (int i = 1; i < luma.QTABLE_SIZE; i++) { 132 if (luma.data[i] > luma.data[largestPos]) { 133 largestPos = i; 134 } 135 } 136 float scaleFactor = ((float)(luma.data[largestPos])) 143 / ((float)(JPEGQTable.K1Div2Luminance.getTable()[largestPos])); 144 JPEGQTable jpegTable = 146 JPEGQTable.K2Div2Chrominance.getScaledInstance(scaleFactor, 147 true); 148 newGuy = new Qtable(jpegTable, 1); 149 } 150 return newGuy; 151 } 152 153 Qtable getQtableFromNode(Node node) throws IIOInvalidTreeException { 154 return new Qtable(node); 155 } 156 157 160 class Qtable implements Cloneable { 161 int elementPrecision; 162 int tableID; 163 final int QTABLE_SIZE = 64; 164 int [] data; 166 170 private final int [] zigzag = { 171 0, 1, 5, 6, 14, 15, 27, 28, 172 2, 4, 7, 13, 16, 26, 29, 42, 173 3, 8, 12, 17, 25, 30, 41, 43, 174 9, 11, 18, 24, 31, 40, 44, 53, 175 10, 19, 23, 32, 39, 45, 52, 54, 176 20, 22, 33, 38, 46, 51, 55, 60, 177 21, 34, 37, 47, 50, 56, 59, 61, 178 35, 36, 48, 49, 57, 58, 62, 63 179 }; 180 181 Qtable(boolean wantLuma, float quality) { 182 elementPrecision = 0; 183 JPEGQTable base = null; 184 if (wantLuma) { 185 tableID = 0; 186 base = JPEGQTable.K1Div2Luminance; 187 } else { 188 tableID = 1; 189 base = JPEGQTable.K2Div2Chrominance; 190 } 191 if (quality != JPEG.DEFAULT_QUALITY) { 192 quality = JPEG.convertToLinearQuality(quality); 193 if (wantLuma) { 194 base = JPEGQTable.K1Luminance.getScaledInstance 195 (quality, true); 196 } else { 197 base = JPEGQTable.K2Div2Chrominance.getScaledInstance 198 (quality, true); 199 } 200 } 201 data = base.getTable(); 202 } 203 204 Qtable(JPEGBuffer buffer) throws IIOException { 205 elementPrecision = buffer.buf[buffer.bufPtr] >>> 4; 206 tableID = buffer.buf[buffer.bufPtr++] & 0xf; 207 if (elementPrecision != 0) { 208 throw new IIOException ("Unsupported element precision"); 210 } 211 data = new int [QTABLE_SIZE]; 212 for (int i = 0; i < QTABLE_SIZE; i++) { 214 data[i] = buffer.buf[buffer.bufPtr+zigzag[i]] & 0xff; 215 } 216 buffer.bufPtr += QTABLE_SIZE; 217 } 218 219 Qtable(JPEGQTable table, int id) { 220 elementPrecision = 0; 221 tableID = id; 222 data = table.getTable(); 223 } 224 225 Qtable(Node node) throws IIOInvalidTreeException { 226 if (node.getNodeName().equals("dqtable")) { 227 NamedNodeMap attrs = node.getAttributes(); 228 int count = attrs.getLength(); 229 if ((count < 1) || (count > 2)) { 230 throw new IIOInvalidTreeException 231 ("dqtable node must have 1 or 2 attributes", node); 232 } 233 elementPrecision = 0; 234 tableID = getAttributeValue(node, attrs, "qtableId", 0, 3, true); 235 if (node instanceof IIOMetadataNode ) { 236 IIOMetadataNode ourNode = (IIOMetadataNode ) node; 237 JPEGQTable table = (JPEGQTable ) ourNode.getUserObject(); 238 if (table == null) { 239 throw new IIOInvalidTreeException 240 ("dqtable node must have user object", node); 241 } 242 data = table.getTable(); 243 } else { 244 throw new IIOInvalidTreeException 245 ("dqtable node must have user object", node); 246 } 247 } else { 248 throw new IIOInvalidTreeException 249 ("Invalid node, expected dqtable", node); 250 } 251 } 252 253 protected Object clone() { 254 Qtable newGuy = null; 255 try { 256 newGuy = (Qtable) super.clone(); 257 } catch (CloneNotSupportedException e) {} if (data != null) { 259 newGuy.data = (int []) data.clone(); 260 } 261 return newGuy; 262 } 263 264 IIOMetadataNode getNativeNode() { 265 IIOMetadataNode node = new IIOMetadataNode ("dqtable"); 266 node.setAttribute("elementPrecision", 267 Integer.toString(elementPrecision)); 268 node.setAttribute("qtableId", 269 Integer.toString(tableID)); 270 node.setUserObject(new JPEGQTable (data)); 271 return node; 272 } 273 274 void print() { 275 System.out.println("Table id: " + Integer.toString(tableID)); 276 System.out.println("Element precision: " 277 + Integer.toString(elementPrecision)); 278 279 (new JPEGQTable (data)).toString(); 280 289 } 290 } 291 } 292 293 | Popular Tags |