Class ImageUtil


  • public final class ImageUtil
    extends java.lang.Object
    This class contains methods for basic image manipulation and conversion.
    Version:
    $Id: common/common-image/src/main/java/com/twelvemonkeys/image/ImageUtil.java#3 $
    Author:
    Harald Kuhr, last modified by $Author: haku $
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      static java.awt.image.BufferedImage accelerate​(java.awt.Image pImage)
      Tries to use H/W-accelerated code for an image for display purposes.
      static java.awt.image.BufferedImage accelerate​(java.awt.Image pImage, java.awt.GraphicsConfiguration pConfiguration)
      Tries to use H/W-accelerated code for an image for display purposes.
      static java.awt.Color blend​(java.awt.Color pColor, java.awt.Color pOther)
      Blends two colors half and half, to create a tone in between.
      static java.awt.Color blend​(java.awt.Color pColor, java.awt.Color pOther, float pBlendFactor)
      Blends two colors, controlled by the blending factor.
      static java.awt.image.BufferedImage blur​(java.awt.image.BufferedImage pOriginal)
      Creates a blurred version of the given image.
      static java.awt.image.BufferedImage blur​(java.awt.image.BufferedImage pOriginal, float pRadius)
      Creates a blurred version of the given image.
      static java.awt.Image brightness​(java.awt.Image pOriginal, float pAmount)
      Changes the brightness of the original image.
      static java.awt.Image contrast​(java.awt.Image pOriginal)
      Adds contrast
      static java.awt.Image contrast​(java.awt.Image pOriginal, float pAmount)
      Changes the contrast of the image
      static java.awt.image.BufferedImage convolve​(java.awt.image.BufferedImage pOriginal, java.awt.image.Kernel pKernel, int pEdgeOperation)
      Convolves an image, using a convolution matrix.
      static java.awt.image.BufferedImage createClear​(int pWidth, int pHeight, int pType, java.awt.Color pBackground)
      Creates a clear image with the given background color.
      static java.awt.image.BufferedImage createClear​(int pWidth, int pHeight, java.awt.Color pBackground)
      Creates a clear image with the given background color.
      static java.awt.image.BufferedImage createCopy​(java.awt.image.BufferedImage pImage)
      Creates a deep copy of the given image.
      static java.awt.image.BufferedImage createFlipped​(java.awt.Image pImage, int pAxis)
      Creates a flipped version of the given image.
      static java.awt.image.BufferedImage createIndexed​(java.awt.Image pImage)
      Creates an indexed version of the given image (a BufferedImage with an IndexColorModel.
      static java.awt.image.BufferedImage createIndexed​(java.awt.Image pImage, int pColors, java.awt.Color pMatte, int pHints)
      Creates an indexed version of the given image (a BufferedImage with an IndexColorModel.
      static java.awt.image.BufferedImage createIndexed​(java.awt.Image pImage, java.awt.image.IndexColorModel pColors, java.awt.Color pMatte, int pHints)
      Creates an indexed version of the given image (a BufferedImage with an IndexColorModel.
      static java.awt.image.BufferedImage createIndexed​(java.awt.Image pImage, java.awt.Image pColors, java.awt.Color pMatte, int pHints)
      Creates an indexed version of the given image (a BufferedImage with an IndexColorModel.
      static java.awt.image.BufferedImage createResampled​(java.awt.image.BufferedImage pImage, int pWidth, int pHeight, int pHints)
      Creates a scaled instance of the given BufferedImage.
      static java.awt.image.BufferedImage createResampled​(java.awt.image.RenderedImage pImage, int pWidth, int pHeight, int pHints)
      Creates a scaled instance of the given RenderedImage, and converts it to a BufferedImage if needed.
      static java.awt.image.BufferedImage createResampled​(java.awt.Image pImage, int pWidth, int pHeight, int pHints)
      Creates a scaled instance of the given Image, and converts it to a BufferedImage if needed.
      static java.awt.image.BufferedImage createRotated​(java.awt.Image pImage, double pAngle)
      Rotates the image to the given angle.
      static java.awt.image.BufferedImage createRotated​(java.awt.Image pImage, int pDirection)
      Rotates the image 90 degrees, clockwise (aka "rotate right"), counter-clockwise (aka "rotate left") or 180 degrees, depending on the pDirection argument.
      static java.awt.image.BufferedImage createScaled​(java.awt.Image pImage, int pWidth, int pHeight, int pHints)
      Creates a scaled instance of the given Image, and converts it to a BufferedImage if needed.
      static java.awt.Color createTranslucent​(java.awt.Color pColor, int pTransparency)
      Creates a translucent version of the given color.
      static java.awt.image.BufferedImage createTransparent​(int pWidth, int pHeight)
      Creates a transparent image.
      static java.awt.image.BufferedImage createTransparent​(int pWidth, int pHeight, int pType)
      Creates a transparent image.
      static java.awt.Image filter​(java.awt.Image pOriginal, java.awt.image.ImageFilter pFilter)
      Filters an image, using the given ImageFilter.
      static int getHeight​(java.awt.Image pImage)
      Gets the height of an Image.
      static java.awt.image.IndexColorModel getIndexColorModel​(java.awt.Image pImage, int pColors, int pHints)
      Extracts an IndexColorModel from the given image.
      static int getWidth​(java.awt.Image pImage)
      Gets the width of an Image.
      static java.awt.Image grayscale​(java.awt.Image pOriginal)
      Converts an image to grayscale.
      static boolean hasTransparentPixels​(java.awt.image.RenderedImage pImage, boolean pFast)
      Tests whether the image has any transparent or semi-transparent pixels.
      static java.awt.image.BufferedImage sharpen​(java.awt.image.BufferedImage pOriginal)
      Sharpens an image using a convolution matrix.
      static java.awt.image.BufferedImage sharpen​(java.awt.image.BufferedImage pOriginal, float pAmount)
      Sharpens an image using a convolution matrix.
      static java.awt.image.BufferedImage toBuffered​(java.awt.Image pOriginal)
      Converts the Image to a BufferedImage.
      static java.awt.image.BufferedImage toBuffered​(java.awt.image.BufferedImage pOriginal, int pType)
      Converts the BufferedImage to a BufferedImage of the given type.
      static java.awt.image.BufferedImage toBuffered​(java.awt.image.RenderedImage pOriginal)
      Converts the RenderedImage to a BufferedImage.
      static java.awt.image.BufferedImage toBuffered​(java.awt.image.RenderedImage pOriginal, int pType)
      Converts the RenderedImage to a BufferedImage of the given type.
      static java.awt.image.BufferedImage toBuffered​(java.awt.Image pOriginal, int pType)
      Converts the Image to a BufferedImage of the given type.
      static boolean waitForImage​(java.awt.Image pImage)
      Waits for an image to load completely.
      static boolean waitForImage​(java.awt.Image pImage, long pTimeOut)
      Waits for an image to load completely.
      static boolean waitForImages​(java.awt.Image[] pImages)
      Waits for a number of images to load completely.
      static boolean waitForImages​(java.awt.Image[] pImages, long pTimeOut)
      Waits for a number of images to load completely.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • toBuffered

        public static java.awt.image.BufferedImage toBuffered​(java.awt.image.RenderedImage pOriginal)
        Converts the RenderedImage to a BufferedImage. The new image will have the same ColorModel, Raster and properties as the original image, if possible.

        If the image is already a BufferedImage, it is simply returned and no conversion takes place.

        Parameters:
        pOriginal - the image to convert.
        Returns:
        a BufferedImage
      • toBuffered

        public static java.awt.image.BufferedImage toBuffered​(java.awt.image.RenderedImage pOriginal,
                                                              int pType)
        Converts the RenderedImage to a BufferedImage of the given type.

        If the image is already a BufferedImage of the given type, it is simply returned and no conversion takes place.

        Parameters:
        pOriginal - the image to convert.
        pType - the type of buffered image
        Returns:
        a BufferedImage
        Throws:
        java.lang.IllegalArgumentException - if pOriginal == null or pType is not a valid type for BufferedImage
        See Also:
        BufferedImage.getType()
      • toBuffered

        public static java.awt.image.BufferedImage toBuffered​(java.awt.image.BufferedImage pOriginal,
                                                              int pType)
        Converts the BufferedImage to a BufferedImage of the given type. The new image will have the same ColorModel, Raster and properties as the original image, if possible.

        If the image is already a BufferedImage of the given type, it is simply returned and no conversion takes place.

        This method simply invokes toBuffered((RenderedImage) pOriginal, pType).

        Parameters:
        pOriginal - the image to convert.
        pType - the type of buffered image
        Returns:
        a BufferedImage
        Throws:
        java.lang.IllegalArgumentException - if pOriginal == null or if pType is not a valid type for BufferedImage
        See Also:
        BufferedImage.getType()
      • toBuffered

        public static java.awt.image.BufferedImage toBuffered​(java.awt.Image pOriginal)
        Converts the Image to a BufferedImage. The new image will have the same ColorModel, Raster and properties as the original image, if possible.

        If the image is already a BufferedImage, it is simply returned and no conversion takes place.

        Parameters:
        pOriginal - the image to convert.
        Returns:
        a BufferedImage
        Throws:
        java.lang.IllegalArgumentException - if pOriginal == null
        ImageConversionException - if the image cannot be converted
      • createCopy

        public static java.awt.image.BufferedImage createCopy​(java.awt.image.BufferedImage pImage)
        Creates a deep copy of the given image. The image will have the same color model and raster type, but will not share image (pixel) data with the input image.
        Parameters:
        pImage - the image to clone.
        Returns:
        a new BufferedImage
        Throws:
        java.lang.IllegalArgumentException - if pImage is null
      • toBuffered

        public static java.awt.image.BufferedImage toBuffered​(java.awt.Image pOriginal,
                                                              int pType)
        Converts the Image to a BufferedImage of the given type. The new image will have the same ColorModel, Raster and properties as the original image, if possible.

        If the image is already a BufferedImage of the given type, it is simply returned and no conversion takes place.

        Parameters:
        pOriginal - the image to convert.
        pType - the type of buffered image
        Returns:
        a BufferedImage
        Throws:
        java.lang.IllegalArgumentException - if pOriginal == null or if pType is not a valid type for BufferedImage
        See Also:
        BufferedImage.getType()
      • createFlipped

        public static java.awt.image.BufferedImage createFlipped​(java.awt.Image pImage,
                                                                 int pAxis)
        Creates a flipped version of the given image.
        Parameters:
        pImage - the image to flip
        pAxis - the axis to flip around
        Returns:
        a new BufferedImage
      • createRotated

        public static java.awt.image.BufferedImage createRotated​(java.awt.Image pImage,
                                                                 int pDirection)
        Rotates the image 90 degrees, clockwise (aka "rotate right"), counter-clockwise (aka "rotate left") or 180 degrees, depending on the pDirection argument.

        The new image will be completely covered with pixels from the source image.

        Parameters:
        pImage - the source image.
        pDirection - the direction, must be either ROTATE_90_CW, ROTATE_90_CCW or ROTATE_180
        Returns:
        a new BufferedImage
      • createRotated

        public static java.awt.image.BufferedImage createRotated​(java.awt.Image pImage,
                                                                 double pAngle)
        Rotates the image to the given angle. Areas not covered with pixels from the source image will be left transparent, if possible.
        Parameters:
        pImage - the source image
        pAngle - the angle of rotation, in radians
        Returns:
        a new BufferedImage, unless pAngle == 0.0
      • createScaled

        public static java.awt.image.BufferedImage createScaled​(java.awt.Image pImage,
                                                                int pWidth,
                                                                int pHeight,
                                                                int pHints)
        Creates a scaled instance of the given Image, and converts it to a BufferedImage if needed. If the original image is a BufferedImage the result will have same type and color model. Note that this implies overhead, and is probably not useful for anything but IndexColorModel images.
        Parameters:
        pImage - the Image to scale
        pWidth - width in pixels
        pHeight - height in pixels
        pHints - scaling ints
        Returns:
        a BufferedImage
        Throws:
        java.lang.NullPointerException - if pImage is null.
        See Also:
        createResampled(java.awt.Image, int, int, int), Image.getScaledInstance(int,int,int), Image.SCALE_AREA_AVERAGING, Image.SCALE_DEFAULT, Image.SCALE_FAST, Image.SCALE_REPLICATE, Image.SCALE_SMOOTH
      • createResampled

        public static java.awt.image.BufferedImage createResampled​(java.awt.Image pImage,
                                                                   int pWidth,
                                                                   int pHeight,
                                                                   int pHints)
        Creates a scaled instance of the given Image, and converts it to a BufferedImage if needed.
        Parameters:
        pImage - the Image to scale
        pWidth - width in pixels
        pHeight - height in pixels
        pHints - scaling mHints
        Returns:
        a BufferedImage
        Throws:
        java.lang.NullPointerException - if pImage is null.
        See Also:
        Image.SCALE_AREA_AVERAGING, Image.SCALE_DEFAULT, Image.SCALE_FAST, Image.SCALE_REPLICATE, Image.SCALE_SMOOTH, ResampleOp
      • createResampled

        public static java.awt.image.BufferedImage createResampled​(java.awt.image.RenderedImage pImage,
                                                                   int pWidth,
                                                                   int pHeight,
                                                                   int pHints)
        Creates a scaled instance of the given RenderedImage, and converts it to a BufferedImage if needed.
        Parameters:
        pImage - the RenderedImage to scale
        pWidth - width in pixels
        pHeight - height in pixels
        pHints - scaling mHints
        Returns:
        a BufferedImage
        Throws:
        java.lang.NullPointerException - if pImage is null.
        See Also:
        Image.SCALE_AREA_AVERAGING, Image.SCALE_DEFAULT, Image.SCALE_FAST, Image.SCALE_REPLICATE, Image.SCALE_SMOOTH, ResampleOp
      • createResampled

        public static java.awt.image.BufferedImage createResampled​(java.awt.image.BufferedImage pImage,
                                                                   int pWidth,
                                                                   int pHeight,
                                                                   int pHints)
        Creates a scaled instance of the given BufferedImage.
        Parameters:
        pImage - the BufferedImage to scale
        pWidth - width in pixels
        pHeight - height in pixels
        pHints - scaling mHints
        Returns:
        a BufferedImage
        Throws:
        java.lang.NullPointerException - if pImage is null.
        See Also:
        Image.SCALE_AREA_AVERAGING, Image.SCALE_DEFAULT, Image.SCALE_FAST, Image.SCALE_REPLICATE, Image.SCALE_SMOOTH, ResampleOp
      • createIndexed

        public static java.awt.image.BufferedImage createIndexed​(java.awt.Image pImage)
        Creates an indexed version of the given image (a BufferedImage with an IndexColorModel. The resulting image will have a maximum of 256 different colors. Transparent parts of the original will be replaced with solid black. Default (possibly HW accelerated) dither will be used.
        Parameters:
        pImage - the image to convert
        Returns:
        an indexed version of the given image
      • sharpen

        public static java.awt.image.BufferedImage sharpen​(java.awt.image.BufferedImage pOriginal)
        Sharpens an image using a convolution matrix. The sharpen kernel used, is defined by the following 3 by 3 matrix:
        Sharpen Kernel Matrix
        0.0-0.30.0
        -0.32.2-0.3
        0.0-0.30.0

        This is the same result returned as sharpen(pOriginal, 0.3f).

        Parameters:
        pOriginal - the BufferedImage to sharpen
        Returns:
        a new BufferedImage, containing the sharpened image.
      • sharpen

        public static java.awt.image.BufferedImage sharpen​(java.awt.image.BufferedImage pOriginal,
                                                           float pAmount)
        Sharpens an image using a convolution matrix. The sharpen kernel used, is defined by the following 3 by 3 matrix:
        Sharpen Kernel Matrix
        0.0-pAmount0.0
        -pAmount 4.0 * pAmount + 1.0 -pAmount
        0.0-pAmount0.0
        Parameters:
        pOriginal - the BufferedImage to sharpen
        pAmount - the amount of sharpening
        Returns:
        a BufferedImage, containing the sharpened image.
      • blur

        public static java.awt.image.BufferedImage blur​(java.awt.image.BufferedImage pOriginal)
        Creates a blurred version of the given image.
        Parameters:
        pOriginal - the original image
        Returns:
        a new BufferedImage with a blurred version of the given image
      • blur

        public static java.awt.image.BufferedImage blur​(java.awt.image.BufferedImage pOriginal,
                                                        float pRadius)
        Creates a blurred version of the given image.
        Parameters:
        pOriginal - the original image
        pRadius - the amount to blur
        Returns:
        a new BufferedImage with a blurred version of the given image
      • convolve

        public static java.awt.image.BufferedImage convolve​(java.awt.image.BufferedImage pOriginal,
                                                            java.awt.image.Kernel pKernel,
                                                            int pEdgeOperation)
        Convolves an image, using a convolution matrix.
        Parameters:
        pOriginal - the BufferedImage to sharpen
        pKernel - the kernel
        pEdgeOperation - the edge operation. Must be one of EDGE_NO_OP, EDGE_ZERO_FILL, EDGE_REFLECT or EDGE_WRAP
        Returns:
        a new BufferedImage, containing the sharpened image.
      • contrast

        public static java.awt.Image contrast​(java.awt.Image pOriginal)
        Adds contrast
        Parameters:
        pOriginal - the BufferedImage to add contrast to
        Returns:
        an Image, containing the contrasted image.
      • contrast

        public static java.awt.Image contrast​(java.awt.Image pOriginal,
                                              float pAmount)
        Changes the contrast of the image
        Parameters:
        pOriginal - the Image to change
        pAmount - the amount of contrast in the range [-1.0..1.0].
        Returns:
        an Image, containing the contrasted image.
      • brightness

        public static java.awt.Image brightness​(java.awt.Image pOriginal,
                                                float pAmount)
        Changes the brightness of the original image.
        Parameters:
        pOriginal - the Image to change
        pAmount - the amount of brightness in the range [-2.0..2.0].
        Returns:
        an Image
      • grayscale

        public static java.awt.Image grayscale​(java.awt.Image pOriginal)
        Converts an image to grayscale.
        Parameters:
        pOriginal - the image to convert.
        Returns:
        a new Image, containing the gray image data.
        See Also:
        GrayFilter, RGBImageFilter
      • filter

        public static java.awt.Image filter​(java.awt.Image pOriginal,
                                            java.awt.image.ImageFilter pFilter)
        Filters an image, using the given ImageFilter.
        Parameters:
        pOriginal - the original image
        pFilter - the filter to apply
        Returns:
        the new Image
      • accelerate

        public static java.awt.image.BufferedImage accelerate​(java.awt.Image pImage)
        Tries to use H/W-accelerated code for an image for display purposes. Note that transparent parts of the image might be replaced by solid color. Additional image information not used by the current diplay hardware may be discarded, like extra bith depth etc.
        Parameters:
        pImage - any Image
        Returns:
        a BufferedImage
      • accelerate

        public static java.awt.image.BufferedImage accelerate​(java.awt.Image pImage,
                                                              java.awt.GraphicsConfiguration pConfiguration)
        Tries to use H/W-accelerated code for an image for display purposes. Note that transparent parts of the image might be replaced by solid color. Additional image information not used by the current diplay hardware may be discarded, like extra bith depth etc.
        Parameters:
        pImage - any Image
        pConfiguration - the GraphicsConfiguration to accelerate for
        Returns:
        a BufferedImage
      • createTransparent

        public static java.awt.image.BufferedImage createTransparent​(int pWidth,
                                                                     int pHeight)
        Creates a transparent image.
        Parameters:
        pWidth - the requested width of the image
        pHeight - the requested height of the image
        Returns:
        the new image
        Throws:
        java.lang.IllegalArgumentException - if pType is not a valid type for BufferedImage
      • createTransparent

        public static java.awt.image.BufferedImage createTransparent​(int pWidth,
                                                                     int pHeight,
                                                                     int pType)
        Creates a transparent image.
        Parameters:
        pWidth - the requested width of the image
        pHeight - the requested height of the image
        pType - the type of BufferedImage to create
        Returns:
        the new image
        Throws:
        java.lang.IllegalArgumentException - if pType is not a valid type for BufferedImage
        See Also:
        BufferedImage(int,int,int)
      • createClear

        public static java.awt.image.BufferedImage createClear​(int pWidth,
                                                               int pHeight,
                                                               java.awt.Color pBackground)
        Creates a clear image with the given background color.
        Parameters:
        pWidth - the requested width of the image
        pHeight - the requested height of the image
        pBackground - the background color. The color may be translucent. May be null, in such case the color is undefined.
        Returns:
        the new image
        Throws:
        java.lang.IllegalArgumentException - if pType is not a valid type for BufferedImage
        See Also:
        BufferedImage(int,int,int)
      • createClear

        public static java.awt.image.BufferedImage createClear​(int pWidth,
                                                               int pHeight,
                                                               int pType,
                                                               java.awt.Color pBackground)
        Creates a clear image with the given background color.
        Parameters:
        pWidth - the width of the image to create
        pHeight - the height of the image to create
        pType - the type of image to create (one of the constants from BufferedImage or BI_TYPE_ANY)
        pBackground - the background color. The color may be translucent. May be null, in such case the color is undefined.
        Returns:
        the new image
        Throws:
        java.lang.IllegalArgumentException - if pType is not a valid type for BufferedImage
        See Also:
        BufferedImage(int,int,int)
      • getWidth

        public static int getWidth​(java.awt.Image pImage)
        Gets the width of an Image. This method has the side-effect of completely loading the image.
        Parameters:
        pImage - an image.
        Returns:
        the width of the image, or -1 if the width could not be determined (i.e. an error occured while waiting for the image to load).
      • getHeight

        public static int getHeight​(java.awt.Image pImage)
        Gets the height of an Image. This method has the side-effect of completely loading the image.
        Parameters:
        pImage - an image.
        Returns:
        the height of the image, or -1 if the height could not be determined (i.e. an error occured while waiting for the image to load).
      • waitForImage

        public static boolean waitForImage​(java.awt.Image pImage)
        Waits for an image to load completely. Will wait forever.
        Parameters:
        pImage - an Image object to wait for.
        Returns:
        true if the image was loaded successfully, false if an error occured, or the wait was interrupted.
        See Also:
        waitForImage(Image,long)
      • waitForImage

        public static boolean waitForImage​(java.awt.Image pImage,
                                           long pTimeOut)
        Waits for an image to load completely. Will wait the specified time.
        Parameters:
        pImage - an Image object to wait for.
        pTimeOut - the time to wait, in milliseconds.
        Returns:
        true if the image was loaded successfully, false if an error occurred, or the wait was interrupted.
        See Also:
        waitForImages(Image[],long)
      • waitForImages

        public static boolean waitForImages​(java.awt.Image[] pImages)
        Waits for a number of images to load completely. Will wait forever.
        Parameters:
        pImages - an array of Image objects to wait for.
        Returns:
        true if the images was loaded successfully, false if an error occurred, or the wait was interrupted.
        See Also:
        waitForImages(Image[],long)
      • waitForImages

        public static boolean waitForImages​(java.awt.Image[] pImages,
                                            long pTimeOut)
        Waits for a number of images to load completely. Will wait the specified time.
        Parameters:
        pImages - an array of Image objects to wait for
        pTimeOut - the time to wait, in milliseconds
        Returns:
        true if the images was loaded successfully, false if an error occurred, or the wait was interrupted.
      • hasTransparentPixels

        public static boolean hasTransparentPixels​(java.awt.image.RenderedImage pImage,
                                                   boolean pFast)
        Tests whether the image has any transparent or semi-transparent pixels.
        Parameters:
        pImage - the image
        pFast - if true, the method tests maximum 10 x 10 pixels, evenly spaced out in the image.
        Returns:
        true if transparent pixels are found, otherwise false.
      • createTranslucent

        public static java.awt.Color createTranslucent​(java.awt.Color pColor,
                                                       int pTransparency)
        Creates a translucent version of the given color.
        Parameters:
        pColor - the original color
        pTransparency - the transparency level (0 - 255)
        Returns:
        a translucent color
        Throws:
        java.lang.NullPointerException - if pColor is null
      • blend

        public static java.awt.Color blend​(java.awt.Color pColor,
                                           java.awt.Color pOther)
        Blends two colors half and half, to create a tone in between.
        Parameters:
        pColor - color 1
        pOther - color 2
        Returns:
        a new Color
      • blend

        public static java.awt.Color blend​(java.awt.Color pColor,
                                           java.awt.Color pOther,
                                           float pBlendFactor)
        Blends two colors, controlled by the blending factor. A factor of 0.0 will return the first color, a factor of 1.0 will return the second.
        Parameters:
        pColor - color 1
        pOther - color 2
        pBlendFactor - [0...1]
        Returns:
        a new Color