@@ -723,6 +723,7 @@ public class ICC_Profile implements Serializable {
723
723
*/
724
724
public static final int icXYZNumberX = 8 ; /* XYZNumber X */
725
725
726
+ private static final int HEADER_SIZE = 128 ;
726
727
727
728
/**
728
729
* Constructs an ICC_Profile object with a given ID.
@@ -767,6 +768,10 @@ public static ICC_Profile getInstance(byte[] data) {
767
768
ProfileDataVerifier .verify (data );
768
769
769
770
try {
771
+ byte [] theHeader = new byte [HEADER_SIZE ];
772
+ System .arraycopy (data , 0 , theHeader , 0 , HEADER_SIZE );
773
+ verifyHeader (theHeader );
774
+
770
775
p = CMSManager .getModule ().loadProfile (data );
771
776
} catch (CMMException c ) {
772
777
throw new IllegalArgumentException ("Invalid ICC Profile Data" );
@@ -1084,16 +1089,18 @@ public int getMinorVersion() {
1084
1089
* @return One of the predefined profile class constants.
1085
1090
*/
1086
1091
public int getProfileClass () {
1087
- byte [] theHeader ;
1088
- int theClassSig , theClass ;
1089
1092
1090
1093
ProfileDeferralInfo info = deferralInfo ;
1091
1094
if (info != null ) {
1092
1095
return info .profileClass ;
1093
1096
}
1094
1097
1095
- theHeader = getData (icSigHead );
1098
+ byte [] theHeader = getData (icSigHead );
1099
+ return getProfileClass (theHeader );
1100
+ }
1096
1101
1102
+ private static int getProfileClass (byte [] theHeader ) {
1103
+ int theClassSig , theClass ;
1097
1104
theClassSig = intFromBigEndian (theHeader , icHdrDeviceClass );
1098
1105
1099
1106
switch (theClassSig ) {
@@ -1163,6 +1170,11 @@ static int getColorSpaceType(Profile p) {
1163
1170
return theColorSpace ;
1164
1171
}
1165
1172
1173
+ private static int getColorSpaceType (byte [] theHeader ) {
1174
+ int theColorSpaceSig = intFromBigEndian (theHeader , icHdrColorSpace );
1175
+ return iccCStoJCS (theColorSpaceSig );
1176
+ }
1177
+
1166
1178
/**
1167
1179
* Returns the color space type of the Profile Connection Space (PCS).
1168
1180
* Returns one of the color space type constants defined by the
@@ -1192,6 +1204,29 @@ static int getPCSType(Profile p) {
1192
1204
}
1193
1205
1194
1206
1207
+ private static int getPCSType (byte [] theHeader ) {
1208
+ int thePCSSig = intFromBigEndian (theHeader , icHdrPcs );
1209
+ int theDeviceClass = intFromBigEndian (theHeader , icHdrDeviceClass );
1210
+ int thePCSType ;
1211
+
1212
+ if (theDeviceClass == icSigLinkClass ) {
1213
+ return iccCStoJCS (thePCSSig );
1214
+ } else {
1215
+ switch (thePCSSig ) {
1216
+ case icSigXYZData :
1217
+ thePCSType = ColorSpace .TYPE_XYZ ;
1218
+ break ;
1219
+ case icSigLabData :
1220
+ thePCSType = ColorSpace .TYPE_Lab ;
1221
+ break ;
1222
+ default :
1223
+ throw new IllegalArgumentException ("Unexpected PCS type" );
1224
+ };
1225
+ }
1226
+
1227
+ return thePCSType ;
1228
+ }
1229
+
1195
1230
/**
1196
1231
* Write this ICC_Profile to a file.
1197
1232
*
@@ -1316,12 +1351,49 @@ static byte[] getData(Profile p, int tagSignature) {
1316
1351
* @see #getData
1317
1352
*/
1318
1353
public void setData (int tagSignature , byte [] tagData ) {
1354
+ if (tagSignature == ICC_Profile .icSigHead ) {
1355
+ verifyHeader (tagData );
1356
+ }
1319
1357
1320
1358
activate ();
1321
1359
1322
1360
CMSManager .getModule ().setTagData (cmmProfile , tagSignature , tagData );
1323
1361
}
1324
1362
1363
+ private static void verifyHeader (byte [] data ) {
1364
+ if (data == null || data .length < HEADER_SIZE ) {
1365
+ throw new IllegalArgumentException ("Invalid header data" );
1366
+ }
1367
+ getProfileClass (data );
1368
+ getColorSpaceType (data );
1369
+ getPCSType (data );
1370
+ checkRenderingIntent (data );
1371
+ }
1372
+
1373
+ private static boolean checkRenderingIntent (byte [] header ) {
1374
+ int index = ICC_Profile .icHdrRenderingIntent ;
1375
+
1376
+ /* According to ICC spec, only the least-significant 16 bits shall be
1377
+ * used to encode the rendering intent. The most significant 16 bits
1378
+ * shall be set to zero. Thus, we are ignoring two most significant
1379
+ * bytes here. Please refer ICC Spec Document for more details.
1380
+ */
1381
+ int renderingIntent = ((header [index +2 ] & 0xff ) << 8 ) |
1382
+ (header [index +3 ] & 0xff );
1383
+
1384
+ switch (renderingIntent ) {
1385
+ case icPerceptual :
1386
+ case icMediaRelativeColorimetric :
1387
+ case icSaturation :
1388
+ case icAbsoluteColorimetric :
1389
+ break ;
1390
+ default :
1391
+ throw new IllegalArgumentException ("Unknown Rendering Intent" );
1392
+ }
1393
+
1394
+ return true ;
1395
+ }
1396
+
1325
1397
/**
1326
1398
* Sets the rendering intent of the profile.
1327
1399
* This is used to select the proper transform from a profile that
0 commit comments