/* * @(#)RGBFormat.java 1.35 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ package javax.media.format; import java.awt.Dimension; import javax.media.Format; /** * Describes uncompressed RGB data. The data is in * interleaved form. RGB components can be packed into * a short or an int. If the pixel components are packed, then the * <CODE>redMask</CODE>, <CODE>greenMask</CODE> and <CODE>blueMask</CODE> fields * specify the bit masks, otherwise * they specify the order of arrangement of the components. For example: * <UL> * <LI>32-bit packed RGB stored as 32-bit integers would have * the following masks: redMask = 0x00FF0000, greenMask = 0x0000FF00, * blueMask = 0x000000FF. </LI> * <LI>24-bit RGB stored as bytes would have the following masks: * redMask = 1, greenMask = 2, blueMask = 3 and pixelStride = 3.</LI> * </UL> * @since JMF 2.0 */ public class RGBFormat extends VideoFormat { /** Mask value for the Red component. */ protected int redMask = NOT_SPECIFIED; /** Mask value for the Green component. */ protected int greenMask = NOT_SPECIFIED; /** Mask value for the Blue component. */ protected int blueMask = NOT_SPECIFIED; /** * The number of bits required to represent a pixel, including all three * color components. */ protected int bitsPerPixel = NOT_SPECIFIED; /** Increment value of the array index from one pixel to the next. */ protected int pixelStride = NOT_SPECIFIED; /** * Increment value of the array index from the first pixel on line n * to the first pixel on line n+1. */ protected int lineStride = NOT_SPECIFIED; /** Indicates whether or not the lines in the video frame are flipped vertically * (upside down). */ protected int flipped = NOT_SPECIFIED; /** Endian ordering of the data where applicable */ protected int endian = NOT_SPECIFIED; public static final int BIG_ENDIAN = 0; public static final int LITTLE_ENDIAN = 1; private static String ENCODING = VideoFormat.RGB; /** * Constructs a default <CODE>RGBFormat</CODE>. */ public RGBFormat() { super(ENCODING); dataType = null; } /** * Constructs an <CODE>RGBFormat</CODE> object with the specified properties. * The pixel stride is * initialized to the default for the specified data type and bits per pixel. * The line stride is initialized using the default pixel stride and specified frame * width. * The image is not flipped and the endian is LITTLE_ENDIAN. * @param size A <CODE>Dimension</CODE> that specifies the frame size. * @param maxDataLength The maximum length of a data chunk. * @param dataType The type of the data. For example, byte array. * @param frameRate The frame rate. * @param bitsPerPixel The number of bits representing a pixel. * @param red The mask for the red color component. * @param green The mask for the green color component. * @param blue The mask for the blue color component. */ public RGBFormat(Dimension size, int maxDataLength, Class dataType, float frameRate, int bitsPerPixel, int red, int green, int blue) { super(ENCODING, size, maxDataLength, dataType, frameRate); this.bitsPerPixel = bitsPerPixel; this.redMask = red; this.greenMask = green; this.blueMask = blue; if (bitsPerPixel != NOT_SPECIFIED && dataType != null) { pixelStride = bitsPerPixel / 8; if (dataType != byteArray) pixelStride = 1; } else { pixelStride = NOT_SPECIFIED; } if (size != null && pixelStride != NOT_SPECIFIED) lineStride = pixelStride * size.width; else lineStride = NOT_SPECIFIED; flipped = FALSE; if (bitsPerPixel == 16 && dataType == byteArray) endian = LITTLE_ENDIAN; else endian = NOT_SPECIFIED; } /** * Constructs an <CODE>RGBFormat</CODE> object with the specified properties. * @param size A <CODE>Dimension</CODE> that specifies the frame size. * @param maxDataLength The maximum length of a data chunk. * @param dataType The type of the data. For example, byte array. * @param frameRate The frame rate. * @param bitsPerPixel The number of bits representing a pixel. * @param red The mask for the red color component. * @param green The mask for the green color component. * @param blue The mask for the blue color component. * @param pixelStride The number of array elements between adjacent pixels. * @param flipped Indicates whether or not the lines in the video frame are * flipped vertically (upside down). <CODE>Format.TRUE</CODE> indicates the image is flipped, * <CODE>Format.FALSE</CODE> indicates that it is not. * @param endian The byte ordering used for this * <code>RGBFormat</code>--<CODE>BIG_ENDIAN</CODE> or <CODE>LITTLE_ENDIAN</CODE>. */ public RGBFormat(Dimension size, int maxDataLength, Class dataType, float frameRate, int bitsPerPixel, int red, int green, int blue, int pixelStride, int lineStride, int flipped, int endian) { super(ENCODING, size, maxDataLength, dataType, frameRate); this.bitsPerPixel = bitsPerPixel; this.redMask = red; this.greenMask = green; this.blueMask = blue; this.pixelStride = pixelStride; this.lineStride = lineStride; this.flipped = flipped; this.endian = endian; } /** * Gets the number of bits required per pixel of data. * @return An integer representing the number of bits per pixel. */ public int getBitsPerPixel() { return bitsPerPixel; } /** * Gets the mask for the red component. * @return The red mask. */ public int getRedMask() { return redMask; } /** * Gets the mask for the green component. * @return The green mask. */ public int getGreenMask() { return greenMask; } /** * Gets the mask for the blue component. * @return The blue mask. */ public int getBlueMask() { return blueMask; } /** * Gets the pixel stride--the number of array elements between adjacent pixels. * @return An integer representing the pixel stride. */ public int getPixelStride() { return pixelStride; } /** * Gets the line stride--the number of array elements between adjacent rows of pixels. * @return An integer representing the line stride. */ public int getLineStride() { return lineStride; } /** * Checks whether or not the video image is vertically flipped. * * @return <CODE>Format.TRUE</CODE> if the video is flipped, <CODE>Format.FALSE</CODE> * if it is not. */ public int getFlipped() { return flipped; } /** * Gets the endian ordering of the data for unpacked 16-bit data. * @return An integer representing the endian ordering: BIG_ENDIAN, LITTLE_ENDIAN or NOT_SPECIFIED */ public int getEndian() { return endian; } /** * Creates a clone of this <CODE>RGBFormat</CODE>. * @return A clone of this <CODE>RGBFormat</CODE>. */ public Object clone() { RGBFormat f = new RGBFormat(size, maxDataLength, dataType, frameRate, bitsPerPixel, redMask, greenMask, blueMask, pixelStride, lineStride, flipped, endian); f.copy(this); return f; } /** * Copies the attributes from the specified <CODE>Format</CODE> into * this <CODE>RGBFormat</CODE>. * @param f The <CODE>Format</CODE> to copy the attributes from. */ protected void copy(Format f) { super.copy(f); if (f instanceof RGBFormat) { RGBFormat other = (RGBFormat) f; bitsPerPixel = other.bitsPerPixel; redMask = other.redMask; greenMask = other.greenMask; blueMask = other.blueMask; pixelStride = other.pixelStride; lineStride = other.lineStride; flipped = other.flipped; endian = other.endian; } } /** * Compares the specified <CODE>Format</CODE> with this <code>RGBFormat</code>. * Returns <CODE>true</CODE> only if the specified <CODE>Format</CODE> * is a <CODE>RGBFormat</CODE> object and all of * its attributes are identical to * the attributes in this <code>RGBFormat</code>. * @param format The <CODE>Format</CODE> to compare. * @return true if the specified <CODE>Format</CODE> is the same as this one. */ public boolean equals(Object format) { if (format instanceof RGBFormat) { RGBFormat other = (RGBFormat) format; return super.equals(format) && bitsPerPixel == other.bitsPerPixel && redMask == other.redMask && greenMask == other.greenMask && blueMask == other.blueMask && pixelStride == other.pixelStride && lineStride == other.lineStride && endian == other.endian && flipped == other.flipped; } else return false; } /** * Checks whether or not the specified <CODE>Format</CODE> <EM>matches</EM> * this <CODE>RGBFormat</CODE>. * Matches only compares the attributes that are defined in the specified * <CODE>Format</CODE>, * unspecified attributes are ignored. * <p> * The two <CODE>Format</CODE> objects do not have to be of the same class * to match. For example, if "A" are "B" are being compared, a * match is possible if "A" is derived from "B" * or "B" is derived from "A". (The compared attributes must still match, * or <CODE>matches</CODE> fails.) * @param format The <CODE>Format</CODE> to compare with this one. * @return <CODE>true</CODE> if the specified <CODE>Format</CODE> * matches this one, <CODE>false</CODE> if it does not. */ public boolean matches(Format format) { if (!super.matches(format)) return false; if (!(format instanceof RGBFormat)) return true; RGBFormat other = (RGBFormat) format; boolean returnVal = (bitsPerPixel == NOT_SPECIFIED || other.bitsPerPixel == NOT_SPECIFIED || bitsPerPixel == other.bitsPerPixel) && (redMask == NOT_SPECIFIED || other.redMask == NOT_SPECIFIED || redMask == other.redMask) && (greenMask == NOT_SPECIFIED || other.greenMask == NOT_SPECIFIED || greenMask == other.greenMask) && (blueMask == NOT_SPECIFIED || other.blueMask == NOT_SPECIFIED || blueMask == other.blueMask) && (pixelStride == NOT_SPECIFIED || other.pixelStride == NOT_SPECIFIED || pixelStride == other.pixelStride) && (endian == NOT_SPECIFIED || other.endian == NOT_SPECIFIED || endian == other.endian) && (flipped == NOT_SPECIFIED || other.flipped == NOT_SPECIFIED || flipped == other.flipped); return returnVal; } /** * Finds the attributes shared by two matching <CODE>Format</CODE> objects. * If the specified <CODE>Format</CODE> does not match this one, the result * is undefined. * @param The matching <CODE>Format</CODE> to intersect with this * <CODE>RGBFormat</CODE>. * @return A <CODE>Format</CODE> object * with its attributes set to those attributes common to both * <CODE>Format</CODE> objects. * @see #matches */ public Format intersects(Format format) { Format fmt; if ((fmt = super.intersects(format)) == null) return null; if (!(format instanceof RGBFormat)) return fmt; RGBFormat other = (RGBFormat)format; RGBFormat res = (RGBFormat)fmt; res.bitsPerPixel = (bitsPerPixel != NOT_SPECIFIED ? bitsPerPixel : other.bitsPerPixel); res.pixelStride = (pixelStride != NOT_SPECIFIED ? pixelStride : other.pixelStride); res.lineStride = (lineStride != NOT_SPECIFIED ? lineStride : other.lineStride); res.redMask = (redMask != NOT_SPECIFIED ? redMask : other.redMask); res.greenMask = (greenMask != NOT_SPECIFIED ? greenMask : other.greenMask); res.blueMask = (blueMask != NOT_SPECIFIED ? blueMask : other.blueMask); res.flipped = (flipped != NOT_SPECIFIED ? flipped : other.flipped); res.endian = (endian != NOT_SPECIFIED ? endian : other.endian); return res; } /** * Generate a format that's less restrictive than this format but * contains the basic attributes that will make this resulting format * useful for format matching. * @return A <CODE>Format</CODE> that's less restrictive than the * this format. */ public Format relax() { RGBFormat fmt; if ((fmt = (RGBFormat)super.relax()) == null) return null; fmt.lineStride = NOT_SPECIFIED; fmt.pixelStride = NOT_SPECIFIED; return fmt; } /** * Gets a <CODE>String</CODE> representation of the attributes of this * <CODE>RGBFormat</CODE>. * For example: "RGB, 352x240, ...". * @return A <CODE>String</CODE> that describes the format attributes. */ public String toString() { String s = getEncoding().toUpperCase(); if (size != null) s += ", " + size.width + "x" + size.height; if (frameRate != NOT_SPECIFIED) s += ", FrameRate=" + ((int)(frameRate * 10) / 10f); if (maxDataLength != NOT_SPECIFIED) s += ", Length=" + maxDataLength; s += ", " + bitsPerPixel + "-bit"; s += ", Masks=" + redMask + ":" + greenMask + ":" + blueMask; if (pixelStride != 1) s += ", PixelStride=" + pixelStride; s += ", LineStride=" + lineStride; if (flipped != NOT_SPECIFIED) s += (flipped == Format.TRUE? ", Flipped" : ""); if (dataType == byteArray && bitsPerPixel == 16 && endian != NOT_SPECIFIED) s += (endian == BIG_ENDIAN? ", BigEndian" : ", LittleEndian"); if (dataType != null && dataType != Format.byteArray) s += ", " + dataType; return s; } }