Source Code Cross Referenced for BMPImageEncoder.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » codecimpl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » com.sun.media.jai.codecimpl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $RCSfile: BMPImageEncoder.java,v $
003:         *
004:         * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * Use is subject to license terms.
007:         *
008:         * $Revision: 1.1 $
009:         * $Date: 2005/02/11 04:55:35 $
010:         * $State: Exp $
011:         */
012:        package com.sun.media.jai.codecimpl;
013:
014:        import java.io.OutputStream;
015:        import java.io.IOException;
016:        import java.awt.image.Raster;
017:        import java.awt.image.DataBuffer;
018:        import java.awt.image.DataBufferByte;
019:        import java.awt.image.DataBufferShort;
020:        import java.awt.image.DataBufferUShort;
021:        import java.awt.image.DataBufferInt;
022:        import java.awt.image.RenderedImage;
023:        import java.awt.image.SampleModel;
024:        import java.awt.Rectangle;
025:        import java.awt.image.PixelInterleavedSampleModel;
026:        import java.awt.image.SinglePixelPackedSampleModel;
027:        import java.awt.image.MultiPixelPackedSampleModel;
028:        import java.awt.image.ColorModel;
029:        import java.awt.image.DirectColorModel;
030:        import java.awt.image.IndexColorModel;
031:        import com.sun.media.jai.codec.ImageEncoderImpl;
032:        import com.sun.media.jai.codec.ImageEncodeParam;
033:        import com.sun.media.jai.codec.BMPEncodeParam;
034:        import com.sun.media.jai.codec.SeekableOutputStream;
035:
036:        /**
037:         * An ImageEncoder for the various versions of the BMP image file format.
038:         *
039:         * Unless specified otherwise by the BMPDecodeParam object passed to the
040:         * constructor, Version 3 will be the default version used.
041:         * 
042:         * <p>If the image to be encoded has an IndexColorModel and can be encoded
043:         * using upto 8 bits per pixel, the image will be written out as a Palette
044:         * color image with an appropriate number of bits per pixel. For example an
045:         * image having a 256 color IndexColorModel will be written out as a Palette
046:         * image with 8 bits per pixel while one with a 16 color palette will be 
047:         * written out as a Palette image with 4 bits per pixel. For all other images,
048:         * the 24 bit image format will be used.
049:         *
050:         *
051:         * @since EA2
052:         */
053:        public class BMPImageEncoder extends ImageEncoderImpl {
054:
055:            private OutputStream output;
056:            private int version;
057:            private boolean isCompressed, isTopDown;
058:            private int w, h;
059:            private int compImageSize = 0;
060:
061:            /**
062:             * An ImageEncoder for the BMP file format.
063:             *
064:             * @param output       The OutputStream to write to.
065:             * @param param        The BMPEncodeParam object.
066:             */
067:            public BMPImageEncoder(OutputStream output, ImageEncodeParam param) {
068:
069:                super (output, param);
070:
071:                this .output = output;
072:
073:                BMPEncodeParam bmpParam;
074:                if (param == null) {
075:                    // Use default valued BMPEncodeParam
076:                    bmpParam = new BMPEncodeParam();
077:                } else {
078:                    bmpParam = (BMPEncodeParam) param;
079:                }
080:
081:                this .version = bmpParam.getVersion();
082:                this .isCompressed = bmpParam.isCompressed();
083:                if (isCompressed && !(output instanceof  SeekableOutputStream)) {
084:                    throw new IllegalArgumentException(JaiI18N
085:                            .getString("BMPImageEncoder6"));
086:                }
087:
088:                this .isTopDown = bmpParam.isTopDown();
089:            }
090:
091:            /**
092:             * Encodes a RenderedImage and writes the output to the
093:             * OutputStream associated with this ImageEncoder.
094:             */
095:            public void encode(RenderedImage im) throws IOException {
096:
097:                // Get image dimensions
098:                int minX = im.getMinX();
099:                int minY = im.getMinY();
100:                w = im.getWidth();
101:                h = im.getHeight();
102:
103:                // Default is using 24 bits per pixel.
104:                int bitsPerPixel = 24;
105:                boolean isPalette = false;
106:                int paletteEntries = 0;
107:                IndexColorModel icm = null;
108:
109:                SampleModel sm = im.getSampleModel();
110:                int numBands = sm.getNumBands();
111:
112:                ColorModel cm = im.getColorModel();
113:
114:                if (numBands != 1 && numBands != 3) {
115:                    throw new IllegalArgumentException(JaiI18N
116:                            .getString("BMPImageEncoder1"));
117:                }
118:
119:                int sampleSize[] = sm.getSampleSize();
120:                if (sampleSize[0] > 8) {
121:                    throw new RuntimeException(JaiI18N
122:                            .getString("BMPImageEncoder2"));
123:                }
124:
125:                for (int i = 1; i < sampleSize.length; i++) {
126:                    if (sampleSize[i] != sampleSize[0]) {
127:                        throw new RuntimeException(JaiI18N
128:                                .getString("BMPImageEncoder3"));
129:                    }
130:                }
131:
132:                // Float and Double data cannot be written in a BMP format.
133:                int dataType = sm.getTransferType();
134:                if (dataType != DataBuffer.TYPE_BYTE
135:                        && !CodecUtils.isPackedByteImage(im)) {
136:                    throw new RuntimeException(JaiI18N
137:                            .getString("BMPImageEncoder0"));
138:                }
139:
140:                // Number of bytes that a scanline for the image written out will have.
141:                int destScanlineBytes = w * numBands;
142:                int compression = 0;
143:
144:                byte r[] = null, g[] = null, b[] = null, a[] = null;
145:
146:                if (cm instanceof  IndexColorModel) {
147:
148:                    isPalette = true;
149:                    icm = (IndexColorModel) cm;
150:                    paletteEntries = icm.getMapSize();
151:
152:                    if (paletteEntries <= 2) {
153:
154:                        bitsPerPixel = 1;
155:                        destScanlineBytes = (int) Math.ceil((double) w / 8.0);
156:
157:                    } else if (paletteEntries <= 16) {
158:
159:                        bitsPerPixel = 4;
160:                        destScanlineBytes = (int) Math.ceil((double) w / 2.0);
161:
162:                    } else if (paletteEntries <= 256) {
163:
164:                        bitsPerPixel = 8;
165:
166:                    } else {
167:
168:                        // Cannot be written as a Palette image. So write out as 
169:                        // 24 bit image.
170:                        bitsPerPixel = 24;
171:                        isPalette = false;
172:                        paletteEntries = 0;
173:                        destScanlineBytes = w * 3;
174:                    }
175:
176:                    if (isPalette == true) {
177:
178:                        r = new byte[paletteEntries];
179:                        g = new byte[paletteEntries];
180:                        b = new byte[paletteEntries];
181:                        a = new byte[paletteEntries];
182:
183:                        icm.getAlphas(a);
184:                        icm.getReds(r);
185:                        icm.getGreens(g);
186:                        icm.getBlues(b);
187:                    }
188:
189:                } else {
190:
191:                    // Grey scale images
192:                    if (numBands == 1) {
193:
194:                        isPalette = true;
195:                        paletteEntries = 256;
196:                        //		int sampleSize[] = sm.getSampleSize();
197:                        bitsPerPixel = sampleSize[0];
198:
199:                        destScanlineBytes = (int) Math
200:                                .ceil((double) (w * bitsPerPixel) / 8.0);
201:
202:                        r = new byte[256];
203:                        g = new byte[256];
204:                        b = new byte[256];
205:                        a = new byte[256];
206:
207:                        for (int i = 0; i < 256; i++) {
208:                            r[i] = (byte) i;
209:                            g[i] = (byte) i;
210:                            b[i] = (byte) i;
211:                            //Fix 4672486: BMPEncoder writes wrong alpha lut into 
212:                            // stream for gray-scale image
213:                            a[i] = (byte) 255;
214:                        }
215:                    } else if (sm instanceof  SinglePixelPackedSampleModel) {
216:                        bitsPerPixel = DataBuffer.getDataTypeSize(sm
217:                                .getDataType());
218:                        destScanlineBytes = w * bitsPerPixel + 7 >> 3;
219:                    }
220:                }
221:
222:                // actual writing of image data
223:                int fileSize = 0;
224:                int offset = 0;
225:                int headerSize = 0;
226:                int imageSize = 0;
227:                int xPelsPerMeter = 0;
228:                int yPelsPerMeter = 0;
229:                int colorsUsed = 0;
230:                int colorsImportant = paletteEntries;
231:                int padding = 0;
232:
233:                // Calculate padding for each scanline
234:                int remainder = destScanlineBytes % 4;
235:                if (remainder != 0) {
236:                    padding = 4 - remainder;
237:                }
238:
239:                switch (version) {
240:                case BMPEncodeParam.VERSION_2:
241:                    offset = 26 + paletteEntries * 3;
242:                    headerSize = 12;
243:                    imageSize = (destScanlineBytes + padding) * h;
244:                    fileSize = imageSize + offset;
245:                    throw new RuntimeException(JaiI18N
246:                            .getString("BMPImageEncoder5"));
247:                    //break;
248:
249:                case BMPEncodeParam.VERSION_3:
250:                    // FileHeader is 14 bytes, BitmapHeader is 40 bytes, 
251:                    // add palette size and that is where the data will begin
252:                    if (isCompressed && bitsPerPixel == 8) {
253:                        compression = 1;
254:                    } else if (isCompressed && bitsPerPixel == 4) {
255:                        compression = 2;
256:                    }
257:                    offset = 54 + paletteEntries * 4;
258:
259:                    imageSize = (destScanlineBytes + padding) * h;
260:                    fileSize = imageSize + offset;
261:                    headerSize = 40;
262:                    break;
263:
264:                case BMPEncodeParam.VERSION_4:
265:                    headerSize = 108;
266:                    throw new RuntimeException(JaiI18N
267:                            .getString("BMPImageEncoder5"));
268:                    // break;
269:                }
270:
271:                int redMask = 0, blueMask = 0, greenMask = 0;
272:                if (cm instanceof  DirectColorModel) {
273:                    redMask = ((DirectColorModel) cm).getRedMask();
274:                    greenMask = ((DirectColorModel) cm).getGreenMask();
275:                    blueMask = ((DirectColorModel) cm).getBlueMask();
276:                    destScanlineBytes = w;
277:                    compression = 3;
278:                    fileSize += 12;
279:                    offset += 12;
280:                }
281:
282:                writeFileHeader(fileSize, offset);
283:
284:                writeInfoHeader(headerSize, bitsPerPixel);
285:
286:                // compression
287:                writeDWord(compression);
288:
289:                // imageSize
290:                writeDWord(imageSize);
291:
292:                // xPelsPerMeter
293:                writeDWord(xPelsPerMeter);
294:
295:                // yPelsPerMeter
296:                writeDWord(yPelsPerMeter);
297:
298:                // Colors Used
299:                writeDWord(colorsUsed);
300:
301:                // Colors Important
302:                writeDWord(colorsImportant);
303:
304:                if (compression == 3) {
305:                    writeDWord(redMask);
306:                    writeDWord(greenMask);
307:                    writeDWord(blueMask);
308:                }
309:
310:                if (compression == 3) {
311:                    for (int i = 0; i < h; i++) {
312:                        int row = minY + i;
313:
314:                        if (!isTopDown)
315:                            row = minY + h - i - 1;
316:
317:                        // Get the pixels
318:                        Rectangle srcRect = new Rectangle(minX, row, w, 1);
319:                        Raster src = im.getData(srcRect);
320:
321:                        SampleModel sm1 = src.getSampleModel();
322:                        int pos = 0;
323:                        int startX = srcRect.x - src.getSampleModelTranslateX();
324:                        int startY = srcRect.y - src.getSampleModelTranslateY();
325:                        if (sm1 instanceof  SinglePixelPackedSampleModel) {
326:                            SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm1;
327:                            pos = sppsm.getOffset(startX, startY);
328:                        }
329:
330:                        switch (dataType) {
331:                        case DataBuffer.TYPE_SHORT:
332:                            short[] sdata = ((DataBufferShort) src
333:                                    .getDataBuffer()).getData();
334:                            for (int m = 0; m < sdata.length; m++)
335:                                writeWord(sdata[m]);
336:                            break;
337:
338:                        case DataBuffer.TYPE_USHORT:
339:                            short[] usdata = ((DataBufferUShort) src
340:                                    .getDataBuffer()).getData();
341:                            for (int m = 0; m < usdata.length; m++)
342:                                writeWord(usdata[m]);
343:                            break;
344:
345:                        case DataBuffer.TYPE_INT:
346:                            int[] idata = ((DataBufferInt) src.getDataBuffer())
347:                                    .getData();
348:                            for (int m = 0; m < idata.length; m++)
349:                                writeDWord(idata[m]);
350:                            break;
351:                        }
352:                    }
353:                    return;
354:                }
355:
356:                // palette
357:                if (isPalette == true) {
358:
359:                    // write palette
360:                    switch (version) {
361:
362:                    // has 3 field entries
363:                    case BMPEncodeParam.VERSION_2:
364:
365:                        for (int i = 0; i < paletteEntries; i++) {
366:                            output.write(b[i]);
367:                            output.write(g[i]);
368:                            output.write(r[i]);
369:                        }
370:                        break;
371:
372:                    // has 4 field entries
373:                    default:
374:
375:                        for (int i = 0; i < paletteEntries; i++) {
376:                            output.write(b[i]);
377:                            output.write(g[i]);
378:                            output.write(r[i]);
379:                            output.write(a[i]);
380:                        }
381:                        break;
382:                    }
383:
384:                } // else no palette
385:
386:                // Writing of actual image data
387:
388:                int scanlineBytes = w * numBands;
389:
390:                // Buffer for up to 8 rows of pixels
391:                int[] pixels = new int[8 * scanlineBytes];
392:
393:                // Also create a buffer to hold one line of the data
394:                // to be written to the file, so we can use array writes.
395:                byte[] bpixels = new byte[destScanlineBytes];
396:
397:                int l;
398:
399:                if (!isTopDown) {
400:                    // Process 8 rows at a time so all but the first will have a
401:                    // multiple of 8 rows.
402:                    int lastRow = minY + h;
403:
404:                    for (int row = (lastRow - 1); row >= minY; row -= 8) {
405:                        // Number of rows being read
406:                        int rows = Math.min(8, row - minY + 1);
407:
408:                        // Get the pixels
409:                        Raster src = im.getData(new Rectangle(minX, row - rows
410:                                + 1, w, rows));
411:
412:                        src.getPixels(minX, row - rows + 1, w, rows, pixels);
413:
414:                        l = 0;
415:
416:                        // Last possible position in the pixels array
417:                        int max = scanlineBytes * rows - 1;
418:
419:                        for (int i = 0; i < rows; i++) {
420:
421:                            // Beginning of each scanline in the pixels array    
422:                            l = max - (i + 1) * scanlineBytes + 1;
423:
424:                            writePixels(l, scanlineBytes, bitsPerPixel, pixels,
425:                                    bpixels, padding, numBands, icm);
426:                        }
427:
428:                    }
429:
430:                } else {
431:                    // Process 8 rows at a time so all but the last will have a
432:                    // multiple of 8 rows.
433:                    int lastRow = minY + h;
434:
435:                    for (int row = minY; row < lastRow; row += 8) {
436:                        int rows = Math.min(8, lastRow - row);
437:
438:                        // Get the pixels
439:                        Raster src = im.getData(new Rectangle(minX, row, w,
440:                                rows));
441:                        src.getPixels(minX, row, w, rows, pixels);
442:
443:                        l = 0;
444:                        for (int i = 0; i < rows; i++) {
445:
446:                            writePixels(l, scanlineBytes, bitsPerPixel, pixels,
447:                                    bpixels, padding, numBands, icm);
448:                        }
449:
450:                    }
451:
452:                }
453:
454:                if (isCompressed && (bitsPerPixel == 4 || bitsPerPixel == 8)) {
455:                    // Write the RLE EOF marker and 
456:                    output.write(0);
457:                    output.write(1);
458:                    incCompImageSize(2);
459:                    // update the file/image Size
460:                    imageSize = compImageSize;
461:                    fileSize = compImageSize + offset;
462:                    writeSize(fileSize, 2);
463:                    writeSize(imageSize, 34);
464:                }
465:
466:            }
467:
468:            private void writePixels(int l, int scanlineBytes,
469:                    int bitsPerPixel, int pixels[], byte bpixels[],
470:                    int padding, int numBands, IndexColorModel icm)
471:                    throws IOException {
472:
473:                int pixel = 0;
474:                int k = 0;
475:                switch (bitsPerPixel) {
476:
477:                case 1:
478:
479:                    for (int j = 0; j < scanlineBytes / 8; j++) {
480:                        bpixels[k++] = (byte) ((pixels[l++] << 7)
481:                                | (pixels[l++] << 6) | (pixels[l++] << 5)
482:                                | (pixels[l++] << 4) | (pixels[l++] << 3)
483:                                | (pixels[l++] << 2) | (pixels[l++] << 1) | pixels[l++]);
484:                    }
485:
486:                    // Partially filled last byte, if any
487:                    if (scanlineBytes % 8 > 0) {
488:                        pixel = 0;
489:                        for (int j = 0; j < scanlineBytes % 8; j++) {
490:                            pixel |= (pixels[l++] << (7 - j));
491:                        }
492:                        bpixels[k++] = (byte) pixel;
493:                    }
494:                    output.write(bpixels, 0, (scanlineBytes + 7) / 8);
495:
496:                    break;
497:
498:                case 4:
499:                    if (isCompressed) {
500:                        byte[] bipixels = new byte[scanlineBytes];
501:                        for (int h = 0; h < scanlineBytes; h++) {
502:                            bipixels[h] = (byte) pixels[l++];
503:                        }
504:                        encodeRLE4(bipixels, scanlineBytes);
505:                    } else {
506:                        for (int j = 0; j < scanlineBytes / 2; j++) {
507:                            pixel = (pixels[l++] << 4) | pixels[l++];
508:                            bpixels[k++] = (byte) pixel;
509:                        }
510:                        // Put the last pixel of odd-length lines in the 4 MSBs
511:                        if ((scanlineBytes % 2) == 1) {
512:                            pixel = pixels[l] << 4;
513:                            bpixels[k++] = (byte) pixel;
514:                        }
515:                        output.write(bpixels, 0, (scanlineBytes + 1) / 2);
516:                    }
517:                    break;
518:
519:                case 8:
520:                    if (isCompressed) {
521:                        for (int h = 0; h < scanlineBytes; h++) {
522:                            bpixels[h] = (byte) pixels[l++];
523:                        }
524:                        encodeRLE8(bpixels, scanlineBytes);
525:                    } else {
526:                        for (int j = 0; j < scanlineBytes; j++) {
527:                            bpixels[j] = (byte) pixels[l++];
528:                        }
529:                        output.write(bpixels, 0, scanlineBytes);
530:                    }
531:                    break;
532:
533:                case 24:
534:                    if (numBands == 3) {
535:                        for (int j = 0; j < scanlineBytes; j += 3) {
536:                            // Since BMP needs BGR format
537:                            bpixels[k++] = (byte) (pixels[l + 2]);
538:                            bpixels[k++] = (byte) (pixels[l + 1]);
539:                            bpixels[k++] = (byte) (pixels[l]);
540:                            l += 3;
541:                        }
542:                        output.write(bpixels, 0, scanlineBytes);
543:                    } else {
544:                        // Case where IndexColorModel had > 256 colors.  
545:                        int entries = icm.getMapSize();
546:
547:                        byte r[] = new byte[entries];
548:                        byte g[] = new byte[entries];
549:                        byte b[] = new byte[entries];
550:
551:                        icm.getReds(r);
552:                        icm.getGreens(g);
553:                        icm.getBlues(b);
554:                        int index;
555:
556:                        for (int j = 0; j < scanlineBytes; j++) {
557:                            index = pixels[l];
558:                            bpixels[k++] = b[index];
559:                            bpixels[k++] = g[index];
560:                            bpixels[k++] = b[index];
561:                            l++;
562:                        }
563:                        output.write(bpixels, 0, scanlineBytes * 3);
564:                    }
565:                    break;
566:
567:                }
568:
569:                // Write out the padding
570:                if (!(isCompressed && (bitsPerPixel == 8 || bitsPerPixel == 4))) {
571:                    for (k = 0; k < padding; k++) {
572:                        output.write(0);
573:                    }
574:                }
575:            }
576:
577:            private void encodeRLE8(byte[] bpixels, int scanlineBytes)
578:                    throws IOException {
579:
580:                int runCount = 1, absVal = -1, j = -1;
581:                byte runVal = 0, nextVal = 0;
582:
583:                runVal = bpixels[++j];
584:                byte[] absBuf = new byte[256];
585:
586:                while (j < scanlineBytes - 1) {
587:                    nextVal = bpixels[++j];
588:                    if (nextVal == runVal) {
589:                        if (absVal >= 3) {
590:                            /// Check if there was an existing Absolute Run
591:                            output.write(0);
592:                            output.write(absVal);
593:                            incCompImageSize(2);
594:                            for (int a = 0; a < absVal; a++) {
595:                                output.write(absBuf[a]);
596:                                incCompImageSize(1);
597:                            }
598:                            if (!isEven(absVal)) {
599:                                //Padding
600:                                output.write(0);
601:                                incCompImageSize(1);
602:                            }
603:                        } else if (absVal > -1) {
604:                            /// Absolute Encoding for less than 3
605:                            /// treated as regular encoding 
606:                            /// Do not include the last element since it will
607:                            /// be inclued in the next encoding/run
608:                            for (int b = 0; b < absVal; b++) {
609:                                output.write(1);
610:                                output.write(absBuf[b]);
611:                                incCompImageSize(2);
612:                            }
613:                        }
614:                        absVal = -1;
615:                        runCount++;
616:                        if (runCount == 256) {
617:                            /// Only 255 values permitted
618:                            output.write(runCount - 1);
619:                            output.write(runVal);
620:                            incCompImageSize(2);
621:                            runCount = 1;
622:                        }
623:                    } else {
624:                        if (runCount > 1) {
625:                            /// If there was an existing run 
626:                            output.write(runCount);
627:                            output.write(runVal);
628:                            incCompImageSize(2);
629:                        } else if (absVal < 0) {
630:                            // First time.. 
631:                            absBuf[++absVal] = runVal;
632:                            absBuf[++absVal] = nextVal;
633:                        } else if (absVal < 254) {
634:                            //  0-254 only
635:                            absBuf[++absVal] = nextVal;
636:                        } else {
637:                            output.write(0);
638:                            output.write(absVal + 1);
639:                            incCompImageSize(2);
640:                            for (int a = 0; a <= absVal; a++) {
641:                                output.write(absBuf[a]);
642:                                incCompImageSize(1);
643:                            }
644:                            // padding since 255 elts is not even
645:                            output.write(0);
646:                            incCompImageSize(1);
647:                            absVal = -1;
648:                        }
649:                        runVal = nextVal;
650:                        runCount = 1;
651:                    }
652:
653:                    if (j == scanlineBytes - 1) { // EOF scanline
654:                        // Write the run
655:                        if (absVal == -1) {
656:                            output.write(runCount);
657:                            output.write(runVal);
658:                            incCompImageSize(2);
659:                            runCount = 1;
660:                        } else {
661:                            // write the Absolute Run
662:                            if (absVal >= 2) {
663:                                output.write(0);
664:                                output.write(absVal + 1);
665:                                incCompImageSize(2);
666:                                for (int a = 0; a <= absVal; a++) {
667:                                    output.write(absBuf[a]);
668:                                    incCompImageSize(1);
669:                                }
670:                                if (!isEven(absVal + 1)) {
671:                                    //Padding
672:                                    output.write(0);
673:                                    incCompImageSize(1);
674:                                }
675:
676:                            } else if (absVal > -1) {
677:                                for (int b = 0; b <= absVal; b++) {
678:                                    output.write(1);
679:                                    output.write(absBuf[b]);
680:                                    incCompImageSize(2);
681:                                }
682:                            }
683:                        }
684:                        /// EOF scanline 
685:
686:                        output.write(0);
687:                        output.write(0);
688:                        incCompImageSize(2);
689:                    }
690:                }
691:            }
692:
693:            private void encodeRLE4(byte[] bipixels, int scanlineBytes)
694:                    throws IOException {
695:
696:                int runCount = 2, absVal = -1, j = -1, pixel = 0, q = 0;
697:                byte runVal1 = 0, runVal2 = 0, nextVal1 = 0, nextVal2 = 0;
698:                byte[] absBuf = new byte[256];
699:
700:                runVal1 = bipixels[++j];
701:                runVal2 = bipixels[++j];
702:
703:                while (j < scanlineBytes - 2) {
704:                    nextVal1 = bipixels[++j];
705:                    nextVal2 = bipixels[++j];
706:
707:                    if (nextVal1 == runVal1) {
708:
709:                        //Check if there was an existing Absolute Run
710:                        if (absVal >= 4) {
711:                            output.write(0);
712:                            output.write(absVal - 1);
713:                            incCompImageSize(2);
714:                            // we need to exclude  last 2 elts, similarity of
715:                            // which caused to enter this part of the code
716:                            for (int a = 0; a < absVal - 2; a += 2) {
717:                                pixel = (absBuf[a] << 4) | absBuf[a + 1];
718:                                output.write((byte) pixel);
719:                                incCompImageSize(1);
720:                            }
721:                            // if # of elts is odd - read the last element
722:                            if (!(isEven(absVal - 1))) {
723:                                q = absBuf[absVal - 2] << 4 | 0;
724:                                output.write(q);
725:                                incCompImageSize(1);
726:                            }
727:                            // Padding to word align absolute encoding
728:                            if (!isEven((int) Math.ceil((absVal - 1) / 2))) {
729:                                output.write(0);
730:                                incCompImageSize(1);
731:                            }
732:                        } else if (absVal > -1) {
733:                            output.write(2);
734:                            pixel = (absBuf[0] << 4) | absBuf[1];
735:                            output.write(pixel);
736:                            incCompImageSize(2);
737:                        }
738:                        absVal = -1;
739:
740:                        if (nextVal2 == runVal2) {
741:                            // Even runlength
742:                            runCount += 2;
743:                            if (runCount == 256) {
744:                                output.write(runCount - 1);
745:                                pixel = (runVal1 << 4) | runVal2;
746:                                output.write(pixel);
747:                                incCompImageSize(2);
748:                                runCount = 2;
749:                                if (j < scanlineBytes - 1) {
750:                                    runVal1 = runVal2;
751:                                    runVal2 = bipixels[++j];
752:                                } else {
753:                                    output.write(01);
754:                                    int r = runVal2 << 4 | 0;
755:                                    output.write(r);
756:                                    incCompImageSize(2);
757:                                    runCount = -1;/// Only EOF required now
758:                                }
759:                            }
760:                        } else {
761:                            // odd runlength and the run ends here
762:                            // runCount wont be > 254 since 256/255 case will
763:                            // be taken care of in above code. 
764:                            runCount++;
765:                            pixel = (runVal1 << 4) | runVal2;
766:                            output.write(runCount);
767:                            output.write(pixel);
768:                            incCompImageSize(2);
769:                            runCount = 2;
770:                            runVal1 = nextVal2;
771:                            // If end of scanline
772:                            if (j < scanlineBytes - 1) {
773:                                runVal2 = bipixels[++j];
774:                            } else {
775:                                output.write(01);
776:                                int r = nextVal2 << 4 | 0;
777:                                output.write(r);
778:                                incCompImageSize(2);
779:                                runCount = -1;/// Only EOF required now
780:                            }
781:
782:                        }
783:                    } else {
784:                        // Check for existing run
785:                        if (runCount > 2) {
786:                            pixel = (runVal1 << 4) | runVal2;
787:                            output.write(runCount);
788:                            output.write(pixel);
789:                            incCompImageSize(2);
790:                        } else if (absVal < 0) { // first time
791:                            absBuf[++absVal] = runVal1;
792:                            absBuf[++absVal] = runVal2;
793:                            absBuf[++absVal] = nextVal1;
794:                            absBuf[++absVal] = nextVal2;
795:                        } else if (absVal < 253) { // only 255 elements
796:                            absBuf[++absVal] = nextVal1;
797:                            absBuf[++absVal] = nextVal2;
798:                        } else {
799:                            output.write(0);
800:                            output.write(absVal + 1);
801:                            incCompImageSize(2);
802:                            for (int a = 0; a < absVal; a += 2) {
803:                                pixel = (absBuf[a] << 4) | absBuf[a + 1];
804:                                output.write((byte) pixel);
805:                                incCompImageSize(1);
806:                            }
807:                            // Padding for word align
808:                            // since it will fit into 127 bytes
809:                            output.write(0);
810:                            incCompImageSize(1);
811:                            absVal = -1;
812:                        }
813:
814:                        runVal1 = nextVal1;
815:                        runVal2 = nextVal2;
816:                        runCount = 2;
817:                    }
818:                    // Handle the End of scanline for the last 2 4bits
819:                    if (j >= scanlineBytes - 2) {
820:                        if (absVal == -1 && runCount >= 2) {
821:                            if (j == scanlineBytes - 2) {
822:                                if (bipixels[++j] == runVal1) {
823:                                    runCount++;
824:                                    pixel = (runVal1 << 4) | runVal2;
825:                                    output.write(runCount);
826:                                    output.write(pixel);
827:                                    incCompImageSize(2);
828:                                } else {
829:                                    pixel = (runVal1 << 4) | runVal2;
830:                                    output.write(runCount);
831:                                    output.write(pixel);
832:                                    output.write(01);
833:                                    pixel = bipixels[j] << 4 | 0;
834:                                    output.write(pixel);
835:                                    int n = bipixels[j] << 4 | 0;
836:                                    incCompImageSize(4);
837:                                }
838:                            } else {
839:                                output.write(runCount);
840:                                pixel = (runVal1 << 4) | runVal2;
841:                                output.write(pixel);
842:                                incCompImageSize(2);
843:                            }
844:                        } else if (absVal > -1) {
845:                            if (j == scanlineBytes - 2) {
846:                                absBuf[++absVal] = bipixels[++j];
847:                            }
848:                            if (absVal >= 2) {
849:                                output.write(0);
850:                                output.write(absVal + 1);
851:                                incCompImageSize(2);
852:                                for (int a = 0; a < absVal; a += 2) {
853:                                    pixel = (absBuf[a] << 4) | absBuf[a + 1];
854:                                    output.write((byte) pixel);
855:                                    incCompImageSize(1);
856:                                }
857:                                if (!(isEven(absVal + 1))) {
858:                                    q = absBuf[absVal] << 4 | 0;
859:                                    output.write(q);
860:                                    incCompImageSize(1);
861:                                }
862:
863:                                // Padding
864:                                if (!isEven((int) Math.ceil((absVal + 1) / 2))) {
865:                                    output.write(0);
866:                                    incCompImageSize(1);
867:                                }
868:
869:                            } else {
870:                                switch (absVal) {
871:                                case 0:
872:                                    output.write(1);
873:                                    int n = absBuf[0] << 4 | 0;
874:                                    output.write(n);
875:                                    incCompImageSize(2);
876:                                    break;
877:                                case 1:
878:                                    output.write(2);
879:                                    pixel = (absBuf[0] << 4) | absBuf[1];
880:                                    output.write(pixel);
881:                                    incCompImageSize(2);
882:                                    break;
883:                                }
884:                            }
885:
886:                        }
887:                        output.write(0);
888:                        output.write(0);
889:                        incCompImageSize(2);
890:                    }
891:                }
892:            }
893:
894:            private synchronized void incCompImageSize(int value) {
895:                compImageSize = compImageSize + value;
896:            }
897:
898:            private boolean isEven(int number) {
899:                return (number % 2 == 0 ? true : false);
900:            }
901:
902:            private void writeFileHeader(int fileSize, int offset)
903:                    throws IOException {
904:                // magic value
905:                output.write('B');
906:                output.write('M');
907:
908:                // File size
909:                writeDWord(fileSize);
910:
911:                // reserved1 and reserved2
912:                output.write(0);
913:                output.write(0);
914:                output.write(0);
915:                output.write(0);
916:
917:                // offset to image data
918:                writeDWord(offset);
919:            }
920:
921:            private void writeInfoHeader(int headerSize, int bitsPerPixel)
922:                    throws IOException {
923:
924:                // size of header
925:                writeDWord(headerSize);
926:
927:                // width
928:                writeDWord(w);
929:
930:                // height
931:                writeDWord(h);
932:
933:                // number of planes
934:                writeWord(1);
935:
936:                // Bits Per Pixel
937:                writeWord(bitsPerPixel);
938:            }
939:
940:            // Methods for little-endian writing
941:            public void writeWord(int word) throws IOException {
942:                output.write(word & 0xff);
943:                output.write((word & 0xff00) >> 8);
944:            }
945:
946:            public void writeDWord(int dword) throws IOException {
947:                output.write(dword & 0xff);
948:                output.write((dword & 0xff00) >> 8);
949:                output.write((dword & 0xff0000) >> 16);
950:                output.write((dword & 0xff000000) >> 24);
951:            }
952:
953:            private void writeSize(int dword, int offset) throws IOException {
954:                ((SeekableOutputStream) output).seek(offset);
955:                writeDWord(dword);
956:            }
957:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.