コード例 #1
0
ファイル: cmsvirt.c プロジェクト: AndresPozo/PCL
// This function creates a named color profile dumping all the contents of transform to a single profile
// In this way, LittleCMS may be used to "group" several named color databases into a single profile.
// It has, however, several minor limitations. PCS is always Lab, which is not very critic since this
// is the normal PCS for named color profiles.
static
cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
{
    _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
    cmsHPROFILE hICC = NULL;
    int i, nColors;
    cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL;

    // Create an empty placeholder
    hICC = cmsCreateProfilePlaceholder(v->ContextID);
    if (hICC == NULL) return NULL;

    // Critical information
    cmsSetDeviceClass(hICC, cmsSigNamedColorClass);
    cmsSetColorSpace(hICC, v ->ExitColorSpace);
    cmsSetPCS(hICC, cmsSigLabData);

    // Tag profile with information
    if (!SetTextTags(hICC, L"Named color devicelink")) goto Error;

    Original = cmsGetNamedColorList(xform);
    if (Original == NULL) goto Error;

    nColors = cmsNamedColorCount(Original);
    nc2     = cmsDupNamedColorList(Original);
    if (nc2 == NULL) goto Error;

    // Colorant count now depends on the output space
    nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut);

    // Make sure we have proper formatters
    cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX,
        FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace))
        | BYTES_SH(2) | CHANNELS_SH(cmsChannelsOf(v ->ExitColorSpace)));

    // Apply the transfor to colorants.
    for (i=0; i < nColors; i++) {
        cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1);
    }

    if (!cmsWriteTag(hICC, cmsSigNamedColor2Tag, (void*) nc2)) goto Error;
    cmsFreeNamedColorList(nc2);

    return hICC;

Error:
    if (hICC != NULL) cmsCloseProfile(hICC);
    return NULL;
}
コード例 #2
0
ファイル: _imagingcms.c プロジェクト: kmike/Pillow
static cmsUInt32Number
findLCMStype(char* PILmode)
{
    if (strcmp(PILmode, "RGB") == 0) {
        return TYPE_RGBA_8;
    }
    else if (strcmp(PILmode, "RGBA") == 0) {
        return TYPE_RGBA_8;
    }
    else if (strcmp(PILmode, "RGBX") == 0) {
        return TYPE_RGBA_8;
    }
    else if (strcmp(PILmode, "RGBA;16B") == 0) {
        return TYPE_RGBA_16;
    }
    else if (strcmp(PILmode, "CMYK") == 0) {
        return TYPE_CMYK_8;
    }
    else if (strcmp(PILmode, "L") == 0) {
        return TYPE_GRAY_8;
    }
    else if (strcmp(PILmode, "L;16") == 0) {
        return TYPE_GRAY_16;
    }
    else if (strcmp(PILmode, "L;16B") == 0) {
        return TYPE_GRAY_16_SE;
    }
    else if (strcmp(PILmode, "YCCA") == 0) {
        return TYPE_YCbCr_8;
    }
    else if (strcmp(PILmode, "YCC") == 0) {
        return TYPE_YCbCr_8;
    }
    else if (strcmp(PILmode, "LAB") == 0) {
        // LabX equvalent like ALab, but not reversed -- no #define in lcms2
        return (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1));
    }

    else {
        /* take a wild guess... but you probably should fail instead. */
        return TYPE_GRAY_8; /* so there's no buffer overrun... */
    }
}
コード例 #3
0
ファイル: gsicc_lcms.c プロジェクト: ststeiger/ghostsvg
/* Transform an entire buffer */
void
gscms_transform_color_buffer(gsicc_link_t *icclink,
                             gsicc_bufferdesc_t *input_buff_desc,
                             gsicc_bufferdesc_t *output_buff_desc,
                             void *inputbuffer,
                             void *outputbuffer)
{

    cmsHTRANSFORM hTransform = (cmsHTRANSFORM) icclink->link_handle;
    DWORD dwInputFormat,dwOutputFormat,curr_input,curr_output;
    int planar,numbytes,big_endian,hasalpha,k;
    unsigned char *inputpos, *outputpos;
    int numchannels;
#if DUMP_CMS_BUFFER
    FILE *fid_in, *fid_out;
#endif
    /* Although little CMS does  make assumptions about data types in its
       transformations you can change it after the fact.  */
    /* Set us to the proper output type */
    /* Note, we could speed this up by passing back the encoded data type
        to the caller so that we could avoid having to go through this
        computation each time if they are doing multiple calls to this
        operation */
    _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) (LPSTR) hTransform;

    curr_input = p->InputFormat;
    curr_output = p->OutputFormat;

    /* Color space MUST be the same */
    dwInputFormat = COLORSPACE_SH(T_COLORSPACE(curr_input));
    dwOutputFormat = COLORSPACE_SH(T_COLORSPACE(curr_output));

    /* Now set if we have planar, num bytes, endian case, and alpha data to skip */
    /* Planar -- pdf14 case for example */
    planar = input_buff_desc->is_planar;
    dwInputFormat = dwInputFormat | PLANAR_SH(planar);
    planar = output_buff_desc->is_planar;
    dwOutputFormat = dwOutputFormat | PLANAR_SH(planar);

    /* 8 or 16 byte input and output */
    numbytes = input_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;  /* littleCMS encodes float with 0 ToDO. */
    dwInputFormat = dwInputFormat | BYTES_SH(numbytes);
    numbytes = output_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;
    dwOutputFormat = dwOutputFormat | BYTES_SH(numbytes);

    /* endian */
    big_endian = !input_buff_desc->little_endian;
    dwInputFormat = dwInputFormat | ENDIAN16_SH(big_endian);
    big_endian = !output_buff_desc->little_endian;
    dwOutputFormat = dwOutputFormat | ENDIAN16_SH(big_endian);

    /* number of channels */
    numchannels = input_buff_desc->num_chan;
    dwInputFormat = dwInputFormat | CHANNELS_SH(numchannels);
    numchannels = output_buff_desc->num_chan;
    dwOutputFormat = dwOutputFormat | CHANNELS_SH(numchannels);

    /* alpha, which is passed through unmolested */
    /* ToDo:  Right now we always must have alpha last */
    /* This is really only going to be an issue when we have
       interleaved alpha data */
    hasalpha = input_buff_desc->has_alpha;
    dwInputFormat = dwInputFormat | EXTRA_SH(hasalpha);
    dwOutputFormat = dwOutputFormat | EXTRA_SH(hasalpha);

    /* Change the formaters */
    cmsChangeBuffersFormat(hTransform,dwInputFormat,dwOutputFormat);

    /* littleCMS knows nothing about word boundarys.  As such, we need to do
       this row by row adjusting for our stride.  Output buffer must already
       be allocated. ToDo:  Check issues with plane and row stride and word
       boundry */
    inputpos = (unsigned char *) inputbuffer;
    outputpos = (unsigned char *) outputbuffer;
    if(input_buff_desc->is_planar){
        /* Do entire buffer.  Care must be taken here
           with respect to row stride, word boundry and number
           of source versus output channels.  We may
           need to take a closer look at this. */
        cmsDoTransform(hTransform,inputpos,outputpos,
                        input_buff_desc->plane_stride);
    } else {
        /* Do row by row. */
        for(k = 0; k < input_buff_desc->num_rows ; k++){
            cmsDoTransform(hTransform,inputpos,outputpos,
                            input_buff_desc->pixels_per_row);
            inputpos += input_buff_desc->row_stride;
            outputpos += output_buff_desc->row_stride;
        }
    }
#if DUMP_CMS_BUFFER
    fid_in = fopen("CM_Input.raw","ab");
    fid_out = fopen("CM_Output.raw","ab");
    fwrite((unsigned char*) inputbuffer,sizeof(unsigned char),
                            input_buff_desc->row_stride,fid_in);
    fwrite((unsigned char*) outputbuffer,sizeof(unsigned char),
                            output_buff_desc->row_stride,fid_out);
    fclose(fid_in);
    fclose(fid_out);
#endif
}
コード例 #4
0
static
DWORD ComputeOutputFormatDescriptor(DWORD dwInput, int OutColorSpace, int bps)
{
    int IsPlanar  = T_PLANAR(dwInput);
    int Channels = 0;
    
    switch (OutColorSpace) {
        
    case PT_GRAY:
        Channels = 1;
        break;
    case PT_RGB:
    case PT_CMY:
    case PT_Lab:
    case PT_YUV:
    case PT_YCbCr:
        Channels = 3;
        break;
        
    case PT_CMYK:
        Channels = 4;
        break;
        
    case  PT_HiFi:
        Channels = 6;
        break;
        
    case PT_HiFi7:
        Channels = 7;
        break;
        
    case  PT_HiFi8:
        Channels = 8;
        break;
        
    case  PT_HiFi9:
        Channels = 9;
        break;
        
    case  PT_HiFi10:
        Channels = 10;
        break;
        
    case  PT_HiFi11:
        Channels = 11;
        break;
        
    case PT_HiFi12:
        Channels = 12;
        break;
        
    case  PT_HiFi13:
        Channels = 13;
        break;
        
    case  PT_HiFi14:
        Channels = 14;
        break;
        
    case  PT_HiFi15:
        Channels = 15;
        break;
        
    default:
        FatalError("Unsupported output color space");
    }
    
    return (COLORSPACE_SH(OutColorSpace)|PLANAR_SH(IsPlanar)|CHANNELS_SH(Channels)|BYTES_SH(bps));
}
コード例 #5
0
static
DWORD GetInputPixelType(TIFF *Bank)
{
     uint16 Photometric, bps, spp, extra, PlanarConfig, *info;
     uint16 Compression, reverse = 0;
     int ColorChannels, IsPlanar = 0, pt = 0;

     TIFFGetField(Bank,           TIFFTAG_PHOTOMETRIC,   &Photometric);
     TIFFGetFieldDefaulted(Bank,  TIFFTAG_BITSPERSAMPLE, &bps);

     if (bps == 1)
       FatalError("Sorry, bilevel TIFFs has nothig to do with ICC profiles");

     if (bps != 8 && bps != 16)
              FatalError("Sorry, 8 or 16 bits per sample only");

     TIFFGetFieldDefaulted(Bank, TIFFTAG_SAMPLESPERPIXEL, &spp);
     TIFFGetFieldDefaulted(Bank, TIFFTAG_PLANARCONFIG, &PlanarConfig);

     switch (PlanarConfig)
     {
     case PLANARCONFIG_CONTIG: IsPlanar = 0; break;
     case PLANARCONFIG_SEPARATE: IsPlanar = 1; break;
     default:

     FatalError("Unsupported planar configuration (=%d) ", (int) PlanarConfig);
     }

     // If Samples per pixel == 1, PlanarConfiguration is irrelevant and need
     // not to be included.

     if (spp == 1) IsPlanar = 0;


     // Any alpha?

     TIFFGetFieldDefaulted(Bank, TIFFTAG_EXTRASAMPLES, &extra, &info);

     // Read alpha channels as colorant

     if (StoreAsAlpha) {

         ColorChannels = spp;
         extra = 0;
     }
     else
        ColorChannels = spp - extra;

     switch (Photometric) {

     case PHOTOMETRIC_MINISWHITE:
                                   
            reverse = 1;

     case PHOTOMETRIC_MINISBLACK:
                                   
            pt = PT_GRAY;                                
            break;

     case PHOTOMETRIC_RGB:
                                   
            pt = PT_RGB;
            break;


     case PHOTOMETRIC_PALETTE:
                                             
            FatalError("Sorry, palette images not supported (at least on this version)"); 

     case PHOTOMETRIC_SEPARATED:
           if (ColorChannels == 4)
                  pt = PT_CMYK;
           else
           if (ColorChannels == 3)
                  pt = PT_CMY;
           else
           if (ColorChannels == 6)
                  pt = PT_HiFi;
           else
           if (ColorChannels == 7)
                  pt = PT_HiFi7;
           else
           if (ColorChannels == 8)
                  pt = PT_HiFi8;           
           else
           if (ColorChannels == 9)
                  pt = PT_HiFi9;           
           else
           if (ColorChannels == 10)
                  pt = PT_HiFi10;           
           else
           if (ColorChannels == 11)
                  pt = PT_HiFi11;           
           else
		   if (ColorChannels == 12)
                  pt = PT_HiFi8;           
		   else
           if (ColorChannels == 13)
                  pt = PT_HiFi13;           
           else
           if (ColorChannels == 14)
                  pt = PT_HiFi14;           
           else
           if (ColorChannels == 15)
                  pt = PT_HiFi15;           
           else
                  FatalError("What a weird separation of %d channels?!?!", ColorChannels);
           break;

     case PHOTOMETRIC_YCBCR:
           TIFFGetField(Bank, TIFFTAG_COMPRESSION, &Compression);
           {
                  uint16 subx, suby;

                  pt = PT_YCbCr;
                  TIFFGetFieldDefaulted(Bank, TIFFTAG_YCBCRSUBSAMPLING, &subx, &suby);
                  if (subx != 1 || suby != 1)
                         FatalError("Sorry, subsampled images not supported");

           }
           break;

     case 9:
			pt = PT_Lab;
			InputLabUsingICC = TRUE;
			break;

     case PHOTOMETRIC_CIELAB:
           pt = PT_Lab;
		   InputLabUsingICC = FALSE;
           break;

    
     case PHOTOMETRIC_LOGLUV:      /* CIE Log2(L) (u',v') */

           TIFFSetField(Bank, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_16BIT);
           pt = PT_YUV;             // *ICCSpace = icSigLuvData;
           bps = 16;               // 16 bits forced by LibTiff
           break;

     default:
           FatalError("Unsupported TIFF color space (Photometric %d)", Photometric);
     }

     // Convert bits per sample to bytes per sample

     bps >>= 3; 

     return (COLORSPACE_SH(pt)|PLANAR_SH(IsPlanar)|EXTRA_SH(extra)|CHANNELS_SH(ColorChannels)|BYTES_SH(bps)|FLAVOR_SH(reverse));
}
コード例 #6
0
// Does convert a transform into a device link profile
cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
{
    cmsHPROFILE hProfile = NULL;
    cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut;
    cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut;
    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
    cmsPipeline* LUT = NULL;
    cmsStage* mpe;
    cmsContext ContextID = cmsGetTransformContextID(hTransform);
    const cmsAllowedLUT* AllowedLUT;
    cmsTagSignature DestinationTag;
    cmsProfileClassSignature deviceClass; 

    _cmsAssert(hTransform != NULL);

    // Get the first mpe to check for named color
    mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);

    // Check if is a named color transform
    if (mpe != NULL) {

        if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
            return CreateNamedColorDevicelink(hTransform);
        }
    }

    // First thing to do is to get a copy of the transformation
    LUT = cmsPipelineDup(xform ->Lut);
    if (LUT == NULL) return NULL;

    // Time to fix the Lab2/Lab4 issue.
    if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {

        if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
            goto Error;
    }

    // On the output side too
    if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {

        if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
            goto Error;
    }


    hProfile = cmsCreateProfilePlaceholder(ContextID);
    if (!hProfile) goto Error;                    // can't allocate

    cmsSetProfileVersion(hProfile, Version);

    FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);

    // Optimize the LUT and precalculate a devicelink

    ChansIn  = cmsChannelsOf(xform -> EntryColorSpace);
    ChansOut = cmsChannelsOf(xform -> ExitColorSpace);

    ColorSpaceBitsIn  = _cmsLCMScolorSpace(xform -> EntryColorSpace);
    ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace);

    FrmIn  = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
    FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);

    deviceClass = cmsGetDeviceClass(hProfile);

     if (deviceClass == cmsSigOutputClass)
         DestinationTag = cmsSigBToA0Tag;
     else
         DestinationTag = cmsSigAToB0Tag;

    // Check if the profile/version can store the result
    if (dwFlags & cmsFLAGS_FORCE_CLUT)
        AllowedLUT = NULL;
    else
        AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);

    if (AllowedLUT == NULL) {

        // Try to optimize
        _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
        AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);

    }

    // If no way, then force CLUT that for sure can be written
    if (AllowedLUT == NULL) {

        dwFlags |= cmsFLAGS_FORCE_CLUT;
        _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);

        // Put identity curves if needed
        if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
             if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)))
                 goto Error;

        if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType)
             if (!cmsPipelineInsertStage(LUT, cmsAT_END,   _cmsStageAllocIdentityCurves(ContextID, ChansOut)))
                 goto Error;

        AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
    }

    // Somethings is wrong...
    if (AllowedLUT == NULL) {
        goto Error;
    }


    if (dwFlags & cmsFLAGS_8BITS_DEVICELINK)
                     cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE);

    // Tag profile with information
    if (!SetTextTags(hProfile, L"devicelink")) goto Error;

    // Store result
    if (!cmsWriteTag(hProfile, DestinationTag, LUT)) goto Error;


    if (xform -> InputColorant != NULL) {
           if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error;
    }

    if (xform -> OutputColorant != NULL) {
           if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
    }

    if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) {
        if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
    }

    // Set the white point
    if (deviceClass == cmsSigInputClass) {
        if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error;
    }
    else {
         if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error;
    }

  
    // Per 7.2.15 in spec 4.3
    cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent);

    cmsPipelineFree(LUT);
    return hProfile;

Error:
    if (LUT != NULL) cmsPipelineFree(LUT);
    cmsCloseProfile(hProfile);
    return NULL;
}
コード例 #7
0
/* Get the link from the CMS, but include proofing and/or a device link
   profile.  Note also, that the source may be a device link profile, in
   which case we will not have a destination profile but could still have
   a proof profile or an additional device link profile */
gcmmhlink_t
gscms_get_link_proof_devlink(gcmmhprofile_t lcms_srchandle,
                             gcmmhprofile_t lcms_proofhandle,
                             gcmmhprofile_t lcms_deshandle,
                             gcmmhprofile_t lcms_devlinkhandle,
                             gsicc_rendering_param_t *rendering_params,
                             bool src_dev_link, int cmm_flags,
                             gs_memory_t *memory)
{
    cmsUInt32Number src_data_type,des_data_type;
    cmsColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;
    int lcms_src_color_space, lcms_des_color_space;
    cmsHPROFILE hProfiles[5];
    int nProfiles = 0;
    unsigned int flag;

    /* Check if the rendering intent is something other than relative colorimetric
       and  if we have a proofing profile.  In this case we need to create the
       combined profile a bit different.  LCMS does not allow us to use different
       intents in the cmsCreateMultiprofileTransform transform.  Also, don't even
       think about doing this if someone has snuck in a source based device link
       profile into the mix */
    if (lcms_proofhandle != NULL &&
            rendering_params->rendering_intent != gsRELATIVECOLORIMETRIC &&
            !src_dev_link) {
        /* First handle the source to proof profile with its particular intent as
           a device link profile */
        cmsHPROFILE src_to_proof;
        cmsHTRANSFORM temptransform;

        temptransform = gscms_get_link(lcms_srchandle, lcms_proofhandle,
                                       rendering_params, cmm_flags, memory);
        /* Now mash that to a device link profile */
        flag = cmsFLAGS_HIGHRESPRECALC;
        if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON ||
                rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
            flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
        }
        src_to_proof = cmsTransform2DeviceLink(temptransform, 3.4, flag);
        /* Free up the link handle */
        cmsDeleteTransform(temptransform);
        src_color_space  = cmsGetColorSpace(src_to_proof);
        lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
        /* littlecms returns -1 for types it does not (but should) understand */
        if (lcms_src_color_space < 0) lcms_src_color_space = 0;
        src_nChannels = cmsChannelsOf(src_color_space);
        /* For now, just do single byte data, interleaved.  We can change this
          when we use the transformation. */
        src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                         CHANNELS_SH(src_nChannels)|BYTES_SH(2));
        if (lcms_devlinkhandle == NULL) {
            des_color_space = cmsGetColorSpace(lcms_deshandle);
        } else {
            des_color_space = cmsGetPCS(lcms_devlinkhandle);
        }
        lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
        if (lcms_des_color_space < 0) lcms_des_color_space = 0;
        des_nChannels = cmsChannelsOf(des_color_space);
        des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                         CHANNELS_SH(des_nChannels)|BYTES_SH(2));
        /* Now, we need to go back through the proofing profile, to the
           destination and then to the device link profile if there was one. */
        hProfiles[nProfiles++] = src_to_proof;  /* Src to proof with special intent */
        hProfiles[nProfiles++] = lcms_proofhandle; /* Proof to CIELAB */
        if (lcms_deshandle != NULL) {
            hProfiles[nProfiles++] = lcms_deshandle;  /* Our destination */
        }
        /* The output device link profile */
        if (lcms_devlinkhandle != NULL) {
            hProfiles[nProfiles++] = lcms_devlinkhandle;
        }
        flag = cmsFLAGS_HIGHRESPRECALC;
        if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON
                || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
            flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
        }
        /* Use relative colorimetric here */
        temptransform = cmsCreateMultiprofileTransformTHR((cmsContext)memory,
                        hProfiles, nProfiles, src_data_type,
                        des_data_type, gsRELATIVECOLORIMETRIC, flag);
        cmsCloseProfile(src_to_proof);
        return temptransform;
    } else {
        /* First handle all the source stuff */
        src_color_space  = cmsGetColorSpace(lcms_srchandle);
        lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
        /* littlecms returns -1 for types it does not (but should) understand */
        if (lcms_src_color_space < 0) lcms_src_color_space = 0;
        src_nChannels = cmsChannelsOf(src_color_space);
        /* For now, just do single byte data, interleaved.  We can change this
          when we use the transformation. */
        src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                         CHANNELS_SH(src_nChannels)|BYTES_SH(2));
        if (lcms_devlinkhandle == NULL) {
            if (src_dev_link) {
                des_color_space = cmsGetPCS(lcms_srchandle);
            } else {
                des_color_space = cmsGetColorSpace(lcms_deshandle);
            }
        } else {
            des_color_space = cmsGetPCS(lcms_devlinkhandle);
        }
        lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
        if (lcms_des_color_space < 0) lcms_des_color_space = 0;
        des_nChannels = cmsChannelsOf(des_color_space);
        des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                         CHANNELS_SH(des_nChannels)|BYTES_SH(2));
        /* lcms proofing transform has a clunky API and can't include the device
           link profile if we have both. So use cmsCreateMultiprofileTransform
           instead and round trip the proofing profile. */
        hProfiles[nProfiles++] = lcms_srchandle;
        /* Note if source is device link, we cannot do any proofing */
        if (lcms_proofhandle != NULL && !src_dev_link) {
            hProfiles[nProfiles++] = lcms_proofhandle;
            hProfiles[nProfiles++] = lcms_proofhandle;
        }
        /* This should be NULL if we have a source device link */
        if (lcms_deshandle != NULL) {
            hProfiles[nProfiles++] = lcms_deshandle;
        }
        /* Someone could have a device link at the output, giving us possibly two
           device link profiles to smash together */
        if (lcms_devlinkhandle != NULL) {
            hProfiles[nProfiles++] = lcms_devlinkhandle;
        }
        flag = cmsFLAGS_HIGHRESPRECALC;
        if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON
                || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
            flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
        }
        return cmsCreateMultiprofileTransformTHR((cmsContext)memory,
                hProfiles, nProfiles, src_data_type,
                des_data_type, rendering_params->rendering_intent, flag);
    }
}
コード例 #8
0
/* Get the link from the CMS. TODO:  Add error checking */
gcmmhlink_t
gscms_get_link(gcmmhprofile_t  lcms_srchandle,
               gcmmhprofile_t lcms_deshandle,
               gsicc_rendering_param_t *rendering_params, int cmm_flags,
               gs_memory_t *memory)
{
    cmsUInt32Number src_data_type,des_data_type;
    cmsColorSpaceSignature src_color_space,des_color_space;
    int src_nChannels,des_nChannels;
    int lcms_src_color_space, lcms_des_color_space;
    unsigned int flag;

    /* Check for case of request for a transfrom from a device link profile
       in that case, the destination profile is NULL */

    /* First handle all the source stuff */
    src_color_space  = cmsGetColorSpace(lcms_srchandle);
    lcms_src_color_space = _cmsLCMScolorSpace(src_color_space);
    /* littlecms returns -1 for types it does not (but should) understand */
    if (lcms_src_color_space < 0) lcms_src_color_space = 0;
    src_nChannels = cmsChannelsOf(src_color_space);
    /* For now, just do single byte data, interleaved.  We can change this
      when we use the transformation. */
    src_data_type = (COLORSPACE_SH(lcms_src_color_space)|
                     CHANNELS_SH(src_nChannels)|BYTES_SH(2));
#if 0
    src_data_type = src_data_type | ENDIAN16_SH(1);
#endif
    if (lcms_deshandle != NULL) {
        des_color_space  = cmsGetColorSpace(lcms_deshandle);
    } else {
        /* We must have a device link profile. */
        des_color_space = cmsGetPCS(lcms_deshandle);
    }
    lcms_des_color_space = _cmsLCMScolorSpace(des_color_space);
    if (lcms_des_color_space < 0) lcms_des_color_space = 0;
    des_nChannels = cmsChannelsOf(des_color_space);
    des_data_type = (COLORSPACE_SH(lcms_des_color_space)|
                     CHANNELS_SH(des_nChannels)|BYTES_SH(2));
    /* endian */
#if 0
    des_data_type = des_data_type | ENDIAN16_SH(1);
#endif
    /* Set up the flags */
    flag = cmsFLAGS_HIGHRESPRECALC;
    if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON
            || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) {
        flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION);
    }
    if (rendering_params->preserve_black == gsBLACKPRESERVE_KONLY) {
        switch (rendering_params->rendering_intent) {
        case INTENT_PERCEPTUAL:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_PERCEPTUAL;
            break;
        case INTENT_RELATIVE_COLORIMETRIC:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC;
            break;
        case INTENT_SATURATION:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_SATURATION;
            break;
        default:
            break;
        }
    }
    if (rendering_params->preserve_black == gsBLACKPRESERVE_KPLANE) {
        switch (rendering_params->rendering_intent) {
        case INTENT_PERCEPTUAL:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_PERCEPTUAL;
            break;
        case INTENT_RELATIVE_COLORIMETRIC:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC;
            break;
        case INTENT_SATURATION:
            rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_SATURATION;
            break;
        default:
            break;
        }
    }
    /* Create the link */
    return cmsCreateTransformTHR((cmsContext)memory,
                                 lcms_srchandle, src_data_type,
                                 lcms_deshandle, des_data_type,
                                 rendering_params->rendering_intent, flag | cmm_flags);
    /* cmsFLAGS_HIGHRESPRECALC)  cmsFLAGS_NOTPRECALC  cmsFLAGS_LOWRESPRECALC*/
}
コード例 #9
0
/* Transform an entire buffer */
void
gscms_transform_color_buffer(gx_device *dev, gsicc_link_t *icclink,
                             gsicc_bufferdesc_t *input_buff_desc,
                             gsicc_bufferdesc_t *output_buff_desc,
                             void *inputbuffer,
                             void *outputbuffer)
{
    cmsHTRANSFORM hTransform = (cmsHTRANSFORM)icclink->link_handle;
    cmsUInt32Number dwInputFormat, dwOutputFormat, num_src_lcms, num_des_lcms;
    int planar,numbytes, big_endian, hasalpha, k;
    unsigned char *inputpos, *outputpos;
#if DUMP_CMS_BUFFER
    FILE *fid_in, *fid_out;
#endif
    /* Although little CMS does  make assumptions about data types in its
       transformations you can change it after the fact.  */
    /* Set us to the proper output type */
    /* Note, we could speed this up by passing back the encoded data type
        to the caller so that we could avoid having to go through this
        computation each time if they are doing multiple calls to this
        operation */
    /* Color space MUST be the same */
    dwInputFormat = COLORSPACE_SH(T_COLORSPACE(cmsGetTransformInputFormat(hTransform)));
    dwOutputFormat = COLORSPACE_SH(T_COLORSPACE(cmsGetTransformOutputFormat(hTransform)));

    /* Now set if we have planar, num bytes, endian case, and alpha data to skip */
    /* Planar -- pdf14 case for example */
    planar = input_buff_desc->is_planar;
    dwInputFormat = dwInputFormat | PLANAR_SH(planar);
    planar = output_buff_desc->is_planar;
    dwOutputFormat = dwOutputFormat | PLANAR_SH(planar);

    /* 8 or 16 byte input and output */
    numbytes = input_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;  /* littleCMS encodes float with 0 ToDO. */
    dwInputFormat = dwInputFormat | BYTES_SH(numbytes);
    numbytes = output_buff_desc->bytes_per_chan;
    if (numbytes>2) numbytes = 0;
    dwOutputFormat = dwOutputFormat | BYTES_SH(numbytes);

    /* endian */
    big_endian = !input_buff_desc->little_endian;
    dwInputFormat = dwInputFormat | ENDIAN16_SH(big_endian);
    big_endian = !output_buff_desc->little_endian;
    dwOutputFormat = dwOutputFormat | ENDIAN16_SH(big_endian);

    /* number of channels.  This should not really be changing! */
    num_src_lcms = T_CHANNELS(cmsGetTransformInputFormat(hTransform));
    num_des_lcms = T_CHANNELS(cmsGetTransformOutputFormat(hTransform));
    if (num_src_lcms != input_buff_desc->num_chan ||
            num_des_lcms != output_buff_desc->num_chan) {
        /* We can't transform this. Someone is doing something odd */
        return;
    }
    dwInputFormat = dwInputFormat | CHANNELS_SH(num_src_lcms);
    dwOutputFormat = dwOutputFormat | CHANNELS_SH(num_des_lcms);

    /* alpha, which is passed through unmolested */
    /* ToDo:  Right now we always must have alpha last */
    /* This is really only going to be an issue when we have
       interleaved alpha data */
    hasalpha = input_buff_desc->has_alpha;
    dwInputFormat = dwInputFormat | EXTRA_SH(hasalpha);
    dwOutputFormat = dwOutputFormat | EXTRA_SH(hasalpha);

    /* Change the formatters */
    cmsChangeBuffersFormat(hTransform,dwInputFormat,dwOutputFormat);

    /* littleCMS knows nothing about word boundarys.  As such, we need to do
       this row by row adjusting for our stride.  Output buffer must already
       be allocated. ToDo:  Check issues with plane and row stride and word
       boundry */
    inputpos = (byte *) inputbuffer;
    outputpos = (byte *) outputbuffer;
    if(input_buff_desc->is_planar) {
        /* Determine if we can do this in one operation or if we have to break
           it up.  Essentially if the width * height = plane_stride then yes.  If
           we are doing some subsection of a plane then no. */
        if (input_buff_desc->num_rows * input_buff_desc->pixels_per_row ==
                input_buff_desc->plane_stride  &&
                output_buff_desc->num_rows * output_buff_desc->pixels_per_row ==
                output_buff_desc->plane_stride) {
            /* Do entire buffer.*/
            cmsDoTransform(hTransform, inputpos, outputpos,
                           input_buff_desc->plane_stride);
        } else {
            /* We have to do this row by row, with memory transfers */
            byte *temp_des, *temp_src;
            int source_size = input_buff_desc->bytes_per_chan *
                              input_buff_desc->pixels_per_row;

            int des_size = output_buff_desc->bytes_per_chan *
                           output_buff_desc->pixels_per_row;
            int y, i;

            temp_src = (byte*) gs_alloc_bytes(icclink->icc_link_cache->memory,
                                              source_size * input_buff_desc->num_chan,
                                              "gscms_transform_color_buffer");
            if (temp_src == NULL)
                return;
            temp_des = (byte*) gs_alloc_bytes(icclink->icc_link_cache->memory,
                                              des_size * output_buff_desc->num_chan,
                                              "gscms_transform_color_buffer");
            if (temp_des == NULL)
                return;
            for (y = 0; y < input_buff_desc->num_rows; y++) {
                byte *src_cm = temp_src;
                byte *src_buff = inputpos;
                byte *des_cm = temp_des;
                byte *des_buff = outputpos;

                /* Put into planar temp buffer */
                for (i = 0; i < input_buff_desc->num_chan; i ++) {
                    memcpy(src_cm, src_buff, source_size);
                    src_cm += source_size;
                    src_buff += input_buff_desc->plane_stride;
                }
                /* Transform */
                cmsDoTransform(hTransform, temp_src, temp_des,
                               input_buff_desc->pixels_per_row);
                /* Get out of temp planar buffer */
                for (i = 0; i < output_buff_desc->num_chan; i ++) {
                    memcpy(des_buff, des_cm, des_size);
                    des_cm += des_size;
                    des_buff += output_buff_desc->plane_stride;
                }
                inputpos += input_buff_desc->row_stride;
                outputpos += output_buff_desc->row_stride;
            }
            gs_free_object(icclink->icc_link_cache->memory, temp_src,
                           "gscms_transform_color_buffer");
            gs_free_object(icclink->icc_link_cache->memory, temp_des,
                           "gscms_transform_color_buffer");
        }
    } else {
        /* Do row by row. */
        for(k = 0; k < input_buff_desc->num_rows ; k++) {
            cmsDoTransform(hTransform, inputpos, outputpos,
                           input_buff_desc->pixels_per_row);
            inputpos += input_buff_desc->row_stride;
            outputpos += output_buff_desc->row_stride;
        }
    }
#if DUMP_CMS_BUFFER
    fid_in = gp_fopen("CM_Input.raw","ab");
    fid_out = gp_fopen("CM_Output.raw","ab");
    fwrite((unsigned char*) inputbuffer,sizeof(unsigned char),
           input_buff_desc->row_stride,fid_in);
    fwrite((unsigned char*) outputbuffer,sizeof(unsigned char),
           output_buff_desc->row_stride,fid_out);
    fclose(fid_in);
    fclose(fid_out);
#endif
}
コード例 #10
0
ファイル: icctrans.c プロジェクト: BorodaZizitopa/ghostscript
static
DWORD MakeFormatDescriptor(icColorSpaceSignature ColorSpace, int Bytes)
{
    int Channels = _cmsChannelsOf(ColorSpace);
    return COLORSPACE_SH(ICC2LCMS(ColorSpace))|BYTES_SH(Bytes)|CHANNELS_SH(Channels)|PLANAR_SH(1);
}