/* * 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); }
/* * 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)); } } } } }
/* * 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); }