Source Code Cross Referenced for CLibImageWriter.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » imageioimpl » plugins » clib » 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.imageioimpl.plugins.clib 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $RCSfile: CLibImageWriter.java,v $
003:         *
004:         * 
005:         * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
006:         * 
007:         * Redistribution and use in source and binary forms, with or without
008:         * modification, are permitted provided that the following conditions
009:         * are met: 
010:         * 
011:         * - Redistribution of source code must retain the above copyright 
012:         *   notice, this  list of conditions and the following disclaimer.
013:         * 
014:         * - Redistribution in binary form must reproduce the above copyright
015:         *   notice, this list of conditions and the following disclaimer in 
016:         *   the documentation and/or other materials provided with the
017:         *   distribution.
018:         * 
019:         * Neither the name of Sun Microsystems, Inc. or the names of 
020:         * contributors may be used to endorse or promote products derived 
021:         * from this software without specific prior written permission.
022:         * 
023:         * This software is provided "AS IS," without a warranty of any 
024:         * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025:         * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026:         * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027:         * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028:         * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029:         * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030:         * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031:         * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032:         * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033:         * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034:         * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035:         * POSSIBILITY OF SUCH DAMAGES. 
036:         * 
037:         * You acknowledge that this software is not designed or intended for 
038:         * use in the design, construction, operation or maintenance of any 
039:         * nuclear facility. 
040:         *
041:         * $Revision: 1.6 $
042:         * $Date: 2007/02/06 22:14:59 $
043:         * $State: Exp $
044:         */
045:        package com.sun.media.imageioimpl.plugins.clib;
046:
047:        import java.awt.Point;
048:        import java.awt.Rectangle;
049:        import java.awt.color.ColorSpace;
050:        import java.awt.geom.AffineTransform;
051:        import java.awt.image.AffineTransformOp;
052:        import java.awt.image.ColorModel;
053:        import java.awt.image.ComponentSampleModel;
054:        import java.awt.image.DataBuffer;
055:        import java.awt.image.DataBufferByte;
056:        import java.awt.image.DataBufferUShort;
057:        import java.awt.image.IndexColorModel;
058:        import java.awt.image.MultiPixelPackedSampleModel;
059:        import java.awt.image.PixelInterleavedSampleModel;
060:        import java.awt.image.Raster;
061:        import java.awt.image.RenderedImage;
062:        import java.awt.image.SampleModel;
063:        import java.awt.image.SinglePixelPackedSampleModel;
064:        import java.awt.image.WritableRaster;
065:        import java.io.IOException;
066:        import javax.imageio.IIOImage;
067:        import javax.imageio.ImageWriter;
068:        import javax.imageio.ImageWriteParam;
069:        import javax.imageio.ImageTypeSpecifier;
070:        import javax.imageio.metadata.IIOMetadata;
071:        import javax.imageio.spi.ImageWriterSpi;
072:        import com.sun.medialib.codec.jiio.Constants;
073:        import com.sun.medialib.codec.jiio.mediaLibImage;
074:
075:        public abstract class CLibImageWriter extends ImageWriter {
076:            /**
077:             * Returns the data array from the <code>DataBuffer</code>.
078:             */
079:            private static final Object getDataBufferData(DataBuffer db) {
080:                Object data;
081:
082:                int dType = db.getDataType();
083:                switch (dType) {
084:                case DataBuffer.TYPE_BYTE:
085:                    data = ((DataBufferByte) db).getData();
086:                    break;
087:                case DataBuffer.TYPE_USHORT:
088:                    data = ((DataBufferUShort) db).getData();
089:                    break;
090:                default:
091:                    throw new IllegalArgumentException(I18N
092:                            .getString("Generic0")
093:                            + " " + dType);
094:                }
095:
096:                return data;
097:            }
098:
099:            /**
100:             * Returns the mediaLib type enum given the Java2D type enum.
101:             */
102:            private static final int getMediaLibDataType(int dataType) {
103:                int mlibType;
104:
105:                switch (dataType) {
106:                case DataBuffer.TYPE_BYTE:
107:                    mlibType = mediaLibImage.MLIB_BYTE;
108:                    break;
109:                case DataBuffer.TYPE_USHORT:
110:                    mlibType = mediaLibImage.MLIB_USHORT;
111:                    break;
112:                default:
113:                    throw new IllegalArgumentException(I18N
114:                            .getString("Generic0")
115:                            + " " + dataType);
116:                }
117:
118:                return mlibType;
119:            }
120:
121:            /**
122:             * Returns the mediaLib format enum given the <code>SampleModel</code>
123:             * and <code>ColorModel</code> of an image. If the format cannot be
124:             * determined to be anything more specific, the value
125:             * <code>Constants.MLIB_FORMAT_UNKNOWN</code> will be returned.
126:             *
127:             * @param sampleModel The <code>SampleModel</code> describing the
128:             * layout of the <code>DataBuffer</code>; may be <code>null</code>.
129:             * @param colorModel The <code>ColorModel</code> describing the
130:             * mapping of the samples in a pixel to a color.
131:             *
132:             * @throws IllegalArgumentExcaption if <code>sampleModel</code> is
133:             * <code>null</code>.
134:             *
135:             * @return One of the <code>Constants.MLIB_FORMAT</code> constants.
136:             */
137:            private static final int getMediaLibFormat(SampleModel sampleModel,
138:                    ColorModel colorModel) {
139:                if (sampleModel == null) {
140:                    throw new IllegalArgumentException("sampleModel == null!");
141:                }
142:
143:                int mlibFormat = Constants.MLIB_FORMAT_UNKNOWN;
144:
145:                if (sampleModel instanceof  SinglePixelPackedSampleModel
146:                        && sampleModel.getNumBands() == 4 && colorModel != null
147:                        && colorModel.hasAlpha()) {
148:                    int[] masks = ((SinglePixelPackedSampleModel) sampleModel)
149:                            .getBitMasks();
150:                    if (masks[3] == 0xff000000) {
151:                        if (masks[0] == 0xff && masks[1] == 0xff00
152:                                && masks[2] == 0xff0000) {
153:                            mlibFormat = Constants.MLIB_FORMAT_PACKED_ABGR;
154:                        } else if (masks[0] == 0xff0000 && masks[1] == 0xff00
155:                                && masks[2] == 0xff) {
156:                            mlibFormat = Constants.MLIB_FORMAT_PACKED_ARGB;
157:                        }
158:                    }
159:                } else if (sampleModel instanceof  ComponentSampleModel) {
160:                    ComponentSampleModel csm = (ComponentSampleModel) sampleModel;
161:                    int bandOffsets[] = csm.getBandOffsets();
162:                    int pixelStride = csm.getPixelStride();
163:
164:                    if (pixelStride == bandOffsets.length) {
165:                        int numBands = pixelStride; // for clarity
166:
167:                        boolean hasOneBank = true;
168:                        int bankIndices[] = csm.getBankIndices();
169:                        for (int i = 1; i < bankIndices.length; i++) {
170:                            if (bankIndices[i] != bankIndices[0]) {
171:                                hasOneBank = false;
172:                            }
173:                        }
174:
175:                        if (hasOneBank) {
176:                            if (colorModel instanceof  IndexColorModel) {
177:                                mlibFormat = Constants.MLIB_FORMAT_INDEXED;
178:                            } else if (numBands == 1) {
179:                                mlibFormat = Constants.MLIB_FORMAT_GRAYSCALE;
180:                            } else if (numBands == 2 && bandOffsets[0] == 0
181:                                    && bandOffsets[1] == 1) {
182:                                mlibFormat = Constants.MLIB_FORMAT_GRAYSCALE_ALPHA;
183:                            } else if (numBands == 3) {
184:                                int csType = colorModel != null ? colorModel
185:                                        .getColorSpace().getType()
186:                                        : ColorSpace.TYPE_RGB;
187:                                if (csType == ColorSpace.TYPE_RGB) {
188:                                    if (bandOffsets[0] == 2
189:                                            && bandOffsets[1] == 1
190:                                            && bandOffsets[2] == 0) {
191:                                        mlibFormat = Constants.MLIB_FORMAT_BGR;
192:                                    } else if (bandOffsets[0] == 0
193:                                            && bandOffsets[1] == 1
194:                                            && bandOffsets[2] == 2) {
195:                                        mlibFormat = Constants.MLIB_FORMAT_RGB;
196:                                    }
197:                                } else if (csType == ColorSpace.TYPE_Yxy
198:                                        && bandOffsets[0] == 0
199:                                        && bandOffsets[1] == 1
200:                                        && bandOffsets[2] == 2) {
201:                                    mlibFormat = Constants.MLIB_FORMAT_YCC;
202:                                }
203:                            } else if (numBands == 4) {
204:                                int csType = colorModel != null ? colorModel
205:                                        .getColorSpace().getType()
206:                                        : ColorSpace.TYPE_RGB;
207:                                if (csType == ColorSpace.TYPE_RGB) {
208:                                    if (bandOffsets[3] == 0) {
209:                                        if (bandOffsets[0] == 3
210:                                                && bandOffsets[1] == 2
211:                                                && bandOffsets[2] == 1) {
212:                                            mlibFormat = Constants.MLIB_FORMAT_ABGR;
213:                                        } else if (bandOffsets[0] == 1
214:                                                && bandOffsets[1] == 2
215:                                                && bandOffsets[2] == 3) {
216:                                            mlibFormat = Constants.MLIB_FORMAT_ARGB;
217:                                        }
218:                                    } else if (bandOffsets[3] == 3) {
219:                                        if (bandOffsets[0] == 0
220:                                                && bandOffsets[1] == 1
221:                                                && bandOffsets[2] == 2) {
222:                                            mlibFormat = Constants.MLIB_FORMAT_RGBA;
223:                                        } else if (bandOffsets[0] == 2
224:                                                && bandOffsets[1] == 1
225:                                                && bandOffsets[2] == 0) {
226:                                            mlibFormat = Constants.MLIB_FORMAT_BGRA;
227:                                        }
228:                                    }
229:                                } else if (csType == ColorSpace.TYPE_CMYK
230:                                        && bandOffsets[0] == 0
231:                                        && bandOffsets[1] == 1
232:                                        && bandOffsets[2] == 2
233:                                        && bandOffsets[3] == 3) {
234:                                    mlibFormat = Constants.MLIB_FORMAT_CMYK;
235:                                } else if (csType == ColorSpace.TYPE_Yxy
236:                                        && bandOffsets[0] == 0
237:                                        && bandOffsets[1] == 1
238:                                        && bandOffsets[2] == 2
239:                                        && bandOffsets[3] == 3) {
240:                                    if (colorModel != null
241:                                            && colorModel.hasAlpha()) {
242:                                        mlibFormat = Constants.MLIB_FORMAT_YCCA;
243:                                    } else {
244:                                        mlibFormat = Constants.MLIB_FORMAT_YCCK;
245:                                    }
246:                                }
247:                            }
248:                        }
249:                    }
250:                }
251:
252:                return mlibFormat;
253:            }
254:
255:            /**
256:             * Returns a contiguous <code>Raster</code> of data over the specified
257:             * <code>Rectangle</code>. If the region is a sub-region of a single
258:             * tile, then a child of that tile will be returned. If the region
259:             * overlaps more than one tile and has 8 bits per sample, then a
260:             * pixel interleaved Raster having band offsets 0,1,... will be returned.
261:             * Otherwise the Raster returned by <code>im.copyData(null)</code> will
262:             * be returned.
263:             */
264:            private static final Raster getContiguousData(RenderedImage im,
265:                    Rectangle region) {
266:                if (im == null) {
267:                    throw new IllegalArgumentException("im == null");
268:                } else if (region == null) {
269:                    throw new IllegalArgumentException("region == null");
270:                }
271:
272:                Raster raster;
273:                if (im.getNumXTiles() == 1 && im.getNumYTiles() == 1) {
274:                    // Image is not tiled so just get a reference to the tile.
275:                    raster = im.getTile(im.getMinTileX(), im.getMinTileY());
276:
277:                    // Ensure result has requested coverage.
278:                    Rectangle bounds = raster.getBounds();
279:                    if (!bounds.equals(region)) {
280:                        raster = raster.createChild(region.x, region.y,
281:                                region.width, region.height, region.x,
282:                                region.y, null);
283:                    }
284:                } else {
285:                    // Image is tiled.
286:
287:                    // Create an interleaved raster for copying for 8-bit case.
288:                    // This ensures that for RGB data the band offsets are {0,1,2}.
289:                    SampleModel sampleModel = im.getSampleModel();
290:                    WritableRaster target = sampleModel.getSampleSize(0) == 8 ? Raster
291:                            .createInterleavedRaster(DataBuffer.TYPE_BYTE, im
292:                                    .getWidth(), im.getHeight(), sampleModel
293:                                    .getNumBands(), new Point(im.getMinX(), im
294:                                    .getMinY()))
295:                            : null;
296:
297:                    // Copy the data.
298:                    raster = im.copyData(target);
299:                }
300:
301:                return raster;
302:            }
303:
304:            /**
305:             * Subsamples and sub-bands the input <code>Raster</code> over a
306:             * sub-region and stores the result in a <code>WritableRaster</code>.
307:             *
308:             * @param src The source <code>Raster</code>
309:             * @param sourceBands The source bands to use; may be <code>null</code>
310:             * @param subsampleX The subsampling factor along the horizontal axis.
311:             * @param subsampleY The subsampling factor along the vertical axis.
312:             * in which case all bands will be used.
313:             * @param dst The destination <code>WritableRaster</code>.
314:             * @throws IllegalArgumentException if <code>source</code> is
315:             * <code>null</code> or empty, <code>dst</code> is <code>null</code>,
316:             * <code>sourceBands.length</code> exceeds the number of bands in
317:             * <code>source</code>, or <code>sourcBands</code> contains an element
318:             * which is negative or greater than or equal to the number of bands
319:             * in <code>source</code>.
320:             */
321:            private static void reformat(Raster source, int[] sourceBands,
322:                    int subsampleX, int subsampleY, WritableRaster dst) {
323:                // Check for nulls.
324:                if (source == null) {
325:                    throw new IllegalArgumentException("source == null!");
326:                } else if (dst == null) {
327:                    throw new IllegalArgumentException("dst == null!");
328:                }
329:
330:                // Validate the source bounds. XXX is this needed?
331:                Rectangle sourceBounds = source.getBounds();
332:                if (sourceBounds.isEmpty()) {
333:                    throw new IllegalArgumentException(
334:                            "source.getBounds().isEmpty()!");
335:                }
336:
337:                // Check sub-banding.
338:                boolean isSubBanding = false;
339:                int numSourceBands = source.getSampleModel().getNumBands();
340:                if (sourceBands != null) {
341:                    if (sourceBands.length > numSourceBands) {
342:                        throw new IllegalArgumentException(
343:                                "sourceBands.length > numSourceBands!");
344:                    }
345:
346:                    boolean isRamp = sourceBands.length == numSourceBands;
347:                    for (int i = 0; i < sourceBands.length; i++) {
348:                        if (sourceBands[i] < 0
349:                                || sourceBands[i] >= numSourceBands) {
350:                            throw new IllegalArgumentException(
351:                                    "sourceBands[i] < 0 || sourceBands[i] >= numSourceBands!");
352:                        } else if (sourceBands[i] != i) {
353:                            isRamp = false;
354:                        }
355:                    }
356:
357:                    isSubBanding = !isRamp;
358:                }
359:
360:                // Allocate buffer for a single source row.
361:                int sourceWidth = sourceBounds.width;
362:                int[] pixels = new int[sourceWidth * numSourceBands];
363:
364:                // Initialize variables used in loop.
365:                int sourceX = sourceBounds.x;
366:                int sourceY = sourceBounds.y;
367:                int numBands = sourceBands != null ? sourceBands.length
368:                        : numSourceBands;
369:                int dstWidth = dst.getWidth();
370:                int dstYMax = dst.getHeight() - 1;
371:                int copyFromIncrement = numSourceBands * subsampleX;
372:
373:                // Loop over source rows, subsample each, and store in destination.
374:                for (int dstY = 0; dstY <= dstYMax; dstY++) {
375:                    // Read one row.
376:                    source.getPixels(sourceX, sourceY, sourceWidth, 1, pixels);
377:
378:                    // Copy within the same buffer by left shifting.
379:                    if (isSubBanding) {
380:                        int copyFrom = 0;
381:                        int copyTo = 0;
382:                        for (int i = 0; i < dstWidth; i++) {
383:                            for (int j = 0; j < numBands; j++) {
384:                                pixels[copyTo++] = pixels[copyFrom
385:                                        + sourceBands[j]];
386:                            }
387:                            copyFrom += copyFromIncrement;
388:                        }
389:                    } else {
390:                        int copyFrom = copyFromIncrement;
391:                        int copyTo = numSourceBands;
392:                        // Start from index 1 as no need to copy the first pixel.
393:                        for (int i = 1; i < dstWidth; i++) {
394:                            int k = copyFrom;
395:                            for (int j = 0; j < numSourceBands; j++) {
396:                                pixels[copyTo++] = pixels[k++];
397:                            }
398:                            copyFrom += copyFromIncrement;
399:                        }
400:                    }
401:
402:                    // Set the destionation row.
403:                    dst.setPixels(0, dstY, dstWidth, 1, pixels);
404:
405:                    // Increment the source row.
406:                    sourceY += subsampleY;
407:                }
408:            }
409:
410:            protected CLibImageWriter(ImageWriterSpi originatingProvider) {
411:                super (originatingProvider);
412:            }
413:
414:            public IIOMetadata convertImageMetadata(IIOMetadata inData,
415:                    ImageTypeSpecifier imageType, ImageWriteParam param) {
416:                return null;
417:            }
418:
419:            public IIOMetadata convertStreamMetadata(IIOMetadata inData,
420:                    ImageWriteParam param) {
421:                return null;
422:            }
423:
424:            public IIOMetadata getDefaultImageMetadata(
425:                    ImageTypeSpecifier imageType, ImageWriteParam param) {
426:                return null;
427:            }
428:
429:            public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
430:                return null;
431:            }
432:
433:            /* XXX
434:            protected int getSignificantBits(RenderedImage image) {
435:                SampleModel sampleModel = image.getSampleModel();
436:                int numBands = sampleModel.getNumBands();
437:                int[] sampleSize = sampleModel.getSampleSize();
438:                int significantBits = sampleSize[0];
439:                for(int i = 1; i < numBands; i++) {
440:                    significantBits = Math.max(significantBits, sampleSize[i]);
441:                }
442:
443:                return significantBits;
444:            }
445:             */
446:
447:            // Code copied from ImageReader.java with ImageReadParam replaced
448:            // by ImageWriteParam.
449:            private static final Rectangle getSourceRegion(
450:                    ImageWriteParam param, int sourceMinX, int sourceMinY,
451:                    int srcWidth, int srcHeight) {
452:                Rectangle sourceRegion = new Rectangle(sourceMinX, sourceMinY,
453:                        srcWidth, srcHeight);
454:                if (param != null) {
455:                    Rectangle region = param.getSourceRegion();
456:                    if (region != null) {
457:                        sourceRegion = sourceRegion.intersection(region);
458:                    }
459:
460:                    int subsampleXOffset = param.getSubsamplingXOffset();
461:                    int subsampleYOffset = param.getSubsamplingYOffset();
462:                    sourceRegion.x += subsampleXOffset;
463:                    sourceRegion.y += subsampleYOffset;
464:                    sourceRegion.width -= subsampleXOffset;
465:                    sourceRegion.height -= subsampleYOffset;
466:                }
467:
468:                return sourceRegion;
469:            }
470:
471:            /**
472:             * Returns a <code>mediaLibImage</code> for a specific encoder to use
473:             * to encode <code>image</code>.
474:             *
475:             * @param image The image to encode.
476:             * @param param The write parameters.
477:             * @param allowBilevel Whether bilevel images are allowed. A bilevel
478:             * image must have one 1-bit sample per pixel, have data type
479:             * <code>DataBuffer.TYE_BYTE</code>, and have a
480:             * <code>MultiPixelPackedSampleModel</code>.
481:             * @param supportedFormats An array containing constan values from
482:             * the set of <code>mediaLibImage.MLIB_FORMAT</code> enums.
483:             *
484:             * @throws IllegalArgumentException if <code>supportedFormats</code>
485:             * is <code>null</code>.
486:             *
487:             * @return A <code>mediaLibImage in a format capable of being written
488:             * by the encoder.
489:             */
490:            protected mediaLibImage getMediaLibImage(RenderedImage image,
491:                    ImageWriteParam param, boolean allowBilevel,
492:                    int[] supportedFormats) {
493:                if (supportedFormats == null) {
494:                    throw new IllegalArgumentException(
495:                            "supportedFormats == null!");
496:                }
497:
498:                // Determine the source region.
499:                Rectangle sourceRegion = getSourceRegion(param,
500:                        image.getMinX(), image.getMinY(), image.getWidth(),
501:                        image.getHeight());
502:
503:                if (sourceRegion.isEmpty()) {
504:                    throw new IllegalArgumentException("sourceRegion.isEmpty()");
505:                }
506:
507:                // Check whether reformatting is necessary to conform to mediaLib
508:                // image format (packed bilevel if allowed or ((G|I)|(RGB))[A]).
509:
510:                // Flag indicating need to reformat data.
511:                boolean reformatData = false;
512:
513:                // Flag indicating bilevel data.
514:                boolean isBilevel = false;
515:
516:                // Value indicating the mediaLib image format.
517:                int mediaLibFormat = Constants.MLIB_FORMAT_UNKNOWN;
518:
519:                // Get the SampleModel.
520:                SampleModel sampleModel = image.getSampleModel();
521:
522:                // Get the number of bands.
523:                int numSourceBands = sampleModel.getNumBands();
524:
525:                // Get the source sub-banding array.
526:                int[] sourceBands = param != null ? param.getSourceBands()
527:                        : null;
528:
529:                // Check for non-nominal sub-banding.
530:                int numBands;
531:                if (sourceBands != null) {
532:                    numBands = sourceBands.length;
533:                    if (numBands != numSourceBands) {
534:                        // The number of bands must be the same.
535:                        reformatData = true;
536:                    } else {
537:                        // The band order must not change.
538:                        for (int i = 0; i < numSourceBands; i++) {
539:                            if (sourceBands[i] != i) {
540:                                reformatData = true;
541:                                break;
542:                            }
543:                        }
544:                    }
545:                } else {
546:                    numBands = numSourceBands;
547:                }
548:
549:                // If sub-banding does not dictate reformatting, check subsampling..
550:                if (!reformatData
551:                        && param != null
552:                        && (param.getSourceXSubsampling() != 1 || param
553:                                .getSourceXSubsampling() != 1)) {
554:                    reformatData = true;
555:                }
556:
557:                // If sub-banding does not dictate reformatting check SampleModel.
558:                if (!reformatData) {
559:                    if (allowBilevel
560:                            && sampleModel.getNumBands() == 1
561:                            && sampleModel.getSampleSize(0) == 1
562:                            && sampleModel instanceof  MultiPixelPackedSampleModel
563:                            && sampleModel.getDataType() == DataBuffer.TYPE_BYTE) {
564:                        // Need continguous packed bits.
565:                        MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel) sampleModel;
566:                        if (mppsm.getPixelBitStride() == 1) {
567:                            isBilevel = true;
568:                        } else {
569:                            reformatData = true;
570:                        }
571:                    } else {
572:                        // Set the mediaLib format flag.
573:                        mediaLibFormat = getMediaLibFormat(sampleModel, image
574:                                .getColorModel());
575:
576:                        // Set the data reformatting flag.
577:                        reformatData = true;
578:                        int len = supportedFormats.length;
579:                        for (int i = 0; i < len; i++) {
580:                            if (mediaLibFormat == supportedFormats[i]) {
581:                                reformatData = false;
582:                                break;
583:                            }
584:                        }
585:                    }
586:                }
587:
588:                // Variable for the eventual destination data.
589:                Raster raster = null;
590:
591:                if (reformatData) {
592:                    // Determine the maximum bit depth.
593:                    int[] sampleSize = sampleModel.getSampleSize();
594:                    int bitDepthMax = sampleSize[0];
595:                    for (int i = 1; i < numSourceBands; i++) {
596:                        bitDepthMax = Math.max(bitDepthMax, sampleSize[i]);
597:                    }
598:
599:                    // Set the data type as a function of bit depth.
600:                    int dataType;
601:                    if (bitDepthMax <= 8) {
602:                        dataType = DataBuffer.TYPE_BYTE;
603:                    } else if (bitDepthMax <= 16) {
604:                        dataType = DataBuffer.TYPE_USHORT;
605:                    } else {
606:                        throw new UnsupportedOperationException(I18N
607:                                .getString("CLibImageWriter0")
608:                                + " " + bitDepthMax);
609:                    }
610:
611:                    // Determine the width and height.
612:                    int width;
613:                    int height;
614:                    if (param != null) {
615:                        int subsampleX = param.getSourceXSubsampling();
616:                        int subsampleY = param.getSourceYSubsampling();
617:                        width = (sourceRegion.width + subsampleX - 1)
618:                                / subsampleX;
619:                        height = (sourceRegion.height + subsampleY - 1)
620:                                / subsampleY;
621:                    } else {
622:                        width = sourceRegion.width;
623:                        height = sourceRegion.height;
624:                    }
625:
626:                    // Load a ramp for band offsets.
627:                    int[] newBandOffsets = new int[numBands];
628:                    for (int i = 0; i < numBands; i++) {
629:                        newBandOffsets[i] = i;
630:                    }
631:
632:                    // Create a new SampleModel.
633:                    SampleModel newSampleModel;
634:                    if (allowBilevel && sampleModel.getNumBands() == 1
635:                            && bitDepthMax == 1) {
636:                        // Bilevel image.
637:                        newSampleModel = new MultiPixelPackedSampleModel(
638:                                dataType, width, height, 1);
639:                        isBilevel = true;
640:                    } else {
641:                        // Pixel interleaved image.
642:                        newSampleModel = new PixelInterleavedSampleModel(
643:                                dataType, width, height, newBandOffsets.length,
644:                                width * numSourceBands, newBandOffsets);
645:                    }
646:
647:                    // Create a new Raster at (0,0).
648:                    WritableRaster newRaster = Raster.createWritableRaster(
649:                            newSampleModel, null);
650:
651:                    // Populate the new Raster.
652:                    if (param != null
653:                            && (param.getSourceXSubsampling() != 1 || param
654:                                    .getSourceXSubsampling() != 1)) {
655:                        // Subsampling, possibly with sub-banding.
656:                        reformat(getContiguousData(image, sourceRegion),
657:                                sourceBands, param.getSourceXSubsampling(),
658:                                param.getSourceYSubsampling(), newRaster);
659:                    } else if (sourceBands == null
660:                            && image.getSampleModel().getClass().isInstance(
661:                                    newSampleModel)
662:                            && newSampleModel.getTransferType() == image
663:                                    .getSampleModel().getTransferType()) {
664:                        // Neither subsampling nor sub-banding.
665:                        WritableRaster translatedChild = newRaster
666:                                .createWritableTranslatedChild(sourceRegion.x,
667:                                        sourceRegion.y);
668:                        // Use copyData() to avoid potentially cobbling the entire
669:                        // source region into an extra Raster via getData().
670:                        image.copyData(translatedChild);
671:                    } else {
672:                        // Cannot use copyData() so use getData() to retrieve and
673:                        // possibly sub-band the source data and use setRect().
674:                        WritableRaster translatedChild = newRaster
675:                                .createWritableTranslatedChild(sourceRegion.x,
676:                                        sourceRegion.y);
677:                        Raster sourceRaster = getContiguousData(image,
678:                                sourceRegion);
679:                        if (sourceBands != null) {
680:                            // Copy only the requested bands.
681:                            sourceRaster = sourceRaster
682:                                    .createChild(sourceRegion.x,
683:                                            sourceRegion.y, sourceRegion.width,
684:                                            sourceRegion.height,
685:                                            sourceRegion.x, sourceRegion.y,
686:                                            sourceBands);
687:                        }
688:
689:                        // Get the region from the image and set it into the Raster.
690:                        translatedChild.setRect(sourceRaster);
691:                    }
692:
693:                    // Replace Raster and SampleModel.
694:                    raster = newRaster;
695:                    sampleModel = newRaster.getSampleModel();
696:                } else { // !reformatData
697:                    // No reformatting needed.
698:                    raster = getContiguousData(image, sourceRegion)
699:                            .createTranslatedChild(0, 0);
700:                    sampleModel = raster.getSampleModel();
701:
702:                    // Update mediaLibFormat indicator in case getContiguousData()
703:                    // has changed the layout of the data.
704:                    mediaLibFormat = getMediaLibFormat(sampleModel, image
705:                            .getColorModel());
706:                }
707:
708:                // The mediaLib image.
709:                mediaLibImage mlibImage = null;
710:
711:                // Create a mediaLibImage with reference to the Raster data.
712:                if (isBilevel) {
713:                    // Bilevel image: either is was already bilevel or was
714:                    // formatted to bilevel.
715:
716:                    MultiPixelPackedSampleModel mppsm = ((MultiPixelPackedSampleModel) sampleModel);
717:
718:                    // Get the line stride.
719:                    int stride = mppsm.getScanlineStride();
720:
721:                    // Determine the offset to the start of the data.
722:                    int offset = raster.getDataBuffer().getOffset()
723:                            - raster.getSampleModelTranslateY() * stride
724:                            - raster.getSampleModelTranslateX() / 8
725:                            + mppsm.getOffset(0, 0);
726:
727:                    // Get a reference to the internal data array.
728:                    Object bitData = getDataBufferData(raster.getDataBuffer());
729:
730:                    mlibImage = new mediaLibImage(mediaLibImage.MLIB_BIT, 1,
731:                            raster.getWidth(), raster.getHeight(), stride,
732:                            offset, (byte) mppsm.getBitOffset(0), bitData);
733:                } else {
734:                    // If the image is not bilevel then it has to be component.
735:                    ComponentSampleModel csm = (ComponentSampleModel) sampleModel;
736:
737:                    // Set the mediaLib data type
738:                    int mlibDataType = getMediaLibDataType(sampleModel
739:                            .getDataType());
740:
741:                    // Get a reference to the internal data array.
742:                    Object data = getDataBufferData(raster.getDataBuffer());
743:
744:                    // Get the line stride.
745:                    int stride = csm.getScanlineStride();
746:
747:                    // Determine the offset of the first sample from the offset
748:                    // indicated by the (x,y) coordinates. This offset is the
749:                    // minimum valued offset, not the offset of, e.g., red (index 0)
750:                    // as the Raster is by now in a contiguous format that
751:                    // the encoder is guaranteed to handle regardless of whether
752:                    // the smallest offset is to the, e.g., red band.
753:                    int[] bandOffsets = csm.getBandOffsets();
754:                    int minBandOffset = bandOffsets[0];
755:                    for (int i = 1; i < bandOffsets.length; i++) {
756:                        if (bandOffsets[i] < minBandOffset) {
757:                            minBandOffset = bandOffsets[i];
758:                        }
759:                    }
760:
761:                    // Determine the offset to the start of the data. The
762:                    // sampleModelTranslate parameters are the translations from
763:                    // Raster to SampleModel coordinates and must be subtracted
764:                    // from the Raster coordinates.
765:                    int offset = (raster.getMinY() - raster
766:                            .getSampleModelTranslateY())
767:                            * stride
768:                            + (raster.getMinX() - raster
769:                                    .getSampleModelTranslateX())
770:                            * numSourceBands + minBandOffset;
771:
772:                    // Create the image.
773:                    mlibImage = !reformatData
774:                            && mediaLibFormat != Constants.MLIB_FORMAT_UNKNOWN ? new mediaLibImage(
775:                            mlibDataType, numSourceBands, raster.getWidth(),
776:                            raster.getHeight(), stride, offset, mediaLibFormat,
777:                            data)
778:                            : new mediaLibImage(mlibDataType, numSourceBands,
779:                                    raster.getWidth(), raster.getHeight(),
780:                                    stride, offset, data);
781:                }
782:
783:                return mlibImage;
784:            }
785:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.