📄 jpegimagewriter.java
字号:
bandOffs, null); // Call the writer, who will call back for every scanline processImageStarted(currentImage); boolean aborted = false; if (debug) { System.out.println("inCsType: " + inCsType); System.out.println("outCsType: " + outCsType); } aborted = writeImage(structPointer, buffer.getData(), inCsType, outCsType, numBandsUsed, bandSizes, sourceWidth, destWidth, destHeight, periodX, periodY, qTables, writeDQT, DCHuffmanTables, ACHuffmanTables, writeDHT, optimizeHuffman, (progressiveMode != ImageWriteParam.MODE_DISABLED), numScans, scans, componentIds, HsamplingFactors, VsamplingFactors, QtableSelectors, haveMetadata, restartInterval); if (aborted) { processWriteAborted(); } else { processImageComplete(); } ios.flush(); currentImage++; // After a successful write } public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException { if (ios == null) { throw new IllegalStateException("Output has not been set!"); } /* * from jpeg_metadata.html: * If no stream metadata is supplied to * <code>ImageWriter.prepareWriteSequence</code>, then no * tables-only image is written. If stream metadata containing * no tables is supplied to * <code>ImageWriter.prepareWriteSequence</code>, then a tables-only * image containing default visually lossless tables is written. */ if (streamMetadata != null) { if (streamMetadata instanceof JPEGMetadata) { // write a complete tables-only image at the beginning of // the stream. JPEGMetadata jmeta = (JPEGMetadata) streamMetadata; if (jmeta.isStream == false) { throw new IllegalArgumentException ("Invalid stream metadata object."); } // Check that we are // at the beginning of the stream, or can go there, and haven't // written out the metadata already. if (currentImage != 0) { throw new IIOException ("JPEG Stream metadata must precede all images"); } if (sequencePrepared == true) { throw new IIOException("Stream metadata already written!"); } // Set the tables // If the metadata has no tables, use default tables. streamQTables = collectQTablesFromMetadata(jmeta); if (debug) { System.out.println("after collecting from stream metadata, " + "streamQTables.length is " + streamQTables.length); } if (streamQTables == null) { streamQTables = JPEG.getDefaultQTables(); } streamDCHuffmanTables = collectHTablesFromMetadata(jmeta, true); if (streamDCHuffmanTables == null) { streamDCHuffmanTables = JPEG.getDefaultHuffmanTables(true); } streamACHuffmanTables = collectHTablesFromMetadata(jmeta, false); if (streamACHuffmanTables == null) { streamACHuffmanTables = JPEG.getDefaultHuffmanTables(false); } // Now write them out writeTables(structPointer, streamQTables, streamDCHuffmanTables, streamACHuffmanTables); } else { throw new IIOException("Stream metadata must be JPEG metadata"); } } sequencePrepared = true; } public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException { if (sequencePrepared == false) { throw new IllegalStateException("sequencePrepared not called!"); } // In the case of JPEG this does nothing different from write write(null, image, param); } public void endWriteSequence() throws IOException { if (sequencePrepared == false) { throw new IllegalStateException("sequencePrepared not called!"); } sequencePrepared = false; } public synchronized void abort() { super.abort(); abortWrite(structPointer); } private void resetInternalState() { // reset C structures resetWriter(structPointer); // reset local Java structures srcRas = null; raster = null; convertTosRGB = false; currentImage = 0; numScans = 0; metadata = null; } /** * Note that there is no need to override reset() here, as the default * implementation will call setOutput(null), which will invoke * resetInternalState(). */ public void dispose() { if (structPointer != 0) { disposerRecord.dispose(); structPointer = 0; } } ////////// End of public API ///////// Package-access API /** * Called by the native code or other classes to signal a warning. * The code is used to lookup a localized message to be used when * sending warnings to listeners. */ void warningOccurred(int code) { if ((code < 0) || (code > MAX_WARNING)){ throw new InternalError("Invalid warning index"); } processWarningOccurred (currentImage, "com.sun.imageio.plugins.jpeg.JPEGImageWriterResources", Integer.toString(code)); } /** * The library has it's own error facility that emits warning messages. * This routine is called by the native code when it has already * formatted a string for output. * XXX For truly complete localization of all warning messages, * the sun_jpeg_output_message routine in the native code should * send only the codes and parameters to a method here in Java, * which will then format and send the warnings, using localized * strings. This method will have to deal with all the parameters * and formats (%u with possibly large numbers, %02d, %02x, etc.) * that actually occur in the JPEG library. For now, this prevents * library warnings from being printed to stderr. */ void warningWithMessage(String msg) { processWarningOccurred(currentImage, msg); } void thumbnailStarted(int thumbnailIndex) { processThumbnailStarted(currentImage, thumbnailIndex); } // Provide access to protected superclass method void thumbnailProgress(float percentageDone) { processThumbnailProgress(percentageDone); } // Provide access to protected superclass method void thumbnailComplete() { processThumbnailComplete(); } ///////// End of Package-access API ///////// Private methods ///////// Metadata handling private void checkSOFBands(SOFMarkerSegment sof, int numBandsUsed) throws IIOException { // Does the metadata frame header, if any, match numBandsUsed? if (sof != null) { if (sof.componentSpecs.length != numBandsUsed) { throw new IIOException ("Metadata components != number of destination bands"); } } } private void checkJFIF(JFIFMarkerSegment jfif, ImageTypeSpecifier type, boolean input) { if (jfif != null) { if (!JPEG.isJFIFcompliant(type, input)) { ignoreJFIF = true; // type overrides metadata warningOccurred(input ? WARNING_IMAGE_METADATA_JFIF_MISMATCH : WARNING_DEST_METADATA_JFIF_MISMATCH); } } } private void checkAdobe(AdobeMarkerSegment adobe, ImageTypeSpecifier type, boolean input) { if (adobe != null) { int rightTransform = JPEG.transformForType(type, input); if (adobe.transform != rightTransform) { warningOccurred(input ? WARNING_IMAGE_METADATA_ADOBE_MISMATCH : WARNING_DEST_METADATA_ADOBE_MISMATCH); if (rightTransform == JPEG.ADOBE_IMPOSSIBLE) { ignoreAdobe = true; } else { newAdobeTransform = rightTransform; } } } } /** * Collect all the scan info from the given metadata, and * organize it into the scan info array required by the * IJG libray. It is much simpler to parse out this * data in Java and then just copy the data in C. */ private int [] collectScans(JPEGMetadata metadata, SOFMarkerSegment sof) { List segments = new ArrayList(); int SCAN_SIZE = 9; int MAX_COMPS_PER_SCAN = 4; for (Iterator iter = metadata.markerSequence.iterator(); iter.hasNext();) { MarkerSegment seg = (MarkerSegment) iter.next(); if (seg instanceof SOSMarkerSegment) { segments.add(seg); } } int [] retval = null; numScans = 0; if (!segments.isEmpty()) { numScans = segments.size(); retval = new int [numScans*SCAN_SIZE]; int index = 0; for (int i = 0; i < numScans; i++) { SOSMarkerSegment sos = (SOSMarkerSegment) segments.get(i); retval[index++] = sos.componentSpecs.length; // num comps for (int j = 0; j < MAX_COMPS_PER_SCAN; j++) { if (j < sos.componentSpecs.length) { int compSel = sos.componentSpecs[j].componentSelector; for (int k = 0; k < sof.componentSpecs.length; k++) { if (compSel == sof.componentSpecs[k].componentId) { retval[index++] = k; break; // out of for over sof comps } } } else { retval[index++] = 0; } } retval[index++] = sos.startSpectralSelection; retval[index++] = sos.endSpectralSelection; retval[index++] = sos.approxHigh; retval[index++] = sos.approxLow; } } return retval; } /** * Finds all DQT marker segments and returns all the q * tables as a single array of JPEGQTables. */ private JPEGQTable [] collectQTablesFromMetadata (JPEGMetadata metadata) { ArrayList tables = new ArrayList(); Iterator iter = metadata.markerSequence.iterator(); while (iter.hasNext()) { MarkerSegment seg = (MarkerSegment) iter.next(); if (seg instanceof DQTMarkerSegment) { DQTMarkerSegment dqt = (DQTMarkerSegment) seg; tables.addAll(dqt.tables); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -