001: // JpegEncoder - write out an image as a JPEG
002: //
003: // Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
004: //
005: // Redistribution and use in source and binary forms, with or without
006: // modification, are permitted provided that the following conditions
007: // are met:
008: // 1. Redistributions of source code must retain the above copyright
009: // notice, this list of conditions and the following disclaimer.
010: // 2. Redistributions in binary form must reproduce the above copyright
011: // notice, this list of conditions and the following disclaimer in the
012: // documentation and/or other materials provided with the distribution.
013: //
014: // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
015: // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
016: // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
017: // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
018: // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
019: // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
020: // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
021: // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
022: // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
023: // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
024: // SUCH DAMAGE.
025: //
026: // Visit the ACME Labs Java page for up-to-date versions of this and other
027: // fine Java utilities: http://www.acme.com/java/
028:
029: package Acme.JPM.Encoders;
030:
031: import java.awt.*;
032: import java.awt.image.ImageProducer;
033: import java.io.IOException;
034: import java.io.OutputStream;
035:
036: /// Write out an image as a JPEG.
037: // DOESN'T WORK YET.
038: // <P>
039: // <A HREF="/resources/classes/Acme/JPM/Encoders/JpegEncoder.java">Fetch the software.</A><BR>
040: // <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
041: // <P>
042: // @see ToJpeg
043:
044: public class JpegEncoder extends ImageEncoder {
045:
046: /// Constructor.
047: // @param img The image to encode.
048: // @param out The stream to write the JPEG to.
049: public JpegEncoder(Image img, OutputStream out) throws IOException {
050: super (img, out);
051: }
052:
053: /// Constructor.
054: // @param prod The ImageProducer to encode.
055: // @param out The stream to write the JPEG to.
056: public JpegEncoder(ImageProducer prod, OutputStream out)
057: throws IOException {
058: super (prod, out);
059: }
060:
061: int qfactor = 100;
062:
063: /// Set the Q-factor.
064: public void setQfactor(int qfactor) {
065: this .qfactor = qfactor;
066: }
067:
068: int width, height;
069: int[][] rgbPixels;
070:
071: void encodeStart(int width, int height) throws IOException {
072: this .width = width;
073: this .height = height;
074: rgbPixels = new int[height][width];
075: }
076:
077: void encodePixels(int x, int y, int w, int h, int[] rgbPixels,
078: int off, int scansize) throws IOException {
079: // Save the pixels.
080: for (int row = 0; row < h; ++row)
081: System.arraycopy(rgbPixels, row * scansize + off,
082: this .rgbPixels[y + row], x, w);
083:
084: }
085:
086: void encodeDone() throws IOException {
087: writeJfifHuffHeader();
088: // !!!
089: }
090:
091: // Some of the following code is derived from the Berkeley Continuous
092: // Media Toolkit (http://bmrc.berkeley.edu/projects/cmt/), which is
093: // Copyright (c) 1996 The Regents of the University of California.
094: // All rights reserved.
095: //
096: // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
097: // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
098: // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
099: // UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
100: // DAMAGE.
101: //
102: // THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
103: // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
104: // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
105: // ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION
106: // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
107:
108: // This array represents the default JFIF header for quality = 100 and
109: // size = 640x480, with Huffman tables. The values are adjusted when a
110: // file is generated.
111: private static byte[] jfifHuff100Header = {
112: // SOI
113: (byte) 0xFF,
114: (byte) 0xD8,
115:
116: // JFIF header
117: (byte) 0xFF,
118: (byte) 0xE0, // Marker
119: (byte) 0x00,
120: (byte) 0x10, // Length = 16 bytes
121: (byte) 0x4A,
122: (byte) 0x46,
123: (byte) 0x49,
124: (byte) 0x46, // "JFIF"
125: (byte) 0x00,
126: (byte) 0x01,
127: (byte) 0x01,
128: (byte) 0x00,
129: (byte) 0x00,
130: (byte) 0x01,
131: (byte) 0x00,
132: (byte) 0x01,
133: (byte) 0x00,
134: (byte) 0x00,
135:
136: // Start of frame (section B.2.2)
137: (byte) 0xFF,
138: (byte) 0xC0, // Baseline DCT
139: (byte) 0x00,
140: (byte) 0x11, // Length = 17 bytes
141: (byte) 0x08, // Sample precision
142: (byte) 0x01,
143: (byte) 0xE0, // Height
144: (byte) 0x02,
145: (byte) 0x80, // Width
146: (byte) 0x03, // Number of components = 3
147: // Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0
148: (byte) 0x01,
149: (byte) 0x21,
150: (byte) 0x00,
151: // Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
152: (byte) 0x02,
153: (byte) 0x11,
154: (byte) 0x01,
155: // Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
156: (byte) 0x03,
157: (byte) 0x11,
158: (byte) 0x01,
159:
160: // Define Quant table (section B.2.4.1)
161: (byte) 0xFF,
162: (byte) 0xDB, // Marker
163: (byte) 0x00,
164: (byte) 0x84, // Length (both tables)
165: (byte) 0x00, // 8 bit values, (byte) table 0
166: (byte) 0x10,
167: (byte) 0x0B,
168: (byte) 0x0C,
169: (byte) 0x0E,
170: (byte) 0x0C,
171: (byte) 0x0A,
172: (byte) 0x10,
173: (byte) 0x0E,
174: (byte) 0x0D,
175: (byte) 0x0E,
176: (byte) 0x12,
177: (byte) 0x11,
178: (byte) 0x10,
179: (byte) 0x13,
180: (byte) 0x18,
181: (byte) 0x28,
182: (byte) 0x1A,
183: (byte) 0x18,
184: (byte) 0x16,
185: (byte) 0x16,
186: (byte) 0x18,
187: (byte) 0x31,
188: (byte) 0x23,
189: (byte) 0x25,
190: (byte) 0x1D,
191: (byte) 0x28,
192: (byte) 0x3A,
193: (byte) 0x33,
194: (byte) 0x3D,
195: (byte) 0x3C,
196: (byte) 0x39,
197: (byte) 0x33,
198: (byte) 0x38,
199: (byte) 0x37,
200: (byte) 0x40,
201: (byte) 0x48,
202: (byte) 0x5C,
203: (byte) 0x4E,
204: (byte) 0x40,
205: (byte) 0x44,
206: (byte) 0x57,
207: (byte) 0x45,
208: (byte) 0x37,
209: (byte) 0x38,
210: (byte) 0x50,
211: (byte) 0x6D,
212: (byte) 0x51,
213: (byte) 0x57,
214: (byte) 0x5F,
215: (byte) 0x62,
216: (byte) 0x67,
217: (byte) 0x68,
218: (byte) 0x67,
219: (byte) 0x3E,
220: (byte) 0x4D,
221: (byte) 0x71,
222: (byte) 0x79,
223: (byte) 0x70,
224: (byte) 0x64,
225: (byte) 0x78,
226: (byte) 0x5C,
227: (byte) 0x65,
228: (byte) 0x67,
229: (byte) 0x63,
230:
231: (byte) 0x01, // 8 bit values, (byte) table 1
232: (byte) 0x11,
233: (byte) 0x12,
234: (byte) 0x12,
235: (byte) 0x18,
236: (byte) 0x15,
237: (byte) 0x18,
238: (byte) 0x2F,
239: (byte) 0x1A,
240: (byte) 0x1A,
241: (byte) 0x2F,
242: (byte) 0x63,
243: (byte) 0x42,
244: (byte) 0x38,
245: (byte) 0x42,
246: (byte) 0x63,
247: (byte) 0x63,
248: (byte) 0x63,
249: (byte) 0x63,
250: (byte) 0x63,
251: (byte) 0x63,
252: (byte) 0x63,
253: (byte) 0x63,
254: (byte) 0x63,
255: (byte) 0x63,
256: (byte) 0x63,
257: (byte) 0x63,
258: (byte) 0x63,
259: (byte) 0x63,
260: (byte) 0x63,
261: (byte) 0x63,
262: (byte) 0x63,
263: (byte) 0x63,
264: (byte) 0x63,
265: (byte) 0x63,
266: (byte) 0x63,
267: (byte) 0x63,
268: (byte) 0x63,
269: (byte) 0x63,
270: (byte) 0x63,
271: (byte) 0x63,
272: (byte) 0x63,
273: (byte) 0x63,
274: (byte) 0x63,
275: (byte) 0x63,
276: (byte) 0x63,
277: (byte) 0x63,
278: (byte) 0x63,
279: (byte) 0x63,
280: (byte) 0x63,
281: (byte) 0x63,
282: (byte) 0x63,
283: (byte) 0x63,
284: (byte) 0x63,
285: (byte) 0x63,
286: (byte) 0x63,
287: (byte) 0x63,
288: (byte) 0x63,
289: (byte) 0x63,
290: (byte) 0x63,
291: (byte) 0x63,
292: (byte) 0x63,
293: (byte) 0x63,
294: (byte) 0x63,
295: (byte) 0x63,
296:
297: // Define huffman table (section B.2.4.1)
298: (byte) 0xFF,
299: (byte) 0xC4, // Marker
300: (byte) 0x00,
301: (byte) 0x1F, // Length (31 bytes)
302: (byte) 0x00, // DC, (byte) table 0
303: (byte) 0x00,
304: (byte) 0x01,
305: (byte) 0x05,
306: (byte) 0x01,
307: (byte) 0x01,
308: (byte) 0x01,
309: (byte) 0x01,
310: (byte) 0x01,
311: (byte) 0x01,
312: (byte) 0x00,
313: (byte) 0x00,
314: (byte) 0x00,
315: (byte) 0x00,
316: (byte) 0x00,
317: (byte) 0x00,
318: (byte) 0x00,
319: (byte) 0x00,
320: (byte) 0x01,
321: (byte) 0x02,
322: (byte) 0x03,
323: (byte) 0x04,
324: (byte) 0x05,
325: (byte) 0x06,
326: (byte) 0x07,
327: (byte) 0x08,
328: (byte) 0x09,
329: (byte) 0x0A,
330: (byte) 0x0B,
331:
332: // Define huffman table (section B.2.4.1)
333: (byte) 0xFF,
334: (byte) 0xC4, // Marker
335: (byte) 0x00,
336: (byte) 0xB5, // Length (181 bytes)
337: (byte) 0x10, // AC, (byte) table 0
338: (byte) 0x00,
339: (byte) 0x02,
340: (byte) 0x01,
341: (byte) 0x03,
342: (byte) 0x03,
343: (byte) 0x02,
344: (byte) 0x04,
345: (byte) 0x03,
346: (byte) 0x05,
347: (byte) 0x05,
348: (byte) 0x04,
349: (byte) 0x04,
350: (byte) 0x00,
351: (byte) 0x00,
352: (byte) 0x01,
353: (byte) 0x7D,
354: (byte) 0x01,
355: (byte) 0x02,
356: (byte) 0x03,
357: (byte) 0x00,
358: (byte) 0x04,
359: (byte) 0x11,
360: (byte) 0x05,
361: (byte) 0x12,
362: (byte) 0x21,
363: (byte) 0x31,
364: (byte) 0x41,
365: (byte) 0x06,
366: (byte) 0x13,
367: (byte) 0x51,
368: (byte) 0x61,
369: (byte) 0x07,
370: (byte) 0x22,
371: (byte) 0x71,
372: (byte) 0x14,
373: (byte) 0x32,
374: (byte) 0x81,
375: (byte) 0x91,
376: (byte) 0xA1,
377: (byte) 0x08,
378: (byte) 0x23,
379: (byte) 0x42,
380: (byte) 0xB1,
381: (byte) 0xC1,
382: (byte) 0x15,
383: (byte) 0x52,
384: (byte) 0xD1,
385: (byte) 0xF0,
386: (byte) 0x24,
387: (byte) 0x33,
388: (byte) 0x62,
389: (byte) 0x72,
390: (byte) 0x82,
391: (byte) 0x09,
392: (byte) 0x0A,
393: (byte) 0x16,
394: (byte) 0x17,
395: (byte) 0x18,
396: (byte) 0x19,
397: (byte) 0x1A,
398: (byte) 0x25,
399: (byte) 0x26,
400: (byte) 0x27,
401: (byte) 0x28,
402: (byte) 0x29,
403: (byte) 0x2A,
404: (byte) 0x34,
405: (byte) 0x35,
406: (byte) 0x36,
407: (byte) 0x37,
408: (byte) 0x38,
409: (byte) 0x39,
410: (byte) 0x3A,
411: (byte) 0x43,
412: (byte) 0x44,
413: (byte) 0x45,
414: (byte) 0x46,
415: (byte) 0x47,
416: (byte) 0x48,
417: (byte) 0x49,
418: (byte) 0x4A,
419: (byte) 0x53,
420: (byte) 0x54,
421: (byte) 0x55,
422: (byte) 0x56,
423: (byte) 0x57,
424: (byte) 0x58,
425: (byte) 0x59,
426: (byte) 0x5A,
427: (byte) 0x63,
428: (byte) 0x64,
429: (byte) 0x65,
430: (byte) 0x66,
431: (byte) 0x67,
432: (byte) 0x68,
433: (byte) 0x69,
434: (byte) 0x6A,
435: (byte) 0x73,
436: (byte) 0x74,
437: (byte) 0x75,
438: (byte) 0x76,
439: (byte) 0x77,
440: (byte) 0x78,
441: (byte) 0x79,
442: (byte) 0x7A,
443: (byte) 0x83,
444: (byte) 0x84,
445: (byte) 0x85,
446: (byte) 0x86,
447: (byte) 0x87,
448: (byte) 0x88,
449: (byte) 0x89,
450: (byte) 0x8A,
451: (byte) 0x92,
452: (byte) 0x93,
453: (byte) 0x94,
454: (byte) 0x95,
455: (byte) 0x96,
456: (byte) 0x97,
457: (byte) 0x98,
458: (byte) 0x99,
459: (byte) 0x9A,
460: (byte) 0xA2,
461: (byte) 0xA3,
462: (byte) 0xA4,
463: (byte) 0xA5,
464: (byte) 0xA6,
465: (byte) 0xA7,
466: (byte) 0xA8,
467: (byte) 0xA9,
468: (byte) 0xAA,
469: (byte) 0xB2,
470: (byte) 0xB3,
471: (byte) 0xB4,
472: (byte) 0xB5,
473: (byte) 0xB6,
474: (byte) 0xB7,
475: (byte) 0xB8,
476: (byte) 0xB9,
477: (byte) 0xBA,
478: (byte) 0xC2,
479: (byte) 0xC3,
480: (byte) 0xC4,
481: (byte) 0xC5,
482: (byte) 0xC6,
483: (byte) 0xC7,
484: (byte) 0xC8,
485: (byte) 0xC9,
486: (byte) 0xCA,
487: (byte) 0xD2,
488: (byte) 0xD3,
489: (byte) 0xD4,
490: (byte) 0xD5,
491: (byte) 0xD6,
492: (byte) 0xD7,
493: (byte) 0xD8,
494: (byte) 0xD9,
495: (byte) 0xDA,
496: (byte) 0xE1,
497: (byte) 0xE2,
498: (byte) 0xE3,
499: (byte) 0xE4,
500: (byte) 0xE5,
501: (byte) 0xE6,
502: (byte) 0xE7,
503: (byte) 0xE8,
504: (byte) 0xE9,
505: (byte) 0xEA,
506: (byte) 0xF1,
507: (byte) 0xF2,
508: (byte) 0xF3,
509: (byte) 0xF4,
510: (byte) 0xF5,
511: (byte) 0xF6,
512: (byte) 0xF7,
513: (byte) 0xF8,
514: (byte) 0xF9,
515: (byte) 0xFA,
516:
517: // Define huffman table (section B.2.4.1)
518: (byte) 0xFF,
519: (byte) 0xC4, // Marker
520: (byte) 0x00,
521: (byte) 0x1F, // Length (31 bytes)
522: (byte) 0x01, // DC, (byte) table 1
523: (byte) 0x00,
524: (byte) 0x03,
525: (byte) 0x01,
526: (byte) 0x01,
527: (byte) 0x01,
528: (byte) 0x01,
529: (byte) 0x01,
530: (byte) 0x01,
531: (byte) 0x01,
532: (byte) 0x01,
533: (byte) 0x01,
534: (byte) 0x00,
535: (byte) 0x00,
536: (byte) 0x00,
537: (byte) 0x00,
538: (byte) 0x00,
539: (byte) 0x00,
540: (byte) 0x01,
541: (byte) 0x02,
542: (byte) 0x03,
543: (byte) 0x04,
544: (byte) 0x05,
545: (byte) 0x06,
546: (byte) 0x07,
547: (byte) 0x08,
548: (byte) 0x09,
549: (byte) 0x0A,
550: (byte) 0x0B,
551:
552: // Define huffman table (section B.2.4.1)
553: (byte) 0xFF,
554: (byte) 0xC4, // Marker
555: (byte) 0x00,
556: (byte) 0xB5, // Length (181 bytes)
557: (byte) 0x11, // AC, (byte) table 1
558: (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x02,
559: (byte) 0x04, (byte) 0x04, (byte) 0x03, (byte) 0x04,
560: (byte) 0x07, (byte) 0x05, (byte) 0x04, (byte) 0x04,
561: (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x77,
562: (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
563: (byte) 0x11, (byte) 0x04, (byte) 0x05, (byte) 0x21,
564: (byte) 0x31, (byte) 0x06, (byte) 0x12, (byte) 0x41,
565: (byte) 0x51, (byte) 0x07, (byte) 0x61, (byte) 0x71,
566: (byte) 0x13, (byte) 0x22, (byte) 0x32, (byte) 0x81,
567: (byte) 0x08, (byte) 0x14, (byte) 0x42, (byte) 0x91,
568: (byte) 0xA1, (byte) 0xB1, (byte) 0xC1, (byte) 0x09,
569: (byte) 0x23, (byte) 0x33, (byte) 0x52, (byte) 0xF0,
570: (byte) 0x15, (byte) 0x62, (byte) 0x72, (byte) 0xD1,
571: (byte) 0x0A, (byte) 0x16, (byte) 0x24, (byte) 0x34,
572: (byte) 0xE1, (byte) 0x25, (byte) 0xF1, (byte) 0x17,
573: (byte) 0x18, (byte) 0x19, (byte) 0x1A, (byte) 0x26,
574: (byte) 0x27, (byte) 0x28, (byte) 0x29, (byte) 0x2A,
575: (byte) 0x35, (byte) 0x36, (byte) 0x37, (byte) 0x38,
576: (byte) 0x39, (byte) 0x3A, (byte) 0x43, (byte) 0x44,
577: (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48,
578: (byte) 0x49, (byte) 0x4A, (byte) 0x53, (byte) 0x54,
579: (byte) 0x55, (byte) 0x56, (byte) 0x57, (byte) 0x58,
580: (byte) 0x59, (byte) 0x5A, (byte) 0x63, (byte) 0x64,
581: (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68,
582: (byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74,
583: (byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78,
584: (byte) 0x79, (byte) 0x7A, (byte) 0x82, (byte) 0x83,
585: (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,
586: (byte) 0x88, (byte) 0x89, (byte) 0x8A, (byte) 0x92,
587: (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96,
588: (byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9A,
589: (byte) 0xA2, (byte) 0xA3, (byte) 0xA4, (byte) 0xA5,
590: (byte) 0xA6, (byte) 0xA7, (byte) 0xA8, (byte) 0xA9,
591: (byte) 0xAA, (byte) 0xB2, (byte) 0xB3, (byte) 0xB4,
592: (byte) 0xB5, (byte) 0xB6, (byte) 0xB7, (byte) 0xB8,
593: (byte) 0xB9, (byte) 0xBA, (byte) 0xC2, (byte) 0xC3,
594: (byte) 0xC4, (byte) 0xC5, (byte) 0xC6, (byte) 0xC7,
595: (byte) 0xC8, (byte) 0xC9, (byte) 0xCA, (byte) 0xD2,
596: (byte) 0xD3, (byte) 0xD4, (byte) 0xD5, (byte) 0xD6,
597: (byte) 0xD7, (byte) 0xD8, (byte) 0xD9, (byte) 0xDA,
598: (byte) 0xE2, (byte) 0xE3, (byte) 0xE4, (byte) 0xE5,
599: (byte) 0xE6, (byte) 0xE7, (byte) 0xE8, (byte) 0xE9,
600: (byte) 0xEA, (byte) 0xF2, (byte) 0xF3, (byte) 0xF4,
601: (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xF8,
602: (byte) 0xF9, (byte) 0xFA,
603:
604: // Start of Scan (section B.2.3)
605: (byte) 0xFF,
606: (byte) 0xDA, // Marker
607: (byte) 0x00,
608: (byte) 0x0C, // Length of header
609: (byte) 0x03, // Number of image components
610: // Scan 1: use DC/AC huff tables 0/0
611: (byte) 0x01, (byte) 0x00,
612: // Scan 2: use DC/AC huff tables 1/1
613: (byte) 0x02, (byte) 0x11,
614: // Scan 3: use DC/AC huff tables 1/1
615: (byte) 0x03, (byte) 0x11, (byte) 0x00, (byte) 0x3F,
616: (byte) 0x00 // Not used
617: };
618:
619: // This array represents the default JFIF header for quality = 100 and
620: // size = 640x480, without Huffman tables. The values are adjusted when a
621: // file is generated.
622: private static byte[] jfifNoHuff100Header = {
623: // SOI
624: (byte) 0xFF,
625: (byte) 0xD8,
626:
627: // JFIF header
628: (byte) 0xFF,
629: (byte) 0xE0, // Marker
630: (byte) 0x00,
631: (byte) 0x10, // Length = 16 bytes
632: (byte) 0x4A,
633: (byte) 0x46,
634: (byte) 0x49,
635: (byte) 0x46, // "JFIF"
636: (byte) 0x00,
637: (byte) 0x01,
638: (byte) 0x01,
639: (byte) 0x00,
640: (byte) 0x00,
641: (byte) 0x01,
642: (byte) 0x00,
643: (byte) 0x01,
644: (byte) 0x00,
645: (byte) 0x00,
646:
647: // Start of frame (section B.2.2)
648: (byte) 0xFF,
649: (byte) 0xC0, // Baseline DCT
650: (byte) 0x00,
651: (byte) 0x11, // Length = 17 bytes
652: (byte) 0x08, // Sample precision
653: (byte) 0x01,
654: (byte) 0xE0, // Height
655: (byte) 0x02,
656: (byte) 0x80, // Width
657: (byte) 0x03, // Number of components = 3
658: // Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0
659: (byte) 0x01,
660: (byte) 0x21,
661: (byte) 0x00,
662: // Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
663: (byte) 0x02,
664: (byte) 0x11,
665: (byte) 0x01,
666: // Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
667: (byte) 0x03,
668: (byte) 0x11,
669: (byte) 0x01,
670:
671: // Define Quant table (section B.2.4.1)
672: (byte) 0xFF,
673: (byte) 0xDB, // Marker
674: (byte) 0x00,
675: (byte) 0x84, // Length (both tables)
676: (byte) 0x00, // 8 bit values, (byte) table 0
677: (byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E,
678: (byte) 0x0C, (byte) 0x0A, (byte) 0x10, (byte) 0x0E,
679: (byte) 0x0D, (byte) 0x0E, (byte) 0x12, (byte) 0x11,
680: (byte) 0x10, (byte) 0x13, (byte) 0x18, (byte) 0x28,
681: (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16,
682: (byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25,
683: (byte) 0x1D, (byte) 0x28, (byte) 0x3A, (byte) 0x33,
684: (byte) 0x3D, (byte) 0x3C, (byte) 0x39, (byte) 0x33,
685: (byte) 0x38, (byte) 0x37, (byte) 0x40, (byte) 0x48,
686: (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44,
687: (byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38,
688: (byte) 0x50,
689: (byte) 0x6D,
690: (byte) 0x51,
691: (byte) 0x57,
692: (byte) 0x5F,
693: (byte) 0x62,
694: (byte) 0x67,
695: (byte) 0x68,
696: (byte) 0x67,
697: (byte) 0x3E,
698: (byte) 0x4D,
699: (byte) 0x71,
700: (byte) 0x79,
701: (byte) 0x70,
702: (byte) 0x64,
703: (byte) 0x78,
704: (byte) 0x5C,
705: (byte) 0x65,
706: (byte) 0x67,
707: (byte) 0x63,
708:
709: (byte) 0x01, // 8 bit values, (byte) table 1
710: (byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18,
711: (byte) 0x15, (byte) 0x18, (byte) 0x2F, (byte) 0x1A,
712: (byte) 0x1A, (byte) 0x2F, (byte) 0x63, (byte) 0x42,
713: (byte) 0x38, (byte) 0x42, (byte) 0x63, (byte) 0x63,
714: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
715: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
716: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
717: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
718: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
719: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
720: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
721: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
722: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
723: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
724: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
725: (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
726:
727: // Start of Scan (section B.2.3)
728: (byte) 0xFF,
729: (byte) 0xDA, // Marker
730: (byte) 0x00,
731: (byte) 0x0C, // Length of header
732: (byte) 0x03, // Number of image components
733: // Scan 1: use DC/AC huff tables 0/0
734: (byte) 0x01, (byte) 0x00,
735: // Scan 2: use DC/AC huff tables 1/1
736: (byte) 0x02, (byte) 0x11,
737: // Scan 3: use DC/AC huff tables 1/1
738: (byte) 0x03, (byte) 0x11, (byte) 0x00, (byte) 0x3F,
739: (byte) 0x00 // Not used
740: };
741:
742: private void writeJfifHuffHeader() throws IOException {
743: byte[] newHeader = new byte[jfifHuff100Header.length];
744:
745: System.arraycopy(jfifHuff100Header, 0, newHeader, 0,
746: jfifHuff100Header.length);
747:
748: // Set image width in JFIF header.
749: newHeader[27] = (byte) ((width >>> 8) & 0xff);
750: newHeader[28] = (byte) (width & 0xff);
751:
752: // Set image height in JFIF header.
753: newHeader[25] = (byte) ((height >>> 8) & 0xff);
754: newHeader[26] = (byte) (height & 0xff);
755:
756: // Adjust the quality factor.
757: //
758: // The default quality factor is 100, therefore if
759: // our quality factor does not equal 100 we must
760: // scale the quantization matrices in the JFIF header.
761: // Note that values are clipped to a max of 255.
762: if (qfactor != 100) {
763: for (int i = 44; i < 108; ++i) {
764: int t = (newHeader[i] * qfactor) / 100;
765: newHeader[i] = (byte) Math.max(t, 0xff);
766: }
767: for (int i = 109; i < 173; ++i) {
768: int t = (newHeader[i] * qfactor) / 100;
769: newHeader[i] = (byte) Math.max(t, 0xff);
770: }
771: }
772:
773: // Write out buffer.
774: out.write(newHeader);
775: }
776:
777: private void writeJfifNoHuffHeader() throws IOException {
778: byte[] newHeader = new byte[jfifNoHuff100Header.length];
779:
780: System.arraycopy(jfifNoHuff100Header, 0, newHeader, 0,
781: jfifNoHuff100Header.length);
782:
783: // Set image width in JFIF header.
784: newHeader[27] = (byte) ((width >>> 8) & 0xff);
785: newHeader[28] = (byte) (width & 0xff);
786:
787: // Set image height in JFIF header.
788: newHeader[25] = (byte) ((height >>> 8) & 0xff);
789: newHeader[26] = (byte) (height & 0xff);
790:
791: // Adjust the quality factor.
792: //
793: // The default quality factor is 100, therefore if
794: // our quality factor does not equal 100 we must
795: // scale the quantization matrices in the JFIF header.
796: // Note that values are clipped to a max of 255.
797: if (qfactor != 100) {
798: for (int i = 44; i < 108; ++i) {
799: int t = (newHeader[i] * qfactor) / 100;
800: newHeader[i] = (byte) Math.max(t, 0xff);
801: }
802: for (int i = 109; i < 173; ++i) {
803: int t = (newHeader[i] * qfactor) / 100;
804: newHeader[i] = (byte) Math.max(t, 0xff);
805: }
806: }
807:
808: // Write out buffer.
809: out.write(newHeader);
810: }
811:
812: }
|