Exemple #1
0
/*
 *	NAME
 *		XcmsConvertColors - Convert XcmsColor structures
 *
 *	SYNOPSIS
 */
Status
XcmsConvertColors(
    XcmsCCC ccc,
    XcmsColor *pColors_in_out,
    unsigned int nColors,
    XcmsColorFormat targetFormat,
    Bool *pCompressed)
/*
 *	DESCRIPTION
 *		Convert XcmsColor structures to another format
 *
 *	RETURNS
 *		XcmsFailure if failed,
 *		XcmsSuccess if succeeded without gamut compression,
 *		XcmsSuccessWithCompression if succeeded with gamut
 *			compression.
 *
 */
{
    XcmsColor clientWhitePt;
    XcmsColor Color1;
    XcmsColor *pColors_tmp;
    int callWhiteAdjustProc = 0;
    XcmsColorFormat format;
    Status retval;
    unsigned char contents_flag = 0x00;
    unsigned int iColors;

    if (ccc == NULL || pColors_in_out == NULL ||
		!(ValidDIColorSpaceID(targetFormat) ||
		ValidDDColorSpaceID(ccc, targetFormat))) {
	return(XcmsFailure);
    }

    /*
     * Check formats in color specification array
     */
    format = pColors_in_out->format;
    for (pColors_tmp = pColors_in_out, iColors = nColors; iColors; pColors_tmp++, iColors--) {
	if (!(ValidDIColorSpaceID(pColors_tmp->format) ||
		ValidDDColorSpaceID(ccc, pColors_tmp->format))) {
	    return(XcmsFailure);
	}
	if (XCMS_DI_ID(pColors_tmp->format)) {
	    contents_flag |= DI_FORMAT;
	} else {
	    contents_flag |= DD_FORMAT;
	}
	if (pColors_tmp->format != format) {
	    contents_flag |= MIX_FORMAT;
	}
    }

    /*
     * Check if we need the Client White Point.
     */
    if ((contents_flag & DI_FORMAT) || XCMS_DI_ID(targetFormat)) {
	/* To proceed, we need to get the Client White Point */
	memcpy((char *)&clientWhitePt, (char *)&ccc->clientWhitePt,
	       sizeof(XcmsColor));
	if (clientWhitePt.format == XcmsUndefinedFormat) {
	    /*
	     * Client White Point is undefined, therefore set to the Screen
	     *   White Point.
	     * Since Client White Point == Screen White Point, WhiteAdjustProc
	     *   is not called.
	     */
	    memcpy((char *)&clientWhitePt,
		   (char *)&ccc->pPerScrnInfo->screenWhitePt,
		   sizeof(XcmsColor));
	} else if ((ccc->whitePtAdjProc != NULL) && !_XcmsEqualWhitePts(ccc,
		&clientWhitePt, ScreenWhitePointOfCCC(ccc))) {
	    /*
	     * Client White Point != Screen White Point, and WhiteAdjustProc
	     *   is not NULL, therefore, will need to call it when
	     *   converting between DI and DD specifications.
	     */
	    callWhiteAdjustProc = 1;
	}
    }

    /*
     * Make copy of array of color specifications
     */
    if (nColors > 1) {
	pColors_tmp = (XcmsColor *) Xmalloc(nColors * sizeof(XcmsColor));
    } else {
	pColors_tmp = &Color1;
    }
    memcpy((char *)pColors_tmp, (char *)pColors_in_out,
	   nColors * sizeof(XcmsColor));

    /*
     * zero out pCompressed
     */
    if (pCompressed) {
	bzero((char *)pCompressed, nColors * sizeof(Bool));
    }

    if (contents_flag == DD_FORMAT || contents_flag == DI_FORMAT) {
	/*
	 * ENTIRE ARRAY IS IN ONE FORMAT.
	 */
	if (XCMS_DI_ID(format) && XCMS_DI_ID(targetFormat)) {
	    /*
	     * DI-to-DI only conversion
	     */
	    retval = _XcmsDIConvertColors(ccc, pColors_tmp,
		    &clientWhitePt, nColors, targetFormat);
	} else if (XCMS_DD_ID(format) && XCMS_DD_ID(targetFormat)) {
	    /*
	     * DD-to-DD only conversion
	     *   Since DD->DD there will be no compressed thus we can
	     *   pass NULL instead of pCompressed.
	     */
	    retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors,
		    targetFormat, (Bool *)NULL);
	} else {
	    /*
	     * Otherwise we have:
	     *    1. Device-Independent to Device-Dependent Conversion
	     *		OR
	     *    2. Device-Dependent to Device-Independent Conversion
	     *
	     *  We need to go from oldFormat -> CIEXYZ -> targetFormat
	     *	adjusting for white points as necessary.
	     */

	    if (XCMS_DI_ID(format)) {
		/*
		 *    1. Device-Independent to Device-Dependent Conversion
		 */
		if (callWhiteAdjustProc) {
		    /*
		     * White Point Adjustment
		     *		Client White Point to Screen White Point
		     */
		    retval = (*ccc->whitePtAdjProc)(ccc, &clientWhitePt,
			    ScreenWhitePointOfCCC(ccc), targetFormat,
			    pColors_tmp, nColors, pCompressed);
		} else {
		    if (_XcmsDIConvertColors(ccc, pColors_tmp,
			    &clientWhitePt, nColors, XcmsCIEXYZFormat)
			    == XcmsFailure) {
			goto Failure;
		    }
		    retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors,
			    targetFormat, pCompressed);
		}
	    } else {
		/*
		 *    2. Device-Dependent to Device-Independent Conversion
		 */
		if (callWhiteAdjustProc) {
		    /*
		     * White Point Adjustment
		     *		Screen White Point to Client White Point
		     */
		    retval = (*ccc->whitePtAdjProc)(ccc,
			    ScreenWhitePointOfCCC(ccc), &clientWhitePt,
			    targetFormat, pColors_tmp, nColors, pCompressed);
		} else {
		    /*
		     * Since DD->CIEXYZ, no compression takes place therefore
		     * we can pass NULL instead of pCompressed.
		     */
		    if (_XcmsDDConvertColors(ccc, pColors_tmp, nColors,
			    XcmsCIEXYZFormat, (Bool *)NULL) == XcmsFailure) {
			goto Failure;
		    }
		    retval = _XcmsDIConvertColors(ccc, pColors_tmp,
			    &clientWhitePt, nColors, targetFormat);
		}
	    }
	}
    } else {
	/*
	 * ARRAY HAS MIXED FORMATS.
	 */
	if ((contents_flag == (DI_FORMAT | MIX_FORMAT)) &&
		XCMS_DI_ID(targetFormat)) {
	    /*
	     * Convert from DI to DI in batches of contiguous formats
	     *
	     * Because DI->DI, WhiteAdjustProc not called.
	     */
	    retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
		    nColors, targetFormat, (unsigned char)DI_FORMAT);
	} else if ((contents_flag == (DD_FORMAT | MIX_FORMAT)) &&
		XCMS_DD_ID(targetFormat)) {
	    /*
	     * Convert from DD to DD in batches of contiguous formats
	     *
	     * Because DD->DD, WhiteAdjustProc not called.
	     */
	    retval = ConvertMixedColors(ccc, pColors_tmp,
		    (XcmsColor *)NULL, nColors, targetFormat,
		    (unsigned char)DD_FORMAT);
	} else if (XCMS_DI_ID(targetFormat)) {
	    /*
	     * We need to convert from DI-to-DI and DD-to-DI, therefore
	     *   1. convert DD specifications to CIEXYZ, then
	     *   2. convert all in batches to the target DI format.
	     *
	     * Note that ConvertMixedColors will call WhiteAdjustProc
	     * as necessary.
	     */

	    /*
	     * Convert only DD specifications in batches of contiguous formats
	     * to CIEXYZ
	     *
	     * Since DD->CIEXYZ, ConvertMixedColors will apply WhiteAdjustProc
	     * if required.
	     */
	    retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
		    nColors, XcmsCIEXYZFormat, (unsigned char)DD_FORMAT);

	    /*
	     * Because at this point we may have a mix of DI formats
	     * (e.g., CIEXYZ, CIELuv) we must convert the specs to the
	     * target DI format in batches of contiguous source formats.
	     */
	    retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
		    nColors, targetFormat, (unsigned char)DI_FORMAT);
	} else {
	    /*
	     * We need to convert from DI-to-DD and DD-to-DD, therefore
	     *   1. convert DI specifications to CIEXYZ, then
	     *   2. convert all to the DD target format.
	     *
	     *   This allows white point adjustment and gamut compression
	     *	 to be applied to all the color specifications in one
	     *   swoop if those functions do in fact modify the entire
	     *   group of color specifications.
	     */

	    /*
	     * Convert in batches to CIEXYZ
	     *
	     * If DD->CIEXYZ, ConvertMixedColors will apply WhiteAdjustProc
	     * if required.
	     */
	    if ((retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
		    nColors, XcmsCIEXYZFormat,
		    (unsigned char)(DI_FORMAT | DD_FORMAT))) == XcmsFailure) {
		goto Failure;
	    }

	    /*
	     * Convert all specifications (now in CIEXYZ format) to
	     * the target DD format.
	     * Since CIEXYZ->DD, compression MAY take place therefore
	     * we must pass pCompressed.
	     * Note that WhiteAdjustProc must be used if necessary.
	     */
	    if (callWhiteAdjustProc) {
		/*
		 * White Point Adjustment
		 *	Client White Point to Screen White Point
		 */
		retval = (*ccc->whitePtAdjProc)(ccc,
			&clientWhitePt, ScreenWhitePointOfCCC(ccc),
			targetFormat, pColors_tmp, nColors, pCompressed);
	    } else {
		retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors,
			targetFormat, pCompressed);
	    }
	}
    }

    if (retval != XcmsFailure) {
	memcpy((char *)pColors_in_out, (char *)pColors_tmp,
	       nColors * sizeof(XcmsColor));
    }
    if (nColors > 1) {
	Xfree((char *)pColors_tmp);
    }
    return(retval);

Failure:
    if (nColors > 1) {
	Xfree((char *)pColors_tmp);
    }
    return(XcmsFailure);
}
Exemple #2
0
/*
 *	NAME
 *		_XcmsResolveColorString -
 *
 *	SYNOPSIS
 */
Status
_XcmsResolveColorString (
    XcmsCCC ccc,
    const char **color_string,
    XcmsColor *pColor_exact_return,
    XcmsColorFormat result_format)
/*
 *	DESCRIPTION
 *		The XcmsLookupColor function finds the color specification
 *		associated with a color name in the Device-Independent Color
 *		Name Database.
 *	RETURNS
 *		XcmsFailure if failed to convert valid color string.
 *		XcmsSuccess if succeeded in converting color string to
 *			XcmsColor.
 *		_XCMS_NEWNAME if failed to parse the string or find it in
 *			the database, or if succeeded in looking it up and
 *			found another name which is not in the database.
 *			Note that the new name is returned in color_string.
 *
 *		This function returns both the color specification found in the
 *		database (db specification) and the color specification for the
 *		color displayable by the specified screen (screen
 *		specification).  The calling routine sets the format for these
 *		returned specifications in the XcmsColor format component.
 *		If XcmsUndefinedFormat, the specification is returned in the
 *		format used to store the color in the database.
 */
{
    XcmsColor dbWhitePt;	/* whitePt associated with pColor_exact_return*/
				/*    the screen's white point */
    XcmsColor *pClientWhitePt;
    int retval;
    const char *strptr = whitePtStr;

/*
 * 0. Check for invalid arguments.
 */
    if (ccc == NULL || (*color_string)[0] == '\0' || pColor_exact_return == NULL) {
	return(XcmsFailure);
    }

/*
 * 1. First attempt to parse the string
 *    If successful, then convert the specification to the target format
 *    and return.
 */
    if (_XcmsParseColorString(ccc, *color_string, pColor_exact_return)
	    == 1) {
	if (result_format != XcmsUndefinedFormat
		&& pColor_exact_return->format != result_format) {
	    /* need to be converted to the target format */
	    return(XcmsConvertColors(ccc, pColor_exact_return, 1,
		    result_format, (Bool *)NULL));
	} else {
	    return(XcmsSuccess);
	}
    }

/*
 * 2. Attempt to find it in the DI Color Name Database
 */

    /*
     * a. Convert String into a XcmsColor structure
     *       Attempt to extract the specification for color_string from the
     *       DI Database (pColor_exact_return).  If the DI Database does not
     *	     have this entry, then return failure.
     */
    retval = _XcmsLookupColorName(ccc, color_string, pColor_exact_return);

    if (retval != XcmsSuccess) {
	/* color_string replaced with a color name, or not found */
	return(_XCMS_NEWNAME);
    }

    if (pColor_exact_return->format == XcmsUndefinedFormat) {
	return(XcmsFailure);
    }

    /*
     * b. If result_format not defined, then assume target format
     *	  is the exact format.
     */
    if (result_format == XcmsUndefinedFormat) {
	result_format = pColor_exact_return->format;
    }

    if ((ClientWhitePointOfCCC(ccc))->format == XcmsUndefinedFormat) {
	pClientWhitePt = ScreenWhitePointOfCCC(ccc);
    } else {
	pClientWhitePt = ClientWhitePointOfCCC(ccc);
    }

    /*
     * c. Convert to the target format, making adjustments for white
     *	  point differences as necessary.
     */
    if (XCMS_DD_ID(pColor_exact_return->format)) {
	/*
	 * The spec format is Device-Dependent, therefore assume the
	 *    its white point is the Screen White Point.
	 */
	if (XCMS_DD_ID(result_format)) {
	    /*
	     * Target format is Device-Dependent
	     *	Therefore, DD --> DD conversion
	     */
	    return(_XcmsDDConvertColors(ccc, pColor_exact_return,
		    1, result_format, (Bool *) NULL));
	} else {
	    /*
	     * Target format is Device-Independent
	     *	Therefore, DD --> DI conversion
	     */
	    if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc,
		    pClientWhitePt, ScreenWhitePointOfCCC(ccc))) {
		return((*ccc->whitePtAdjProc)(ccc, ScreenWhitePointOfCCC(ccc),
			pClientWhitePt, result_format,
			pColor_exact_return, 1, (Bool *) NULL));
	    } else {
		if (_XcmsDDConvertColors(ccc, pColor_exact_return, 1,
			XcmsCIEXYZFormat, (Bool *) NULL) == XcmsFailure) {
		    return(XcmsFailure);
		}
		return(_XcmsDIConvertColors(ccc, pColor_exact_return,
			pClientWhitePt, 1, result_format));
	    }
	}
    } else {
	/*
	 * The spec format is Device-Independent, therefore attempt
	 * to find a database white point.
	 *
	 * If the Database does not have a white point, then assume the
	 * database white point is the same as the Screen White Point.
	 */

	if (_XcmsLookupColorName(ccc, &strptr, &dbWhitePt) != 1) {
	    memcpy((char *)&dbWhitePt,
		   (char *)&ccc->pPerScrnInfo->screenWhitePt,
		   sizeof(XcmsColor));
	}
	if (XCMS_DD_ID(result_format)) {
	    /*
	     * Target format is Device-Dependent
	     *	Therefore, DI --> DD conversion
	     */
	    if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc,
		    &dbWhitePt, ScreenWhitePointOfCCC(ccc))) {
		return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt,
			ScreenWhitePointOfCCC(ccc), result_format,
			pColor_exact_return, 1, (Bool *)NULL));
	    } else {
		if (pColor_exact_return->format != XcmsCIEXYZFormat) {
		    if (_XcmsDIConvertColors(ccc, pColor_exact_return,
			    &dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) {
			return(XcmsFailure);
		    }
		}
		return (_XcmsDDConvertColors(ccc, pColor_exact_return, 1,
			result_format, (Bool *)NULL));
	    }
	} else {
	    /*
	     * Target format is Device-Independent
	     *	Therefore, DI --> DI conversion
	     */
	    if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc,
		    &dbWhitePt, pClientWhitePt)) {
		/*
		 * The calling routine wants to resolve this color
		 * in terms if it's white point (i.e. Client White Point).
		 * Therefore, apply white adjustment for the displacement
		 * between dbWhitePt to clientWhitePt.
		 */
		return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt,
			pClientWhitePt, result_format,
			pColor_exact_return, 1, (Bool *)NULL));
	    } else if (_XcmsEqualWhitePts(ccc,
		    &dbWhitePt, pClientWhitePt)) {
		/*
		 * Can use either dbWhitePt or pClientWhitePt to
		 * convert to the result_format.
		 */
		if (pColor_exact_return->format == result_format) {
		    return(XcmsSuccess);
		} else {
		    return (_XcmsDIConvertColors(ccc, pColor_exact_return,
			    &dbWhitePt, 1, result_format));
		}
	    } else {
		/*
		 * Need to convert to a white point independent color
		 * space (let's choose CIEXYZ) then convert to the
		 * target color space.  Why? Lets assume that
		 * pColor_exact_return->format and result format
		 * are white point dependent format (e.g., CIELUV, CIELAB,
		 * TekHVC ... same or any combination). If so, we'll
		 * need to convert the color with dbWhitePt to an absolute
		 * spec (i.e.  non-white point dependent) then convert that
		 * absolute value with clientWhitePt to the result_format.
		 */
		if (pColor_exact_return->format != XcmsCIEXYZFormat) {
		    if (_XcmsDIConvertColors(ccc, pColor_exact_return,
			    &dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) {
			return(XcmsFailure);
		    }
		}
		if (result_format == XcmsCIEXYZFormat) {
		    return(XcmsSuccess);
		} else {
		    return(_XcmsDIConvertColors(ccc, pColor_exact_return,
			    pClientWhitePt, 1, result_format));
		}
	    }
	}
    }
}
Exemple #3
0
/*
 *	NAME
 *		ConvertMixedColors - Convert XcmsColor structures
 *
 *	SYNOPSIS
 */
static Status
ConvertMixedColors(
    XcmsCCC ccc,
    XcmsColor *pColors_in_out,
    XcmsColor *pWhitePt,
    unsigned int nColors,
    XcmsColorFormat targetFormat,
    unsigned char format_flag)
/*
 *	DESCRIPTION
 *		This routine will only convert the following types of
 *		batches:
 *			DI to DI
 *			DD to DD
 *			DD to CIEXYZ
 *		In other words, it will not convert the following types of
 *		batches:
 *			DI to DD
 *			DD to DI(not CIEXYZ)
 *
 *		format_flag:
 *		    0x01 : convert Device-Dependent only specifications to the
 *			target format.
 *		    0x02 : convert Device-Independent only specifications to the
 *			target format.
 *		    0x03 : convert all specifications to the target format.
 *
 *	RETURNS
 *		XcmsFailure if failed,
 *		XcmsSuccess if none of the color specifications were
 *			compressed in the conversion process
 *		XcmsSuccessWithCompression if at least one of the
 *			color specifications were compressed in the
 *			conversion process.
 *
 */
{
    XcmsColor *pColor, *pColors_start;
    XcmsColorFormat format;
    Status retval_tmp;
    Status retval = XcmsSuccess;
    unsigned int iColors;
    unsigned int nBatch;

    /*
     * Convert array of mixed color specifications in batches of
     * contiguous formats to the target format
     */
    iColors = 0;
    while (iColors < nColors) {
	/*
	 * Find contiguous array of color specifications with the
	 * same format
	 */
	pColor = pColors_start = pColors_in_out + iColors;
	format = pColors_start->format;
	nBatch = 0;
	while (iColors < nColors && pColor->format == format) {
		pColor++;
		nBatch++;
		iColors++;
	}
	if (format != targetFormat) {
	    /*
	     * Need to convert this batch from current format to target format.
	     */
	    if (XCMS_DI_ID(format) && (format_flag & DI_FORMAT) &&
		XCMS_DI_ID(targetFormat)) {
		/*
		 * DI->DI
		 *
		 * Format of interest is Device-Independent,
		 * This batch contains Device-Independent specifications, and
		 * the Target format is Device-Independent.
		 */
		retval_tmp = _XcmsDIConvertColors(ccc, pColors_start, pWhitePt,
			nBatch, targetFormat);
	    } else if (XCMS_DD_ID(format) && (format_flag & DD_FORMAT) &&
		    (targetFormat == XcmsCIEXYZFormat)) {
		/*
		 * DD->CIEXYZ
		 *
		 * Format of interest is Device-Dependent,
		 * This batch contains Device-Dependent specifications, and
		 * the Target format is CIEXYZ.
		 *
		 * Since DD->CIEXYZ we can use NULL instead of pCompressed.
		 */
		if ((ccc->whitePtAdjProc != NULL) && !_XcmsEqualWhitePts(ccc,
			pWhitePt, ScreenWhitePointOfCCC(ccc))) {
		    /*
		     * Need to call WhiteAdjustProc (Screen White Point to
		     *   White Point).
		     */
		    retval_tmp = (*ccc->whitePtAdjProc)(ccc,
			    ScreenWhitePointOfCCC(ccc), pWhitePt,
			    XcmsCIEXYZFormat, pColors_start, nBatch,
			    (Bool *)NULL);
		} else {
		    retval_tmp = _XcmsDDConvertColors(ccc, pColors_start,
			    nBatch, XcmsCIEXYZFormat, (Bool *)NULL);
		}
	    } else if (XCMS_DD_ID(format) && (format_flag & DD_FORMAT) &&
		    XCMS_DD_ID(targetFormat)) {
		/*
		 * DD->DD(not CIEXYZ)
		 *
		 * Format of interest is Device-Dependent,
		 * This batch contains Device-Dependent specifications, and
		 * the Target format is Device-Dependent and not CIEXYZ.
		 */
		retval_tmp = _XcmsDDConvertColors(ccc, pColors_start, nBatch,
			targetFormat, (Bool *)NULL);
	    } else {
		/*
		 * This routine is called for the wrong reason.
		 */
		return(XcmsFailure);
	    }
	    if (retval_tmp == XcmsFailure) {
		return(XcmsFailure);
	    }
	    retval = MAX(retval, retval_tmp);
	}
    }
    return(retval);
}