📄 jfifmarkersegment.java
字号:
} } /* * Write out the values in the integer array as a sequence of bytes, * reporting progress to the writer argument. */ void writeThumbnailData(ImageOutputStream ios, int [] thumbData, JPEGImageWriter writer) throws IOException { int progInterval = thumbData.length / 20; // approx. every 5% if (progInterval == 0) { progInterval = 1; } for (int i = 0; i < thumbData.length; i++) { ios.write(thumbData[i]); if ((i > progInterval) && (i % progInterval == 0)) { writer.thumbnailProgress (((float) i * 100) / ((float) thumbData.length)); } } } /** * Write out this JFIF Marker Segment, including a thumbnail or * appending a series of JFXX Marker Segments, as appropriate. * Warnings and progress reports are sent to the writer argument. * The list of thumbnails is matched to the list of JFXX extension * segments, if any, in order to determine how to encode the * thumbnails. If there are more thumbnails than metadata segments, * default encoding is used for the extra thumbnails. */ void writeWithThumbs(ImageOutputStream ios, List thumbnails, JPEGImageWriter writer) throws IOException { if (thumbnails != null) { JFIFExtensionMarkerSegment jfxx = null; if (thumbnails.size() == 1) { if (!extSegments.isEmpty()) { jfxx = (JFIFExtensionMarkerSegment) extSegments.get(0); } writeThumb(ios, (BufferedImage) thumbnails.get(0), jfxx, 0, true, writer); } else { // All others write as separate JFXX segments write(ios, writer); // Just the header without any thumbnail for (int i = 0; i < thumbnails.size(); i++) { jfxx = null; if (i < extSegments.size()) { jfxx = (JFIFExtensionMarkerSegment) extSegments.get(i); } writeThumb(ios, (BufferedImage) thumbnails.get(i), jfxx, i, false, writer); } } } else { // No thumbnails write(ios, writer); } } private void writeThumb(ImageOutputStream ios, BufferedImage thumb, JFIFExtensionMarkerSegment jfxx, int index, boolean onlyOne, JPEGImageWriter writer) throws IOException { ColorModel cm = thumb.getColorModel(); ColorSpace cs = cm.getColorSpace(); if (cm instanceof IndexColorModel) { // We never write a palette image into the header // So if it's the only one, we need to write the header first if (onlyOne) { write(ios, writer); } if ((jfxx == null) || (jfxx.code == THUMB_PALETTE)) { writeJFXXSegment(index, thumb, ios, writer); // default } else { // Expand to RGB BufferedImage thumbRGB = ((IndexColorModel) cm).convertToIntDiscrete (thumb.getRaster(), false); jfxx.setThumbnail(thumbRGB); writer.thumbnailStarted(index); jfxx.write(ios, writer); // Handles clipping if needed writer.thumbnailComplete(); } } else if (cs.getType() == ColorSpace.TYPE_RGB) { if (jfxx == null) { if (onlyOne) { write(ios, thumb, writer); // As part of the header } else { writeJFXXSegment(index, thumb, ios, writer); // default } } else { // If this is the only one, write the header first if (onlyOne) { write(ios, writer); } if (jfxx.code == THUMB_PALETTE) { writeJFXXSegment(index, thumb, ios, writer); // default writer.warningOccurred (JPEGImageWriter.WARNING_NO_RGB_THUMB_AS_INDEXED); } else { jfxx.setThumbnail(thumb); writer.thumbnailStarted(index); jfxx.write(ios, writer); // Handles clipping if needed writer.thumbnailComplete(); } } } else if (cs.getType() == ColorSpace.TYPE_GRAY) { if (jfxx == null) { if (onlyOne) { BufferedImage thumbRGB = expandGrayThumb(thumb); write(ios, thumbRGB, writer); // As part of the header } else { writeJFXXSegment(index, thumb, ios, writer); // default } } else { // If this is the only one, write the header first if (onlyOne) { write(ios, writer); } if (jfxx.code == THUMB_RGB) { BufferedImage thumbRGB = expandGrayThumb(thumb); writeJFXXSegment(index, thumbRGB, ios, writer); } else if (jfxx.code == THUMB_JPEG) { jfxx.setThumbnail(thumb); writer.thumbnailStarted(index); jfxx.write(ios, writer); // Handles clipping if needed writer.thumbnailComplete(); } else if (jfxx.code == THUMB_PALETTE) { writeJFXXSegment(index, thumb, ios, writer); // default writer.warningOccurred (JPEGImageWriter.WARNING_NO_GRAY_THUMB_AS_INDEXED); } } } else { writer.warningOccurred (JPEGImageWriter.WARNING_ILLEGAL_THUMBNAIL); } } // Could put reason codes in here to be parsed in writeJFXXSegment // in order to provide more meaningful warnings. private class IllegalThumbException extends Exception {} /** * Writes out a new JFXX extension segment, without saving it. */ private void writeJFXXSegment(int index, BufferedImage thumbnail, ImageOutputStream ios, JPEGImageWriter writer) throws IOException { JFIFExtensionMarkerSegment jfxx = null; try { jfxx = new JFIFExtensionMarkerSegment(thumbnail); } catch (IllegalThumbException e) { writer.warningOccurred (JPEGImageWriter.WARNING_ILLEGAL_THUMBNAIL); return; } writer.thumbnailStarted(index); jfxx.write(ios, writer); writer.thumbnailComplete(); } /** * Return an RGB image that is the expansion of the given grayscale * image. */ private static BufferedImage expandGrayThumb(BufferedImage thumb) { BufferedImage ret = new BufferedImage(thumb.getWidth(), thumb.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics g = ret.getGraphics(); g.drawImage(thumb, 0, 0, null); return ret; } /** * Writes out a default JFIF marker segment to the given * output stream. If <code>thumbnails</code> is not <code>null</code>, * writes out the set of thumbnail images as JFXX marker segments, or * incorporated into the JFIF segment if appropriate. * If <code>iccProfile</code> is not <code>null</code>, * writes out the profile after the JFIF segment using as many APP2 * marker segments as necessary. */ static void writeDefaultJFIF(ImageOutputStream ios, List thumbnails, ICC_Profile iccProfile, JPEGImageWriter writer) throws IOException { JFIFMarkerSegment jfif = new JFIFMarkerSegment(); jfif.writeWithThumbs(ios, thumbnails, writer); if (iccProfile != null) { writeICC(iccProfile, ios); } } /** * Prints out the contents of this object to System.out for debugging. */ void print() { printTag("JFIF"); System.out.print("Version "); System.out.print(majorVersion); System.out.println(".0" + Integer.toString(minorVersion)); System.out.print("Resolution units: "); System.out.println(resUnits); System.out.print("X density: "); System.out.println(Xdensity); System.out.print("Y density: "); System.out.println(Ydensity); System.out.print("Thumbnail Width: "); System.out.println(thumbWidth); System.out.print("Thumbnail Height: "); System.out.println(thumbHeight); if (!extSegments.isEmpty()) { for (Iterator iter = extSegments.iterator(); iter.hasNext();) { JFIFExtensionMarkerSegment extSegment = (JFIFExtensionMarkerSegment) iter.next(); extSegment.print(); } } if (iccSegment != null) { iccSegment.print(); } } /** * A JFIF extension APP0 marker segment. */ class JFIFExtensionMarkerSegment extends MarkerSegment { int code; JFIFThumb thumb; private static final int DATA_SIZE = 6; private static final int ID_SIZE = 5; JFIFExtensionMarkerSegment(JPEGBuffer buffer, JPEGImageReader reader) throws IOException { super(buffer); buffer.bufPtr += ID_SIZE; // skip the id, we already checked it code = buffer.buf[buffer.bufPtr++] & 0xff; buffer.bufAvail -= DATA_SIZE; if (code == THUMB_JPEG) { thumb = new JFIFThumbJPEG(buffer, length, reader); } else { buffer.loadBuf(2); int thumbX = buffer.buf[buffer.bufPtr++] & 0xff; int thumbY = buffer.buf[buffer.bufPtr++] & 0xff; buffer.bufAvail -= 2; // following constructors handle bufAvail if (code == THUMB_PALETTE) { thumb = new JFIFThumbPalette(buffer, thumbX, thumbY); } else { thumb = new JFIFThumbRGB(buffer, thumbX, thumbY); } } } JFIFExtensionMarkerSegment(Node node) throws IIOInvalidTreeException { super(JPEG.APP0); NamedNodeMap attrs = node.getAttributes(); if (attrs.getLength() > 0) { code = getAttributeValue(node, attrs, "extensionCode", THUMB_JPEG, THUMB_RGB, false); if (code == THUMB_UNASSIGNED) { throw new IIOInvalidTreeException ("invalid extensionCode attribute value", node); } } else { code = THUMB_UNASSIGNED; } // Now the child if (node.getChildNodes().getLength() != 1) { throw new IIOInvalidTreeException ("app0JFXX node must have exactly 1 child", node); } Node child = node.getFirstChild(); String name = child.getNodeName(); if (name.equals("JFIFthumbJPEG")) { if (code == THUMB_UNASSIGNED) { code = THUMB_JPEG; } thumb = new JFIFThumbJPEG(child); } else if (name.equals("JFIFthumbPalette")) { if (code == THUMB_UNASSIGNED) { code = THUMB_PALETTE; } thumb = new JFIFThumbPalette(child); } else if (name.equals("JFIFthumbRGB")) { if (code == THUMB_UNASSIGNED) { code = THUMB_RGB; } thumb = new JFIFThumbRGB(child); } else { throw new IIOInvalidTreeException ("unrecognized app0JFXX child node", node); } } JFIFExtensionMarkerSegment(BufferedImage thumbnail) throws IllegalThumbException { super(JPEG.APP0); ColorModel cm = thumbnail.getColorModel(); int csType = cm.getColorSpace().getType(); if (cm.hasAlpha()) { throw new IllegalThumbException(); } if (cm instanceof IndexColorModel) { code = THUMB_PALETTE; thumb = new JFIFThumbPalette(thumbnail); } else if (csType == ColorSpace.TYPE_RGB) { code = THUMB_RGB; thumb = new JFIFThumbRGB(thumbnail); } else if (csType == ColorSpace.TYPE_GRAY) { code = THUMB_JPEG; thumb = new JFIFThumbJPEG(thumbnail); } else { throw new IllegalThumbException(); } } void setThumbnail(BufferedImage thumbnail) { try { switch (code) { case THUMB_PALETTE: thumb = new JFIFThumbPalette(thumbnail); break; case THUMB_RGB: thumb = new JFIFThumbRGB(thumbnail); break; case THUMB_JPEG: thumb = new JFIFThumbJPEG(thumbnail); break; } } catch (IllegalThumbException e) { // Should never happen throw new InternalError("Illegal thumb in setThumbnail!"); } } protected Object clone() { JFIFExtensionMarkerSegment newGuy = (JFIFExtensionMarkerSegment) super.clone(); if (thumb != null) { newGuy.thumb = (JFIFThumb) thumb.clone(); } return newGuy; } IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode("app0JFXX"); node.setAttribute("extensionCode", Integer.toString(code)); node.appendChild(thumb.getNativeNode()); return node; } void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { length = LENGTH_SIZE + DATA_SIZE + thumb.getLength(); writeTag(ios); byte [] id = {0x4A, 0x46, 0x58, 0x58, 0x00}; ios.write(id); ios.write(code);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -