Source for gnu.java.awt.color.ProfileHeader

   1: /* ProfileHeader.java -- Encapsules ICC Profile header data
   2:    Copyright (C) 2004 Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.awt.color;
  39: 
  40: import java.awt.color.ColorSpace;
  41: import java.awt.color.ICC_Profile;
  42: import java.nio.ByteBuffer;
  43: 
  44: 
  45: /**
  46:  * Header, abstracts and validates the header data.
  47:  *
  48:  * @author Sven de Marothy
  49:  */
  50: public class ProfileHeader
  51: {
  52:   /**
  53:    * Magic identifier (ASCII 'acsp')
  54:    */
  55:   private static final int icMagicNumber = 0x61637370;
  56: 
  57:   /**
  58:    * Mapping from ICC Profile signatures to ColorSpace types
  59:    */
  60:   private static final int[] csTypeMap =
  61:                                          {
  62:                                            ICC_Profile.icSigXYZData,
  63:                                            ColorSpace.TYPE_XYZ,
  64:                                            ICC_Profile.icSigLabData,
  65:                                            ColorSpace.TYPE_Lab,
  66:                                            ICC_Profile.icSigLuvData,
  67:                                            ColorSpace.TYPE_Luv,
  68:                                            ICC_Profile.icSigYCbCrData,
  69:                                            ColorSpace.TYPE_YCbCr,
  70:                                            ICC_Profile.icSigYxyData,
  71:                                            ColorSpace.TYPE_Yxy,
  72:                                            ICC_Profile.icSigRgbData,
  73:                                            ColorSpace.TYPE_RGB,
  74:                                            ICC_Profile.icSigGrayData,
  75:                                            ColorSpace.TYPE_GRAY,
  76:                                            ICC_Profile.icSigHsvData,
  77:                                            ColorSpace.TYPE_HSV,
  78:                                            ICC_Profile.icSigHlsData,
  79:                                            ColorSpace.TYPE_HLS,
  80:                                            ICC_Profile.icSigCmykData,
  81:                                            ColorSpace.TYPE_CMYK,
  82:                                            ICC_Profile.icSigCmyData,
  83:                                            ColorSpace.TYPE_CMY,
  84:                                            ICC_Profile.icSigSpace2CLR,
  85:                                            ColorSpace.TYPE_2CLR,
  86:                                            ICC_Profile.icSigSpace3CLR,
  87:                                            ColorSpace.TYPE_3CLR,
  88:                                            ICC_Profile.icSigSpace4CLR,
  89:                                            ColorSpace.TYPE_4CLR,
  90:                                            ICC_Profile.icSigSpace5CLR,
  91:                                            ColorSpace.TYPE_5CLR,
  92:                                            ICC_Profile.icSigSpace6CLR,
  93:                                            ColorSpace.TYPE_6CLR,
  94:                                            ICC_Profile.icSigSpace7CLR,
  95:                                            ColorSpace.TYPE_7CLR,
  96:                                            ICC_Profile.icSigSpace8CLR,
  97:                                            ColorSpace.TYPE_8CLR,
  98:                                            ICC_Profile.icSigSpace9CLR,
  99:                                            ColorSpace.TYPE_9CLR,
 100:                                            ICC_Profile.icSigSpaceACLR,
 101:                                            ColorSpace.TYPE_ACLR,
 102:                                            ICC_Profile.icSigSpaceBCLR,
 103:                                            ColorSpace.TYPE_BCLR,
 104:                                            ICC_Profile.icSigSpaceCCLR,
 105:                                            ColorSpace.TYPE_CCLR,
 106:                                            ICC_Profile.icSigSpaceDCLR,
 107:                                            ColorSpace.TYPE_DCLR,
 108:                                            ICC_Profile.icSigSpaceECLR,
 109:                                            ColorSpace.TYPE_ECLR,
 110:                                            ICC_Profile.icSigSpaceFCLR,
 111:                                            ColorSpace.TYPE_FCLR
 112:                                          };
 113: 
 114:   /**
 115:    * Size of an ICC header (128 bytes)
 116:    */
 117:   public static final int HEADERSIZE = 128;
 118: 
 119:   /**
 120:    * Mapping of ICC class signatures to profile class constants
 121:    */
 122:   private static final int[] classMap =
 123:                                         {
 124:                                           ICC_Profile.icSigInputClass,
 125:                                           ICC_Profile.CLASS_INPUT,
 126:                                           ICC_Profile.icSigDisplayClass,
 127:                                           ICC_Profile.CLASS_DISPLAY,
 128:                                           ICC_Profile.icSigOutputClass,
 129:                                           ICC_Profile.CLASS_OUTPUT,
 130:                                           ICC_Profile.icSigLinkClass,
 131:                                           ICC_Profile.CLASS_DEVICELINK,
 132:                                           ICC_Profile.icSigColorSpaceClass,
 133:                                           ICC_Profile.CLASS_COLORSPACECONVERSION,
 134:                                           ICC_Profile.icSigAbstractClass,
 135:                                           ICC_Profile.CLASS_ABSTRACT,
 136:                                           ICC_Profile.icSigNamedColorClass,
 137:                                           ICC_Profile.CLASS_NAMEDCOLOR
 138:                                         };
 139:   private int size;
 140:   private int cmmId;
 141: 
 142:   // Major/Minor version, The ICC-1998 spec is major v2
 143:   private int majorVersion;
 144: 
 145:   // Major/Minor version, The ICC-1998 spec is major v2
 146:   private int minorVersion;
 147:   private int profileClass; // profile device class
 148:   private int colorSpace; // data color space type
 149:   private int profileColorSpace; // profile connection space (PCS) type
 150:   private byte[] timestamp; // original creation timestamp
 151:   private int platform; // platform signature
 152:   private int flags; // flags
 153:   private int magic; // magic number.
 154:   private int manufacturerSig; // manufacturer sig
 155:   private int modelSig; // model sig
 156:   private byte[] attributes; // Attributes
 157:   private int intent; // rendering intent
 158:   private byte[] illuminant; // illuminant info (Coordinates of D50 in the PCS)
 159:   private int creatorSig; // Creator sig (same type as manufacturer)
 160: 
 161:   /**
 162:    * Creates a 'default' header for use with our predefined profiles.
 163:    * Note the device and profile color spaces are not set.
 164:    */
 165:   public ProfileHeader()
 166:   {
 167:     creatorSig = 0;
 168:     intent = 0;
 169:     modelSig = manufacturerSig = (int) 0x6E6f6E65; // 'none'
 170:     magic = icMagicNumber;
 171:     cmmId = 0;
 172:     platform = 0; // no preferred platform
 173:     timestamp = new byte[8];
 174:     majorVersion = 2;
 175:     minorVersion = 0x10;
 176:     flags = 0;
 177: 
 178:     // D50 in XYZ format (encoded)
 179:     illuminant = new byte[]
 180:                  {
 181:                    (byte) 0x00, (byte) 0x00, (byte) 0xf6, (byte) 0xd6,
 182:                    (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
 183:                    (byte) 0x00, (byte) 0x00, (byte) 0xd3, (byte) 0x2d
 184:                  };
 185:     attributes = new byte[8];
 186:     profileClass = ICC_Profile.CLASS_DISPLAY;
 187:   }
 188: 
 189:   /**
 190:    * Creates a header from profile data. Only the header portion (128 bytes)
 191:    * is read, so the array passed need not be the full profile.
 192:    */
 193:   public ProfileHeader(byte[] data)
 194:   {
 195:     ByteBuffer buf = ByteBuffer.wrap(data);
 196: 
 197:     // Get size (the sign bit shouldn't matter.
 198:     // A valid profile can never be +2Gb)
 199:     size = buf.getInt(ICC_Profile.icHdrSize);
 200: 
 201:     // CMM ID
 202:     cmmId = buf.getInt(ICC_Profile.icHdrCmmId);
 203: 
 204:     // Version number
 205:     majorVersion = (int) (data[ICC_Profile.icHdrVersion]);
 206:     minorVersion = (int) (data[ICC_Profile.icHdrVersion + 1]);
 207: 
 208:     // Profile/Device class
 209:     int classSig = buf.getInt(ICC_Profile.icHdrDeviceClass);
 210:     profileClass = -1;
 211:     for (int i = 0; i < classMap.length; i += 2)
 212:       if (classMap[i] == classSig)
 213:         {
 214:           profileClass = classMap[i + 1];
 215:           break;
 216:         }
 217: 
 218:     // get the data color space
 219:     int csSig = buf.getInt(ICC_Profile.icHdrColorSpace);
 220:     colorSpace = -1;
 221:     for (int i = 0; i < csTypeMap.length; i += 2)
 222:       if (csTypeMap[i] == csSig)
 223:         {
 224:           colorSpace = csTypeMap[i + 1];
 225:           break;
 226:         }
 227: 
 228:     // get the profile color space (PCS), must be xyz or lab except
 229:     // for device-link-class profiles
 230:     int pcsSig = buf.getInt(ICC_Profile.icHdrPcs);
 231:     profileColorSpace = -1;
 232:     if (profileClass != ICC_Profile.CLASS_DEVICELINK)
 233:       {
 234:         if (pcsSig == ICC_Profile.icSigXYZData)
 235:           profileColorSpace = ColorSpace.TYPE_XYZ;
 236:         if (pcsSig == ICC_Profile.icSigLabData)
 237:           profileColorSpace = ColorSpace.TYPE_Lab;
 238:       }
 239:     else
 240:       {
 241:         for (int i = 0; i < csTypeMap.length; i += 2)
 242:           if (csTypeMap[i] == pcsSig)
 243:             {
 244:               profileColorSpace = csTypeMap[i + 1];
 245:               break;
 246:             }
 247:       }
 248: 
 249:     // creation timestamp
 250:     timestamp = new byte[8];
 251:     System.arraycopy(data, ICC_Profile.icHdrDate, timestamp, 0, 8);
 252: 
 253:     // magic number
 254:     magic = buf.getInt(ICC_Profile.icHdrMagic);
 255: 
 256:     //  platform info
 257:     platform = buf.getInt(ICC_Profile.icHdrPlatform);
 258:     // get flags
 259:     flags = buf.getInt(ICC_Profile.icHdrFlags);
 260:     // get manufacturer sign
 261:     manufacturerSig = buf.getInt(ICC_Profile.icHdrManufacturer);
 262:     // get header model
 263:     modelSig = buf.getInt(ICC_Profile.icHdrModel);
 264:     // attributes
 265:     attributes = new byte[8];
 266:     System.arraycopy(data, ICC_Profile.icHdrAttributes, attributes, 0, 8);
 267:     // rendering intent
 268:     intent = buf.getInt(ICC_Profile.icHdrRenderingIntent);
 269:     // illuminant info
 270:     illuminant = new byte[12];
 271:     System.arraycopy(data, ICC_Profile.icHdrIlluminant, illuminant, 0, 12);
 272:     // Creator signature
 273:     creatorSig = buf.getInt(ICC_Profile.icHdrCreator);
 274:     // The rest of the header (Total size: 128 bytes) is unused..
 275:   }
 276: 
 277:   /**
 278:    * Verify that the header is valid
 279:    * @param size equals the file size if it is to be verified, -1 otherwise
 280:    * @throws IllegalArgumentException if the header is found to be invalid.
 281:    */
 282:   public void verifyHeader(int size) throws IllegalArgumentException
 283:   {
 284:     // verify size
 285:     if (size != -1 && this.size != size)
 286:       throw new IllegalArgumentException("Invalid profile length:" + size);
 287: 
 288:     // Check version number
 289:     if (majorVersion != 2)
 290:       throw new IllegalArgumentException("Wrong major version number:"
 291:                                          + majorVersion);
 292: 
 293:     // Profile/Device class
 294:     if (profileClass == -1)
 295:       throw new IllegalArgumentException("Invalid profile/device class");
 296: 
 297:     // get the data color space
 298:     if (colorSpace == -1)
 299:       throw new IllegalArgumentException("Invalid colorspace");
 300: 
 301:     // profile color space
 302:     if (profileColorSpace == -1)
 303:       throw new IllegalArgumentException("Invalid PCS.");
 304: 
 305:     // check magic number
 306:     if (magic != icMagicNumber)
 307:       throw new IllegalArgumentException("Invalid magic number!");
 308:   }
 309: 
 310:   /**
 311:    * Creates a header, setting the header file size at the same time.
 312:    * @param size the profile file size.
 313:    */
 314:   public byte[] getData(int size)
 315:   {
 316:     byte[] data = new byte[HEADERSIZE];
 317:     ByteBuffer buf = ByteBuffer.wrap(data);
 318:     buf.putInt(ICC_Profile.icHdrSize, size);
 319:     buf.putInt(ICC_Profile.icHdrCmmId, cmmId);
 320:     buf.putShort(ICC_Profile.icHdrVersion,
 321:                  (short) (majorVersion << 8 | minorVersion));
 322:     for (int i = 1; i < classMap.length; i += 2)
 323:       if (profileClass == classMap[i])
 324:         buf.putInt(ICC_Profile.icHdrDeviceClass, classMap[i - 1]);
 325:     for (int i = 1; i < csTypeMap.length; i += 2)
 326:       if (csTypeMap[i] == colorSpace)
 327:         buf.putInt(ICC_Profile.icHdrColorSpace, csTypeMap[i - 1]);
 328:     for (int i = 1; i < csTypeMap.length; i += 2)
 329:       if (csTypeMap[i] == profileColorSpace)
 330:         buf.putInt(ICC_Profile.icHdrPcs, csTypeMap[i - 1]);
 331: 
 332:     System.arraycopy(timestamp, 0, data, ICC_Profile.icHdrDate,
 333:                      timestamp.length);
 334:     buf.putInt(ICC_Profile.icHdrMagic, icMagicNumber);
 335:     buf.putInt(ICC_Profile.icHdrPlatform, platform);
 336:     buf.putInt(ICC_Profile.icHdrFlags, flags);
 337:     buf.putInt(ICC_Profile.icHdrManufacturer, manufacturerSig);
 338:     buf.putInt(ICC_Profile.icHdrModel, modelSig);
 339:     System.arraycopy(attributes, 0, data, ICC_Profile.icHdrAttributes,
 340:                      attributes.length);
 341:     buf.putInt(ICC_Profile.icHdrRenderingIntent, intent);
 342:     System.arraycopy(illuminant, 0, data, ICC_Profile.icHdrIlluminant,
 343:                      illuminant.length);
 344:     buf.putInt(ICC_Profile.icHdrCreator, creatorSig);
 345:     return buf.array();
 346:   }
 347: 
 348:   public int getSize()
 349:   {
 350:     return size;
 351:   }
 352: 
 353:   public void setSize(int s)
 354:   {
 355:     size = s;
 356:   }
 357: 
 358:   public int getMajorVersion()
 359:   {
 360:     return majorVersion;
 361:   }
 362: 
 363:   public int getMinorVersion()
 364:   {
 365:     return minorVersion;
 366:   }
 367: 
 368:   public int getProfileClass()
 369:   {
 370:     return profileClass;
 371:   }
 372: 
 373:   public void setProfileClass(int pc)
 374:   {
 375:     profileClass = pc;
 376:   }
 377: 
 378:   public int getColorSpace()
 379:   {
 380:     return colorSpace;
 381:   }
 382: 
 383:   public int getProfileColorSpace()
 384:   {
 385:     return profileColorSpace;
 386:   }
 387: 
 388:   public void setColorSpace(int cs)
 389:   {
 390:     colorSpace = cs;
 391:   }
 392: 
 393:   public void setProfileColorSpace(int pcs)
 394:   {
 395:     profileColorSpace = pcs;
 396:   }
 397: 
 398: }