1#include "./AOI_SoftProofRenderer.h" 
    2#include "../GDocument.h" 
    3#include "../GRenderer.h" 
    6#include "../GProfile.h" 
    7#include <PNG Library/png.h> 
    9#include <JPEG Library/jpeglib.h> 
   12#include "../GInstance.h" 
   13#include <ACPL/Utilities.h> 
   14#include <ACPL/FileStream.h> 
   16#include "../GVector.h" 
   17#include "../ColorSpace.h" 
   18#include "../GPlaceHolder.h" 
   19#include "../GRectangle.h" 
   20#include "../FindSpotcolorInLibraries.h" 
   23using namespace aur::PDF;
 
   24using namespace aur::ACPL;
 
   26class ThumbnailRenderer : 
public aur::PDF::Renderer
 
   30        virtual                 ~ThumbnailRenderer();
 
   31        void                    SetProfile( aur::PDF::Document* doc, aur::PDF::ProfilePtr refProf, aur::PDF::Intent intent, aur::PDF::CMM* deviceCMMs );
 
   32        void                    CopyBits( uint8_t* dest, 
const aur::PDF::LRectangle& updateBounds, int32_t rowBytes, 
bool bImageAlphaBlending = 
false );
 
   33        bool                    Update( int32_t, int32_t );
 
   34        const aur::PDF::CMM*    GetDeviceCMM() 
const;
 
   35        void                    SetVisiblePlates( uint64_t mask );
 
   38        typedef struct RGBValues
 
   42        aur::PDF::ProfilePtr            mProofProfile;
 
   43        aur::PDF::CMM*                          mDeviceCMM;
 
   44        aur::PDF::Intent                        mProofIntent;
 
   45        bool                                            mProofProfileOpen;
 
   46        std::vector<RGBValues>          mChannelRGB;
 
   47        double                                          mChannelSolidity[MAX_CHANNELS];
 
   48        std::vector<aur::ACPL::String>  mExtraPlates;
 
   49        uint64_t                                        mVisiblePlates;
 
   50        bool                                            mTransparencyGrid;
 
   58        void                    CopyBitsDeviceN( uint8_t*, 
const aur::PDF::LRectangle&, int32_t, 
bool bImageAlphaBlending );
 
   59        void                    CopyBitsICC( uint8_t*, 
const aur::PDF::LRectangle&, int32_t, 
bool bImageAlphaBlending );
 
   60        void                    CopyBitsNoMatch( uint8_t*, 
const aur::PDF::LRectangle&, int32_t, 
bool bImageAlphaBlending );
 
   61        void                    CopyBitsSingleChannel( uint8_t*, 
const aur::PDF::LRectangle&, int32_t, 
bool bImageAlphaBlending );
 
   63        void                    AddDocumentColorants( aur::PDF::Document* doc );        
 
   64        void                    DeterminePlates( PDF::Document* doc );
 
   67inline const aur::PDF::CMM* ThumbnailRenderer::GetDeviceCMM()
 const 
   72static void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 
   74        fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
 
   85static bool SaveAsPNG( 
const FileSpec& filePath, 
const uint8_t* buf, int32_t width, int32_t height )
 
   87        uint8_t * * buffer = 
new uint8_t*[height];
 
   88        int32_t lineLen = 4 * width;
 
   89        for ( int32_t nCount = 0; nCount < height; nCount++ )
 
   91                buffer[nCount] = 
new unsigned char[lineLen];
 
   92                memcpy( buffer[nCount], buf + (nCount * lineLen) , lineLen );
 
  100        fp = _wfopen( filePath.GetPOSIXPath().w_str(), L
"wb" );
 
  102        fp = fopen( filePath.GetPOSIXPath().ToUTF8(), 
"wb" );
 
  107        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
  109        info_ptr = png_create_info_struct(png_ptr);
 
  110        png_ptr->io_ptr = (png_voidp)fp;
 
  112        png_set_compression_level(png_ptr, 6);
 
  114        png_set_IHDR(png_ptr, info_ptr, width, height,
 
  115                8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
 
  116                PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
  118        double filegamma_ = 0.5;
 
  120        png_set_gAMA(png_ptr, info_ptr, filegamma_);
 
  121        png_set_gAMA(png_ptr, info_ptr, 0.5 );
 
  125        png_text        text_ptr[5];
 
  127        png_convert_from_time_t(&mod_time, gmt);
 
  128        png_set_tIME(png_ptr, info_ptr, &mod_time);
 
  129        text_ptr[0].key = 
"Title";
 
  130        text_ptr[0].text = 
"Preview";
 
  131        text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
 
  132        text_ptr[1].key = 
"Author";
 
  133        text_ptr[1].text = 
"Aurelon";
 
  134        text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
 
  135        text_ptr[2].key = 
"Description";
 
  136        text_ptr[2].text = 
"";
 
  137        text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE;
 
  138        text_ptr[3].key = 
"Creation Time";
 
  139#if defined(PNG_TIME_RFC1123_SUPPORTED) 
  140        text_ptr[3].text = png_convert_to_rfc1123(png_ptr, &mod_time);
 
  142        static const char short_months[12][4] =
 
  143        {
"Jan", 
"Feb", 
"Mar", 
"Apr", 
"May", 
"Jun", 
"Jul", 
"Aug", 
"Sep", 
"Oct", 
"Nov", 
"Dec"};
 
  145        text_ptr[3].text = 
new char[128];
 
  146        sprintf(text_ptr[3].text, 
"%d %s %d %02d:%02d:%02d +0000",
 
  147                mod_time.day % 32, short_months[(mod_time.month - 1) % 12],
 
  148                mod_time.year, mod_time.hour % 24, mod_time.minute % 60,
 
  149                mod_time.second % 61);
 
  151        text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE;
 
  152        text_ptr[4].key = 
"Software";
 
  153        text_ptr[4].text = 
"";
 
  154        text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE;
 
  155        png_set_text(png_ptr, info_ptr, text_ptr, 5);
 
  156        png_ptr->write_data_fn = png_write_data;
 
  157        png_write_info(png_ptr, info_ptr);
 
  159        png_write_image(png_ptr, buffer);
 
  160        png_write_end(png_ptr, info_ptr);
 
  161        png_destroy_write_struct(&png_ptr, &info_ptr);
 
  164        for (
int i = 0; i < height; i++)
 
  180static bool SaveAsJPG(
const ACPL::FileSpec& filePath, 
const uint8_t* buf, int32_t width, int32_t height, int32_t quality )
 
  188        struct jpeg_compress_struct cinfo;
 
  197        struct jpeg_error_mgr jerr;
 
  200        JSAMPROW row_pointer[1];  
 
  210        cinfo.err = jpeg_std_error(&jerr);
 
  212        jpeg_create_compress(&cinfo);
 
  223        fp = _wfopen( filePath.GetPOSIXPath().w_str(), L
"wb" );
 
  225        fp = fopen( filePath.GetPOSIXPath().ToUTF8(), 
"wb" );
 
  230        jpeg_stdio_dest(&cinfo, fp);
 
  237        cinfo.image_width = width;  
 
  238        cinfo.image_height = height;
 
  239        cinfo.input_components = 3;       
 
  240        cinfo.in_color_space = JCS_RGB;     
 
  245        jpeg_set_defaults(&cinfo);
 
  249        jpeg_set_quality(&cinfo, quality, TRUE );
 
  256        jpeg_start_compress(&cinfo, TRUE);
 
  266        row_stride = width * 3; 
 
  268        while (cinfo.next_scanline < cinfo.image_height) {
 
  273                row_pointer[0] =  (JSAMPROW)&buf[cinfo.next_scanline * row_stride];
 
  274                (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
 
  279        jpeg_finish_compress(&cinfo);
 
  286        jpeg_destroy_compress(&cinfo);
 
  310                mDocument = document->mDocument;
 
 
  325        if( !referenceProfile.Exists() )
 
  328        if( !outputProfile.Exists() )
 
  331        mCMM = 
new PDF::CMM();
 
  332        mCMM->Open( outputProfile, PDF::CMM::eOutput, PDF::eRelativeColorimetric );
 
  334        PDF::ColorSpaceObject* cs = NULL;
 
  336        if( mDocument->GetPage()->GetPageColorSpace() )
 
  337                cs = mDocument->GetPage()->GetPageColorSpace();
 
  338        else if( mDocument->GetDocumentColorSpace() )
 
  339                cs = mDocument->GetDocumentColorSpace();
 
  341        if( cs && cs->ResourceType() == PDF::ICCColorSpace::eResourceType )
 
  342                mProfile = 
new PDF::Profile( 
static_cast<PDF::ICCColorSpace*
>( cs ) );
 
  344                mProfile = 
new PDF::Profile( referenceProfile );
 
  346        ThumbnailRenderer* renderer = 
new ThumbnailRenderer();
 
  347        renderer->SetProfile( mDocument, mProfile, PDF::eRelativeColorimetric, mCMM );
 
  348        mDocument->SetRenderer( renderer );
 
 
  358        PDF::ColorSpaceObject* cs = NULL;
 
  359        PDF::ProfilePtr profile = NULL;
 
  361        if( mDocument->GetPage()->GetPageColorSpace() )
 
  362                cs = mDocument->GetPage()->GetPageColorSpace();
 
  364        if( cs && cs->ResourceType() == PDF::ICCColorSpace::eResourceType )
 
  366                profile = 
new PDF::Profile( 
static_cast<PDF::ICCColorSpace*
>( cs ) );
 
  369        if( profile != NULL )
 
  371                ( (ThumbnailRenderer*)mDocument->GetRenderer() )->SetProfile( mDocument, profile, PDF::eRelativeColorimetric, mCMM );
 
  377                ( (ThumbnailRenderer*)mDocument->GetRenderer() )->SetProfile( mDocument, mProfile, PDF::eRelativeColorimetric, mCMM );
 
 
  396bool AOI_SoftProofRenderer::Render( 
const FileSpec& outputPath, 
const char* thumbnailType, int32_t x, int32_t y, int32_t width, int32_t height, uint32_t quality, uint64_t visiblePlates )
 
  398        ( (ThumbnailRenderer*)mDocument->GetRenderer() )->SetVisiblePlates( visiblePlates );
 
  401        float srcPageWidth, srcPageHeight;
 
  402        mDocument->GetPage()->GetDimensions( srcPageWidth, srcPageHeight );
 
  404        if( srcPageWidth > srcPageHeight ) 
 
  406                mDPU = width / srcPageWidth;
 
  410                mDPU = height / srcPageHeight;
 
  416        map.map[0][0] = mDPU;
 
  417        map.map[1][1] = mDPU;
 
  418        map.map[2][0] = float( -1 * x * width );
 
  419        map.map[2][1] = float( -1 * y * height );
 
  421        ( (ThumbnailRenderer*)mDocument->GetRenderer() )->SetMapping( map );
 
  423        ( (ThumbnailRenderer*)mDocument->GetRenderer() )->RenderDocument( mDocument, 
true, 
true, NULL );
 
  426        int32_t destLineBytes;
 
  427        if(::strcmp( thumbnailType, 
"png" ) == 0)
 
  429                destLineBytes = width * (( (ThumbnailRenderer*)mDocument->GetRenderer() )->GetDeviceCMM()->GetSpaceComponents() + 1 );
 
  431        else if(::strcmp( thumbnailType, 
"jpg" ) == 0)
 
  433                destLineBytes = width * ( (ThumbnailRenderer*)mDocument->GetRenderer() )->GetDeviceCMM()->GetSpaceComponents();
 
  440        uint32_t dataLen = destLineBytes * height;
 
  441        uint8_t* data = 
new uint8_t[dataLen];
 
  442        ::memset( data, 0, dataLen );
 
  443        PDF::LRectangle ubounds;
 
  446        ubounds.right = x + width;
 
  447        ubounds.bottom = y + height;
 
  449        if( ::strcmp( thumbnailType, 
"png" ) == 0 )
 
  451                ( (ThumbnailRenderer*)mDocument->GetRenderer() )->CopyBits( data, ubounds, destLineBytes );
 
  452                SaveAsPNG( outputPath, data, width, height );
 
  454        else if( ::strcmp( thumbnailType, 
"jpg" ) == 0 )
 
  456                ( (ThumbnailRenderer*)mDocument->GetRenderer() )->CopyBits( data, ubounds, destLineBytes, 
true );
 
  457                SaveAsJPG( outputPath, data, width, height, quality );
 
 
  474        if( ( (ThumbnailRenderer*)mDocument->GetRenderer() )->Update( width, height ) )
 
  476                mDocument->Invalidate();
 
 
  489        return mDocument->GetRenderer()->mChannelNames[index];
 
 
  499        return (uint32_t)mDocument->GetRenderer()->mChannelNames.size();
 
 
  502typedef enum EProfileSelector
 
  514static  bool    IsDeviceSpace( 
const PDF::ColorSpaceObject* inSpace )
 
  516        if( inSpace->ResourceType() == PDF::IndexColorSpace::eResourceType )
 
  517                return IsDeviceSpace( 
static_cast<const PDF::IndexColorSpace*
>( inSpace )->GetBase() );
 
  518        return dynamic_cast<const PDF::DeviceColorSpace*
>( inSpace ) != NULL;
 
  521static int GetIndex( 
const char* name )
 
  523        static const char * 
const       kChannelNames[] =
 
  525                "Cyan", 
"Magenta", 
"Yellow", 
"Black" 
  527        for( 
int i = 0; i != 4; ++i )
 
  528                if( !::stricmp( name, kChannelNames[ i ] ) )
 
  533static bool IsSubsetOfCMYK( PDF::ColorSpaceObject* cs, uint32_t mappingArray[4] )
 
  535        if( cs->ResourceType() != PDF::DeviceN::eResourceType || cs->NrOfComponents() > 4 )
 
  538        PDF::DeviceN* devN = (PDF::DeviceN*)cs;
 
  540        for( uint32_t i = 0 ; i != devN->NrOfComponents(); ++i )
 
  542                if( ( index = GetIndex( devN->ChannelName( i ) ) ) == -1 )
 
  544                mappingArray[ i ] = uint32_t( index );
 
  549static  PDF::Intent     ConvertIntent( 
bool vector, PDF::Intent intents[4], PDF::ColorSpaceObject* inSpace, 
bool wasDeviceSpace )
 
  551        PDF::Intent     changedIntent = PDF::eMaxEnumIntent;
 
  553                switch( NONINDEXED( inSpace->Space() ) )
 
  556                        changedIntent = intents[ vector ? eRGB_Vector : eRGB_Image ];
 
  558                case PDF::CMYKSpace :
 
  559                        changedIntent = intents[ vector ? eCMYK_Vector : eCMYK_Image ];
 
  561                case PDF::GraySpace :
 
  562                        changedIntent = intents[ vector ? eGray_Vector : eGray_Image ];
 
  565                        changedIntent = intents[ vector ? eCIELab_Vector : eCIELab_Image ];
 
  570        return changedIntent;
 
  573static  PDF::ColorSpace ConvertColorSpace( PDF::Document* doc, PDF::ColorSpaceObject*& inSpace, PDF::ColorSpaceObject* inRGB, PDF::ColorSpaceObject* inCMYK, PDF::ColorSpaceObject* inGray )
 
  575        PDF::ColorSpace changedSpace = PDF::NoSpace;
 
  578                switch( inSpace->Space() )
 
  581                        inSpace = doc->GetDeviceRGBColorSpace();
 
  582                        changedSpace = PDF::RGBSpace;
 
  584                case PDF::CMYKSpace :
 
  585                        inSpace = doc->GetDeviceCMYKColorSpace();
 
  586                        changedSpace = PDF::CMYKSpace;
 
  588                case PDF::GraySpace :
 
  589                        inSpace = doc->GetDeviceGrayColorSpace();
 
  590                        changedSpace = PDF::GraySpace;
 
  596        switch( inSpace->ResourceType() )
 
  598        case PDF::DeviceRGB::eResourceType :
 
  602                        changedSpace = PDF::RGBSpace;
 
  605        case PDF::DeviceCMYK::eResourceType :
 
  606        case PDF::IllustratorCMYK::eResourceType :
 
  610                        changedSpace = PDF::CMYKSpace;
 
  613        case PDF::DeviceGray::eResourceType :
 
  617                        changedSpace = PDF::GraySpace;
 
  620        case PDF::IndexColorSpace::eResourceType :
 
  622                        PDF::IndexColorSpace* idxCS = 
static_cast<PDF::IndexColorSpace*
>( inSpace );
 
  623                        PDF::ColorSpaceObject*  baseCS = idxCS->GetBase();
 
  624                        if( baseCS->ResourceType() != PDF::DeviceN::eResourceType )     
 
  626                                changedSpace = ConvertColorSpace( doc, baseCS, inRGB, inCMYK, inGray );
 
  627                                if( baseCS != idxCS->GetBase() )
 
  628                                        idxCS->SetBase( baseCS );
 
  632        case PDF::DeviceN::eResourceType :
 
  635                        uint32_t        cmykLink[4];
 
  636                        if( IsSubsetOfCMYK( inSpace, cmykLink ) )
 
  639                                changedSpace = PDF::CMYKSpace;
 
  647static bool     ConvertRasterToDeviceCMYK( PDF::RasterPtr ras, PDF::DocumentPtr doc, PDF::RasterPtr& newRaster )
 
  649        uint32_t        cmykLink[4];
 
  650        if( !IsSubsetOfCMYK( ras->GetColorSpace(), cmykLink ) )
 
  652        uint32_t comps = ras->GetColorSpace()->NrOfComponents();
 
  654        PDF::BitmapPtr bitmapPtr = ras->GetBitmap();
 
  655        PDF::BitmapT bitmap = *bitmapPtr->GetBitmap();
 
  656        bitmap.space = doc->GetDeviceCMYKColorSpace();
 
  658        bitmap.rowBytes = bitmap.width * 4;
 
  660        PDF::Import 
import( doc );
 
  661        import.OpenRaster( bitmap );
 
  663        uint8_t* buffer = 
new uint8_t[ bitmap.rowBytes ];
 
  664        ::memset( buffer, 0, bitmap.rowBytes );
 
  666        bitmapPtr->Open( NULL );
 
  668        for( int32_t y = 0; y != bitmap.height; ++y )
 
  670                uint8_t* out = buffer;
 
  671                for( int32_t x = 0; x != bitmap.width; ++x )
 
  673                        data = bitmapPtr->GetPixelPtr( x, y );
 
  674                        for( uint32_t i = 0; i != comps; ++i )
 
  675                                out[ cmykLink[i] ] = data[i];
 
  678                import.SaveLine( buffer );
 
  684        newRaster = 
import.CloseRaster( 
true ); 
 
  686        newRaster->Map( ras->mapping() );
 
  688        newRaster->SetBlendMode( ras->GetBlendMode() );
 
  689        newRaster->SetBlendValue( ras->GetBlendValue() );
 
  690        newRaster->SetIntent( ras->GetIntent() );
 
  691        newRaster->SetVisible( ras->Visible() );
 
  692        newRaster->SetLock( ras->Locked() );
 
  697static void     AssignDefaultProfiles( PDF::ObjectPtr obj, PDF::ICCColorSpace* cs[3], PDF::Intent intents[4], PDF::DocumentPtr doc )
 
  699        PDF::ColorSpaceObject* ioCS;
 
  700        PDF::ColorSpace changedSpace;
 
  701        PDF::Intent             changedIntent;
 
  703        uint32_t                i, cmykLink[4];
 
  707        while( doc->TraverseNext( obj ) )
 
  709                PDF::VectorPtr  vec = 
dynamic_cast<PDF::VectorPtr
>( obj );
 
  712                        if( vec->GetStrokeStyle() )
 
  714                                if( vec->GetStrokeStyle()->ResourceType() == PDF::Solid::eResourceType )
 
  716                                        PDF::SolidPtr   col = 
static_cast<PDF::SolidPtr
>( vec->GetStrokeStyle() );
 
  717                                        ioCS = col->GetSpace();
 
  718                                        isDeviceSpace = IsDeviceSpace( ioCS );
 
  719                                        if( ( changedSpace = ConvertColorSpace( doc, ioCS, cs[eRGB_Vector], cs[eCMYK_Vector], cs[eGray_Vector] ) ) != PDF::NoSpace )
 
  722                                                if( changedSpace == PDF::CMYKSpace )
 
  724                                                        if( IsSubsetOfCMYK( c.space, cmykLink ) )
 
  727                                                                ::memset( c.channel, 0, 4*
sizeof(uint16_t) );
 
  728                                                                for( i = 0 ; i != c.space->NrOfComponents(); ++i )
 
  729                                                                        c.channel[ cmykLink[i] ] = org.channel[i];
 
  730                                                                if( vec->GetBlendMode() == PDF::eBMOverprint1 && vec->GetBlendValue() == 1 )
 
  731                                                                        vec->SetBlendMode( PDF::eBMMultiply );
 
  733                                                        else if( c.space->ResourceType() == PDF::IllustratorCMYK::eResourceType &&
 
  734                                                                vec->GetBlendMode() == PDF::eBMOverprint1 && vec->GetBlendValue() == 1 )
 
  736                                                                for( i = 0 ; i != 4; ++i )
 
  737                                                                        if( c.channel[i] == 0 ) 
 
  739                                                                                vec->SetBlendMode( PDF::eBMMultiply );
 
  745                                                col = 
new PDF::Solid( doc, c );
 
  746                                                vec->SetStrokeStyle( col );
 
  748                                                col = 
static_cast<PDF::SolidPtr
>( vec->GetStrokeStyle() );      
 
  750                                        if( ( changedIntent = ConvertIntent( 
true, intents, ioCS, isDeviceSpace && changedSpace != PDF::NoSpace ) ) != PDF::eMaxEnumIntent )
 
  751                                                vec->SetIntent( changedIntent );
 
  755                                        PDF::ShadingSpacePtr shad = 
dynamic_cast<PDF::ShadingSpacePtr
>( vec->GetStrokeStyle() );
 
  758                                                ioCS = shad->GetColorSpace();
 
  759                                                isDeviceSpace = IsDeviceSpace( ioCS );
 
  760                                                if( ( changedSpace = ConvertColorSpace( doc, ioCS, cs[eRGB_Vector], cs[eCMYK_Vector], cs[eGray_Vector] ) ) != PDF::NoSpace )
 
  762                                                        if( changedSpace == PDF::CMYKSpace && IsSubsetOfCMYK( shad->GetColorSpace(), cmykLink ) )
 
  764                                                                shad->ConvertToDeviceCMYK( cmykLink );
 
  765                                                                if( vec->GetBlendMode() == PDF::eBMOverprint1 && vec->GetBlendValue() == 1 )
 
  766                                                                        vec->SetBlendMode( PDF::eBMMultiply );
 
  768                                                        shad->SetColorSpace( ioCS );
 
  770                                                if( ( changedIntent = ConvertIntent( 
true, intents, ioCS, isDeviceSpace && changedSpace != PDF::NoSpace ) ) != PDF::eMaxEnumIntent )
 
  771                                                        vec->SetIntent( changedIntent );
 
  775                        if( vec->GetFillStyle() )
 
  777                                if( vec->GetFillStyle()->ResourceType() == PDF::Solid::eResourceType )
 
  779                                        PDF::SolidPtr   col = 
static_cast<PDF::SolidPtr
>( vec->GetFillStyle() );
 
  780                                        ioCS = col->GetSpace();
 
  781                                        isDeviceSpace = IsDeviceSpace( ioCS );
 
  782                                        if( ( changedSpace = ConvertColorSpace( doc, ioCS, cs[eRGB_Vector], cs[eCMYK_Vector], cs[eGray_Vector] ) ) != PDF::NoSpace )
 
  785                                                if( changedSpace == PDF::CMYKSpace )
 
  787                                                        if( IsSubsetOfCMYK( c.space, cmykLink ) )
 
  790                                                                ::memset( c.channel, 0, 4*
sizeof(uint16_t) );
 
  791                                                                for( i = 0 ; i != c.space->NrOfComponents(); ++i )
 
  792                                                                        c.channel[ cmykLink[i] ] = org.channel[i];
 
  793                                                                if( vec->GetBlendMode() == PDF::eBMOverprint1 && vec->GetBlendValue() == 1 )
 
  794                                                                        vec->SetBlendMode( PDF::eBMMultiply );
 
  796                                                        else if( c.space->ResourceType() == PDF::IllustratorCMYK::eResourceType &&
 
  797                                                                vec->GetBlendMode() == PDF::eBMOverprint1 && vec->GetBlendValue() == 1 )
 
  799                                                                for( i = 0 ; i != 4; ++i )
 
  800                                                                        if( c.channel[i] == 0 ) 
 
  802                                                                                vec->SetBlendMode( PDF::eBMMultiply );
 
  808                                                col = 
new PDF::Solid( doc, c );
 
  809                                                vec->SetFillStyle( col );
 
  811                                                col = 
static_cast<PDF::SolidPtr
>( vec->GetFillStyle() );        
 
  813                                        if( ( changedIntent = ConvertIntent( 
true, intents, ioCS, isDeviceSpace && changedSpace != PDF::NoSpace ) ) != PDF::eMaxEnumIntent )
 
  814                                                vec->SetIntent( changedIntent );
 
  818                                        PDF::ShadingSpacePtr shad = 
dynamic_cast<PDF::ShadingSpacePtr
>( vec->GetFillStyle() );
 
  821                                                ioCS = shad->GetColorSpace();
 
  822                                                isDeviceSpace = IsDeviceSpace( ioCS );
 
  823                                                if( ( changedSpace = ConvertColorSpace( doc, ioCS, cs[eRGB_Vector], cs[eCMYK_Vector], cs[eGray_Vector] ) ) != PDF::NoSpace )
 
  825                                                        if( changedSpace == PDF::CMYKSpace && IsSubsetOfCMYK( shad->GetColorSpace(), cmykLink ) )
 
  827                                                                shad->ConvertToDeviceCMYK( cmykLink );
 
  828                                                                if( vec->GetBlendMode() == PDF::eBMOverprint1 && vec->GetBlendValue() == 1 )
 
  829                                                                        vec->SetBlendMode( PDF::eBMMultiply );
 
  831                                                        shad->SetColorSpace( ioCS );
 
  833                                                if( ( changedIntent = ConvertIntent( 
true, intents, ioCS, isDeviceSpace && changedSpace != PDF::NoSpace ) ) != PDF::eMaxEnumIntent )
 
  834                                                        vec->SetIntent( changedIntent );
 
  838                                                if( 
auto pattern = 
dynamic_cast<PDF::PatternSpacePtr
>( vec->GetFillStyle() ) )
 
  839                                                        if( pattern->GetTile() && pattern->GetTile()->GetObject() )
 
  840                                                                AssignDefaultProfiles( pattern->GetTile()->GetObject(), cs, intents, doc );
 
  845                else if( obj->GetType() == PDF::gRasterType )
 
  847                        PDF::RasterPtr raster = NULL;
 
  849                        raster = PDF::RasterPtr(obj);
 
  851                        ioCS = raster->GetColorSpace();
 
  852                        isDeviceSpace = IsDeviceSpace( ioCS );
 
  853                        if( ( changedSpace = ConvertColorSpace( doc, ioCS, cs[eRGB_Image], cs[eCMYK_Image], cs[eGray_Image] ) ) != PDF::NoSpace )
 
  855                                if( changedSpace == PDF::CMYKSpace && ConvertRasterToDeviceCMYK( raster, doc, raster ) )
 
  857                                        if( obj->GetBlendMode() == PDF::eBMOverprint1 && obj->GetBlendValue() == 1 )
 
  858                                                raster->SetBlendMode( PDF::eBMMultiply );
 
  859                                        obj->Replace( raster );
 
  863                                raster->SetColorSpace( ioCS );
 
  864                                ioCS = raster->GetColorSpace();
 
  866                        if( ( changedIntent = ConvertIntent( 
false, intents, ioCS, isDeviceSpace && changedSpace != PDF::NoSpace ) ) != PDF::eMaxEnumIntent )
 
  867                                raster->SetIntent( changedIntent );
 
  871                        PDF::SymbolPtr sym = 
dynamic_cast<PDF::SymbolPtr
>( obj );
 
  872                        if( sym && sym->GetObject() )
 
  873                                AssignDefaultProfiles( sym->GetObject(), cs, intents, doc );
 
  890        PDF::ICCColorSpace* cs[3];
 
  891        ACPL::FileSpec sp[3];
 
  895        for( int16_t i = 0; i < 3; i++ )
 
  902                                PDF::ICCColorSpace* newCS = 
new PDF::ICCColorSpace( mDocument, sp[i] );
 
  903                                cs[i] = (PDF::ICCColorSpace*)mDocument->FindEqualResource( newCS );
 
  913        PDF::Intent intents[4];
 
  917                        intents[0] = PDF::eRelativeColorimetric;
 
  920                        intents[0] = PDF::ePerceptual;
 
  923                        intents[0] = PDF::eAbsoluteColorimetric;
 
  926                        intents[0] = PDF::eRelativeColorimetric;
 
  930        intents[3] = intents[1] = intents[2] = intents[0];
 
  931        AssignDefaultProfiles( NULL, cs, intents, mDocument );
 
  932        for( int16_t i = 0; i < 3; i++ )
 
 
  950        TileGenerator tg( tileSettings );
 
  952        float srcPageWidth, srcPageHeight;
 
  953        mDocument->GetPage()->GetDimensions( srcPageWidth, srcPageHeight );
 
  954        tg.InitPage( srcPageWidth, srcPageHeight );
 
  956        if( srcPageWidth > srcPageHeight ) 
 
  958                mDPU = tg.GetPageWidth() * 2 / srcPageWidth;
 
  962                mDPU = tg.GetPageHeight() * 2 / srcPageHeight;
 
  964        ACPL::FileStream* multiStream = NULL;
 
  966        if( !multichannelRender.IsEmpty() )
 
  968                ACPL::FileSpec multiSpec;
 
  969                multiSpec.Make( multichannelRender );
 
  970                if( !multiSpec.Exists() )
 
  972                multiStream = 
new ACPL::FileStream( multiSpec );
 
  976        int32_t multiPixelBytes, multiLineBytes;
 
  979        if( channelIndex == -1 ) 
 
  981                ( (ThumbnailRenderer*)mDocument->GetRenderer() )->SetVisiblePlates( tileSettings.mVisiblePlates );
 
  983        else if( multiStream )
 
  986                *multiStream >> multiPixelBytes;
 
  987                *multiStream >> multiLineBytes;
 
  988                *multiStream >> hasAlpha;
 
  992        struct jpeg_compress_struct cinfo;
 
  993        struct jpeg_error_mgr jerr;
 
  996        JSAMPROW row_pointer[1];  
 
  998        cinfo.err = jpeg_std_error(&jerr);
 
  999        jpeg_create_compress(&cinfo);
 
 1001        ACPL::UString filePath;
 
 1003                if( !outputPath.DirectoryExists() )
 
 1004                        outputPath.CreateDirectory();
 
 1006                f2.Make( outputPath, L
"Converted.jpg" );
 
 1007                filePath = f2.GetPOSIXPath();
 
 1010        fp = _wfopen( filePath.w_str(), L
"wb" );
 
 1012        fp = fopen( filePath.ToUTF8(), 
"wb" );
 
 1016        jpeg_stdio_dest(&cinfo, fp);
 
 1019        ACPL::FileSpec inputSpec, outputSpec;
 
 1021        int32_t currentZoomLevel = tg.GetNrZoomLevels() - 1;
 
 1022        int32_t remainingNrOfTiles = tg.GetTotalNrOfTiles();
 
 1023        uint32_t positionInZoomLevel;
 
 1024        while( currentZoomLevel >= 0 )
 
 1026                tg.SetZoomLevel( currentZoomLevel );
 
 1028                positionInZoomLevel = 1;
 
 1030                uint32_t tilesVertical = 0;
 
 1032                outputSpec.CreateTemporary();
 
 1034                        ACPL::FileStream outputStream( outputSpec );
 
 1035                        ACPL::FileStream* inputFileStream = NULL;
 
 1037                        if( currentZoomLevel != tg.GetNrZoomLevels() - 1 )
 
 1039                                inputFileStream = 
new ACPL::FileStream( inputSpec );
 
 1044                                cinfo.image_width = tg.GetScaledWidth();  
 
 1045                                cinfo.image_height = tg.GetScaledHeight();
 
 1046                                cinfo.input_components = 3;       
 
 1047                                cinfo.in_color_space = JCS_RGB;     
 
 1048                                jpeg_set_defaults(&cinfo);
 
 1049                                jpeg_set_quality(&cinfo, tileSettings.mJpgQuality, TRUE );
 
 1050                                jpeg_start_compress(&cinfo, TRUE);
 
 1051                                row_stride = tg.GetScaledWidth() * 3;
 
 1054                        for( uint32_t band = 0; band != tg.GetNrBands(); ++band )
 
 1056                                uint32_t bandSize = tg.GetBandHeight() * tg.GetScaledWidth() * 3;
 
 1057                                uint8_t* bandData = 
new uint8_t[ bandSize ];
 
 1059                                if( currentZoomLevel == tg.GetNrZoomLevels() - 1 )
 
 1061                                        uint8_t* doubleBandData = NULL;
 
 1062                                        if( channelIndex == -1 )
 
 1064                                                doubleBandData = 
new uint8_t[ 4 * tg.GetBandHeight() * tg.GetScaledWidth() * 4 ];
 
 1066                                                RenderBand( doubleBandData, band * tg.GetBandHeight() * 2, 2 * tg.GetScaledHeight(), tg.GetScaledWidth() * 2, tg.GetBandHeight() * 2 );
 
 1068                                                        SaveMultichannelRender( *multiStream, tg.GetScaledWidth() * 2, 2 * tg.GetBandHeight() );
 
 1069                                                DownsampleRGBBy2( doubleBandData, bandData, 4 * 2 * tg.GetScaledWidth(), 2 * tg.GetBandHeight(), 2 * tg.GetScaledWidth(), 3 * tg.GetScaledWidth(), 4 );
 
 1073                                                doubleBandData = 
new uint8_t[ 4 * tg.GetBandHeight() * tg.GetScaledWidth() * 3 ];
 
 1075                                                        LoadMultiChannelRender(doubleBandData, channelIndex, *multiStream, tg.GetScaledWidth() * 2, 2 * tg.GetBandHeight(), multiPixelBytes, multiLineBytes, hasAlpha );
 
 1076                                                DownsampleRGBBy2( doubleBandData, bandData, 3 * 2 * tg.GetScaledWidth(), 2 * tg.GetBandHeight(), 2 * tg.GetScaledWidth(), 3 * tg.GetScaledWidth(), 3 );
 
 1080                                        uint32_t previewY = 0;
 
 1081                                        while( previewY < tg.GetBandHeight() && jpegY < tg.GetScaledHeight() )
 
 1083                                                row_pointer[0] =  (JSAMPROW)&bandData[previewY * row_stride];
 
 1084                                                (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
 
 1088                                        delete[] doubleBandData;
 
 1092                                        LoadBand( bandData, *inputFileStream, bandSize );
 
 1095                                for( uint32_t j = 0; j < tg.GetTilesVerticalInBand() && tilesVertical != tg.GetTilesVertical(); j++ )
 
 1097                                        for( uint32_t i = 0; i < tg.GetTilesHorizontal(); i++ )
 
 1099                                                tg.WriteTile( i, tilesVertical, remainingNrOfTiles, j, bandData, 3 * tg.GetScaledWidth(), outputPath, positionInZoomLevel );
 
 1100                                                positionInZoomLevel++;
 
 1104                                if( currentZoomLevel > 0 )
 
 1106                                        uint32_t newBandSize = ( tg.GetBandHeight() / 2 ) * ( tg.GetScaledWidth() / 2 ) * 3;
 
 1107                                        uint8_t* newBand = 
new uint8_t[ newBandSize ];
 
 1109                                        DownsampleRGBBy2( bandData, newBand, 3 * tg.GetScaledWidth(), tg.GetBandHeight(), tg.GetScaledWidth(), 3 * ( tg.GetScaledWidth() / 2 ), 3 );
 
 1110                                        SaveBand( newBand, outputStream, newBandSize );
 
 1116                        delete inputFileStream;
 
 1119                inputSpec = outputSpec;
 
 1120                if( currentZoomLevel == tg.GetNrZoomLevels() - 1 )
 
 1122                        jpeg_finish_compress(&cinfo);
 
 1124                        jpeg_destroy_compress(&cinfo);
 
 1129                remainingNrOfTiles -= tg.GetTilesHorizontal() * tg.GetTilesVertical();
 
 1132        if( outputSpec.Exists() )
 
 1133                outputSpec.Delete();
 
 1135        tg.CreateTilesXML( outputPath );
 
 
 1142void AOI_SoftProofRenderer::DownsampleRGBBy2( uint8_t* inBandData, uint8_t* outBandData, uint32_t inRowbytes, uint32_t inHeight, uint32_t inWidth, uint32_t outRowBytes, uint32_t inComponents )
 
 1144        uint8_t* dest8 = outBandData;
 
 1146        bool    evenLine = 
false;
 
 1148        uint32_t height = inHeight / 2;
 
 1149        uint32_t width = inWidth / 2;
 
 1153        uint16_t* extLine = 
new uint16_t[ width * inComponents ];
 
 1156        while( y != height )
 
 1161                        memset( extLine, 0, 2 * width * inComponents );
 
 1168                        *dest16++ += *line++;
 
 1169                        *dest16++ += *line++;
 
 1170                        *dest16++ += *line++;
 
 1171                        line += inComponents - 3;
 
 1179                inBandData += inRowbytes;
 
 1187                                *dest8++ = (uint8_t)( *dest16++ >> 2 );
 
 1188                                *dest8++ = (uint8_t)( *dest16++ >> 2 );
 
 1189                                *dest8++ = (uint8_t)( *dest16++ >> 2 );
 
 1193                evenLine = !evenLine;
 
 1203        mProfile->Dispose();
 
 1205        PDF::Renderer* renderer = mDocument->GetRenderer();
 
 
 1209void AOI_SoftProofRenderer::RenderBand( uint8_t* doubleBandData, uint32_t y, uint32_t height, uint32_t renderingWidth, uint32_t renderingHeight )
 
 1215        map.map[0][0] = mDPU;
 
 1216        map.map[1][1] = mDPU;
 
 1217        map.map[2][1] = - float( y );
 
 1219        ( (ThumbnailRenderer*)mDocument->GetRenderer() )->SetMapping( map );
 
 1220        mDocument->Invalidate();
 
 1221        ( (ThumbnailRenderer*)mDocument->GetRenderer() )->RenderDocument( mDocument, 
true, 
true, NULL );
 
 1223        PDF::LRectangle ubounds;
 
 1226        ubounds.right = renderingWidth;
 
 1227        ubounds.bottom = renderingHeight;
 
 1229        ( (ThumbnailRenderer*)mDocument->GetRenderer() )->CopyBits( doubleBandData, ubounds, renderingWidth * 4 );
 
 1232void AOI_SoftProofRenderer::SaveMultichannelRender( aur::ACPL::FileStream& stream, uint32_t renderingWidth, uint32_t renderingHeight )
 
 1234        if( stream.GetMarker() == 0 )
 
 1237                stream << mDocument->GetRenderer()->mDestPixelBytes;
 
 1238                stream << mDocument->GetRenderer()->mDestLineBytes;
 
 1239                stream << mDocument->GetRenderer()->mHasAlpha;
 
 1241        int32_t size = mDocument->GetRenderer()->mDestLineBytes * renderingHeight;
 
 1242        stream.PutBytes( mDocument->GetRenderer()->mDestImage, size );
 
 1245void AOI_SoftProofRenderer::LoadMultiChannelRender( uint8_t* doubleBandData, int16_t channelIndex, aur::ACPL::FileStream& stream, uint32_t renderingWidth, uint32_t renderingHeight, uint32_t pixelBytes, uint32_t lineBytes, 
bool hasAlpha )
 
 1248        uint8_t* linePointer = 
new uint8_t[ lineBytes ];
 
 1251        register uint8_t backDrop8;
 
 1253        for( uint32_t y = 0; y != renderingHeight; ++y )
 
 1256                stream.GetBytes( linePointer, size );
 
 1258                for (uint32_t x = 0; x != renderingWidth; ++x)
 
 1260                        if( ( alpha = hasAlpha ? p[pixelBytes - 1] : 255 ) == 255 )
 
 1261                                backDrop8 = 255 - p[channelIndex];
 
 1262                        else if( alpha == 0 )
 
 1268                                register uint16_t       backDrop;
 
 1269                                backDrop = ( 255 - alpha ) << 8;
 
 1270                                backDrop8 = uint8_t( ( backDrop + ( 255 - p[channelIndex] ) * alpha ) >> 8 );
 
 1272                        doubleBandData[0] = doubleBandData[1] = doubleBandData[2] = backDrop8;
 
 1273                        doubleBandData += 3;
 
 1277        delete[] linePointer;
 
 1280void AOI_SoftProofRenderer::SaveBand( 
const uint8_t* bandData, ACPL::FileStream& fileStream, int32_t byteCount )
 
 1282        fileStream.PutBytes( bandData, byteCount );
 
 1285void AOI_SoftProofRenderer::LoadBand( uint8_t* bandData, ACPL::FileStream& fileStream, int32_t byteCount )
 
 1287        fileStream.GetBytes( bandData, byteCount );
 
 1290AOI_SoftProofRenderer::TileGenerator::TileGenerator( 
const TileSettings& settings ) :
 
 1291mSettings( settings )
 
 1295void AOI_SoftProofRenderer::TileGenerator::InitPage( 
float pageWidth, 
float pageHeight )
 
 1297        mPageWidth = (uint32_t)( pageWidth / 18 * mSettings.mMaxDpi );
 
 1298        mPageHeight = (uint32_t)( pageHeight / 18 * mSettings.mMaxDpi );
 
 1300        uint32_t maxSize = mPageHeight;
 
 1302        if (mPageWidth > mPageHeight)
 
 1303                maxSize = mPageWidth;
 
 1305        mNrOfzoomLevels = 1;
 
 1306        while (maxSize > mSettings.mTileSize)
 
 1312        int32_t currentZoomlevel = mNrOfzoomLevels - 1;
 
 1313        mTotalNrOfTiles = 1;
 
 1314        uint32_t tilesperColumn, tilesPerRows;
 
 1315        while( currentZoomlevel )
 
 1317                tilesPerRows = ( ( mPageWidth >> ( mNrOfzoomLevels - currentZoomlevel - 1 ) ) + mSettings.mTileSize - 1 ) / mSettings.mTileSize;
 
 1318                tilesperColumn = ( ( mPageHeight >> ( mNrOfzoomLevels - currentZoomlevel - 1 ) ) + mSettings.mTileSize - 1 ) / mSettings.mTileSize;
 
 1319                mTotalNrOfTiles += tilesPerRows * tilesperColumn;
 
 1324void AOI_SoftProofRenderer::TileGenerator::SetZoomLevel( uint32_t level )
 
 1326        mCurrentZoomLevel = level;
 
 1327        mScaledHeight = mPageHeight >> ( mNrOfzoomLevels - level - 1 );
 
 1328        mScaledWidth = mPageWidth >> ( mNrOfzoomLevels - level - 1 );
 
 1329        mTilesHorizontal = ( mScaledWidth + mSettings.mTileSize - 1 ) / mSettings.mTileSize;
 
 1330        mTilesVertical = ( mScaledHeight + mSettings.mTileSize - 1 ) / mSettings.mTileSize;
 
 1331        uint32_t maxMem = mSettings.mMaxMemoryUsage * 1024 * 1024;
 
 1332        uint32_t maxLines = maxMem / ( 3 * mScaledWidth );
 
 1333        if( maxLines >= mScaledHeight )
 
 1336                mBandHeight = mScaledHeight;
 
 1340                mBandHeight = maxLines / mSettings.mTileSize;
 
 1341                mBandHeight = mBandHeight * mSettings.mTileSize;
 
 1342                if( mBandHeight < mSettings.mTileSize )
 
 1343                        mBandHeight = mSettings.mTileSize;
 
 1344                mNrBands = ( mScaledHeight + mBandHeight - 1 ) / mBandHeight;
 
 1348bool AOI_SoftProofRenderer::TileGenerator::WriteTile( uint32_t x, uint32_t y, uint32_t remainingNrOfTiles, uint32_t yInBand, uint8_t* bandData, uint32_t rowbytes, 
const FileSpec& outputPath, uint32_t positionInZoomLevel )
 
 1351        uint32_t tileX = mSettings.mTileSize * x;
 
 1352        uint32_t tileY = mSettings.mTileSize * yInBand;
 
 1354        if( tileX > mScaledWidth|| tileY > mScaledHeight )
 
 1358        uint32_t tileWidth = mSettings.mTileSize;
 
 1359        if ( tileWidth > mScaledWidth )
 
 1361                tileWidth = mScaledWidth;
 
 1363        else if( ( x + 1 ) * mSettings.mTileSize > mScaledWidth )
 
 1365                tileWidth = mScaledWidth - tileX;
 
 1372        uint32_t tileHeight = mSettings.mTileSize;
 
 1373        if( tileHeight > mScaledHeight )
 
 1375                tileHeight = mScaledHeight;
 
 1377        else if( ( y + 1 ) * mSettings.mTileSize > mScaledHeight )
 
 1379                tileHeight = mScaledHeight - mSettings.mTileSize * y;
 
 1382        if( tileHeight <= 0 )
 
 1385        uint32_t folderIndex = ( remainingNrOfTiles - ( mTilesVertical * mTilesHorizontal -  positionInZoomLevel ) - 1 ) / mSettings.mTileSize;
 
 1389        ACPL::UString folderName;
 
 1390        folderName.Format( L
"TileGroup%d", folderIndex );
 
 1391        ACPL::FileSpec outputFolder;
 
 1392        outputFolder.Make( outputPath, folderName );
 
 1393        if( !outputFolder.DirectoryExists() )
 
 1394                outputFolder.CreateDirectory();
 
 1396        ACPL::UString tileName;
 
 1397        tileName.Format( L
"%d-%d-%d.jpg", mCurrentZoomLevel, x, y );
 
 1398        tileSpec.Make( outputFolder, tileName );
 
 1400  struct jpeg_compress_struct cinfo;
 
 1401  struct jpeg_error_mgr jerr;
 
 1403  JSAMPROW row_pointer[1];  
 
 1405  cinfo.err = jpeg_std_error(&jerr);
 
 1406  jpeg_create_compress(&cinfo);
 
 1409  fp = _wfopen( tileSpec.GetPOSIXPath().w_str(), L
"wb" );
 
 1411  fp = fopen( tileSpec.GetPOSIXPath().ToUTF8(), 
"wb" );
 
 1416  jpeg_stdio_dest(&cinfo, fp);
 
 1423  cinfo.image_width = tileWidth;  
 
 1424  cinfo.image_height = tileHeight;
 
 1425  cinfo.input_components = 3;       
 
 1426  cinfo.in_color_space = JCS_RGB;     
 
 1427  jpeg_set_defaults(&cinfo);
 
 1428  jpeg_set_quality(&cinfo, mSettings.mJpgQuality, TRUE );
 
 1429  jpeg_start_compress(&cinfo, TRUE);
 
 1431  row_stride = tileWidth * 3; 
 
 1433  uint8_t* buffer = bandData + tileY * rowbytes + tileX * 3;
 
 1435  while (cinfo.next_scanline < cinfo.image_height) {
 
 1440    row_pointer[0] =  (JSAMPROW)buffer;
 
 1441    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
 
 1444  jpeg_finish_compress(&cinfo);
 
 1446  jpeg_destroy_compress(&cinfo);
 
 1451void AOI_SoftProofRenderer::TileGenerator::CreateTilesXML( 
const FileSpec& outputPath )
 
 1453        ACPL::FileSpec imageProperties;
 
 1454        imageProperties.Make( outputPath, L
"ImageProperties.xml" );
 
 1456        ACPL::XML imagePropertiesXML( 
"IMAGE_PROPERTIES" );
 
 1457        ACPL::XML::Node* xmlRoot = imagePropertiesXML.root;
 
 1458        xmlRoot->AddAttribute( 
"WIDTH", mPageWidth );
 
 1459        xmlRoot->AddAttribute( 
"HEIGHT", mPageHeight );
 
 1460        xmlRoot->AddAttribute( 
"NUMTILES", mTotalNrOfTiles );
 
 1461        xmlRoot->AddAttribute( 
"NUMIMAGES", 1 );
 
 1462        xmlRoot->AddAttribute( 
"VERSION", 1.8 );
 
 1463        xmlRoot->AddAttribute( 
"TILESIZE", mSettings.mTileSize );
 
 1464        xmlRoot->AddAttribute( 
"THUMBNAIL_WIDTH", 128 );
 
 1465        xmlRoot->AddAttribute( 
"THUMBNAIL_HEIGHT", 128 );
 
 1466        xmlRoot->AddAttribute( 
"RESOLUTION", mSettings.mMaxDpi );
 
 1467        imagePropertiesXML.Save( imageProperties );
 
 1470uint32_t AOI_SoftProofRenderer::TileGenerator::GetPageWidth()
 const 
 1475uint32_t AOI_SoftProofRenderer::TileGenerator::GetPageHeight()
 const 
 1480uint32_t AOI_SoftProofRenderer::TileGenerator::GetNrBands()
 const 
 1485uint32_t AOI_SoftProofRenderer::TileGenerator::GetBandHeight()
 const 
 1490uint32_t AOI_SoftProofRenderer::TileGenerator::GetScaledHeight()
 const 
 1492        return mScaledHeight;
 
 1495uint32_t AOI_SoftProofRenderer::TileGenerator::GetScaledWidth()
 const 
 1497        return mScaledWidth;
 
 1500uint32_t AOI_SoftProofRenderer::TileGenerator::GetTilesHorizontal()
 const 
 1502        return mTilesHorizontal;
 
 1505uint32_t AOI_SoftProofRenderer::TileGenerator::GetTilesVertical()
 const 
 1507        return mTilesVertical;
 
 1510uint32_t AOI_SoftProofRenderer::TileGenerator::GetTilesVerticalInBand()
 const 
 1512        return ( mBandHeight + mSettings.mTileSize - 1 ) / mSettings.mTileSize;
 
 1515uint32_t AOI_SoftProofRenderer::TileGenerator::GetNrZoomLevels()
 const 
 1517        return mNrOfzoomLevels;
 
 1520uint32_t AOI_SoftProofRenderer::TileGenerator::GetCurrentZoomLevel()
 const 
 1522        return mCurrentZoomLevel;
 
 1525uint32_t AOI_SoftProofRenderer::TileGenerator::GetTotalNrOfTiles()
 const 
 1527        return mTotalNrOfTiles;
 
 1546AOI_SoftProofRenderer::TileSettings::TileSettings( uint32_t tileSize, uint32_t minZoomSize, uint32_t maxMemoryUsage, 
float maxDpi, int16_t jpgQuality, uint64_t visiblePlates )
 
 1548        mTileSize = tileSize;
 
 1549        mMinZoomSize = minZoomSize;
 
 1550        mMaxMemoryUsage = maxMemoryUsage;
 
 1552        mJpgQuality = jpgQuality;
 
 1553        mVisiblePlates = visiblePlates;
 
 1562void AOI_SoftProofRenderer::TileSettings::SetVisiblePlates( uint64_t visiblePlates )
 
 1564        mVisiblePlates = visiblePlates;
 
 1568ThumbnailRenderer::ThumbnailRenderer() :
 
 1570        mProofProfile( NULL ),
 
 1572        mProofIntent( PDF::eRelativeColorimetric ),
 
 1573        mProofProfileOpen( false ),
 
 1574        mWhichCopy( eNoMatch )
 
 1576        SetAntiAliasGlyph( 
true );
 
 1579        for( uint32_t i = 0; i != MAX_CHANNELS; ++i )
 
 1580                mChannelSolidity[i] = 0;
 
 1583ThumbnailRenderer::~ThumbnailRenderer()
 
 1587                if( mProofProfileOpen )
 
 1588                        mProofProfile->Close( PDF::CMM::eInput, mProofIntent );
 
 1589                mProofProfile->Dispose();
 
 1591        mDeviceCMM->Dispose();
 
 1594void ThumbnailRenderer::SetProfile( PDF::Document* doc, PDF::ProfilePtr refProf, PDF::Intent intent, PDF::CMM* deviceCMM )
 
 1599                if( mProofProfileOpen )
 
 1600                        mProofProfile->Close( PDF::CMM::eInput, mProofIntent );
 
 1601                mProofProfile->Dispose();
 
 1603        mProofProfile = refProf;
 
 1604        mProofIntent = intent;
 
 1606        mDeviceCMM->Dispose();
 
 1607        mDeviceCMM = deviceCMM;
 
 1608        mProofProfileOpen = 
false;
 
 1609        mVisiblePlates = UINT64_MAX;
 
 1614        for( uint32_t i = 0; i != MAX_CHANNELS; ++i )
 
 1615                mChannelSolidity[i] = 0;
 
 1616        mChannelRGB.clear();
 
 1617        mExtraPlates.clear();
 
 1623                DeterminePlates( doc );
 
 1624                AddDocumentColorants( doc );
 
 1627        Setup( mProofProfile->GetFileSpec(), mExtraPlates, mDeviceWidth, mDeviceHeight, 
true, 
false, 
true );
 
 1629        switch( mProofProfile->GetSpace() )
 
 1631        case PDF::RGBSpace :
 
 1632                if( mComponents > 3 )
 
 1633                        mWhichCopy = eDeviceN;
 
 1635                        mWhichCopy = ::memcmp( &mProofProfile->GetHeader(), &mDeviceCMM->GetHeader(), 16 * 
sizeof(uint32_t) ) == 0 &&
 
 1636                        ::memcmp( &mProofProfile->GetHeader().illuminant, &mDeviceCMM->GetHeader().illuminant, 6 + 4 ) == 0 ? eNoMatch : eICC;
 
 1638        case PDF::CMYKSpace :
 
 1639                if( mComponents > 4 )
 
 1640                        mWhichCopy = eDeviceN;
 
 1645                mWhichCopy = eDeviceN;
 
 1649        if( mWhichCopy == eICC || mWhichCopy == eDeviceN )
 
 1651                mProofProfile->Open( PDF::CMM::eInput, mProofIntent );
 
 1656                mProofProfileOpen = 
true;
 
 1660bool    ThumbnailRenderer::Update( int32_t inWidth, int32_t inHeight )
 
 1662        if( mDeviceWidth != inWidth || mDeviceHeight != inHeight )
 
 1664                Setup( mProofProfile->GetFileSpec(), mExtraPlates, inWidth, inHeight, 
true, 
false, 
true );
 
 1670static void     DetermineCIELab( 
const double* in, PDF::ColorSpaceObject* inSpace, PDF::CMM* destCMM, 
double outLab[3] )
 
 1673        if( inSpace->Space() == PDF::LABSpace )
 
 1682        uint32_t        inComps = inSpace->NrOfComponents();
 
 1683        uint32_t        outComps = destCMM->GetSpaceComponents();
 
 1684        if( inComps <= outComps && 
dynamic_cast<PDF::DeviceColorSpace*
>( inSpace ) != NULL )
 
 1687                uint32_t        linkCnt = 0;
 
 1688                double  val[MAX_CHANNELS];
 
 1689                ::memset( val, 0, MAX_CHANNELS*
sizeof(
double) );
 
 1690                for( uint32_t i = 0; i != inComps && linkCnt == i; ++i )
 
 1692                        const char* inChannelName = inSpace->ChannelName( i );
 
 1693                        for( uint32_t j = 0; j != outComps; ++j )
 
 1695                                const char* outChannelName = destCMM->GetChannelName( j );
 
 1696                                if( ::stricmp( inChannelName, outChannelName ) == 0 )
 
 1705                if( linkCnt == inComps )
 
 1707                        destCMM->Color2Lab( val, outLab );
 
 1712        uint16_t        in16[MAX_CHANNELS];
 
 1713        for( uint32_t i = 0; i != inComps; ++i )
 
 1714                in16[i] = uint16_t( in[i] * PDF::Component1 );
 
 1715        inSpace->GetCIELab( in16, outLab );
 
 1718void    ThumbnailRenderer::DeterminePlates( PDF::Document* doc )
 
 1724        int32_t         profileChannelCount = ColorSpaceComponents( mProofProfile->GetSpace() );
 
 1725        std::vector<PDF::Document::Colorant> extraPlates;
 
 1726        std::vector<PDF::Function*>                     colorantFunc;
 
 1727        std::vector<PDF::ColorSpaceObject*>     colorantSpace;
 
 1728        std::vector<PDF::DeviceN*>                      devNs;
 
 1729        PDF::Document::Colorant                         colorant;
 
 1731        PDF::DeviceN*   devn = NULL;
 
 1732        int32_t devNCnt = 0;
 
 1733        while( ( devn = (PDF::DeviceN*)doc->TraverseCommitedResources( PDF::DeviceN::eResourceType, devn ) ) != NULL )
 
 1736                for( j = 0; j != devn->NrOfComponents(); ++j )
 
 1738                        const char* n = devn->ChannelName( j );
 
 1739                        bool    found = ::strcmp( n, 
"None" ) == 0 || ::strcmp( n, 
"All" ) == 0;
 
 1741                        if( mProofProfile->GetSpace() == PDF::GraySpace || mProofProfile->GetSpace() == PDF::RGBSpace )
 
 1744                                for( int32_t ch = 0; !found && ch != profileChannelCount; ++ch )
 
 1746                                        String  profChannelName = mProofProfile->GetChannel( ch );
 
 1747                                        found = profChannelName == n;
 
 1751                                found = doc->colorantIndex( n ) >= 0;
 
 1754                                for( i = 0; i != extraPlates.size() && ::stricmp( n, extraPlates[i].name ); ++i )
 
 1756                                if( i < uint32_t( doc->GetInstance()->GetMaxChannels()-profileChannelCount-doc->colorantCount() ) )
 
 1758                                        if( i == extraPlates.size() )
 
 1761                                                bool inRepo = 
false;
 
 1762                                                if( devn->NrOfComponents() == 1 && devn->OwnerCount() == 1 )
 
 1763                                                        for( int32_t r = 0 ; r != doc->GetRepositoryStyleCount(); ++r )
 
 1765                                                                PDF::Style*     s = doc->GetRepositoryStyle( r );
 
 1766                                                                if( s->ResourceType() == PDF::Solid::eResourceType )
 
 1768                                                                        if( devn->GetResourceID() == PDF::SolidPtr(s)->GetSpace()->GetResourceID() )
 
 1773                                                        if( inRepo == 
false )
 
 1775                                                                colorant = PDF::Document::Colorant();
 
 1777                                                                extraPlates.push_back( colorant );
 
 1778                                                                colorantSpace.push_back( devn->ChannelSpace( j ) );
 
 1779                                                                colorantFunc.push_back( devn->ChannelFunction( j ) );
 
 1780                                                                devNs.push_back( devn );
 
 1783                                        else if( colorantSpace[i] == NULL )
 
 1785                                                colorantSpace[i] = devn->ChannelSpace( j );
 
 1786                                                colorantFunc[i] = devn->ChannelFunction( j );
 
 1793        if( extraPlates.empty() )
 
 1796        mProofProfile->Open( PDF::CMM::eInput, PDF::eAbsoluteColorimetric );
 
 1797        PDF::CMM* proofCMM = mProofProfile->GetCMM( PDF::CMM::eInput, PDF::eAbsoluteColorimetric );
 
 1799        PDF::LookupSpotColor    fe;
 
 1800        for( 
size_t col = 0; col != extraPlates.size(); ++col )
 
 1802                colorant = extraPlates[col];
 
 1803                double  tr[MAX_CHANNELS];
 
 1804                if( colorantSpace[col] )
 
 1807                        colorantFunc[col]->Transform( &in, tr );
 
 1808                        DetermineCIELab( tr, colorantSpace[col], proofCMM, colorant.lab );
 
 1812                        if( fe.FindInLibraries( colorant.name ) && fe.mSpace == PDF::LABSpace )
 
 1814                                colorant.lab[0] = fe.mLab[ 0 ];
 
 1815                                colorant.lab[1] = fe.mLab[ 1 ];
 
 1816                                colorant.lab[2] = fe.mLab[ 2 ];
 
 1820                                if( !::stricmp( colorant.name, 
"Red" ) ||
 
 1821                                        !::stricmp( colorant.name, 
"Green" ) ||
 
 1822                                        !::stricmp( colorant.name, 
"Blue" ) )
 
 1824                                        uint16_t        rgb16[3] = { 0, 0, 0 };
 
 1825                                        if( !::stricmp( colorant.name, 
"Red" ) )
 
 1826                                                rgb16[1] = rgb16[2] = PDF::Component1;
 
 1827                                        else if( !::stricmp( colorant.name, 
"Green" ) )
 
 1828                                                rgb16[0] = rgb16[2] = PDF::Component1;
 
 1830                                                rgb16[0] = rgb16[1] = PDF::Component1;
 
 1832                                        doc->GetDeviceCMYKColorSpace()->GetCIELab( rgb16, lab );
 
 1833                                        colorant.lab[0] = float( lab[0] );
 
 1834                                        colorant.lab[1] = float( lab[1] );
 
 1835                                        colorant.lab[2] = float( lab[2] );
 
 1839                                        PDF::DeviceN*   devN = devNs[ col ];
 
 1841                                        double  in[MAX_CHANNELS];
 
 1842                                        ::memset( in, 0, MAX_CHANNELS * 
sizeof( 
double ) );
 
 1845                                        while( ::stricmp( devN->ChannelName( index ), colorant.name ) )
 
 1849                                        devN->GetFunction()->Transform( in, tr );
 
 1850                                        DetermineCIELab( tr, devN->GetAlternate(), proofCMM, colorant.lab );
 
 1856                        if( doc->GetPageCount() == 1 &&
 
 1857                                doc->GetPage()->GetFirstLayer()->GetNext() == NULL &&
 
 1858                                doc->GetPage()->GetFirstLayer()->GetFirstChild() &&
 
 1859                                doc->GetPage()->GetFirstLayer()->GetFirstChild()->GetNext() == NULL &&
 
 1860                                doc->GetPage()->GetFirstLayer()->GetFirstChild()->GetType() == PDF::gRasterType )
 
 1862                                PDF::RasterPtr ras = (PDF::RasterPtr)doc->GetPage()->GetFirstLayer()->GetFirstChild();
 
 1863                                XML* xml = ras->MetaData( 
false );
 
 1866                                        for( 
auto& chan : *xml->root->GetNodeByName( 
"ChannelInfo" ) )
 
 1867                                                if( chan.GetAttributeByName( 
"Name" )->ToString() == colorant.name )
 
 1868                                                        colorant.solidity = chan.GetNodeByName( 
"Opacity" )->ToFloat();
 
 1874                while( cIdx != doc->colorantCount() )
 
 1876                        if( ::stricmp( doc->colorant( cIdx ).name, colorant.name ) == 0 )
 
 1880                doc->setColorant( cIdx, colorant );
 
 1883        mProofProfile->Close( PDF::CMM::eInput, PDF::eAbsoluteColorimetric );
 
 1886void    ThumbnailRenderer::AddDocumentColorants( PDF::Document* doc )
 
 1893        int32_t profileChannelCount = ColorSpaceComponents( mProofProfile->GetSpace() );
 
 1894        for( i = 0; i != doc->colorantCount() && i < uint32_t( doc->GetInstance()->GetMaxChannels() - profileChannelCount ); ++i )
 
 1897                const PDF::Document::Colorant& colorant = doc->colorant(i);
 
 1898                if( mProofProfile->GetSpace() == PDF::GraySpace || mProofProfile->GetSpace() == PDF::RGBSpace )
 
 1901                        for( int32_t ch = 0; !found && ch != profileChannelCount; ++ch )
 
 1903                                ACPL::String    profChannelName = mProofProfile->GetChannel( ch );
 
 1904                                found = profChannelName == colorant.name;
 
 1908                                j = mExtraPlates.size();
 
 1909                                mExtraPlates.push_back( colorant.name );
 
 1913                                RGBValues       channelRGB;
 
 1915                                double  dL = ( ( colorant.lab[0] / 100 ) - 1 ) * 0xFF;
 
 1916                                double  da = colorant.lab[1];
 
 1917                                double  db = colorant.lab[2];
 
 1919                                if( colorant.tvi == 0 )
 
 1921                                        for( v = 0; v != 256; ++v )
 
 1923                                                labV[0] = uint16_t( 0xFF00 + v * dL );
 
 1924                                                labV[1] = uint16_t( 0x8000 + v * da );
 
 1925                                                labV[2] = uint16_t( 0x8000 + v * db );
 
 1926                                                mDeviceCMM->Lab2Image( labV, rgb8, 1 );
 
 1927                                                channelRGB.v[v][0] = rgb8[ 0 ];
 
 1928                                                channelRGB.v[v][1] = rgb8[ 1 ];
 
 1929                                                channelRGB.v[v][2] = rgb8[ 2 ];
 
 1934                                        for( v = 0; v != 256; ++v )
 
 1936                                                double  percentage = v / 255.0;
 
 1937                                                percentage += sin( percentage * M_PI ) * colorant.tvi;
 
 1938                                                if( percentage < 0 )
 
 1940                                                else if( percentage > 1 )
 
 1944                                                labV[0] = uint16_t( 0xFF00 + percentage * dL );
 
 1945                                                labV[1] = uint16_t( 0x8000 + percentage * da );
 
 1946                                                labV[2] = uint16_t( 0x8000 + percentage * db );
 
 1947                                                mDeviceCMM->Lab2Image( labV, rgb8, 1 );
 
 1948                                                channelRGB.v[v][0] = rgb8[ 0 ];
 
 1949                                                channelRGB.v[v][1] = rgb8[ 1 ];
 
 1950                                                channelRGB.v[v][2] = rgb8[ 2 ];
 
 1953                                mChannelRGB.push_back( channelRGB );
 
 1954                                mChannelSolidity[j] = colorant.solidity;
 
 1959void    ThumbnailRenderer::CopyBitsDeviceN( uint8_t* dest, 
const PDF::LRectangle& updateBounds, int32_t rowBytes, 
bool bImageAlphaBlending )
 
 1961        int32_t w = updateBounds.right - updateBounds.left;
 
 1968        int32_t top = updateBounds.top - int32_t( mState.mapping.map[2][1] );
 
 1969        int32_t bottom = top + updateBounds.bottom - updateBounds.top;
 
 1970        int32_t left = updateBounds.left - int32_t( mState.mapping.map[2][0] );
 
 1971        int32_t right = left + w;
 
 1974        int32_t components = mComponents;
 
 1975        int32_t profComponents = ColorSpaceComponents( mProofProfile->GetSpace() );
 
 1976        bool    showBack = 
false;
 
 1977        bool    mask[MAX_CHANNELS];
 
 1979        for( c = 0, x = 0; c != components; ++c )
 
 1980                if( ( mask[c] = ( ( 1ll << c ) & mVisiblePlates ) == 0 ) == 
false )
 
 1984                CopyBitsSingleChannel( dest, updateBounds, rowBytes, bImageAlphaBlending );
 
 1987        uint16_t*       lab = 
new uint16_t[ w * 3 ];
 
 1988        uint8_t*        blended = 
new uint8_t[ w * ( mComponents > 3 ? mComponents : 3 ) ];
 
 1990        src = mDestImage + updateBounds.top * mDestLineBytes + updateBounds.left * mDestPixelBytes;
 
 1992        for( y = top; y != bottom; ++y )
 
 1996                if( mIsSubstractive )
 
 1998                        for( x = left; x != right; ++x )
 
 2000                                if( ( alpha = srcX[components] ) == 255 )
 
 2002                                        for( c = 0; c != profComponents; ++c )
 
 2004                                                *destX = mask[c] ? 0 : *srcX;
 
 2008                                        srcX += components - profComponents;
 
 2010                                else if( alpha == 0 )
 
 2012                                        for( c = 0; c != profComponents; ++c )
 
 2018                                        for( c = 0; c != profComponents; ++c )
 
 2020                                                *destX = mask[c] ? 0 : uint8_t( ( *srcX * alpha ) >> 8 );
 
 2024                                        srcX += components - profComponents;
 
 2031                        for( x = left; x != right; ++x )
 
 2033                                if( ( alpha = srcX[components] ) == 255 )
 
 2035                                        for( c = 0; c != profComponents; ++c )
 
 2037                                                *destX = mask[c] ? 0 : *srcX;
 
 2041                                        srcX += components - profComponents;
 
 2043                                else if( alpha == 0 )
 
 2045                                        for( c = 0; c != profComponents; ++c )
 
 2051                                        backDrop = ( 255 - alpha ) << 8;
 
 2052                                        for( c = 0; c != profComponents; ++c )
 
 2054                                                *destX = mask[c] ? 0 : uint8_t( ( backDrop + *srcX * alpha ) >> 8 );
 
 2058                                        srcX += components - profComponents;
 
 2066                mProofProfile->Image2Lab( mProofIntent, blended, lab, w );
 
 2067                mDeviceCMM->Lab2Image( lab, blended, w );
 
 2071                for( c = profComponents; c != components; ++c )
 
 2072                        if( mask[c] == 
false )
 
 2074                                const uint8_t (*mul)[256] = GetMUL8();
 
 2075                                const RGBValues&        component = mChannelRGB[c-profComponents];
 
 2077                                srcAlpha = src + components;
 
 2079                                if( mChannelSolidity[c-profComponents] == 0 )
 
 2081                                        for( x = left; x != right; ++x )
 
 2083                                                if( ( alpha = *srcAlpha ) == 255 )
 
 2085                                                else if( alpha != 0 )
 
 2086                                                        alpha = ( *srcX * alpha ) >> 8;
 
 2087                                                uint8_t srcR = component.v[alpha][0];
 
 2088                                                uint8_t srcG = component.v[alpha][1];
 
 2089                                                uint8_t srcB = component.v[alpha][2];
 
 2090                                                srcX += components + 1;
 
 2091                                                srcAlpha += components + 1;
 
 2092                                                *destX = mul[ srcR ][ *destX ];
 
 2094                                                *destX = mul[ srcG ][ *destX ];
 
 2096                                                *destX = mul[ srcB ][ *destX ];
 
 2102                                        double  solidity = mChannelSolidity[c-profComponents];
 
 2104                                        for( x = left; x != right; ++x )
 
 2106                                                if( ( alpha = *srcAlpha ) == 255 )
 
 2108                                                else if( alpha != 0 )
 
 2109                                                        alpha = ( *srcX * alpha ) >> 8;
 
 2110                                                uint8_t srcR = component.v[alpha][0];
 
 2111                                                uint8_t srcG = component.v[alpha][1];
 
 2112                                                uint8_t srcB = component.v[alpha][2];
 
 2113                                                srcX += components + 1;
 
 2114                                                srcAlpha += components + 1;
 
 2125                                                if( ( invSolidity = 1 - ( solidity * alpha / 255 ) ) == 1 )
 
 2127                                                        *destX = mul[ srcR ][ *destX ];
 
 2129                                                        *destX = mul[ srcG ][ *destX ];
 
 2131                                                        *destX = mul[ srcB ][ *destX ];
 
 2136                                                        *destX = mul[ srcR ][ 255 - uint8_t( ( 255 - *destX ) * invSolidity ) ];
 
 2138                                                        *destX = mul[ srcG ][ 255 - uint8_t( ( 255 - *destX ) * invSolidity ) ];
 
 2140                                                        *destX = mul[ srcB ][ 255 - uint8_t( ( 255 - *destX ) * invSolidity ) ];
 
 2151                        srcAlpha = src + components;
 
 2152                        for( x = left; x != right; ++x )
 
 2157                                if( !bImageAlphaBlending )
 
 2158                                        *destX++ = *srcAlpha;
 
 2159                                srcAlpha += components + 1;
 
 2161                        src += mDestLineBytes;
 
 2168void    ThumbnailRenderer::CopyBitsNoMatch( uint8_t* dest, 
const PDF::LRectangle& updateBounds, int32_t rowBytes, 
bool bImageAlphaBlending )
 
 2170        if( ( mVisiblePlates&7 ) == ( 1 << 0 ) || ( mVisiblePlates&7 ) == ( 1 << 1 ) || ( mVisiblePlates&7 ) == ( 1 << 2 ) )
 
 2172                CopyBitsSingleChannel( dest, updateBounds, rowBytes, bImageAlphaBlending );
 
 2181        bool    showBack = 
false;
 
 2183        int32_t top = updateBounds.top - int32_t( mState.mapping.map[2][1] );
 
 2184        int32_t bottom = top + updateBounds.bottom - updateBounds.top;
 
 2185        int32_t left = updateBounds.left - int32_t( mState.mapping.map[2][0] );
 
 2186        int32_t right = left + updateBounds.right - updateBounds.left;
 
 2188        mask[0] = ( ( 1 << 0 ) & mVisiblePlates ) == 0;
 
 2189        mask[1] = ( ( 1 << 1 ) & mVisiblePlates ) == 0;
 
 2190        mask[2] = ( ( 1 << 2 ) & mVisiblePlates ) == 0;
 
 2192        src = mDestImage + updateBounds.top * mDestLineBytes + updateBounds.left * mDestPixelBytes;
 
 2194        for( int32_t y = top; y != bottom; ++y )
 
 2198                src += mDestLineBytes;
 
 2200                for( int32_t x = left; x != right; ++x )
 
 2202                        if( !bImageAlphaBlending )
 
 2211                                if( ( alpha = srcX[3] ) == 255 )
 
 2213                                        *destX++ = mask[0] ? 0 : srcX[0];
 
 2214                                        *destX++ = mask[1] ? 0 : srcX[1];
 
 2215                                        *destX++ = mask[2] ? 0 : srcX[2];
 
 2217                                else if( alpha == 0 )
 
 2219                                        register uint8_t backDrop8;
 
 2220                                        if( showBack && ( ( ( x >> 3 ) + ( y >> 3 ) ) & 1 ) == 0 )
 
 2224                                        *destX++ = backDrop8;
 
 2225                                        *destX++ = backDrop8;
 
 2226                                        *destX++ = backDrop8;
 
 2230                                        if( showBack && ( ( ( x >> 3 ) + ( y >> 3 ) ) & 1 ) == 0 )
 
 2231                                                backDrop = ( 255 - alpha ) * 192;
 
 2233                                                backDrop = ( 255 - alpha ) << 8;
 
 2234                                        *destX++ = uint8_t( ( backDrop + ( mask[0] ? 0 : srcX[0] ) * alpha ) >> 8 );
 
 2235                                        *destX++ = uint8_t( ( backDrop + ( mask[1] ? 0 : srcX[1] ) * alpha ) >> 8 );
 
 2236                                        *destX++ = uint8_t( ( backDrop + ( mask[2] ? 0 : srcX[2] ) * alpha ) >> 8 );
 
 2244void    ThumbnailRenderer::CopyBitsICC( uint8_t* dest, 
const PDF::LRectangle& updateBounds, int32_t rowBytes, 
bool bImageAlphaBlending )
 
 2246        int32_t w = updateBounds.right - updateBounds.left;
 
 2253        int32_t top = updateBounds.top - int32_t( mState.mapping.map[2][1] );
 
 2254        int32_t bottom = top + updateBounds.bottom - updateBounds.top;
 
 2255        int32_t left = updateBounds.left - int32_t( mState.mapping.map[2][0] );
 
 2256        int32_t right = left + w;
 
 2259        int32_t components = mComponents;
 
 2260        bool    mask[MAX_CHANNELS];
 
 2262        for( c = 0, x = 0; c != components; ++c )
 
 2263                if( ( mask[c] = ( int64_t( 1LL << c ) & mVisiblePlates ) == 0 ) == 
false )
 
 2267                CopyBitsSingleChannel( dest, updateBounds, rowBytes, bImageAlphaBlending );
 
 2270        uint16_t*       lab = 
new uint16_t[ w * 3 ];
 
 2271        uint8_t*        blended = 
new uint8_t[ w * ( mComponents > 3 ? mComponents : 3 ) ];
 
 2273        src = mDestImage + updateBounds.top * mDestLineBytes + updateBounds.left * mDestPixelBytes;
 
 2275        for( y = top; y != bottom; ++y )
 
 2279                if( mIsSubstractive )
 
 2281                        for( x = left; x != right; ++x )
 
 2283                                if( ( alpha = srcX[components] ) == 255 )
 
 2285                                        for( c = 0; c != components; ++c )
 
 2287                                                *destX = mask[c] ? 0 : *srcX;
 
 2292                                else if( alpha == 0 )
 
 2294                                        for( c = 0; c != components; ++c )
 
 2300                                        for( c = 0; c != components; ++c )
 
 2302                                                *destX = mask[c] ? 0 : uint8_t( ( *srcX * alpha ) >> 8 );
 
 2312                        for( x = left; x != right; ++x )
 
 2314                                if( ( alpha = srcX[components] ) == 255 )
 
 2316                                        for( c = 0; c != components; ++c )
 
 2318                                                *destX = mask[c] ? 0 : *srcX;
 
 2323                                else if( alpha == 0 )
 
 2325                                        for( c = 0; c != components; ++c )
 
 2331                                        backDrop = ( 255 - alpha ) << 8;
 
 2332                                        for( c = 0; c != components; ++c )
 
 2334                                                *destX = mask[c] ? 0 : uint8_t( ( backDrop + *srcX * alpha ) >> 8 );
 
 2342                mProofProfile->Image2Lab( mProofIntent, blended, lab, w );
 
 2343                mDeviceCMM->Lab2Image( lab, blended, w );
 
 2346                srcAlpha = src + components;
 
 2347                for( x = left; x != right; ++x )
 
 2352                        if( !bImageAlphaBlending )
 
 2353                                *destX++ = *srcAlpha;
 
 2354                        srcAlpha += components + 1;
 
 2356                src += mDestLineBytes;
 
 2363void    ThumbnailRenderer::CopyBitsSingleChannel( uint8_t* dest, 
const PDF::LRectangle& updateBounds, int32_t rowBytes, 
bool bImageAlphaBlending )
 
 2369        bool    showBack = 
false;
 
 2370        int32_t top = updateBounds.top - int32_t( mState.mapping.map[2][1] );
 
 2371        int32_t bottom = top + updateBounds.bottom - updateBounds.top;
 
 2372        int32_t left = updateBounds.left - int32_t( mState.mapping.map[2][0] );
 
 2373        int32_t right = left + updateBounds.right - updateBounds.left;
 
 2374        int32_t components = mComponents;
 
 2376        register uint8_t backDrop8;
 
 2378        for( c = 0; c != components; ++c )
 
 2379                if( ( int64_t( 1LL << c ) & mVisiblePlates ) != 0 )
 
 2382        src = mDestImage + updateBounds.top * mDestLineBytes + updateBounds.left * mDestPixelBytes;
 
 2384        for( int32_t y = top; y != bottom; ++y )
 
 2388                src += mDestLineBytes;
 
 2390                if( mIsSubstractive )
 
 2392                        for( int32_t x = left; x != right; ++x )
 
 2394                                if( ( alpha = srcX[components] ) == 255 )
 
 2395                                        backDrop8 = 255 - srcX[c];
 
 2396                                else if( alpha == 0 )
 
 2398                                        if( showBack && ( ( ( x >> 3 ) + ( y >> 3 ) ) & 1 ) == 0 )
 
 2405                                        register uint16_t       backDrop;
 
 2406                                        if( showBack && ( ( ( x >> 3 ) + ( y >> 3 ) ) & 1 ) == 0 )
 
 2407                                                backDrop = ( 255 - alpha ) * 192;
 
 2409                                                backDrop = ( 255 - alpha ) << 8;
 
 2410                                        backDrop8 = uint8_t( ( backDrop + ( 255 - srcX[c] ) * alpha ) >> 8 );
 
 2412                                *destX++ = backDrop8;
 
 2413                                *destX++ = backDrop8;
 
 2414                                *destX++ = backDrop8;
 
 2416                                if( !bImageAlphaBlending )
 
 2421                                srcX += mDestPixelBytes;
 
 2426                        for( int32_t x = left; x != right; ++x )
 
 2428                                if( ( alpha = srcX[components] ) == 255 )
 
 2429                                        backDrop8 = srcX[c];
 
 2430                                else if( alpha == 0 )
 
 2432                                        if( showBack && ( ( ( x >> 3 ) + ( y >> 3 ) ) & 1 ) == 0 )
 
 2439                                        register uint16_t       backDrop;
 
 2440                                        if( showBack && ( ( ( x >> 3 ) + ( y >> 3 ) ) & 1 ) == 0 )
 
 2441                                                backDrop = ( 255 - alpha ) * 192;
 
 2443                                                backDrop = ( 255 - alpha ) << 8;
 
 2444                                        backDrop8 = uint8_t( ( backDrop + srcX[c] * alpha ) >> 8 );
 
 2446                                *destX++ = backDrop8;
 
 2447                                *destX++ = backDrop8;
 
 2448                                *destX++ = backDrop8;
 
 2450                                if( !bImageAlphaBlending )
 
 2455                                srcX += mDestPixelBytes;
 
 2461void    ThumbnailRenderer::CopyBits( uint8_t* dest, 
const PDF::LRectangle& updateBounds, int32_t rowBytes, 
bool bImageAlphaBlending )
 
 2463        switch( mWhichCopy )
 
 2466                CopyBitsNoMatch( dest, updateBounds, rowBytes, bImageAlphaBlending );
 
 2469                CopyBitsDeviceN( dest, updateBounds, rowBytes, bImageAlphaBlending );
 
 2472                CopyBitsICC( dest, updateBounds, rowBytes, bImageAlphaBlending );
 
 2477void ThumbnailRenderer::SetVisiblePlates( uint64_t mask )
 
 2479        mVisiblePlates = mask;
 
bool RenderTiles(const TileSettings &tileSettings, const aur::ACPL::FileSpec &outputPath, int16_t channelIndex, const aur::ACPL::UString &multichannelRender)
 
void AssignInputProfiles(const aur::ACPL::FileSpec &rgbProfile, const aur::ACPL::FileSpec &cmykProfile, const aur::ACPL::FileSpec &grayProfile, int32_t intent)
 
bool Render(const aur::ACPL::FileSpec &outputPath, const char *thumbnailType, int32_t x, int32_t y, int32_t width, int32_t height, uint32_t quality=100, uint64_t visiblePlates=UINT64_MAX)
 
bool Setup(const aur::ACPL::FileSpec &profileFile, const aur::ACPL::FileSpec &cmmFile)
 
const char * GetDocumentChannelName(uint32_t index)
 
AOI_SoftProofRenderer(AOI_Document *document)
 
uint32_t GetDocumentChannelCount()
 
void UpdateRenderer(uint32_t width, uint32_t height)