📄 jpegmetadata.java
字号:
// Now that we've read up to the EOI, we need to push back // whatever is left in the buffer, so that the next read // in the native code will work. buffer.pushBack(); if (!isConsistent()) { throw new IIOException("Inconsistent metadata read from stream"); } } /** * Constructs a default stream <code>JPEGMetadata</code> object appropriate * for the given write parameters. */ JPEGMetadata(ImageWriteParam param, JPEGImageWriter writer) { this(true, false); JPEGImageWriteParam jparam = null; if ((param != null) && (param instanceof JPEGImageWriteParam)) { jparam = (JPEGImageWriteParam) param; if (!jparam.areTablesSet()) { jparam = null; } } if (jparam != null) { markerSequence.add(new DQTMarkerSegment(jparam.getQTables())); markerSequence.add (new DHTMarkerSegment(jparam.getDCHuffmanTables(), jparam.getACHuffmanTables())); } else { // default tables. markerSequence.add(new DQTMarkerSegment(JPEG.getDefaultQTables())); markerSequence.add(new DHTMarkerSegment(JPEG.getDefaultHuffmanTables(true), JPEG.getDefaultHuffmanTables(false))); } // Defensive programming if (!isConsistent()) { throw new InternalError("Default stream metadata is inconsistent"); } } /** * Constructs a default image <code>JPEGMetadata</code> object appropriate * for the given image type and write parameters. */ JPEGMetadata(ImageTypeSpecifier imageType, ImageWriteParam param, JPEGImageWriter writer) { this(false, false); boolean wantJFIF = true; boolean wantAdobe = false; int transform = JPEG.ADOBE_UNKNOWN; boolean willSubsample = true; boolean wantICC = false; boolean wantProg = false; boolean wantOptimized = false; boolean wantExtended = false; boolean wantQTables = true; boolean wantHTables = true; float quality = JPEG.DEFAULT_QUALITY; byte[] componentIDs = { 1, 2, 3, 4}; int numComponents = 0; ImageTypeSpecifier destType = null; if (param != null) { destType = param.getDestinationType(); if (destType != null) { if (imageType != null) { // Ignore the destination type. writer.warningOccurred (JPEGImageWriter.WARNING_DEST_IGNORED); destType = null; } } // The only progressive mode that makes sense here is MODE_DEFAULT if (param.canWriteProgressive()) { // the param may not be one of ours, so it may return false. // If so, the following would throw an exception if (param.getProgressiveMode() == ImageWriteParam.MODE_DEFAULT) { wantProg = true; wantOptimized = true; wantHTables = false; } } if (param instanceof JPEGImageWriteParam) { JPEGImageWriteParam jparam = (JPEGImageWriteParam) param; if (jparam.areTablesSet()) { wantQTables = false; // If the param has them, metadata shouldn't wantHTables = false; if ((jparam.getDCHuffmanTables().length > 2) || (jparam.getACHuffmanTables().length > 2)) { wantExtended = true; } } // Progressive forces optimized, regardless of param setting // so consult the param re optimized only if not progressive if (!wantProg) { wantOptimized = jparam.getOptimizeHuffmanTables(); if (wantOptimized) { wantHTables = false; } } } // compression quality should determine the q tables. Note that this // will be ignored if we already decided not to create any. // Again, the param may not be one of ours, so we must check that it // supports compression settings if (param.canWriteCompressed()) { if (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { quality = param.getCompressionQuality(); } } } // We are done with the param, now for the image types ColorSpace cs = null; if (destType != null) { ColorModel cm = destType.getColorModel(); numComponents = cm.getNumComponents(); boolean hasExtraComponents = (cm.getNumColorComponents() != numComponents); boolean hasAlpha = cm.hasAlpha(); cs = cm.getColorSpace(); int type = cs.getType(); switch(type) { case ColorSpace.TYPE_GRAY: willSubsample = false; if (hasExtraComponents) { // e.g. alpha wantJFIF = false; } break; case ColorSpace.TYPE_3CLR: if (cs == JPEG.JCS.YCC) { wantJFIF = false; componentIDs[0] = (byte) 'Y'; componentIDs[1] = (byte) 'C'; componentIDs[2] = (byte) 'c'; if (hasAlpha) { componentIDs[3] = (byte) 'A'; } } break; case ColorSpace.TYPE_YCbCr: if (hasExtraComponents) { // e.g. K or alpha wantJFIF = false; if (!hasAlpha) { // Not alpha, so must be K wantAdobe = true; transform = JPEG.ADOBE_YCCK; } } break; case ColorSpace.TYPE_RGB: // with or without alpha wantJFIF = false; wantAdobe = true; willSubsample = false; componentIDs[0] = (byte) 'R'; componentIDs[1] = (byte) 'G'; componentIDs[2] = (byte) 'B'; if (hasAlpha) { componentIDs[3] = (byte) 'A'; } break; default: // Everything else is not subsampled, gets no special marker, // and component ids are 1 - N wantJFIF = false; willSubsample = false; } } else if (imageType != null) { ColorModel cm = imageType.getColorModel(); numComponents = cm.getNumComponents(); boolean hasExtraComponents = (cm.getNumColorComponents() != numComponents); boolean hasAlpha = cm.hasAlpha(); cs = cm.getColorSpace(); int type = cs.getType(); switch(type) { case ColorSpace.TYPE_GRAY: willSubsample = false; if (hasExtraComponents) { // e.g. alpha wantJFIF = false; } break; case ColorSpace.TYPE_RGB: // with or without alpha // without alpha we just accept the JFIF defaults if (hasAlpha) { wantJFIF = false; } break; case ColorSpace.TYPE_3CLR: wantJFIF = false; willSubsample = false; if (cs.equals(ColorSpace.getInstance(ColorSpace.CS_PYCC))) { willSubsample = true; wantAdobe = true; componentIDs[0] = (byte) 'Y'; componentIDs[1] = (byte) 'C'; componentIDs[2] = (byte) 'c'; if (hasAlpha) { componentIDs[3] = (byte) 'A'; } } break; case ColorSpace.TYPE_YCbCr: if (hasExtraComponents) { // e.g. K or alpha wantJFIF = false; if (!hasAlpha) { // then it must be K wantAdobe = true; transform = JPEG.ADOBE_YCCK; } } break; case ColorSpace.TYPE_CMYK: wantJFIF = false; wantAdobe = true; transform = JPEG.ADOBE_YCCK; break; default: // Everything else is not subsampled, gets no special marker, // and component ids are 0 - N wantJFIF = false; willSubsample = false; } } // do we want an ICC profile? if (wantJFIF && JPEG.isNonStandardICC(cs)) { wantICC = true; } // Now step through the markers, consulting our variables. if (wantJFIF) { JFIFMarkerSegment jfif = new JFIFMarkerSegment(); markerSequence.add(jfif); if (wantICC) { try { jfif.addICC((ICC_ColorSpace)cs); } catch (IOException e) {} // Can't happen here } } // Adobe if (wantAdobe) { markerSequence.add(new AdobeMarkerSegment(transform)); } // dqt if (wantQTables) { markerSequence.add(new DQTMarkerSegment(quality, willSubsample)); } // dht if (wantHTables) { markerSequence.add(new DHTMarkerSegment(willSubsample)); } // sof markerSequence.add(new SOFMarkerSegment(wantProg, wantExtended, willSubsample, componentIDs, numComponents)); // sos if (!wantProg) { // Default progression scans are done in the writer markerSequence.add(new SOSMarkerSegment(willSubsample, componentIDs, numComponents)); } // Defensive programming if (!isConsistent()) { throw new InternalError("Default image metadata is inconsistent"); } } ////// End of constructors // Utilities for dealing with the marker sequence. // The first ones have package access for access from the writer. /** * Returns the first MarkerSegment object in the list * with the given tag, or null if none is found. */ MarkerSegment findMarkerSegment(int tag) { Iterator iter = markerSequence.iterator(); while (iter.hasNext()) { MarkerSegment seg = (MarkerSegment)iter.next(); if (seg.tag == tag) { return seg; } } return null; } /** * Returns the first or last MarkerSegment object in the list * of the given class, or null if none is found. */ MarkerSegment findMarkerSegment(Class cls, boolean first) { if (first) { Iterator iter = markerSequence.iterator(); while (iter.hasNext()) { MarkerSegment seg = (MarkerSegment)iter.next(); if (cls.isInstance(seg)) { return seg; } } } else { ListIterator iter = markerSequence.listIterator(markerSequence.size()); while (iter.hasPrevious()) { MarkerSegment seg = (MarkerSegment)iter.previous(); if (cls.isInstance(seg)) { return seg; } } } return null; } /** * Returns the index of the first or last MarkerSegment in the list * of the given class, or -1 if none is found. */ private int findMarkerSegmentPosition(Class cls, boolean first) { if (first) { ListIterator iter = markerSequence.listIterator();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -