public ColorModel createColorModel() { int[] bits; if (hasAlpha) bits = new int[cspace.getNumComponents() + 1]; else bits = new int[cspace.getNumComponents()]; Arrays.fill(bits, 8); return new ComponentColorModel(cspace, bits, hasAlpha, alphaPre, transparency, transferType); }
// Create an appropriate array of bits, given a colorspace (ie, number of // bands), size of the storage data type, and presence of an alpha band. private static int[] findBits(ColorSpace colorSpace, int transferType, boolean hasAlpha) { int[] bits; if (hasAlpha) bits = new int[colorSpace.getNumComponents() + 1]; else bits = new int[colorSpace.getNumComponents()]; Arrays.fill(bits, DataBuffer.getDataTypeSize(transferType)); return bits; }
/** * Creates a color in the specified <code>ColorSpace</code> with the color components specified in * the <code>float</code> array and the specified alpha. The number of components is determined by * the type of the <code>ColorSpace</code>. For example, RGB requires 3 components, but CMYK * requires 4 components. * * @param cspace the <code>ColorSpace</code> to be used to interpret the components * @param components an arbitrary number of color components that is compatible with the <code> * ColorSpace</code> * @param alpha alpha value * @throws IllegalArgumentException if any of the values in the <code>components</code> array or * <code>alpha</code> is outside of the range supported by cspace. * @see #getComponents * @see #getColorComponents */ public CompositeColor(ColorSpace cspace, float components[], float alpha) { super(((int) (alpha * 255) << 24) | ColorUtil.toRGB24(cspace, components), true); boolean rangeError = false; StringBuilder badComponentString = new StringBuilder(); int n = cspace.getNumComponents(); fvalue = new float[n]; for (int i = 0; i < n; i++) { if (components[i] < cspace.getMinValue(i) || components[i] > cspace.getMaxValue(i)) { rangeError = true; badComponentString.append("Component "); badComponentString.append(i); badComponentString.append(' '); } else { fvalue[i] = components[i]; } } if (alpha < 0.0 || alpha > 1.0) { rangeError = true; badComponentString.append("Alpha"); } else { falpha = alpha; } if (rangeError) { throw new IllegalArgumentException( "Color parameter outside of expected range: " + badComponentString); } cs = cspace; }
private static int calculateColor(float[] f, ColorSpace colorSpace) { int n = colorSpace.getNumComponents(); // Get the reverse of f, and only take n values // Might as well limit the bounds while we're at it float[] fvalue = new float[n]; int toCopy = n; int fLength = f.length; if (fLength < toCopy) { toCopy = fLength; } for (int i = 0; i < toCopy; i++) { float curr = f[fLength - 1 - i]; if (curr < 0.0f) { curr = 0.0f; } else if (curr > 1.0f) { curr = 1.0f; } fvalue[i] = curr; } float[] frgbvalue = colorSpace.toRGB(fvalue); return (0xFF000000) | ((((int) (frgbvalue[0] * 255)) & 0xFF) << 16) | ((((int) (frgbvalue[1] * 255)) & 0xFF) << 8) | ((((int) (frgbvalue[2] * 255)) & 0xFF)); }
private ICC_Profile buildICCProfile( final ImageInfo info, final ColorSpace colorSpace, final ByteArrayOutputStream iccStream) throws IOException { if (iccStream != null && iccStream.size() > 0) { if (log.isDebugEnabled()) { log.debug("Effective ICC profile size: " + iccStream.size()); } final int alignment = 4; final int padding = (alignment - iccStream.size() % alignment) % alignment; if (padding != 0) { try { iccStream.write(new byte[padding]); } catch (final IOException ioe) { throw new IOException("Error while aligning ICC stream: " + ioe.getMessage()); } } ICC_Profile iccProfile = null; try { iccProfile = ColorProfileUtil.getICC_Profile(iccStream.toByteArray()); if (log.isDebugEnabled()) { log.debug("JPEG has an ICC profile: " + iccProfile.toString()); } } catch (final IllegalArgumentException iae) { log.warn( "An ICC profile is present in the JPEG file but it is invalid (" + iae.getMessage() + "). The color profile will be ignored. (" + info.getOriginalURI() + ")"); return null; } if (iccProfile.getNumComponents() != colorSpace.getNumComponents()) { log.warn( "The number of components of the ICC profile (" + iccProfile.getNumComponents() + ") doesn't match the image (" + colorSpace.getNumComponents() + "). Ignoring the ICC color profile."); return null; } else { return iccProfile; } } else { return null; // no ICC profile available } }
public Iterator getImageTypes(int imageIndex) throws IIOException { List l; // List of ImageTypeSpecifiers Integer imageIndexInteger = new Integer(imageIndex); if (imageTypeMap.containsKey(imageIndexInteger)) { // Return the cached ITS List. l = (List) imageTypeMap.get(imageIndexInteger); } else { // Create a new ITS List. l = new ArrayList(1); // Create the ITS and cache if for later use so that this method // always returns an Iterator containing the same ITS objects. seekToImage(imageIndex); ImageTypeSpecifier itsRaw = TIFFDecompressor.getRawImageTypeSpecifier( photometricInterpretation, compression, samplesPerPixel, bitsPerSample, sampleFormat, extraSamples, colorMap); // Check for an ICCProfile field. TIFFField iccProfileField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE); // If an ICCProfile field is present change the ImageTypeSpecifier // to use it if the data layout is component type. if (iccProfileField != null && itsRaw.getColorModel() instanceof ComponentColorModel) { // Create a ColorSpace from the profile. byte[] iccProfileValue = iccProfileField.getAsBytes(); ICC_Profile iccProfile = ICC_Profile.getInstance(iccProfileValue); ICC_ColorSpace iccColorSpace = new ICC_ColorSpace(iccProfile); // Get the raw sample and color information. ColorModel cmRaw = itsRaw.getColorModel(); ColorSpace csRaw = cmRaw.getColorSpace(); SampleModel smRaw = itsRaw.getSampleModel(); // Get the number of samples per pixel and the number // of color components. int numBands = smRaw.getNumBands(); int numComponents = iccColorSpace.getNumComponents(); // Replace the ColorModel with the ICC ColorModel if the // numbers of samples and color components are amenable. if (numBands == numComponents || numBands == numComponents + 1) { // Set alpha flags. boolean hasAlpha = numComponents != numBands; boolean isAlphaPre = hasAlpha && cmRaw.isAlphaPremultiplied(); // Create a ColorModel of the same class and with // the same transfer type. ColorModel iccColorModel = new ComponentColorModel( iccColorSpace, cmRaw.getComponentSize(), hasAlpha, isAlphaPre, cmRaw.getTransparency(), cmRaw.getTransferType()); // Prepend the ICC profile-based ITS to the List. The // ColorModel and SampleModel are guaranteed to be // compatible as the old and new ColorModels are both // ComponentColorModels with the same transfer type // and the same number of components. l.add(new ImageTypeSpecifier(iccColorModel, smRaw)); // Append the raw ITS to the List if and only if its // ColorSpace has the same type and number of components // as the ICC ColorSpace. if (csRaw.getType() == iccColorSpace.getType() && csRaw.getNumComponents() == iccColorSpace.getNumComponents()) { l.add(itsRaw); } } else { // ICCProfile not compatible with SampleModel. // Append the raw ITS to the List. l.add(itsRaw); } } else { // No ICCProfile field or raw ColorModel not component. // Append the raw ITS to the List. l.add(itsRaw); } // Cache the ITS List. imageTypeMap.put(imageIndexInteger, l); } return l.iterator(); }
/** * get a Java ColorModel consistent with the current color space, number of bits per component and * decode array * * @param bpc the number of bits per component */ private ColorModel getColorModel() { PDFColorSpace cs = getColorSpace(); if (cs instanceof IndexedColor) { IndexedColor ics = (IndexedColor) cs; byte[] components = ics.getColorComponents(); int num = ics.getCount(); // process the decode array if (this.decode != null) { byte[] normComps = new byte[components.length]; // move the components array around for (int i = 0; i < num; i++) { byte[] orig = new byte[1]; orig[0] = (byte) i; float[] res = normalize(orig, null, 0); int idx = (int) res[0]; normComps[i * 3] = components[idx * 3]; normComps[(i * 3) + 1] = components[(idx * 3) + 1]; normComps[(i * 3) + 2] = components[(idx * 3) + 2]; } components = normComps; } // make sure the size of the components array is 2 ^ numBits // since if it's not, Java will complain int correctCount = 1 << getBitsPerComponent(); if (correctCount < num) { byte[] fewerComps = new byte[correctCount * 3]; System.arraycopy(components, 0, fewerComps, 0, correctCount * 3); components = fewerComps; num = correctCount; } if (this.colorKeyMask == null || this.colorKeyMask.length == 0) { return new IndexColorModel(getBitsPerComponent(), num, components, 0, false); } else { byte[] aComps = new byte[num * 4]; int idx = 0; for (int i = 0; i < num; i++) { aComps[idx++] = components[(i * 3)]; aComps[idx++] = components[(i * 3) + 1]; aComps[idx++] = components[(i * 3) + 2]; aComps[idx++] = (byte) 0xFF; } for (int i = 0; i < this.colorKeyMask.length; i += 2) { for (int j = this.colorKeyMask[i]; j <= this.colorKeyMask[i + 1]; j++) { aComps[(j * 4) + 3] = 0; // make transparent } } return new IndexColorModel(getBitsPerComponent(), num, aComps, 0, true); } } else if (cs instanceof AlternateColorSpace) { ColorSpace altCS = new AltColorSpace(((AlternateColorSpace) cs).getFunktion(), cs.getColorSpace()); int[] bits = new int[altCS.getNumComponents()]; for (int i = 0; i < bits.length; i++) { bits[i] = getBitsPerComponent(); } return new DecodeComponentColorModel(altCS, bits); } else { // CMYK color space has been converted to RGB in DCTDecode if (cs.getColorSpace().getType() == ColorSpace.TYPE_CMYK) { ColorSpace rgbCS = ColorSpace.getInstance(ColorSpace.CS_sRGB); int[] bits = new int[rgbCS.getNumComponents()]; for (int i = 0; i < bits.length; i++) { bits[i] = getBitsPerComponent(); } return new DecodeComponentColorModel(rgbCS, bits); } int[] bits = new int[cs.getNumComponents()]; for (int i = 0; i < bits.length; i++) { bits[i] = getBitsPerComponent(); } return new DecodeComponentColorModel(cs.getColorSpace(), bits); } }