📄 jpegmetadata.java
字号:
private void mergeCOMNode(Node node) throws IIOInvalidTreeException { COMMarkerSegment newGuy = new COMMarkerSegment(node); insertCOMMarkerSegment(newGuy); } /** * Insert a new COM marker segment into an appropriate place in the * marker sequence, as follows: * If there already exist COM marker segments, the new one is inserted * after the last one. * If there are no COM segments, the new COM segment is inserted after the * JFIF segment, if there is one. * If there is no JFIF segment, the new COM segment is inserted after the * Adobe marker segment, if there is one. * If there is no Adobe segment, the new COM segment is inserted * at the beginning of the sequence. */ private void insertCOMMarkerSegment(COMMarkerSegment newGuy) { int lastCOM = findMarkerSegmentPosition(COMMarkerSegment.class, false); boolean hasJFIF = (findMarkerSegment(JFIFMarkerSegment.class, true) != null); int firstAdobe = findMarkerSegmentPosition(AdobeMarkerSegment.class, true); if (lastCOM != -1) { markerSequence.add(lastCOM+1, newGuy); } else if (hasJFIF) { markerSequence.add(1, newGuy); // JFIF is always 0 } else if (firstAdobe != -1) { markerSequence.add(firstAdobe+1, newGuy); } else { markerSequence.add(0, newGuy); } } /** * Merge the given Adobe APP14 node into the marker sequence. * If there already exists an Adobe marker segment, then its attributes * are updated from the node. * If there is no Adobe segment, then a new one is created and added * using insertAdobeMarkerSegment. */ private void mergeAdobeNode(Node node) throws IIOInvalidTreeException { AdobeMarkerSegment adobe = (AdobeMarkerSegment) findMarkerSegment(AdobeMarkerSegment.class, true); if (adobe != null) { adobe.updateFromNativeNode(node, false); } else { AdobeMarkerSegment newGuy = new AdobeMarkerSegment(node); insertAdobeMarkerSegment(newGuy); } } /** * Insert the given AdobeMarkerSegment into the marker sequence, as * follows (we assume there is no Adobe segment yet): * If there is a JFIF segment, then the new Adobe segment is inserted * after it. * If there is no JFIF segment, the new Adobe segment is inserted after the * last Unknown segment, if there are any. * If there are no Unknown segments, the new Adobe segment is inserted * at the beginning of the sequence. */ private void insertAdobeMarkerSegment(AdobeMarkerSegment newGuy) { boolean hasJFIF = (findMarkerSegment(JFIFMarkerSegment.class, true) != null); int lastUnknown = findLastUnknownMarkerSegmentPosition(); if (hasJFIF) { markerSequence.add(1, newGuy); // JFIF is always 0 } else if (lastUnknown != -1) { markerSequence.add(lastUnknown+1, newGuy); } else { markerSequence.add(0, newGuy); } } /** * Merge the given Unknown node into the marker sequence. * A new Unknown marker segment is created and added to the sequence as * follows: * If there already exist Unknown marker segments, the new one is inserted * after the last one. * If there are no Unknown marker segments, the new Unknown marker segment * is inserted after the JFIF segment, if there is one. * If there is no JFIF segment, the new Unknown segment is inserted before * the Adobe marker segment, if there is one. * If there is no Adobe segment, the new Unknown segment is inserted * at the beginning of the sequence. */ private void mergeUnknownNode(Node node) throws IIOInvalidTreeException { MarkerSegment newGuy = new MarkerSegment(node); int lastUnknown = findLastUnknownMarkerSegmentPosition(); boolean hasJFIF = (findMarkerSegment(JFIFMarkerSegment.class, true) != null); int firstAdobe = findMarkerSegmentPosition(AdobeMarkerSegment.class, true); if (lastUnknown != -1) { markerSequence.add(lastUnknown+1, newGuy); } else if (hasJFIF) { markerSequence.add(1, newGuy); // JFIF is always 0 } if (firstAdobe != -1) { markerSequence.add(firstAdobe, newGuy); } else { markerSequence.add(0, newGuy); } } /** * Merge the given SOF node into the marker sequence. * If there already exists an SOF marker segment in the sequence, then * its values are updated from the node. * If there is no SOF segment, then a new one is created and added as * follows: * If there are any SOS segments, the new SOF segment is inserted before * the first one. * If there is no SOS segment, the new SOF segment is added to the end * of the sequence. * */ private void mergeSOFNode(Node node) throws IIOInvalidTreeException { SOFMarkerSegment sof = (SOFMarkerSegment) findMarkerSegment(SOFMarkerSegment.class, true); if (sof != null) { sof.updateFromNativeNode(node, false); } else { SOFMarkerSegment newGuy = new SOFMarkerSegment(node); int firstSOS = findMarkerSegmentPosition(SOSMarkerSegment.class, true); if (firstSOS != -1) { markerSequence.add(firstSOS, newGuy); } else { markerSequence.add(newGuy); } } } /** * Merge the given SOS node into the marker sequence. * If there already exists a single SOS marker segment, then the values * are updated from the node. * If there are more than one existing SOS marker segments, then an * IIOInvalidTreeException is thrown, as SOS segments cannot be merged * into a set of progressive scans. * If there are no SOS marker segments, a new one is created and added * to the end of the sequence. */ private void mergeSOSNode(Node node) throws IIOInvalidTreeException { SOSMarkerSegment firstSOS = (SOSMarkerSegment) findMarkerSegment(SOSMarkerSegment.class, true); SOSMarkerSegment lastSOS = (SOSMarkerSegment) findMarkerSegment(SOSMarkerSegment.class, false); if (firstSOS != null) { if (firstSOS != lastSOS) { throw new IIOInvalidTreeException ("Can't merge SOS node into a tree with > 1 SOS node", node); } firstSOS.updateFromNativeNode(node, false); } else { markerSequence.add(new SOSMarkerSegment(node)); } } private boolean transparencyDone; private void mergeStandardTree(Node root) throws IIOInvalidTreeException { transparencyDone = false; NodeList children = root.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); String name = node.getNodeName(); if (name.equals("Chroma")) { mergeStandardChromaNode(node, children); } else if (name.equals("Compression")) { mergeStandardCompressionNode(node); } else if (name.equals("Data")) { mergeStandardDataNode(node); } else if (name.equals("Dimension")) { mergeStandardDimensionNode(node); } else if (name.equals("Document")) { mergeStandardDocumentNode(node); } else if (name.equals("Text")) { mergeStandardTextNode(node); } else if (name.equals("Transparency")) { mergeStandardTransparencyNode(node); } else { throw new IIOInvalidTreeException("Invalid node: " + name, node); } } } /* * In general, it could be possible to convert all non-pixel data to some * textual form and include it in comments, but then this would create the * expectation that these comment forms be recognized by the reader, thus * creating a defacto extension to JPEG metadata capabilities. This is * probably best avoided, so the following convert only text nodes to * comments, and lose the keywords as well. */ private void mergeStandardChromaNode(Node node, NodeList siblings) throws IIOInvalidTreeException { // ColorSpaceType can change the target colorspace for compression // This must take any transparency node into account as well, as // that affects the number of channels (if alpha is present). If // a transparency node is dealt with here, set a flag to indicate // this to the transparency processor below. If we discover that // the nodes are not in order, throw an exception as the tree is // invalid. if (transparencyDone) { throw new IIOInvalidTreeException ("Transparency node must follow Chroma node", node); } Node csType = node.getFirstChild(); if ((csType == null) || !csType.getNodeName().equals("ColorSpaceType")) { // If there is no ColorSpaceType node, we have nothing to do return; } String csName = csType.getAttributes().getNamedItem("name").getNodeValue(); int numChannels = 0; boolean wantJFIF = false; boolean wantAdobe = false; int transform = 0; boolean willSubsample = false; byte [] ids = {1, 2, 3, 4}; // JFIF compatible if (csName.equals("GRAY")) { numChannels = 1; wantJFIF = true; } else if (csName.equals("YCbCr")) { numChannels = 3; wantJFIF = true; willSubsample = true; } else if (csName.equals("PhotoYCC")) { numChannels = 3; wantAdobe = true; transform = JPEG.ADOBE_YCC; ids[0] = (byte) 'Y'; ids[1] = (byte) 'C'; ids[2] = (byte) 'c'; } else if (csName.equals("RGB")) { numChannels = 3; wantAdobe = true; transform = JPEG.ADOBE_UNKNOWN; ids[0] = (byte) 'R'; ids[1] = (byte) 'G'; ids[2] = (byte) 'B'; } else if ((csName.equals("XYZ")) || (csName.equals("Lab")) || (csName.equals("Luv")) || (csName.equals("YxY")) || (csName.equals("HSV")) || (csName.equals("HLS")) || (csName.equals("CMY")) || (csName.equals("3CLR"))) { numChannels = 3; } else if (csName.equals("YCCK")) { numChannels = 4; wantAdobe = true; transform = JPEG.ADOBE_YCCK; willSubsample = true; } else if (csName.equals("CMYK")) { numChannels = 4; wantAdobe = true; transform = JPEG.ADOBE_UNKNOWN; } else if (csName.equals("4CLR")) { numChannels = 4; } else { // We can't handle them, so don't modify any metadata return; } boolean wantAlpha = false; for (int i = 0; i < siblings.getLength(); i++) { Node trans = siblings.item(i); if (trans.getNodeName().equals("Transparency")) { wantAlpha = wantAlpha(trans); break; // out of for } } if (wantAlpha) { numChannels++; wantJFIF = false; if (ids[0] == (byte) 'R') { ids[3] = (byte) 'A'; wantAdobe = false; } } JFIFMarkerSegment jfif = (JFIFMarkerSegment) findMarkerSegment(JFIFMarkerSegment.class, true); AdobeMarkerSegment adobe = (AdobeMarkerSegment) findMarkerSegment(AdobeMarkerSegment.class, true); SOFMarkerSegment sof = (SOFMarkerSegment) findMarkerSegment(SOFMarkerSegment.class, true); SOSMarkerSegment sos = (SOSMarkerSegment) findMarkerSegment(SOSMarkerSegment.class, true); // If the metadata specifies progressive, then the number of channels // must match, so that we can modify all the existing SOS marker segments. // If they don't match, we don't know what to do with SOS so we can't do // the merge. We then just return silently. // An exception would not be appropriate. A warning might, but we have // nowhere to send it to. if ((sof != null) && (sof.tag == JPEG.SOF2)) { // Progressive if ((sof.componentSpecs.length != numChannels) && (sos != null)) { return; } } // JFIF header might be removed if (!wantJFIF && (jfif != null)) { markerSequence.remove(jfif); } // Now add a JFIF if we do want one, but only if it isn't stream metadata if (wantJFIF && !isStream) { markerSequence.add(0, new JFIFMarkerSegment()); } // Adobe header might be removed or the transform modified, if it isn't // stream metadata if (wantAdobe) { if ((adobe == null) && !isStream) { adobe = new AdobeMarkerSegment(transform); insertAdobeMarkerSegment(adobe); } else { adobe.transform = transform; } } else if (adobe != null) { markerSequence.remove(adobe); } boolean updateQtables = false; boolean updateHtables = false; boolean progressive = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -