1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 package com.lightcrafts.jai;
4 
5 import com.lightcrafts.jai.operator.*;
6 import com.lightcrafts.jai.opimage.*;
7 import com.lightcrafts.jai.utils.LCTileCache;
8 import com.lightcrafts.jai.utils.LCRecyclingTileFactory;
9 import com.lightcrafts.utils.ColorScience;
10 import com.lightcrafts.utils.ColorProfileInfo;
11 import com.lightcrafts.platform.Platform;
12 import com.lightcrafts.media.jai.util.SunTileCache;
13 
14 import com.lightcrafts.mediax.jai.*;
15 import com.lightcrafts.mediax.jai.registry.CRIFRegistry;
16 import com.lightcrafts.mediax.jai.registry.RIFRegistry;
17 import java.awt.*;
18 import java.awt.color.ColorSpace;
19 import java.awt.color.ICC_ColorSpace;
20 import java.awt.color.ICC_Profile;
21 import java.awt.image.*;
22 import java.awt.image.renderable.ContextualRenderedImageFactory;
23 import java.awt.image.renderable.RenderedImageFactory;
24 import java.io.*;
25 import java.util.Collection;
26 import java.util.ArrayList;
27 
28 /**
29  * Created by IntelliJ IDEA.
30  * User: fabio
31  * Date: Feb 27, 2005
32  * Time: 6:33:47 PM
33  * To change this template use File | Settings | File Templates.
34  */
35 public class JAIContext {
36     public static final Collection<ColorProfileInfo> systemProfiles;
37 
38     public static final ICC_Profile linearProfile;
39     public static final ICC_ColorSpace linearColorSpace;
40     public static final ICC_Profile labProfile;
41     public static final ICC_ColorSpace labColorSpace;
42     public static final ICC_Profile gray22Profile;
43     public static final ICC_ColorSpace gray22ColorSpace;
44     public static final ICC_Profile oldLinearProfile;
45     public static final ICC_ColorSpace oldLinearColorSpace;
46 
47     public static final ICC_Profile CMYKProfile;
48     public static final ICC_ColorSpace CMYKColorSpace;
49 
50     public static final ICC_Profile systemProfile;
51     public static final ColorSpace systemColorSpace;
52 
53     public static final ICC_ColorSpace linearGrayColorSpace = (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
54 
55     public static final ICC_ColorSpace sRGBColorSpace;
56     public static final ICC_Profile sRGBColorProfile;
57     public static final ICC_Profile sRGBExportColorProfile;
58 
59     public static final ICC_Profile adobeRGBProfile;
60     public static final ColorSpace adobeRGBColorSpace;
61 
62     public static final ColorModel colorModel_linear16;
63     public static final ColorModel colorModel_linear8;
64     public static final ColorModel colorModel_sRGB16;
65     public static final ColorModel colorModel_sRGB8;
66     public static final ColorModel systemColorModel;
67     public static final RenderingHints noCacheHint;
68     public static final String PERSISTENT_CACHE_TAG = "LCPersistentCache";
69     public static final TileCache noTileCache = new SunTileCache(0);
70     public static final RenderingHints fileCacheHint;
71     public static final TileCache fileCache;
72     public static final TileCache defaultTileCache;
73 
74     /** Tile dimensions. */
75     public static final int TILE_WIDTH = 512;
76     public static final int TILE_HEIGHT = 512;
77 
78     // public static final int fastMode = DataBuffer.TYPE_BYTE;
79     // public static final int preciseMode = DataBuffer.TYPE_USHORT;
80 
dumpProperty(ICC_Profile profile, int tag, String name)81     static void dumpProperty(ICC_Profile profile, int tag, String name)
82     {
83         byte[] data = profile.getData(tag);
84         if (data != null) {
85             System.out.print(name + " (" + data.length + ") :");
86             for (byte aData : data)
87                 System.out.print(" " + (aData & 0xFF));
88             System.out.println();
89 
90             for (byte aData : data)
91                 System.out.print((char) (aData & 0xFF));
92             System.out.println();
93         } else {
94             System.out.println("no " + name + " info");
95         }
96     }
97 
98     /**
99      * Given a {@link ColorSpace} and a {@link Raster}, get the
100      * {@link ColorModel} for them.
101      *
102      * @param colorSpace The {@link ColorSpace}.
103      * @param raster The {@link Raster}.
104      * @return Returns the relevant {@link ColorModel} or <code>null</code> if
105      * none can be determined.
106      */
getColorModelFrom( ColorSpace colorSpace, Raster raster )107     public static ColorModel getColorModelFrom( ColorSpace colorSpace,
108                                                 Raster raster ) {
109         return new ComponentColorModel(
110             colorSpace, false, false, Transparency.OPAQUE,
111             raster.getSampleModel().getDataType()
112         );
113     }
114 
115     /**
116      * Given an {@link ICC_Profile} and a {@link Raster}, get the
117      * {@link ColorModel} for them.
118      *
119      * @param profile The {@link ICC_Profile}.
120      * @param raster The {@link Raster}.
121      * @return Returns the relevant {@link ColorModel} or <code>null</code> if
122      * none can be determined.
123      */
getColorModelFrom( ICC_Profile profile, Raster raster )124     public static ColorModel getColorModelFrom( ICC_Profile profile,
125                                                 Raster raster ) {
126         return getColorModelFrom(
127             getColorSpaceFrom( profile, raster ), raster
128         );
129     }
130 
131 
132     /**
133      * Given an {@link ICC_Profile} and a {@link Raster}, get the
134      * {@link ColorSpace} for them.
135      *
136      * @param profile The {@link ICC_Profile}.
137      * @param raster The {@link Raster}.
138      * @return Returns the relevant {@link ColorSpace} or <code>null</code> if
139      * none can be determined.
140      */
getColorSpaceFrom( ICC_Profile profile, Raster raster )141     public static ColorSpace getColorSpaceFrom( ICC_Profile profile,
142                                                 Raster raster ) {
143         if ( profile != null )
144             return new ICC_ColorSpace( profile );
145         switch ( raster.getSampleModel().getNumBands() ) {
146             case 1:
147                 return gray22ColorSpace;
148             case 3:
149                 return sRGBColorSpace;
150             case 4:
151                 return CMYKColorSpace;
152             default:
153                 return null;
154         }
155     }
156 
zlum(ICC_ColorSpace cs)157     static void zlum(ICC_ColorSpace cs) {
158         float[] zero;
159         synchronized (ColorSpace.class) {
160             zero = cs.fromCIEXYZ(new float[] {0, 0, 0});
161         }
162         System.out.println("zero: "  + zero[0] + " : " + zero[1] + " : " + zero[2]);
163         double zlum = ColorScience.Wr * zero[0] + ColorScience.Wg * zero[1] + ColorScience.Wb * zero[2];
164         System.out.println("zero lum: " + zlum);
165     }
166 
167     static {
168         final long maxMemory = Runtime.getRuntime().maxMemory();
169         System.out.printf("Max Memory:   %11d%n", maxMemory);
170         System.out.printf("Total Memory: %11d%n", Runtime.getRuntime().totalMemory());
171 
172         JAI jaiInstance = JAI.getDefaultInstance();
173 
174         // Use our own Tile Scheduler -- TODO: Needs more testing
175         // jaiInstance.setTileScheduler(new LCTileScheduler());
176 
177         int processors = Runtime.getRuntime().availableProcessors();
178 
179         String VMVersion[] = System.getProperty("java.version").split("[._]");
180         String OSArch = System.getProperty("os.arch");
181 
182         System.out.println("Running on " + processors + " processors");
183 
184         if (OSArch.equals("ppc") && Integer.parseInt(VMVersion[3]) < 7) {
185             processors = Math.min(processors, 2);
186             System.out.println("Old PPC Java, limiting to " + processors + " processors");
187         }
188 
189         // don't use more than 2 processors, it uses too much memory,
190         // and use 2 procs only if we have more than 750MB of heap
191 
192         final int MB = 1024 * 1024;
193 
194         if (maxMemory >= 400 * MB)
195             jaiInstance.getTileScheduler().setParallelism(processors);
196         else
197             jaiInstance.getTileScheduler().setParallelism(1);
198 
199         fileCache = new LCTileCache(maxMemory <= 1024 * MB ? maxMemory/2 : maxMemory -  512 * MB, true);
200         // fileCache.setMemoryThreshold(0.5f);
201         jaiInstance.setTileCache(fileCache);
202         fileCacheHint = new RenderingHints(JAI.KEY_TILE_CACHE, fileCache);
203         defaultTileCache = jaiInstance.getTileCache();
204 
205         TileFactory rtf = new LCRecyclingTileFactory();
jaiInstance.setRenderingHint(JAI.KEY_TILE_FACTORY, rtf)206         jaiInstance.setRenderingHint(JAI.KEY_TILE_FACTORY, rtf);
jaiInstance.setRenderingHint(JAI.KEY_TILE_RECYCLER, rtf)207         jaiInstance.setRenderingHint(JAI.KEY_TILE_RECYCLER, rtf);
208         // TODO: causes rendering artifacts
209         // jaiInstance.setRenderingHint(JAI.KEY_CACHED_TILE_RECYCLING_ENABLED, Boolean.TRUE);
210 
211         OperationRegistry or = jaiInstance.getOperationRegistry();
212 
213         // register LCColorConvert
214         OperationDescriptor desc = new LCColorConvertDescriptor();
215         or.registerDescriptor(desc);
216         ContextualRenderedImageFactory crif = new LCColorConvertCRIF();
RIFRegistry.register(or, desc.getName(), R, crif)217         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", crif);
CRIFRegistry.register(or, desc.getName(), crif)218         CRIFRegistry.register(or, desc.getName(), crif);
219 
220         // register LCMSColorConvert
221         desc = new LCMSColorConvertDescriptor();
222         or.registerDescriptor(desc);
223         crif = new LCMSColorConvertCRIF();
RIFRegistry.register(or, desc.getName(), R, crif)224         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", crif);
CRIFRegistry.register(or, desc.getName(), crif)225         CRIFRegistry.register(or, desc.getName(), crif);
226 
227         // register BlendOp
228         desc = new BlendDescriptor();
229         or.registerDescriptor(desc);
230         crif = new BlendCRIF();
RIFRegistry.register(or, desc.getName(), R, crif)231         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", crif);
CRIFRegistry.register(or, desc.getName(), crif)232         CRIFRegistry.register(or, desc.getName(), crif);
233 
234         // register LCSeparableConvolve
235         desc = new LCSeparableConvolveDescriptor();
236         or.registerDescriptor(desc);
237         RenderedImageFactory rif = new LCSeparableConvolveRIF();
RIFRegistry.register(or, desc.getName(), R, rif)238         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", rif);
239 
240         // register NOPOp
241         desc = new NOPDescriptor();
242         or.registerDescriptor(desc);
243         crif = new NOPCRIF();
RIFRegistry.register(or, desc.getName(), R, crif)244         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", crif);
CRIFRegistry.register(or, desc.getName(), crif)245         CRIFRegistry.register(or, desc.getName(), crif);
246 
247         // register UnSharpMaskOp
248         desc = new UnSharpMaskDescriptor();
249         or.registerDescriptor(desc);
250         crif = new UnSharpMaskCRIF();
RIFRegistry.register(or, desc.getName(), R, crif)251         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", crif);
CRIFRegistry.register(or, desc.getName(), crif)252         CRIFRegistry.register(or, desc.getName(), crif);
253 
254         // register LCErode
255         desc = new LCErodeDescriptor();
256         or.registerDescriptor(desc);
257         rif = new LCErodeRIF();
RIFRegistry.register(or, desc.getName(), R, rif)258         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", rif);
259 
260         // register RawAdjustments
261         desc = new RawAdjustmentsDescriptor();
262         or.registerDescriptor(desc);
263         rif = new RawAdjustmentsCRIF();
RIFRegistry.register(or, desc.getName(), R, rif)264         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", rif);
265 
266         // register LCBandCombine
267         desc = new LCBandCombineDescriptor();
268         or.registerDescriptor(desc);
269         rif = new LCBandCombineCRIF();
RIFRegistry.register(or, desc.getName(), R, rif)270         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", rif);
271 
272         // register LCBandCombine
273         desc = new BilateralFilterDescriptor();
274         or.registerDescriptor(desc);
275         rif = new BilateralFilterRIF();
RIFRegistry.register(or, desc.getName(), R, rif)276         RIFRegistry.register(or, desc.getName(), "com.lightcrafts", rif);
277 
JAI.setDefaultTileSize(new Dimension(JAIContext.TILE_WIDTH, JAIContext.TILE_HEIGHT))278         JAI.setDefaultTileSize(new Dimension(JAIContext.TILE_WIDTH, JAIContext.TILE_HEIGHT));
279 
280         systemProfiles = new ArrayList<ColorProfileInfo>();
281         final Collection<ColorProfileInfo> exportProfiles =
282             Platform.getPlatform().getExportProfiles();
283         if (exportProfiles != null) {
284             systemProfiles.addAll(exportProfiles);
285         }
286         final Collection<ColorProfileInfo> printerProfiles =
287             Platform.getPlatform().getPrinterProfiles();
288         if (printerProfiles != null) {
289             systemProfiles.addAll(printerProfiles);
290         }
291 
292         ICC_Profile _sRGBColorProfile = null;
293         for (ColorProfileInfo cpi : systemProfiles) {
294             if ((cpi.getName().equals("sRGB Profile") || cpi.getName().equals("sRGB IEC61966-2.1"))) {
295                 try {
296                     _sRGBColorProfile = ICC_Profile.getInstance(cpi.getPath());
297                     System.out.println("found " + cpi.getName());
298                     if (_sRGBColorProfile != null)
299                         break;
300                 } catch (IOException e) {
301                     e.printStackTrace();
302                 }
303             }
304         }
305 
306         if (_sRGBColorProfile == null) {
307             InputStream in = JAIContext.class.getResourceAsStream("resources/sRGB.icc");
308             try {
309                 _sRGBColorProfile = ICC_Profile.getInstance(in);
310             } catch (IOException e) {
311                 System.err.println("Can't load resource sRGB profile, defaulting on Java's");
312                 _sRGBColorProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
313             }
314         }
315         sRGBExportColorProfile = _sRGBColorProfile;
316 
317         sRGBColorProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
318         sRGBColorSpace = (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
319 
320         ICC_Profile _linearProfile;
321         ICC_Profile _oldLinearProfile;
322         ICC_Profile _labProfile;
323         // ICC_Profile _uniformLabProfile;
324         ICC_Profile _gray22Profile;
325         ICC_Profile _adobeRGBProfile;
326         ICC_ColorSpace _linearColorSpace;
327         ICC_ColorSpace _oldLinearColorSpace;
328         ICC_ColorSpace _labColorSpace;
329         // ICC_ColorSpace _uniformLabColorSpace;
330         ICC_ColorSpace _gray22ColorSpace;
331         ICC_ColorSpace _adobeRGBColorSpace;
332         ColorModel _colorModel_linear16;
333         ColorModel _colorModel_linear8;
334         ColorModel _colorModel_sRGB16;
335         ColorModel _colorModel_sRGB8;
336 
337         ICC_Profile _CMYKProfile;
338         ICC_ColorSpace _CMYKColorSpace;
339 
340         RenderingHints _noCacheHint;
341 
342         ICC_Profile _systemProfile;
343         ICC_ColorSpace _systemColorSpace;
344         ColorModel _systemColorModel;
345 
346         try {
347             InputStream in = JAIContext.class.getResourceAsStream("resources/rimm.icm");
348             _linearProfile = ICC_Profile.getInstance(in);
349             _linearColorSpace = new ICC_ColorSpace(_linearProfile);
350 
351             in = JAIContext.class.getResourceAsStream("resources/CIE 1931 D50 Gamma 1.icm");
352             _oldLinearProfile = ICC_Profile.getInstance(in);
353             _oldLinearColorSpace = new ICC_ColorSpace(_linearProfile);
354 
355             in = JAIContext.class.getResourceAsStream("resources/Generic CMYK Profile.icc");
356             _CMYKProfile = ICC_Profile.getInstance(in);
357             _CMYKColorSpace = new ICC_ColorSpace(_CMYKProfile);
358 
359             in = JAIContext.class.getResourceAsStream("resources/Generic Lab Profile.icm");
360             _labProfile = ICC_Profile.getInstance(in);
361             _labColorSpace = new ICC_ColorSpace(_labProfile);
362 
363             in = JAIContext.class.getResourceAsStream("resources/Gray Gamma 2.2.icc");
364             _gray22Profile = ICC_Profile.getInstance(in);
365             _gray22ColorSpace = new ICC_ColorSpace(_gray22Profile);
366 
367             in = JAIContext.class.getResourceAsStream("resources/compatibleWithAdobeRGB1998.icc");
368             _adobeRGBProfile = ICC_Profile.getInstance(in);
369             _adobeRGBColorSpace = new ICC_ColorSpace(_adobeRGBProfile);
370 
371             _colorModel_linear16 =
372                     RasterFactory.createComponentColorModel(DataBuffer.TYPE_USHORT,
373                             _linearColorSpace,
374                             false,
375                             false,
376                             Transparency.OPAQUE);
377             _colorModel_linear8 =
378                     RasterFactory.createComponentColorModel(DataBuffer.TYPE_BYTE,
379                             _linearColorSpace,
380                             false,
381                             false,
382                             Transparency.OPAQUE);
383             _colorModel_sRGB16 =
384                     RasterFactory.createComponentColorModel(DataBuffer.TYPE_USHORT,
385                             JAIContext.sRGBColorSpace,
386                             false,
387                             false,
388                             Transparency.OPAQUE);
389             _colorModel_sRGB8 =
390                     RasterFactory.createComponentColorModel(DataBuffer.TYPE_BYTE,
391                             JAIContext.sRGBColorSpace,
392                             false,
393                             false,
394                             Transparency.OPAQUE);
395 
396             _systemColorSpace = sRGBColorSpace;
397             _systemColorModel = _colorModel_sRGB8;
398             _systemProfile = _sRGBColorProfile;
399 
400             try {
401                 final ICC_Profile displayProfile = Platform.getPlatform().getDisplayProfile();
402                 if (displayProfile != null) {
403                     _systemProfile = displayProfile;
404                     _systemColorSpace = new ICC_ColorSpace(_systemProfile);
405                     _systemColorModel = RasterFactory.createComponentColorModel(DataBuffer.TYPE_BYTE,
406                                                                                 _systemColorSpace,
407                                                                                 false,
408                                                                                 false,
409                                                                                 Transparency.OPAQUE);
410                 }
411             } catch (Exception e) {
412                 e.printStackTrace();
413             }
414 
415             _noCacheHint = new RenderingHints(JAI.KEY_TILE_CACHE, noTileCache);
416             // _noCacheHint = new RenderingHints(JAI.KEY_TILE_CACHE, defaultTileCache);
417         } catch (IOException e) {
418             e.printStackTrace();
419             // Rethrow so the Application will notice the problem:
420             throw new RuntimeException(
421                 "Couldn't access color space resource",
422                 e
423             );
424         }
425         linearProfile = _linearProfile;
426         linearColorSpace = _linearColorSpace;
427 
428         oldLinearProfile = _oldLinearProfile;
429         oldLinearColorSpace = _oldLinearColorSpace;
430 
431         colorModel_linear16 = _colorModel_linear16;
432         colorModel_linear8 = _colorModel_linear8;
433         colorModel_sRGB16 = _colorModel_sRGB16;
434         colorModel_sRGB8 = _colorModel_sRGB8;
435 
436         CMYKProfile = _CMYKProfile;
437         CMYKColorSpace = _CMYKColorSpace;
438 
439         labProfile = _labProfile;
440         labColorSpace = _labColorSpace;
441 
442         gray22Profile = _gray22Profile;
443         gray22ColorSpace = _gray22ColorSpace;
444 
445         adobeRGBProfile = _adobeRGBProfile;
446         adobeRGBColorSpace = _adobeRGBColorSpace;
447 
448         systemProfile = _systemProfile;
449 
450         systemColorSpace = _systemColorSpace;
451         systemColorModel = _systemColorModel;
452 
453         noCacheHint = _noCacheHint;
454     }
455 }
456 /* vim:set et sw=4 ts=4: */
457