jpegcommentwriter.java
来自「很棒的web服务器源代码」· Java 代码 · 共 358 行
JAVA
358 行
// JpegCOmmentWriter.java// $Id: JpegCommentWriter.java,v 1.5 2000/10/19 15:53:26 ylafon Exp $// (c) COPYRIGHT MIT, INRIA and Keio, 1999.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.tools.jpeg;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;import java.io.Writer;/** * Allow you to write text comments to jpeg stream * Some code has been adapted from wrjpgcom.c from The Independent JPEG Group */public class JpegCommentWriter extends Writer { // usual debug stuff private static final boolean debug = true; InputStream inJpegData; OutputStream outJpegData; ByteArrayOutputStream byteStream; OutputStreamWriter osw; boolean init; int lastMarker; /** * Create a JpegCommentWriter, using an Input stream as the jpeg binary * source, and writing in the output stream * @param out, the output stream where the image will be written * @param in, the input stream of the jpeg file, it MUST point to the * beginning of the jpeg to avoid problems */ public JpegCommentWriter(OutputStream out, InputStream in) { super(out); inJpegData = in; outJpegData = out; byteStream = new ByteArrayOutputStream(65536); osw = new OutputStreamWriter(byteStream); init = false; } /** * Create a JpegCommentWriter, using an Input stream as the jpeg binary * source, and writing in the output stream * @param out, the output stream where the image will be written * @param in, the input stream of the jpeg file, it MUST point to the * beginning of the jpeg to avoid problems * @param enc, the encoding name used when you write comments */ public JpegCommentWriter(OutputStream out, InputStream in, String enc) throws UnsupportedEncodingException { super(out); inJpegData = in; outJpegData = out; byteStream = new ByteArrayOutputStream(65536); osw = new OutputStreamWriter(byteStream, enc); init = false; } /** * gets the encoding used by the comment writer */ public String getEncoding() { return osw.getEncoding(); } /** * write one character */ public void write(int ch) throws IOException { osw.write(ch); } /** * write an array of characters */ public void write(char[] buffer) throws IOException { osw.write(buffer); } /** * write a portion of an array of characters */ public void write(char[] buffer, int off, int len) throws IOException { osw.write(buffer, off, len); } /** * Write a String */ public void write(String s) throws IOException { osw.write(s); } /** * Write a portion of a String */ public void write(String s, int off, int len) throws IOException { osw.write(s, off, len); } public void flush() throws IOException { if (!init) { dupFirstHeaders(); init = true; } osw.flush(); byte[] buffer; synchronized(byteStream) { buffer = byteStream.toByteArray(); byteStream.reset(); } int buflen = buffer.length; int curlen; int curpos = 0; // write the comments, using chunks if necessary while (buflen > 0) { writeMarker(Jpeg.M_COM); curlen = Math.min(Jpeg.M_MAX_COM_LENGTH, buflen); writeMarkerLength(curlen+2); outJpegData.write(buffer, curpos, curlen); curpos += curlen; buflen -= curlen; }; } public void close() throws IOException { flush(); byte[] buf = new byte[1024]; int got; // first dump the last marker writeMarker(lastMarker); // then the end of the file do { got = inJpegData.read(buf); if (got < 0) break; outJpegData.write(buf, 0, got); } while (got >= 0); } /** * copy the marker and return it */ protected int dupFirstMarker() throws IOException, JpegException { int c1, c2; c1 = inJpegData.read(); c2 = inJpegData.read(); if (c1 != 0xFF || c2 != Jpeg.M_SOI) throw new JpegException("Not a JPEG file"); outJpegData.write(c1); outJpegData.write(c2); return c2; } /** * read 2 bytes and create an integer out of it */ protected int read2bytes() throws IOException, JpegException { int c1, c2; c1 = inJpegData.read(); if (c1 == -1) throw new JpegException("Premature EOF in JPEG file"); c2 = inJpegData.read(); if (c2 == -1) throw new JpegException("Premature EOF in JPEG file"); return (((int) c1) << 8) + ((int) c2); } /** * get the next marker, and eat extra bytes */ protected int nextMarker() throws IOException { int discarded_bytes = 0; int c; /* Find 0xFF byte; count and skip any non-FFs. */ c = inJpegData.read(); while (c != 0xFF) c = inJpegData.read(); /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs * are legal as pad bytes, so don't count them in discarded_bytes. */ do { c = inJpegData.read(); } while (c == 0xFF); return c; } /** * skip the body after a marker */ protected void skipVariable() throws IOException, JpegException { long len = (long)read2bytes() - 2; if (len < 0 ) throw new JpegException("Erroneous JPEG marker length"); while (len > 0) { long saved = inJpegData.skip(len); if (saved < 0) throw new IOException("Error while reading jpeg stream"); len -= saved; } } /** * dup the marker and the body */ protected void dupHeader(int marker) throws IOException, JpegException { int len = read2bytes(); if (len < 2 ) throw new JpegException("Erroneous JPEG marker length"); // dump the marker writeMarker(marker); // write the length writeMarkerLength(len); // and now copy the bytes byte[] buf = new byte[1024]; int got; len -= 2; while (len > 0) { got = inJpegData.read(buf, 0, Math.min(buf.length, len)); if (got < 0) throw new IOException("Error while reading jpeg stream (EOF)"); outJpegData.write(buf, 0, got); len -= got; } } protected void writeMarker(int marker) throws IOException { outJpegData.write(0xFF); outJpegData.write(marker); } protected void writeMarkerLength(int len) throws IOException { outJpegData.write((len >> 8) & 0xFF); outJpegData.write(len & 0xFF); } /** * the the first headers until a SOF parker is found */ protected void dupFirstHeaders() throws IOException { int marker; // first duplicate the header and make sure it is valid try { dupFirstMarker(); } catch (JpegException ex) { if (debug) { ex.printStackTrace(); } throw new IOException(ex.getMessage()); } // now dump the headers while (true) { marker = nextMarker(); switch (marker) { case Jpeg.M_SOF0: /* Baseline */ case Jpeg.M_SOF1: /* Extended sequential, Huffman */ case Jpeg.M_SOF2: /* Progressive, Huffman */ case Jpeg.M_SOF3: /* Lossless, Huffman */ case Jpeg.M_SOF5: /* Differential sequential, Huffman */ case Jpeg.M_SOF6: /* Differential progressive, Huffman */ case Jpeg.M_SOF7: /* Differential lossless, Huffman */ case Jpeg.M_SOF9: /* Extended sequential, arithmetic */ case Jpeg.M_SOF10: /* Progressive, arithmetic */ case Jpeg.M_SOF11: /* Lossless, arithmetic */ case Jpeg.M_SOF13: /* Differential sequential, arithmetic */ case Jpeg.M_SOF14: /* Differential progressive, arithmetic */ case Jpeg.M_SOF15: /* Differential lossless, arithmetic */ // bye! lastMarker = marker; return; case Jpeg.M_SOS: break; case Jpeg.M_EOI: lastMarker = marker; return; case Jpeg.M_APP12: case Jpeg.M_COM: // remove previous comments try { skipVariable(); } catch (JpegException jex) { if (debug) jex.printStackTrace(); throw new IOException(jex.getMessage()); } break; default: try { dupHeader(marker); } catch (JpegException jex) { if (debug) jex.printStackTrace(); throw new IOException(jex.getMessage()); } break; } } } /** * The usual debugging tool */ public static void main(String args[]) { try { File jpegFile = new File(args[0]); JpegCommentWriter jcw = new JpegCommentWriter(System.out, new FileInputStream(jpegFile)); jcw.write(args[1]); jcw.close(); } catch (Exception ex) { ex.printStackTrace(); } } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?