1#include "./AOI_TIFFRenderer.h"
2#include "../GDocument.h"
3#include "../GInstance.h"
4#include "../GProfile.h"
5#include <ACPL/Utilities.h>
6#include "../TIFF/CTiff.h"
7#include "../JPEG/CJPeg.h"
10# define Sleep( x ) usleep( x * 1000 )
14using namespace aur::PDF;
15using namespace aur::ACPL;
17#define kDataUnitsLimit ( 64 * 1024 * 1024 )
24 mDocument( doc.mDocument ),
25 mColorConvertor( NULL ),
26 mImageSpec( doc.mImageSpec ),
32 mColorConvertCallBack( NULL )
36AOI_TIFFRenderer::~AOI_TIFFRenderer()
41void AOI_TIFFRenderer::SetColorConvertCallBack(
::ColorConvertCB cb,
void* ref )
43 mColorConvertCallBack = cb;
44 mColorConvertRef = ref;
47void AOI_TIFFRenderer::Cleanup()
50 while( mReaderEnded ==
false )
52 while( mCMMEnded ==
false )
55 mReaderQueue.DestroyBuffers();
56 mCMMQueue.DestroyBuffers();
57 mWriterQueue.DestroyBuffers();
59 delete mColorConvertor;
60 mColorConvertor = NULL;
62 mOutputCMM->Dispose();
71aur::ExceptionCode AOI_TIFFRenderer::Setup(
const FileSpec& profSpec,
const StringList& extraChannels,
void* banddata, int32_t w, int32_t h,
bool alpha )
75 if( w <= 0 || h <= 0 )
76 throw ErrAssertFailed;
81 Document::GetInfo( *mImageSpec, info );
83 mImageMapping.Reset();
84 mImageMapping.Scale( 0, 0, 18/info.xResolution, 18/info.yResolution );
88 mInputCMM =
new CMM();
89 mInputCMM->Open( info.reference->GetFileSpec(), CMM::eInput, eRelativeColorimetric );
90 mInputCS =
new ICCColorSpace( mDocument, info.reference->GetFileSpec() );
94 switch( NONINDEXED( info.space ) )
97 mInputCS = mDocument->GetDeviceGrayColorSpace();
100 mInputCS = mDocument->GetDeviceRGBColorSpace();
103 mInputCS = mDocument->GetDeviceCMYKColorSpace();
106 mInputCS = mDocument->GetLabColorSpace();
111 if( NONINDEXED( info.space ) == info.space )
114 mInputCS =
new IndexColorSpace( mDocument, mInputCS );
117 mOutputCMM =
new CMM();
118 mOutputCMM->Open( profSpec, CMM::eOutput, eRelativeColorimetric );
119 mOutputCS =
new ICCColorSpace( mDocument, profSpec );
120 mWhite = mOutputCS->Space() == RGBSpace || mOutputCS->Space() == GraySpace ? 255 : 0;
122 mInputOriginal.channelCount = mInputCS->NrOfComponents();
123 mInputOriginal.width = info.pixelWidth;
124 mInputOriginal.height = info.pixelHeight;
125 mInputOriginal.rowBytes = mInputOriginal.channelCount * mInputOriginal.width;
127 mOutputOriginal.channelCount = mOutputCMM->GetSpaceComponents() + (uint32_t)extraChannels.size();
128 mOutputOriginal.width = w;
129 mOutputOriginal.height = h;
130 mOutputOriginal.rowBytes = mOutputOriginal.channelCount * mOutputOriginal.width;
133 if( mInputOriginal.width < mOutputOriginal.width )
134 pixelSize = mOutputOriginal.width;
136 pixelSize = mInputOriginal.width;
137 mLABLine =
new uint16_t[ pixelSize * 3 ];
139 mColorConvertor =
new PDF::Renderer();
140 mDocument->SetRenderer( mColorConvertor );
141 mColorConvertor->Setup( profSpec, extraChannels, w, h, alpha,
false,
false );
143 mOutputBand = (uint8_t*)banddata;
146 if( mInputOriginal.rowBytes < mOutputOriginal.rowBytes )
147 bufferSize = mOutputOriginal.rowBytes;
149 bufferSize = mInputOriginal.rowBytes;
150 uint32_t bufferCnt = kDataUnitsLimit / (bufferSize + bufferSize );
151 if( bufferCnt > 512 )
155 Unit* unit =
new Unit;
156 ::memset( unit, 0,
sizeof(Unit) );
157 unit->mInputData =
new uint8_t[ bufferSize ];
158 unit->mOutputData =
new uint8_t[ bufferSize ];
159 mReaderQueue.AddBuffer( unit );
165 mDocument->GetPage()->GetDimensions( mPageWidth, mPageHeight );
167 catch( aur::ExceptionCode err )
176void AOI_TIFFRenderer::SetMapping(
const AOI_Mapping& docToBandMap )
178 mRenderMapping = (
const Mapping&)docToBandMap;
181void AOI_TIFFRenderer::Render()
184 Mapping map( mImageMapping );
185 map.Map( mRenderMapping );
189 if( ( map.map[1][1] > 0 && map.map[2][1] >= mPreviousMapY ) ||
190 ( map.map[1][1] < 0 && map.map[2][1] <= mPreviousMapY ) )
193 while( mReaderEnded ==
false )
195 while( mCMMEnded ==
false )
198 while( ( unit = mWriterQueue.AquireBuffer() ) != NULL )
199 mReaderQueue.AddBuffer( unit );
200 while( ( unit = mCMMQueue.AquireBuffer() ) != NULL )
201 mReaderQueue.AddBuffer( unit );
204 if( mContinue ==
false )
206 mPreviousMapY = map.map[2][1];
207 mYScale = fabsf( map.map[1][1] );
211 Mapping invmap( map );
213 PDF::Point topLeft( 0, 0 );
214 PDF::Point bottomRight( (
float)mOutputOriginal.width, (
float)mOutputOriginal.height );
215 topLeft.Map( invmap );
216 bottomRight.Map( invmap );
217 if( bottomRight.y < topLeft.y )
219 float h = bottomRight.y;
220 bottomRight.y = topLeft.y;
223 bottomRight.x = topLeft.x;
228 mY_Input_Start = uint32_t( topLeft.y );
232 uint32_t offsetInPixels;
235 offsetInPixels = uint32_t( topLeft.x );
236 if( offsetInPixels > mInputOriginal.width )
237 offsetInPixels = mInputOriginal.width;
241 mInputClipped = mInputOriginal;
242 mInput_X_OffsetBytes = offsetInPixels * mInputOriginal.channelCount;
243 if( uint32_t( bottomRight.x ) < mInputOriginal.width )
244 mInputClipped.width = uint32_t( bottomRight.x );
245 mInputClipped.width -= offsetInPixels;
246 mInputClipped.rowBytes = mInputClipped.width * mInputClipped.channelCount;
249 topLeft.x = topLeft.y = 0;
250 bottomRight.x = (float)mInputOriginal.width;
251 bottomRight.y = (float)mInputOriginal.height;
253 bottomRight.Map( map );
254 if( bottomRight.y < topLeft.y )
256 float h = bottomRight.y;
257 bottomRight.y = topLeft.y;
260 bottomRight.x = topLeft.x;
263 if( bottomRight.y < 0 )
266 mY_Output_Start = uint32_t( bottomRight.y );
271 mY_Output_Start = uint32_t( topLeft.y );
277 offsetInPixels = uint32_t( topLeft.x );
278 if( offsetInPixels > mOutputOriginal.width )
279 offsetInPixels = mOutputOriginal.width;
283 mOutputClipped = mOutputOriginal;
284 mOutput_X_OffsetBytes = offsetInPixels * mOutputClipped.channelCount;
285 if( uint32_t( bottomRight.x ) < mOutputClipped.width )
286 mOutputClipped.width = uint32_t( bottomRight.x );
287 mOutputClipped.width -= offsetInPixels;
288 mOutputClipped.rowBytes = mOutputClipped.width * mOutputClipped.channelCount;
290 mY_Input_Threshold = 0;
291 mY_Output_Threshold = 0;
296 mImageExhausted =
false;
300 mCMMThreadH = ::_beginthread( CMMCreate, 0,
this );
302 ::pthread_create( &mCMMThreadH, NULL, CMMCreate,
this );
303 ::pthread_detach( mCMMThreadH );
306 mReaderEnded =
false;
308 mReaderThreadH = ::_beginthread( ReaderCreate, 0,
this );
310 ::pthread_create( &mReaderThreadH, NULL, ReaderCreate,
this );
311 ::pthread_detach( mReaderThreadH );
315 bool quitThis =
false;
317 uint32_t rightSide_X_Bytes = mOutputOriginal.rowBytes - mOutputClipped.rowBytes - mOutput_X_OffsetBytes;
318 if( mRenderMapping.map[1][1] > 0 )
322 uint8_t* outputLinePtr = mOutputBand;
323 uint32_t outputY = 0;
324 while( outputY < mY_Output_Start && bandY != mOutputOriginal.height )
326 ::memset( outputLinePtr, mWhite, mOutputOriginal.rowBytes );
329 outputLinePtr += mOutputOriginal.rowBytes;
331 mY_Output_Start -= outputY;
332 if( bandY == mOutputOriginal.height )
334 if( mImageExhausted ==
false )
341 while( ( unit = mWriterQueue.AquireBuffer() ) == NULL && mContinue )
348 mImageExhausted =
true;
349 mReaderQueue.AddBuffer( unit );
354 while( mY_Output_Threshold <= mYScale && bandY != mOutputOriginal.height )
356 if( mOutput_X_OffsetBytes )
357 ::memset( outputLinePtr, mWhite, mOutput_X_OffsetBytes );
358 ::memcpy( outputLinePtr + mOutput_X_OffsetBytes, unit->mOutputData, mOutputClipped.rowBytes );
359 if( rightSide_X_Bytes )
360 ::memset( outputLinePtr + mOutput_X_OffsetBytes + mOutputClipped.rowBytes, mWhite, rightSide_X_Bytes );
362 outputLinePtr += mOutputOriginal.rowBytes;
363 mY_Output_Threshold += 1;
365 mY_Output_Threshold -= mYScale;
368 mReaderQueue.AddBuffer( unit );
371 while( mContinue && bandY != mOutputOriginal.height );
378 while( ( unit = mWriterQueue.AquireBuffer() ) == NULL && mContinue )
385 mImageExhausted =
true;
386 mReaderQueue.AddBuffer( unit );
391 if( mOutput_X_OffsetBytes )
392 ::memset( outputLinePtr, mWhite, mOutput_X_OffsetBytes );
393 ::memcpy( outputLinePtr + mOutput_X_OffsetBytes, unit->mOutputData, mOutputClipped.rowBytes );
394 if( rightSide_X_Bytes )
395 ::memset( outputLinePtr + mOutput_X_OffsetBytes + mOutputClipped.rowBytes, mWhite, rightSide_X_Bytes );
397 outputLinePtr += mOutputOriginal.rowBytes;
400 quitThis = unit->mIsLast;
401 mReaderQueue.AddBuffer( unit );
404 while( mContinue && bandY != mOutputOriginal.height );
407 while( bandY != mOutputOriginal.height )
409 ::memset( outputLinePtr, mWhite, mOutputOriginal.rowBytes );
411 outputLinePtr += mOutputOriginal.rowBytes;
420 uint32_t bandY = mOutputOriginal.height;
421 uint8_t* outputLinePtr = mOutputBand + bandY * mOutputOriginal.rowBytes;
422 uint32_t outputY = bandY;
423 while( outputY > mY_Output_Start && bandY != 0 )
427 outputLinePtr -= mOutputOriginal.rowBytes;
428 ::memset( outputLinePtr, mWhite, mOutputOriginal.rowBytes );
430 mY_Output_Start -= outputY;
433 if( mImageExhausted ==
false )
440 while( ( unit = mWriterQueue.AquireBuffer() ) == NULL && mContinue )
447 mImageExhausted =
true;
448 mReaderQueue.AddBuffer( unit );
453 while( mY_Output_Threshold <= mYScale && bandY != 0 )
456 outputLinePtr -= mOutputOriginal.rowBytes;
457 mY_Output_Threshold += 1;
458 if( mOutput_X_OffsetBytes )
459 ::memset( outputLinePtr, mWhite, mOutput_X_OffsetBytes );
461 const uint8_t* in = unit->mOutputData;
462 uint8_t* out = outputLinePtr + mOutput_X_OffsetBytes + mOutputClipped.rowBytes - mOutputClipped.channelCount;
463 uint32_t twoPixels = mOutputClipped.channelCount * 2;
464 for( uint32_t i = 0 ; i != mOutputClipped.width; ++i )
466 for( uint32_t c = 0 ;c != mOutputClipped.channelCount; ++c )
471 if( rightSide_X_Bytes )
472 ::memset( outputLinePtr + mOutput_X_OffsetBytes + mOutputClipped.rowBytes, mWhite, rightSide_X_Bytes );
474 mY_Output_Threshold -= mYScale;
477 quitThis = unit->mIsLast;
478 mReaderQueue.AddBuffer( unit );
481 while( mContinue && bandY != 0 );
488 while( ( unit = mWriterQueue.AquireBuffer() ) == NULL && mContinue )
495 mImageExhausted =
true;
496 mReaderQueue.AddBuffer( unit );
501 outputLinePtr -= mOutputOriginal.rowBytes;
503 if( mOutput_X_OffsetBytes )
504 ::memset( outputLinePtr, mWhite, mOutput_X_OffsetBytes );
506 const uint8_t* in = unit->mOutputData;
507 uint8_t* out = outputLinePtr + mOutput_X_OffsetBytes + mOutputClipped.rowBytes - mOutputClipped.channelCount;
508 uint32_t twoPixels = mOutputClipped.channelCount * 2;
509 for( uint32_t i = 0 ; i != mOutputClipped.width; ++i )
511 for( uint32_t c = 0 ;c != mOutputClipped.channelCount; ++c )
516 if( rightSide_X_Bytes )
517 ::memset( outputLinePtr + mOutput_X_OffsetBytes + mOutputClipped.rowBytes, mWhite, rightSide_X_Bytes );
520 quitThis = unit->mIsLast;
521 mReaderQueue.AddBuffer( unit );
524 while( mContinue && bandY != 0 );
530 outputLinePtr -= mOutputOriginal.rowBytes;
531 ::memset( outputLinePtr, mWhite, mOutputOriginal.rowBytes );
536ACPL_RES AOI_TIFFRenderer::ReaderCreate(
void* param )
538 AOI_TIFFRenderer* obj = (AOI_TIFFRenderer*)param;
543void AOI_TIFFRenderer::Reader()
550 Document::DetermineFileType( *mImageSpec, fileType );
551 if( fileType ==
"tif" )
553 CTiff* tif =
new CTiff( mDocument );
554 plug = tif->GetImport();
555 plug->SetCB(
this, ReaderPlugSetup, ReaderPlugSaveLine );
556 aur::ExceptionCode err = tif->Open( mImageSpec );
560 else if( fileType ==
"jpg" )
562 CJPeg* jpg =
new CJPeg( mDocument );
564 plug->SetCB(
this, ReaderPlugSetup, ReaderPlugSaveLine );
565 aur::ExceptionCode err = jpg->Open( mImageSpec );
571 mDocument->GetPage()->SetDimensions( mPageWidth, mPageHeight );
582aur::ExceptionCode AOI_TIFFRenderer::ReaderPlugSetup(
void* ref,
const aur::PDF::BitmapT& inBitmap)
584 AOI_TIFFRenderer* obj = (AOI_TIFFRenderer*)ref;
585 inBitmap.space->Clone();
586 obj->mInputCS->Dispose();
587 obj->mInputCS = inBitmap.space;
588 obj->mInputOriginal.width = inBitmap.width;
589 obj->mInputOriginal.height = inBitmap.height;
590 obj->mInputOriginal.rowBytes = obj->mInputOriginal.channelCount * obj->mInputOriginal.width;
591 if( obj->mInputClipped.height > obj->mInputOriginal.height )
592 obj->mInputClipped.height = obj->mInputOriginal.height;
597aur::ExceptionCode AOI_TIFFRenderer::ReaderPlugSaveLine(
void* ref,
const uint8_t* inImageLine )
599 AOI_TIFFRenderer* obj = (AOI_TIFFRenderer*)ref;
600 bool postResult =
true;
602 if( obj->mYScale < 1 )
604 postResult = obj->mY_Input_Threshold >= 0;
606 obj->mY_Input_Threshold -= 1;
607 obj->mY_Input_Threshold += obj->mYScale;
609 if( obj->mY_Input < obj->mY_Input_Start )
615 while( ( unit = obj->mReaderQueue.AquireBuffer() ) == NULL && obj->mContinue )
620 ::memcpy( unit->mInputData, inImageLine + obj->mInput_X_OffsetBytes, obj->mInputClipped.rowBytes );
621 unit->mIsLast =
false;
622 obj->mCMMQueue.AddBuffer( unit );
625 if( obj->mY_Input == obj->mInputClipped.height )
628 while( ( unit = obj->mReaderQueue.AquireBuffer() ) == NULL && obj->mContinue )
632 unit->mIsLast =
true;
633 obj->mCMMQueue.AddBuffer( unit );
636 return obj->mContinue ? NoError : ErrUserCanceled;
639ACPL_RES AOI_TIFFRenderer::CMMCreate(
void* param )
641 AOI_TIFFRenderer* obj = (AOI_TIFFRenderer*)param;
646void AOI_TIFFRenderer::ScaleCMM()
648 bool quitThis =
false;
650 if( mColorConvertCallBack )
652 bool set[ MAX_CHANNELS ];
663 if( mInputClipped.width > mOutputClipped.width )
664 sz = mInputClipped.channelCount * mOutputClipped.width;
666 sz = mInputClipped.width * mOutputClipped.channelCount;
669 while( ( unit = mCMMQueue.AquireBuffer() ) == NULL && mContinue )
673 if( unit->mIsLast ==
false )
678 if( mInputClipped.width > mOutputClipped.width )
680 DownscaleFree( mInputClipped.channelCount, unit->mInputData, mInputClipped.width, unit->mOutputData, mOutputClipped.width );
681 ::memcpy( unit->mInputData, unit->mOutputData, sz );
687 if( mColorConvertCallBack( ccd, mColorConvertRef ) ==
false )
691 mInputCMM->Image2Lab( unit->mInputData, mLABLine, mOutputClipped.width );
692 mOutputCMM->Lab2Image( mLABLine, unit->mOutputData, mOutputClipped.width );
695 SimpleConvert( mOutputClipped.width, unit->mInputData, unit->mOutputData );
698 else if( mInputClipped.width == mOutputClipped.width )
704 if( mColorConvertCallBack( ccd, mColorConvertRef ) ==
false )
708 mInputCMM->Image2Lab( unit->mInputData, mLABLine, mInputClipped.width );
709 mOutputCMM->Lab2Image( mLABLine, unit->mOutputData, mOutputClipped.width );
712 SimpleConvert( mOutputClipped.width, unit->mInputData, unit->mOutputData );
721 if( mColorConvertCallBack( ccd, mColorConvertRef ) ==
false )
725 mInputCMM->Image2Lab( unit->mInputData, mLABLine, mInputClipped.width );
726 mOutputCMM->Lab2Image( mLABLine, unit->mInputData, mInputClipped.width );
730 SimpleConvert( mInputClipped.width, unit->mInputData, unit->mOutputData );
731 ::memcpy( unit->mInputData, unit->mOutputData, sz );
735 ::memcpy( unit->mInputData, unit->mOutputData, sz );
737 UpscaleFree( mOutputClipped.channelCount, unit->mInputData, mInputClipped.width, unit->mOutputData, mOutputClipped.width );
742 mWriterQueue.AddBuffer( unit );
744 while( mContinue && !quitThis );
750 while( ( unit = mCMMQueue.AquireBuffer() ) == NULL && mContinue )
755 if( unit->mIsLast ==
false )
757 if( mInputClipped.width > mOutputClipped.width )
759 DownscaleFree( mInputClipped.channelCount, unit->mInputData, mInputClipped.width, unit->mOutputData, mOutputClipped.width );
760 mInputCMM->Image2Lab( unit->mOutputData, mLABLine, mOutputClipped.width );
761 mOutputCMM->Lab2Image( mLABLine, unit->mOutputData, mOutputClipped.width );
763 else if( mInputClipped.width == mOutputClipped.width )
765 mInputCMM->Image2Lab( unit->mInputData, mLABLine, mInputClipped.width );
766 mOutputCMM->Lab2Image( mLABLine, unit->mOutputData, mOutputClipped.width );
770 mInputCMM->Image2Lab( unit->mInputData, mLABLine, mInputClipped.width );
771 mOutputCMM->Lab2Image( mLABLine, unit->mInputData, mInputClipped.width );
772 UpscaleFree( mOutputClipped.channelCount, unit->mInputData, mInputClipped.width, unit->mOutputData, mOutputClipped.width );
777 mWriterQueue.AddBuffer( unit );
779 while( mContinue && !quitThis );
785 while( ( unit = mCMMQueue.AquireBuffer() ) == NULL && mContinue )
790 if( unit->mIsLast ==
false )
792 if( mInputClipped.width > mOutputClipped.width )
794 DownscaleFree( mInputClipped.channelCount, unit->mInputData, mInputClipped.width, unit->mOutputData, mOutputClipped.width );
795 SimpleConvert( mOutputClipped.width, unit->mOutputData, unit->mInputData );
796 ::memcpy( unit->mOutputData, unit->mInputData, mOutputClipped.rowBytes );
798 else if( mInputClipped.width == mOutputClipped.width )
800 SimpleConvert( mInputClipped.width, unit->mInputData, unit->mOutputData );
804 SimpleConvert( mInputClipped.width, unit->mInputData, unit->mOutputData );
805 ::memcpy( unit->mInputData, unit->mOutputData, mInputClipped.width * mOutputClipped.channelCount );
806 UpscaleFree( mOutputClipped.channelCount, unit->mInputData, mInputClipped.width, unit->mOutputData, mOutputClipped.width );
811 mWriterQueue.AddBuffer( unit );
813 while( mContinue && !quitThis );
819void AOI_TIFFRenderer::SimpleConvert( uint32_t width,
const uint8_t* src, uint8_t* dest )
822 uint16_t inChannels[4];
823 uint32_t inChannelCount = mInputCS->NrOfComponents();
824 uint32_t outChannelCount = mOutputOriginal.channelCount;
827 if( mInputCS->ResourceType() == IndexColorSpace::eResourceType )
829 for( uint32_t x = 0; x != width; ++x )
831 inChannels[0] = uint16_t(*src++);
832 mInputCS->SetRenderChannels( mColorConvertor, inChannels, cc );
833 for( p = 0; p != outChannelCount; ++p )
834 *dest++ = uint8_t( cc.value[p] >> 8 );
839 for( uint32_t x = 0; x != width; ++x )
841 for( p = 0; p != inChannelCount; ++p )
842 inChannels[p] = uint16_t(*src++) << 8;
843 mInputCS->SetRenderChannels( mColorConvertor, inChannels, cc );
844 for( p = 0; p != outChannelCount; ++p )
845 *dest++ = uint8_t( cc.value[p] >> 8 );
850void AOI_TIFFRenderer::DownscaleFree( uint32_t channels,
const uint8_t* inImage, int32_t inWidth, uint8_t* outImage, int32_t outWidth )
853 double step = double( inWidth ) / outWidth;
855 uint8_t* dest = outImage;
856 const uint8_t* end = outImage + outWidth * channels;
860 src = inImage + uint32_t( x ) * channels;
862 for( p = 0; p != channels; ++p )
867void AOI_TIFFRenderer::UpscaleFree( uint32_t channels,
const uint8_t* inImage, int32_t inWidth, uint8_t* outImage, int32_t outWidth )
869 double pixelsNeeded = 0;
870 double step = double( outWidth ) / inWidth;
871 const uint8_t* src = inImage;
872 uint8_t* dest = outImage;
873 const uint8_t* end = outImage + outWidth * channels;
874 const uint8_t* inEnd = inImage + inWidth * channels;
878 pixelsNeeded += step;
879 while( dest != end && pixelsNeeded >= 1 )
881 for( p = 0; p != channels; ++p )
892AOI_TIFFRenderer::UnitQueue::UnitQueue()
897AOI_TIFFRenderer::UnitQueue::~UnitQueue()
902void AOI_TIFFRenderer::UnitQueue::AddBuffer( Unit* unit )
905 Unit** prev = &mUnits;
907 prev = &(*prev)->mNext;
913AOI_TIFFRenderer::Unit* AOI_TIFFRenderer::UnitQueue::AquireBuffer()
918 mUnits = mUnits->mNext;
923void AOI_TIFFRenderer::UnitQueue::DestroyBuffers()
930 mUnits = unit->mNext;
931 delete[] unit->mInputData;
932 delete[] unit->mOutputData;
bool(* ColorConvertCB)(ColorConvert_Data &, void *)
CMM callback routine.
Color information for CMM callback.
aur::PDF::ColorSpaceObject * inSourceSpace
const aur::PDF::Object * inObject
const uint16_t * inChannels16
const uint8_t * inChannels8
aur::PDF::ColorSpaceObject * inDestinationSpace