12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450 |
- //---------------------------------------------------------------------------------
- //
- // Little Color Management System, fast floating point extensions
- // Copyright (c) 1998-2022 Marti Maria Saguer, all rights reserved
- //
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
- //---------------------------------------------------------------------------------
- #include "fast_float_internal.h"
- #include <stdlib.h>
- #include <memory.h>
- // Some pixel representations
- typedef struct { cmsUInt8Number r, g, b; } Scanline_rgb8bits;
- typedef struct { cmsUInt8Number r, g, b, a; } Scanline_rgba8bits;
- typedef struct { cmsUInt8Number c, m, y, k; } Scanline_cmyk8bits;
- typedef struct { cmsUInt16Number r, g, b; } Scanline_rgb16bits;
- typedef struct { cmsUInt16Number r, g, b, a; } Scanline_rgba16bits;
- typedef struct { cmsUInt16Number c, m, y, k; } Scanline_cmyk16bits;
- typedef struct { cmsUInt16Number r, g, b; } Scanline_rgb15bits;
- typedef struct { cmsUInt16Number r, g, b, a; } Scanline_rgba15bits;
- typedef struct { cmsUInt16Number r, g, b, a; } Scanline_cmyk15bits;
- typedef struct { cmsFloat32Number r, g, b; } Scanline_rgbFloat;
- typedef struct { cmsFloat32Number r, g, b, a; } Scanline_rgbaFloat;
- typedef struct { cmsFloat32Number c, m, y, k; } Scanline_cmykFloat;
- typedef struct { cmsFloat32Number L, a, b; } Scanline_LabFloat;
- // 15 bit mode. <=> 8 bits mode
- #define FROM_8_TO_15(x8) (cmsUInt16Number) ((((cmsUInt64Number)x8 << 15)) / 0xFF)
- #define FROM_15_TO_8(x15) (cmsUInt8Number) (((cmsUInt64Number) x15 * 0xFF + 0x4000) >> 15)
- // Floating point accuracy for tests
- #define EPSILON_FLOAT_TESTS 0.005
- // A flushed printf
- static
- void trace(const char* frm, ...)
- {
- va_list args;
- va_start(args, frm);
- vfprintf(stderr, frm, args);
- fflush(stderr);
- va_end(args);
- }
- // The callback function used by cmsSetLogErrorHandler()
- static
- void FatalErrorQuit(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
- {
- UNUSED_PARAMETER(ContextID);
- UNUSED_PARAMETER(ErrorCode);
- trace("** Fatal error: %s\n", Text);
- exit(1);
- }
- // Rise an error and exit
- static
- void Fail(const char* frm, ...)
- {
- char ReasonToFailBuffer[1024];
- va_list args;
- va_start(args, frm);
- vsprintf(ReasonToFailBuffer, frm, args);
- FatalErrorQuit(0, 0, ReasonToFailBuffer);
- // unreachable va_end(args);
- }
- // Creates a fake profile that only has a curve. Used in several places
- static
- cmsHPROFILE CreateCurves(void)
- {
- cmsToneCurve* Gamma = cmsBuildGamma(0, 1.1);
- cmsToneCurve* Transfer[3];
- cmsHPROFILE h;
- Transfer[0] = Transfer[1] = Transfer[2] = Gamma;
- h = cmsCreateLinearizationDeviceLink(cmsSigRgbData, Transfer);
- cmsFreeToneCurve(Gamma);
- return h;
- }
- // Check for a single 15 bit Photoshop-like formatter
- static
- void CheckSingleFormatter15(cmsContext id, cmsUInt32Number Type, const char* Text)
- {
- cmsUInt16Number Values[cmsMAXCHANNELS];
- cmsUInt8Number Buffer[1024];
- cmsFormatter f, b;
- cmsInt32Number i, j, nChannels, bytes;
- _xform_head info;
- UNUSED_PARAMETER(id);
- memset(&info, 0, sizeof(info));
- info.OutputFormat = info.InputFormat = Type;
- // Get functions to go forth and back
- f = Formatter_15Bit_Factory(Type, cmsFormatterInput, CMS_PACK_FLAGS_16BITS);
- b = Formatter_15Bit_Factory(Type, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS);
- if (f.Fmt16 == NULL || b.Fmt16 == NULL) {
- Fail("no formatter for %s", Text);
- return;
- }
- nChannels = T_CHANNELS(Type);
- bytes = T_BYTES(Type);
- for (j = 0; j < 5; j++) {
- for (i = 0; i < nChannels; i++) {
- Values[i] = (cmsUInt16Number)(i + j) << 1;
- }
- b.Fmt16((struct _cmstransform_struct*) &info, Values, Buffer, 1);
- memset(Values, 0, sizeof(Values));
- f.Fmt16((struct _cmstransform_struct*) &info, Values, Buffer, 1);
- for (i = 0; i < nChannels; i++) {
- if (Values[i] != ((i + j) << 1)) {
- Fail("%s failed", Text);
- return;
- }
- }
- }
- }
- #define C(a) CheckSingleFormatter15(0, a, #a)
- // Check for all 15 bits formatters
- static
- void CheckFormatters15(void)
- {
- C(TYPE_GRAY_15);
- C(TYPE_GRAY_15_REV);
- C(TYPE_GRAY_15_SE);
- C(TYPE_GRAYA_15);
- C(TYPE_GRAYA_15_SE);
- C(TYPE_GRAYA_15_PLANAR);
- C(TYPE_RGB_15);
- C(TYPE_RGB_15_PLANAR);
- C(TYPE_RGB_15_SE);
- C(TYPE_BGR_15);
- C(TYPE_BGR_15_PLANAR);
- C(TYPE_BGR_15_SE);
- C(TYPE_RGBA_15);
- C(TYPE_RGBA_15_PLANAR);
- C(TYPE_RGBA_15_SE);
- C(TYPE_ARGB_15);
- C(TYPE_ABGR_15);
- C(TYPE_ABGR_15_PLANAR);
- C(TYPE_ABGR_15_SE);
- C(TYPE_BGRA_15);
- C(TYPE_BGRA_15_SE);
- C(TYPE_YMC_15);
- C(TYPE_CMY_15);
- C(TYPE_CMY_15_PLANAR);
- C(TYPE_CMY_15_SE);
- C(TYPE_CMYK_15);
- C(TYPE_CMYK_15_REV);
- C(TYPE_CMYK_15_PLANAR);
- C(TYPE_CMYK_15_SE);
- C(TYPE_KYMC_15);
- C(TYPE_KYMC_15_SE);
- C(TYPE_KCMY_15);
- C(TYPE_KCMY_15_REV);
- C(TYPE_KCMY_15_SE);
- }
- #undef C
- static
- cmsInt32Number checkSingleComputeIncrements(cmsUInt32Number Format, cmsUInt32Number planeStride, cmsUInt32Number ExpectedChannels, cmsUInt32Number ExpectedAlpha, ...)
- {
- cmsUInt32Number nChannels, nAlpha, nTotal, i, rc = 0 ;
- cmsUInt32Number ComponentStartingOrder[cmsMAXCHANNELS], ComponentPointerIncrements[cmsMAXCHANNELS];
- va_list args;
-
- va_start(args, ExpectedAlpha);
- _cmsComputeComponentIncrements(Format, planeStride, &nChannels, &nAlpha, ComponentStartingOrder, ComponentPointerIncrements);
- if (nChannels != ExpectedChannels)
- return 0;
- if (nAlpha != ExpectedAlpha)
- return 0;
- nTotal = nAlpha + nChannels;
-
- for (i = 0; i < nTotal; i++)
- {
- cmsUInt32Number so = va_arg(args, cmsUInt32Number);
- if (so != ComponentStartingOrder[i])
- goto Error;
- }
- for (i = 0; i < nTotal; i++)
- {
- cmsUInt32Number so = va_arg(args, cmsUInt32Number);
- if (so != ComponentPointerIncrements[i])
- goto Error;
- }
- // Success
- rc = 1;
- Error:
- va_end(args);
- return rc;
- }
- #define CHECK(frm, plane, chans, alpha, ...) if (!checkSingleComputeIncrements(frm, plane, chans, alpha, __VA_ARGS__)) { trace("Format failed!\n"); return 0; }
- // Validate the compute increments function
- cmsInt32Number CheckComputeIncrements(void)
- {
- CHECK(TYPE_GRAY_8, 0, 1, 0, /**/ 0, /**/ 1);
- CHECK(TYPE_GRAYA_8, 0, 1, 1, /**/ 0, 1, /**/ 2, 2);
- CHECK(TYPE_AGRAY_8, 0, 1, 1, /**/ 1, 0, /**/ 2, 2);
- CHECK(TYPE_GRAY_16, 0, 1, 0, /**/ 0, /**/ 2);
- CHECK(TYPE_GRAYA_16, 0, 1, 1, /**/ 0, 2, /**/ 4, 4);
- CHECK(TYPE_AGRAY_16, 0, 1, 1, /**/ 2, 0, /**/ 4, 4);
- CHECK(TYPE_GRAY_FLT, 0, 1, 0, /**/ 0, /**/ 4);
- CHECK(TYPE_GRAYA_FLT, 0, 1, 1, /**/ 0, 4, /**/ 8, 8);
- CHECK(TYPE_AGRAY_FLT, 0, 1, 1, /**/ 4, 0, /**/ 8, 8);
- CHECK(TYPE_GRAY_DBL, 0, 1, 0, /**/ 0, /**/ 8);
- CHECK(TYPE_AGRAY_DBL, 0, 1, 1, /**/ 8, 0, /**/ 16, 16);
- CHECK(TYPE_RGB_8, 0, 3, 0, /**/ 0, 1, 2, /**/ 3, 3, 3);
- CHECK(TYPE_RGBA_8, 0, 3, 1, /**/ 0, 1, 2, 3, /**/ 4, 4, 4, 4);
- CHECK(TYPE_ARGB_8, 0, 3, 1, /**/ 1, 2, 3, 0, /**/ 4, 4, 4, 4);
- CHECK(TYPE_RGB_16, 0, 3, 0, /**/ 0, 2, 4, /**/ 6, 6, 6);
- CHECK(TYPE_RGBA_16, 0, 3, 1, /**/ 0, 2, 4, 6, /**/ 8, 8, 8, 8);
- CHECK(TYPE_ARGB_16, 0, 3, 1, /**/ 2, 4, 6, 0, /**/ 8, 8, 8, 8);
- CHECK(TYPE_RGB_FLT, 0, 3, 0, /**/ 0, 4, 8, /**/ 12, 12, 12);
- CHECK(TYPE_RGBA_FLT, 0, 3, 1, /**/ 0, 4, 8, 12, /**/ 16, 16, 16, 16);
- CHECK(TYPE_ARGB_FLT, 0, 3, 1, /**/ 4, 8, 12, 0, /**/ 16, 16, 16, 16);
- CHECK(TYPE_BGR_8, 0, 3, 0, /**/ 2, 1, 0, /**/ 3, 3, 3);
- CHECK(TYPE_BGRA_8, 0, 3, 1, /**/ 2, 1, 0, 3, /**/ 4, 4, 4, 4);
- CHECK(TYPE_ABGR_8, 0, 3, 1, /**/ 3, 2, 1, 0, /**/ 4, 4, 4, 4);
- CHECK(TYPE_BGR_16, 0, 3, 0, /**/ 4, 2, 0, /**/ 6, 6, 6);
- CHECK(TYPE_BGRA_16, 0, 3, 1, /**/ 4, 2, 0, 6, /**/ 8, 8, 8, 8);
- CHECK(TYPE_ABGR_16, 0, 3, 1, /**/ 6, 4, 2, 0, /**/ 8, 8, 8, 8);
- CHECK(TYPE_BGR_FLT, 0, 3, 0, /**/ 8, 4, 0, /**/ 12, 12, 12);
- CHECK(TYPE_BGRA_FLT, 0, 3, 1, /**/ 8, 4, 0, 12, /**/ 16, 16, 16, 16);
- CHECK(TYPE_ABGR_FLT, 0, 3, 1, /**/ 12, 8, 4, 0, /**/ 16, 16, 16, 16);
- CHECK(TYPE_CMYK_8, 0, 4, 0, /**/ 0, 1, 2, 3, /**/ 4, 4, 4, 4);
- CHECK(TYPE_CMYKA_8, 0, 4, 1, /**/ 0, 1, 2, 3, 4, /**/ 5, 5, 5, 5, 5);
- CHECK(TYPE_ACMYK_8, 0, 4, 1, /**/ 1, 2, 3, 4, 0, /**/ 5, 5, 5, 5, 5);
- CHECK(TYPE_KYMC_8, 0, 4, 0, /**/ 3, 2, 1, 0, /**/ 4, 4, 4, 4);
- CHECK(TYPE_KYMCA_8, 0, 4, 1, /**/ 3, 2, 1, 0, 4, /**/ 5, 5, 5, 5, 5);
- CHECK(TYPE_AKYMC_8, 0, 4, 1, /**/ 4, 3, 2, 1, 0, /**/ 5, 5, 5, 5, 5);
- CHECK(TYPE_KCMY_8, 0, 4, 0, /**/ 1, 2, 3, 0, /**/ 4, 4, 4, 4);
-
- CHECK(TYPE_CMYK_16, 0, 4, 0, /**/ 0, 2, 4, 6, /**/ 8, 8, 8, 8);
- CHECK(TYPE_CMYKA_16, 0, 4, 1, /**/ 0, 2, 4, 6, 8, /**/ 10, 10, 10, 10, 10);
- CHECK(TYPE_ACMYK_16, 0, 4, 1, /**/ 2, 4, 6, 8, 0, /**/ 10, 10, 10, 10, 10);
- CHECK(TYPE_KYMC_16, 0, 4, 0, /**/ 6, 4, 2, 0, /**/ 8, 8, 8, 8);
- CHECK(TYPE_KYMCA_16, 0, 4, 1, /**/ 6, 4, 2, 0, 8, /**/ 10, 10, 10, 10, 10);
- CHECK(TYPE_AKYMC_16, 0, 4, 1, /**/ 8, 6, 4, 2, 0, /**/ 10, 10, 10, 10, 10);
- CHECK(TYPE_KCMY_16, 0, 4, 0, /**/ 2, 4, 6, 0, /**/ 8, 8, 8, 8);
- // Planar
- CHECK(TYPE_GRAYA_8_PLANAR, 100, 1, 1, /**/ 0, 100, /**/ 1, 1);
- CHECK(TYPE_AGRAY_8_PLANAR, 100, 1, 1, /**/ 100, 0, /**/ 1, 1);
- CHECK(TYPE_GRAYA_16_PLANAR, 100, 1, 1, /**/ 0, 100, /**/ 2, 2);
- CHECK(TYPE_AGRAY_16_PLANAR, 100, 1, 1, /**/ 100, 0, /**/ 2, 2);
- CHECK(TYPE_GRAYA_FLT_PLANAR, 100, 1, 1, /**/ 0, 100, /**/ 4, 4);
- CHECK(TYPE_AGRAY_FLT_PLANAR, 100, 1, 1, /**/ 100, 0, /**/ 4, 4);
- CHECK(TYPE_GRAYA_DBL_PLANAR, 100, 1, 1, /**/ 0, 100, /**/ 8, 8);
- CHECK(TYPE_AGRAY_DBL_PLANAR, 100, 1, 1, /**/ 100, 0, /**/ 8, 8);
- CHECK(TYPE_RGB_8_PLANAR, 100, 3, 0, /**/ 0, 100, 200, /**/ 1, 1, 1);
- CHECK(TYPE_RGBA_8_PLANAR, 100, 3, 1, /**/ 0, 100, 200, 300, /**/ 1, 1, 1, 1);
- CHECK(TYPE_ARGB_8_PLANAR, 100, 3, 1, /**/ 100, 200, 300, 0, /**/ 1, 1, 1, 1);
- CHECK(TYPE_BGR_8_PLANAR, 100, 3, 0, /**/ 200, 100, 0, /**/ 1, 1, 1);
- CHECK(TYPE_BGRA_8_PLANAR, 100, 3, 1, /**/ 200, 100, 0, 300, /**/ 1, 1, 1, 1);
- CHECK(TYPE_ABGR_8_PLANAR, 100, 3, 1, /**/ 300, 200, 100, 0, /**/ 1, 1, 1, 1);
- CHECK(TYPE_RGB_16_PLANAR, 100, 3, 0, /**/ 0, 100, 200, /**/ 2, 2, 2);
- CHECK(TYPE_RGBA_16_PLANAR, 100, 3, 1, /**/ 0, 100, 200, 300, /**/ 2, 2, 2, 2);
- CHECK(TYPE_ARGB_16_PLANAR, 100, 3, 1, /**/ 100, 200, 300, 0, /**/ 2, 2, 2, 2);
- CHECK(TYPE_BGR_16_PLANAR, 100, 3, 0, /**/ 200, 100, 0, /**/ 2, 2, 2);
- CHECK(TYPE_BGRA_16_PLANAR, 100, 3, 1, /**/ 200, 100, 0, 300, /**/ 2, 2, 2, 2);
- CHECK(TYPE_ABGR_16_PLANAR, 100, 3, 1, /**/ 300, 200, 100, 0, /**/ 2, 2, 2, 2);
- return 1;
- }
- // Check 15 bit mode accuracy
- static
- cmsBool Valid15(cmsUInt16Number a, cmsUInt8Number b)
- {
- return abs(FROM_15_TO_8(a) - b) <= 2;
- }
- // Check the test macros itselves
- static
- void Check15bitMacros(void)
- {
- int i;
- trace("Checking 15 bit <=> 8 bit macros...");
- for (i = 0; i < 256; i++)
- {
- cmsUInt16Number n = FROM_8_TO_15(i);
- cmsUInt8Number m = FROM_15_TO_8(n);
- if (m != i)
- Fail("Failed on %d (->%d->%d)", i, n, m);
- }
- trace("ok\n");
- }
- // Do an in-depth test by checking all RGB cube of 8 bits, going from profilein to profileout.
- // Results should be same except for 2 contone levels allowed for roundoff. Note 15 bits is more
- // precise than 8 bits and this is a source of discrepancies. Cache is disabled
- static
- void TryAllValues15(cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent)
- {
- Scanline_rgb8bits* buffer8in;
- Scanline_rgb15bits* buffer15in;
- Scanline_rgb8bits* buffer8out;
- Scanline_rgb15bits* buffer15out;
- int r, g, b, j;
- cmsUInt32Number npixels = 256 * 256 * 256; // All RGB cube in 8 bits
- cmsHTRANSFORM xform15 = cmsCreateTransformTHR(0, hlcmsProfileIn, TYPE_RGB_15, hlcmsProfileOut, TYPE_RGB_15, Intent, cmsFLAGS_NOCACHE);
- cmsHTRANSFORM xform8 = cmsCreateTransformTHR(0, hlcmsProfileIn, TYPE_RGB_8, hlcmsProfileOut, TYPE_RGB_8, Intent, cmsFLAGS_NOCACHE); // Transforms already created
-
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- if (xform15 == NULL || xform8 == NULL) {
- Fail("NULL transforms on check for 15 bit conversions");
- }
- // Since this is just a test, I will not check memory allocation...
- buffer8in = (Scanline_rgb8bits*)malloc(npixels * sizeof(Scanline_rgb8bits));
- buffer15in = (Scanline_rgb15bits*)malloc(npixels * sizeof(Scanline_rgb15bits));
- buffer8out = (Scanline_rgb8bits*)malloc(npixels * sizeof(Scanline_rgb8bits));
- buffer15out = (Scanline_rgb15bits*)malloc(npixels * sizeof(Scanline_rgb15bits));
- // Fill input values for 8 and 15 bits
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- buffer8in[j].r = (cmsUInt8Number)r;
- buffer8in[j].g = (cmsUInt8Number)g;
- buffer8in[j].b = (cmsUInt8Number)b;
- buffer15in[j].r = FROM_8_TO_15(r);
- buffer15in[j].g = FROM_8_TO_15(g);
- buffer15in[j].b = FROM_8_TO_15(b);
- j++;
- }
-
- cmsDoTransform(xform15, buffer15in, buffer15out, npixels);
- cmsDoTransform(xform8, buffer8in, buffer8out, npixels);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- // Check the results
- if (!Valid15(buffer15out[j].r, buffer8out[j].r) ||
- !Valid15(buffer15out[j].g, buffer8out[j].g) ||
- !Valid15(buffer15out[j].b, buffer8out[j].b))
- Fail("Conversion failed at (%d %d %d) != (%d %d %d)", buffer8out[j].r, buffer8out[j].g, buffer8out[j].b,
- FROM_15_TO_8(buffer15out[j].r), FROM_15_TO_8(buffer15out[j].g), FROM_15_TO_8(buffer15out[j].b));
- j++;
- }
- free(buffer8in); free(buffer15in);
- free(buffer8out); free(buffer15out);
- cmsDeleteTransform(xform15);
- cmsDeleteTransform(xform8);
- }
- // Convert some known values
- static
- void Check15bitsConversions(void)
- {
- Check15bitMacros();
- trace("Checking accuracy of 15 bits on CLUT...");
- TryAllValues15(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- trace("Checking accuracy of 15 bits on same profile ...");
- TryAllValues15(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- trace("Checking accuracy of 15 bits on Matrix...");
- TryAllValues15(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- trace("All 15 bits tests passed OK\n\n");
- }
- // Next test checks results of optimized 16 bits versus raw 16 bits.
- static
- void TryAllValues16bits(cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent)
- {
- cmsContext Raw = cmsCreateContext(NULL, NULL);
- cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- Scanline_rgba16bits* bufferIn;
- Scanline_rgba16bits* bufferRawOut;
- Scanline_rgba16bits* bufferPluginOut;
- int r, g, b;
- int j;
- cmsUInt32Number npixels = 256 * 256 * 256;
- cmsHTRANSFORM xformRaw = cmsCreateTransformTHR(Raw, hlcmsProfileIn, TYPE_RGBA_16, hlcmsProfileOut, TYPE_RGBA_16, Intent, cmsFLAGS_NOCACHE| cmsFLAGS_COPY_ALPHA);
- cmsHTRANSFORM xformPlugin = cmsCreateTransformTHR(Plugin, hlcmsProfileIn, TYPE_RGBA_16, hlcmsProfileOut, TYPE_RGBA_16, Intent, cmsFLAGS_NOCACHE| cmsFLAGS_COPY_ALPHA);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- if (xformRaw == NULL || xformPlugin == NULL) {
- Fail("NULL transforms on check float conversions");
- }
- // Again, no checking on mem alloc because this is just a test
- bufferIn = (Scanline_rgba16bits*)malloc(npixels * sizeof(Scanline_rgba16bits));
- bufferRawOut = (Scanline_rgba16bits*)malloc(npixels * sizeof(Scanline_rgba16bits));
- bufferPluginOut = (Scanline_rgba16bits*)malloc(npixels * sizeof(Scanline_rgba16bits));
- // Same input to both transforms
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- bufferIn[j].r = FROM_8_TO_16(0xf8);
- bufferIn[j].g = FROM_8_TO_16(0xf8);
- bufferIn[j].b = FROM_8_TO_16(0xf8);
- bufferIn[j].a = 0xffff;
- j++;
- }
- // Different transforms, different output buffers
- cmsDoTransform(xformRaw, bufferIn, bufferRawOut, npixels);
- cmsDoTransform(xformPlugin, bufferIn, bufferPluginOut, npixels);
- // Lets compare results
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- if (bufferRawOut[j].r != bufferPluginOut[j].r ||
- bufferRawOut[j].g != bufferPluginOut[j].g ||
- bufferRawOut[j].b != bufferPluginOut[j].b ||
- bufferRawOut[j].a != bufferPluginOut[j].a)
- Fail(
- "Conversion failed at [%x %x %x %x] (%x %x %x %x) != (%x %x %x %x)",
- bufferIn[j].r, bufferIn[j].g, bufferIn[j].b, bufferIn[j].a,
- bufferRawOut[j].r, bufferRawOut[j].g, bufferRawOut[j].b, bufferRawOut[j].a,
- bufferPluginOut[j].r, bufferPluginOut[j].g, bufferPluginOut[j].b, bufferPluginOut[j].a);
- j++;
- }
- free(bufferIn); free(bufferRawOut);
- free(bufferPluginOut);
- cmsDeleteTransform(xformRaw);
- cmsDeleteTransform(xformPlugin);
- cmsDeleteContext(Plugin);
- cmsDeleteContext(Raw);
- }
- static
- void CheckAccuracy16Bits(void)
- {
- // CLUT should be as 16 bits or better
- trace("Checking accuracy of 16 bits CLUT...");
- TryAllValues16bits(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL);
- trace("All 16 bits tests passed OK\n\n");
- }
- // Try values that are denormalized, not-a-number and out of range
- static
- void CheckUncommonValues(cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent)
- {
- union
- {
- cmsFloat32Number subnormal;
- cmsUInt32Number Int;
- } sub_pos, sub_neg;
- Scanline_rgbFloat* bufferIn;
- Scanline_rgbFloat* bufferPluginOut;
- cmsUInt32Number i, npixels = 100;
- cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- cmsHTRANSFORM xformPlugin = cmsCreateTransformTHR(Plugin, hlcmsProfileIn, TYPE_RGB_FLT, hlcmsProfileOut, TYPE_RGB_FLT, Intent, 0);
-
- sub_pos.Int = 0x00000002;
- sub_neg.Int = 0x80000002;
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- if (xformPlugin == NULL) {
- Fail("NULL transform on check uncommon values");
- }
- bufferIn = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- bufferPluginOut = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- for (i = 0; i < npixels; i++)
- {
- bufferIn[i].r = i / 40.0 - 0.5;
- bufferIn[i].g = i / 20.0 - 0.5;
- bufferIn[i].b = i / 60.0 - 0.5;
- }
- cmsDoTransform(xformPlugin, bufferIn, bufferPluginOut, npixels);
- bufferIn[0].r = NAN;
- bufferIn[0].g = NAN;
- bufferIn[0].b = NAN;
- bufferIn[1].r = INFINITY;
- bufferIn[1].g = INFINITY;
- bufferIn[1].b = INFINITY;
- bufferIn[2].r = sub_pos.subnormal;
- bufferIn[2].g = sub_pos.subnormal;
- bufferIn[2].b = sub_pos.subnormal;
- bufferIn[3].r = sub_neg.subnormal;
- bufferIn[3].g = sub_neg.subnormal;
- bufferIn[3].b = sub_neg.subnormal;
- cmsDoTransform(xformPlugin, bufferIn, bufferPluginOut, 4);
- free(bufferIn);
- free(bufferPluginOut);
- cmsDeleteTransform(xformPlugin);
- cmsDeleteContext(Plugin);
- }
- static
- void lab8toLab(cmsUInt8Number lab8[3], cmsCIELab* Lab)
- {
- cmsUInt16Number lab16[3];
- lab16[0] = FROM_8_TO_16(lab8[0]);
- lab16[1] = FROM_8_TO_16(lab8[1]);
- lab16[2] = FROM_8_TO_16(lab8[2]);
- cmsLabEncoded2Float(Lab, lab16);
- }
- static
- void CheckToEncodedLab(void)
- {
- cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- cmsContext Raw = cmsCreateContext(NULL, NULL);
- cmsHPROFILE hsRGB = cmsCreate_sRGBProfile();
- cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
- cmsHTRANSFORM xform_plugin = cmsCreateTransformTHR(Plugin, hsRGB, TYPE_RGB_8, hLab, TYPE_Lab_8, INTENT_PERCEPTUAL, 0);
- cmsHTRANSFORM xform = cmsCreateTransformTHR(Raw, hsRGB, TYPE_RGB_8, hLab, TYPE_Lab_8, INTENT_PERCEPTUAL, 0);
- int r, g, b;
- cmsCIELab Lab1, Lab2;
- cmsUInt8Number rgb[3], lab1[3], lab2[3];
- double err;
- for (r=0; r < 256; r += 5)
- for (g = 0; g < 256; g += 5)
- for (b = 0; b < 256; b += 5)
- {
- rgb[0] = (cmsUInt8Number) r; rgb[1] = (cmsUInt8Number) g; rgb[2] = (cmsUInt8Number) b;
- cmsDoTransform(xform_plugin, rgb, lab1, 1);
- cmsDoTransform(xform, rgb, lab2, 1);
-
- lab8toLab(lab1, &Lab1);
- lab8toLab(lab2, &Lab2);
-
- err = cmsDeltaE(&Lab1, &Lab2);
- if (err > 0.1)
- {
- trace("Error on lab encoded (%f, %f, %f) <> (% f, % f, % f)\n",
- Lab1.L, Lab1.a, Lab1.b, Lab2.L, Lab2.a, Lab2.b);
- }
- }
- cmsDeleteTransform(xform);
- cmsCloseProfile(hsRGB); cmsCloseProfile(hLab);
- cmsDeleteContext(Raw);
- cmsDeleteContext(Plugin);
- }
- static
- void CheckToFloatLab(void)
- {
- cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- cmsContext Raw = cmsCreateContext(NULL, NULL);
- cmsHPROFILE hsRGB = cmsCreate_sRGBProfile();
- cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
- cmsHTRANSFORM xform_plugin = cmsCreateTransformTHR(Plugin, hsRGB, TYPE_RGB_8, hLab, TYPE_Lab_DBL, INTENT_PERCEPTUAL, 0);
- cmsHTRANSFORM xform = cmsCreateTransformTHR(Raw, hsRGB, TYPE_RGB_8, hLab, TYPE_Lab_DBL, INTENT_PERCEPTUAL, 0);
- int r, g, b;
- cmsCIELab Lab1, Lab2;
- cmsUInt8Number rgb[3];
- double err;
- for (r = 0; r < 256; r += 10)
- for (g = 0; g < 256; g += 10)
- for (b = 0; b < 256; b += 10)
- {
- rgb[0] = (cmsUInt8Number)r; rgb[1] = (cmsUInt8Number)g; rgb[2] = (cmsUInt8Number)b;
- cmsDoTransform(xform_plugin, rgb, &Lab1, 1);
- cmsDoTransform(xform, rgb, &Lab2, 1);
-
- err = cmsDeltaE(&Lab1, &Lab2);
- if (err > 0.1)
- {
- trace("Error on lab encoded (%f, %f, %f) <> (% f, % f, % f)\n",
- Lab1.L, Lab1.a, Lab1.b, Lab2.L, Lab2.a, Lab2.b);
- }
- }
- cmsDeleteTransform(xform);
- cmsCloseProfile(hsRGB); cmsCloseProfile(hLab);
- cmsDeleteContext(Raw);
- cmsDeleteContext(Plugin);
- }
- // --------------------------------------------------------------------------------------------------
- // A C C U R A C Y C H E C K S
- // --------------------------------------------------------------------------------------------------
- // Check result accuracy
- static
- cmsBool ValidFloat(cmsFloat32Number a, cmsFloat32Number b)
- {
- return fabsf(a-b) < EPSILON_FLOAT_TESTS;
- }
- // Do an in-depth test by checking all RGB cube of 8 bits, going from profilein to profileout.
- // Values with and without optimization are checked (different contexts, one with the plugin and another without)
- // Results should be same except for EPSILON_FLOAT_TESTS allowed for accuracy/speed tradeoff. Cache is disabled
- static
- void TryAllValuesFloat(cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent)
- {
- cmsContext Raw = cmsCreateContext(NULL, NULL);
- cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- Scanline_rgbFloat* bufferIn;
- Scanline_rgbFloat* bufferRawOut;
- Scanline_rgbFloat* bufferPluginOut;
- int r, g, b;
-
- int j;
- cmsUInt32Number npixels = 256 * 256 * 256;
- cmsHTRANSFORM xformRaw = cmsCreateTransformTHR(Raw, hlcmsProfileIn, TYPE_RGB_FLT, hlcmsProfileOut, TYPE_RGB_FLT, Intent, cmsFLAGS_NOCACHE);
- cmsHTRANSFORM xformPlugin = cmsCreateTransformTHR(Plugin, hlcmsProfileIn, TYPE_RGB_FLT, hlcmsProfileOut, TYPE_RGB_FLT, Intent, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- if (xformRaw == NULL || xformPlugin == NULL) {
- Fail("NULL transforms on check float conversions");
- }
- // Again, no checking on mem alloc because this is just a test
- bufferIn = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- bufferRawOut = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- bufferPluginOut = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- // Same input to both transforms
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- bufferIn[j].r = (cmsFloat32Number)r / 255.0f;
- bufferIn[j].g = (cmsFloat32Number)g / 255.0f;
- bufferIn[j].b = (cmsFloat32Number)b / 255.0f;
-
- j++;
- }
-
- // Different transforms, different output buffers
- cmsDoTransform(xformRaw, bufferIn, bufferRawOut, npixels);
- cmsDoTransform(xformPlugin, bufferIn, bufferPluginOut, npixels);
- // Lets compare results
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- if (!ValidFloat(bufferRawOut[j].r, bufferPluginOut[j].r) ||
- !ValidFloat(bufferRawOut[j].g, bufferPluginOut[j].g) ||
- !ValidFloat(bufferRawOut[j].b, bufferPluginOut[j].b))
- Fail("Conversion failed at (%f %f %f) != (%f %f %f)", bufferRawOut[j].r, bufferRawOut[j].g, bufferRawOut[j].b,
- bufferPluginOut[j].r, bufferPluginOut[j].g, bufferPluginOut[j].b);
- j++;
- }
- free(bufferIn); free(bufferRawOut);
- free(bufferPluginOut);
- cmsDeleteTransform(xformRaw);
- cmsDeleteTransform(xformPlugin);
- cmsDeleteContext(Plugin);
- cmsDeleteContext(Raw);
- }
- static
- void TryAllValuesFloatAlpha(cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent, cmsBool copyAlpha)
- {
- cmsContext Raw = cmsCreateContext(NULL, NULL);
- cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- Scanline_rgbaFloat* bufferIn;
- Scanline_rgbaFloat* bufferRawOut;
- Scanline_rgbaFloat* bufferPluginOut;
- int r, g, b;
-
- int j;
- cmsUInt32Number npixels = 256 * 256 * 256;
- cmsUInt32Number flags = cmsFLAGS_NOCACHE | ( copyAlpha? cmsFLAGS_COPY_ALPHA : 0);
- cmsHTRANSFORM xformRaw = cmsCreateTransformTHR(Raw, hlcmsProfileIn, TYPE_RGBA_FLT, hlcmsProfileOut, TYPE_RGBA_FLT, Intent, flags);
- cmsHTRANSFORM xformPlugin = cmsCreateTransformTHR(Plugin, hlcmsProfileIn, TYPE_RGBA_FLT, hlcmsProfileOut, TYPE_RGBA_FLT, Intent, flags);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- if (xformRaw == NULL || xformPlugin == NULL) {
- Fail("NULL transforms on check float conversions");
- }
- // Again, no checking on mem alloc because this is just a test
- bufferIn = (Scanline_rgbaFloat*)malloc(npixels * sizeof(Scanline_rgbaFloat));
- bufferRawOut = (Scanline_rgbaFloat*)malloc(npixels * sizeof(Scanline_rgbaFloat));
- bufferPluginOut = (Scanline_rgbaFloat*)malloc(npixels * sizeof(Scanline_rgbaFloat));
- memset(bufferRawOut, 0, npixels * sizeof(Scanline_rgbaFloat));
- memset(bufferPluginOut, 0, npixels * sizeof(Scanline_rgbaFloat));
- // Same input to both transforms
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- bufferIn[j].r = (cmsFloat32Number)r / 255.0f;
- bufferIn[j].g = (cmsFloat32Number)g / 255.0f;
- bufferIn[j].b = (cmsFloat32Number)b / 255.0f;
- bufferIn[j].a = (cmsFloat32Number) 1.0f;
-
- j++;
- }
-
- // Different transforms, different output buffers
- cmsDoTransform(xformRaw, bufferIn, bufferRawOut, npixels);
- cmsDoTransform(xformPlugin, bufferIn, bufferPluginOut, npixels);
- // Lets compare results
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- if (!ValidFloat(bufferRawOut[j].r, bufferPluginOut[j].r) ||
- !ValidFloat(bufferRawOut[j].g, bufferPluginOut[j].g) ||
- !ValidFloat(bufferRawOut[j].b, bufferPluginOut[j].b) ||
- !ValidFloat(bufferRawOut[j].a, bufferPluginOut[j].a))
- Fail("Conversion failed at (%f %f %f %f) != (%f %f %f %f)", bufferRawOut[j].r, bufferRawOut[j].g, bufferRawOut[j].b, bufferRawOut[j].a,
- bufferPluginOut[j].r, bufferPluginOut[j].g, bufferPluginOut[j].b, bufferPluginOut[j].a);
- j++;
- }
- free(bufferIn); free(bufferRawOut);
- free(bufferPluginOut);
- cmsDeleteTransform(xformRaw);
- cmsDeleteTransform(xformPlugin);
- cmsDeleteContext(Plugin);
- cmsDeleteContext(Raw);
- }
- // Next test checks results of optimized floating point versus 16 bits. That is, converting the float to 16 bits, operating
- // in 16 bits and back to float. Results again should be in range of epsilon
- static
- cmsBool Valid16Float(cmsUInt16Number a, cmsFloat32Number b)
- {
- return fabs(((cmsFloat32Number)a / (cmsFloat32Number) 0xFFFF) - b) < EPSILON_FLOAT_TESTS;
- }
- // Do an in-depth test by checking all RGB cube of 8 bits, going from profilein to profileout. 16 bits temporary is used as reference
- static
- void TryAllValuesFloatVs16(cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent)
- {
- Scanline_rgbFloat* bufferIn;
- Scanline_rgb16bits* bufferIn16;
- Scanline_rgbFloat* bufferFloatOut;
- Scanline_rgb16bits* buffer16Out;
- int r, g, b;
- int j;
- cmsUInt32Number npixels = 256 * 256 * 256;
- cmsHTRANSFORM xformRaw = cmsCreateTransform(hlcmsProfileIn, TYPE_RGB_16, hlcmsProfileOut, TYPE_RGB_16, Intent, cmsFLAGS_NOCACHE);
- cmsHTRANSFORM xformPlugin = cmsCreateTransform(hlcmsProfileIn, TYPE_RGB_FLT, hlcmsProfileOut, TYPE_RGB_FLT, Intent, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- if (xformRaw == NULL || xformPlugin == NULL) {
- Fail("NULL transforms on check float vs 16 conversions");
- }
- // Again, no checking on mem alloc because this is just a test
- bufferIn = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- bufferIn16 = (Scanline_rgb16bits*)malloc(npixels * sizeof(Scanline_rgb16bits));
- bufferFloatOut = (Scanline_rgbFloat*)malloc(npixels * sizeof(Scanline_rgbFloat));
- buffer16Out = (Scanline_rgb16bits*)malloc(npixels * sizeof(Scanline_rgb16bits));
- // Fill two equivalent input buffers
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- bufferIn[j].r = (cmsFloat32Number)r / 255.0f;
- bufferIn[j].g = (cmsFloat32Number)g / 255.0f;
- bufferIn[j].b = (cmsFloat32Number)b / 255.0f;
- bufferIn16[j].r = FROM_8_TO_16(r);
- bufferIn16[j].g = FROM_8_TO_16(g);
- bufferIn16[j].b = FROM_8_TO_16(b);
- j++;
- }
- // Convert
- cmsDoTransform(xformRaw, bufferIn16, buffer16Out, npixels);
- cmsDoTransform(xformPlugin, bufferIn, bufferFloatOut, npixels);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- // Check for same values
- if (!Valid16Float(buffer16Out[j].r, bufferFloatOut[j].r) ||
- !Valid16Float(buffer16Out[j].g, bufferFloatOut[j].g) ||
- !Valid16Float(buffer16Out[j].b, bufferFloatOut[j].b))
- Fail("Conversion failed at (%f %f %f) != (%f %f %f)", buffer16Out[j].r / 65535.0, buffer16Out[j].g / 65535.0, buffer16Out[j].b / 65535.0,
- bufferFloatOut[j].r, bufferFloatOut[j].g, bufferFloatOut[j].b);
- j++;
- }
- free(bufferIn16); free(buffer16Out);
- free(bufferIn); free(bufferFloatOut);
- cmsDeleteTransform(xformRaw);
- cmsDeleteTransform(xformPlugin);
- }
- // Check change format feature
- static
- void CheckChangeFormat(void)
- {
- cmsHPROFILE hsRGB, hLab;
- cmsHTRANSFORM xform;
- cmsUInt8Number rgb8[3] = { 10, 120, 40 };
- cmsUInt16Number rgb16[3] = { 10* 257, 120*257, 40*257 };
- cmsUInt16Number lab16_1[3], lab16_2[3];
- trace("Checking change format feature...");
- hsRGB = cmsCreate_sRGBProfile();
- hLab = cmsCreateLab4Profile(NULL);
- xform = cmsCreateTransform(hsRGB, TYPE_RGB_16, hLab, TYPE_Lab_16, INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(hsRGB);
- cmsCloseProfile(hLab);
- cmsDoTransform(xform, rgb16, lab16_1, 1);
- cmsChangeBuffersFormat(xform, TYPE_RGB_8, TYPE_Lab_16);
- cmsDoTransform(xform, rgb8, lab16_2, 1);
- cmsDeleteTransform(xform);
- if (memcmp(lab16_1, lab16_2, sizeof(lab16_1)) != 0)
- Fail("Change format failed!");
- trace("Ok\n");
- }
- static
- cmsBool ValidInt(cmsUInt16Number a, cmsUInt16Number b)
- {
- return abs(a - b) <= 32;
- }
- static
- void CheckLab2Roundtrip(void)
- {
- cmsHPROFILE hsRGB, hLab;
- cmsHTRANSFORM xform, xform2;
- cmsInt8Number* lab;
- cmsInt32Number Mb, j;
- cmsInt32Number r, g, b;
- Scanline_rgb8bits* In;
- Scanline_rgb8bits* Out;
- trace("Checking lab2 roundtrip...");
- hsRGB = cmsCreate_sRGBProfile();
- hLab = cmsCreateLab2Profile(NULL);
- xform = cmsCreateTransform(hsRGB, TYPE_RGB_8, hLab, TYPE_Lab_8, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_BLACKPOINTCOMPENSATION);
- xform2 = cmsCreateTransform(hLab, TYPE_Lab_8, hsRGB, TYPE_RGB_8, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_BLACKPOINTCOMPENSATION);
- cmsCloseProfile(hsRGB);
- cmsCloseProfile(hLab);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgb8bits);
- In = (Scanline_rgb8bits*)malloc(Mb);
- Out = (Scanline_rgb8bits*)malloc(Mb);
- lab = (cmsInt8Number*)malloc(256 * 256 * 256 * 3 * sizeof(cmsInt8Number));
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++)
- {
- In[j].r = (cmsUInt8Number)r;
- In[j].g = (cmsUInt8Number)g;
- In[j].b = (cmsUInt8Number)b;
- j++;
- }
- cmsDoTransform(xform, In, lab, 256 * 256 * 256);
- cmsDoTransform(xform2, lab, Out, 256 * 256 * 256);
- cmsDeleteTransform(xform);
- cmsDeleteTransform(xform2);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- // Check for same values
- if (!ValidInt(In[j].r, Out[j].r) ||
- !ValidInt(In[j].g, Out[j].g) ||
- !ValidInt(In[j].b, Out[j].b))
- Fail("Conversion failed at (%d %d %d) != (%d %d %d)", In[j].r, In[j].g, In[j].b,
- Out[j].r, Out[j].g, Out[j].b);
- j++;
- }
- free(In);
- free(Out);
- free(lab);
- trace("Ok\n");
- }
- // Convert some known values
- static
- void CheckConversionFloat(void)
- {
- trace("Crash test.");
- TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, FALSE);
- trace("..");
- TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, TRUE);
- trace("Ok\n");
- trace("Crash (II) test.");
- TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, FALSE);
- trace("..");
- TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, TRUE);
- trace("Ok\n");
-
- trace("Crash (III) test.");
- CheckUncommonValues(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL);
- trace("..");
- CheckUncommonValues(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- trace("Checking conversion to Lab...");
- CheckToEncodedLab();
- CheckToFloatLab();
- trace("Ok\n");
- // Matrix-shaper should be accurate
- trace("Checking accuracy on Matrix-shaper...");
- TryAllValuesFloat(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- // CLUT should be as 16 bits or better
- trace("Checking accuracy of CLUT...");
- TryAllValuesFloatVs16(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- // Same profile should give same values (we test both methods)
- trace("Checking accuracy on same profile ...");
- TryAllValuesFloatVs16(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL);
- TryAllValuesFloat(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL);
- trace("Ok\n");
- }
- static
- cmsBool ValidFloat2(cmsFloat32Number a, cmsFloat32Number b)
- {
- return fabsf(a - b) < 0.007;
- }
- static
- cmsFloat32Number distance(cmsFloat32Number rgb1[], cmsFloat32Number rgb2[])
- {
- cmsFloat32Number dr = rgb2[0] - rgb1[0];
- cmsFloat32Number dg = rgb2[1] - rgb1[1];
- cmsFloat32Number db = rgb2[2] - rgb1[2];
- return dr * dr + dg * dg + db * db;
- }
- static
- void CheckLab2RGB(void)
- {
- cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
- cmsHPROFILE hRGB = cmsOpenProfileFromFile("test3.icc", "r");
- cmsContext noPlugin = cmsCreateContext(0, 0);
- cmsHTRANSFORM hXformNoPlugin = cmsCreateTransformTHR(noPlugin, hLab, TYPE_Lab_FLT, hRGB, TYPE_RGB_FLT, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOCACHE);
- cmsHTRANSFORM hXformPlugin = cmsCreateTransformTHR(0, hLab, TYPE_Lab_FLT, hRGB, TYPE_RGB_FLT, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOCACHE);
- cmsFloat32Number Lab[3], RGB[3], RGB2[3];
- cmsFloat32Number maxInside = 0, maxOutside = 0, L, a, b;
- trace("Checking Lab -> RGB...");
- for (L = 4; L <= 100; L++)
- {
- for (a = -30; a < +30; a++)
- for (b = -30; b < +30; b++)
- {
- cmsFloat32Number d;
- Lab[0] = L; Lab[1] = a; Lab[2] = b;
- cmsDoTransform(hXformNoPlugin, Lab, RGB, 1);
- cmsDoTransform(hXformPlugin, Lab, RGB2, 1);
- d = distance(RGB, RGB2);
- if (d > maxInside)
- maxInside = d;
- }
- }
- for (L = 1; L <= 100; L += 5)
- {
- for (a = -100; a < +100; a += 5)
- for (b = -100; b < +100; b += 5)
- {
- cmsFloat32Number d;
- Lab[0] = L; Lab[1] = a; Lab[2] = b;
- cmsDoTransform(hXformNoPlugin, Lab, RGB, 1);
- cmsDoTransform(hXformPlugin, Lab, RGB2, 1);
- d = distance(RGB, RGB2);
- if (d > maxOutside)
- maxOutside = d;
- }
- }
- trace("Max distance: Inside gamut %f, Outside gamut %f\n", sqrtf(maxInside), sqrtf(maxOutside));
- cmsDeleteTransform(hXformNoPlugin);
- cmsDeleteTransform(hXformPlugin);
- cmsDeleteContext(noPlugin);
- }
- static
- void CheckSoftProofing(void)
- {
- cmsHPROFILE hRGB1 = cmsOpenProfileFromFile("test5.icc", "r");
- cmsHPROFILE hRGB2 = cmsOpenProfileFromFile("test3.icc", "r");
- cmsContext noPlugin = cmsCreateContext(0, 0);
- cmsHTRANSFORM hXformNoPlugin = cmsCreateProofingTransformTHR(noPlugin, hRGB1, TYPE_RGB_FLT, hRGB1, TYPE_RGB_FLT, hRGB2, INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_GAMUTCHECK | cmsFLAGS_SOFTPROOFING);
- cmsHTRANSFORM hXformPlugin = cmsCreateProofingTransformTHR(0, hRGB1, TYPE_RGB_FLT, hRGB1, TYPE_RGB_FLT, hRGB2, INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_GAMUTCHECK | cmsFLAGS_SOFTPROOFING);
- cmsUInt32Number Mb, j, r, g, b;
- Scanline_rgbFloat* In;
- Scanline_rgbFloat* Out1, *Out2;
- trace("Checking soft proofing and gamut check ...");
- cmsCloseProfile(hRGB1);
- cmsCloseProfile(hRGB2);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgbFloat);
- In = (Scanline_rgbFloat*)malloc(Mb);
- Out1 = (Scanline_rgbFloat*)malloc(Mb);
- Out2 = (Scanline_rgbFloat*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++)
- {
- In[j].r = (cmsFloat32Number)r / 255.0f;
- In[j].g = (cmsFloat32Number)g / 255.0f;
- In[j].b = (cmsFloat32Number)b / 255.0f;
- j++;
- }
- cmsDoTransform(hXformNoPlugin, In, Out1, 256 * 256 * 256);
- cmsDoTransform(hXformPlugin, In, Out2, 256 * 256 * 256);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- // Check for same values
- if (!ValidFloat(Out1[j].r, Out2[j].r) ||
- !ValidFloat(Out1[j].g, Out2[j].g) ||
- !ValidFloat(Out1[j].b, Out2[j].b))
- Fail("Conversion failed at (%f %f %f) != (%f %f %f)", Out1[j].r, Out1[j].g, Out1[j].b,
- Out2[j].r, Out2[j].g, Out2[j].b);
- j++;
- }
- cmsDeleteTransform(hXformNoPlugin);
- cmsDeleteTransform(hXformPlugin);
- cmsDeleteContext(noPlugin);
- trace("Ok\n");
- }
- // --------------------------------------------------------------------------------------------------
- // P E R F O R M A N C E C H E C K S
- // --------------------------------------------------------------------------------------------------
- static
- cmsFloat64Number MPixSec(cmsFloat64Number diff)
- {
- cmsFloat64Number seconds = (cmsFloat64Number)diff / (cmsFloat64Number)CLOCKS_PER_SEC;
- return (256.0 * 256.0 * 256.0) / (1024.0*1024.0*seconds);
- }
- typedef cmsFloat64Number(*perf_fn)(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut);
- static
- void PerformanceHeader(void)
- {
- trace(" MPixel/sec. MByte/sec.\n");
- }
- static
- cmsHPROFILE loadProfile(const char* name)
- {
- if (*name == '*')
- {
- if (strcmp(name, "*lab") == 0)
- {
- return cmsCreateLab4Profile(NULL);
- }
- else
- if (strcmp(name, "*xyz") == 0)
- {
- return cmsCreateXYZProfile();
- }
- else
- if (strcmp(name, "*curves") == 0)
- {
- return CreateCurves();
- }
- else
- Fail("Unknown builtin '%s'", name);
- }
-
- return cmsOpenProfileFromFile(name, "r");
- }
- static
- cmsFloat64Number Performance(const char* Title, perf_fn fn, cmsContext ct, const char* inICC, const char* outICC, size_t sz, cmsFloat64Number prev)
- {
- cmsHPROFILE hlcmsProfileIn = loadProfile(inICC);
- cmsHPROFILE hlcmsProfileOut = loadProfile(outICC);
-
- cmsFloat64Number n = fn(ct, hlcmsProfileIn, hlcmsProfileOut);
- trace("%-30s: ", Title); fflush(stdout);
- trace("%-12.2f %-12.2f", n, n * sz);
- if (prev > 0.0) {
- cmsFloat64Number imp = n / prev;
- if (imp > 1)
- trace(" (x %-2.1f)", imp);
- }
- trace("\n"); fflush(stdout);
- return n;
- }
- static
- void ComparativeCt(cmsContext ct1, cmsContext ct2, const char* Title, perf_fn fn1, perf_fn fn2, const char* inICC, const char* outICC)
- {
- cmsHPROFILE hlcmsProfileIn;
- cmsHPROFILE hlcmsProfileOut;
- if (inICC == NULL)
- hlcmsProfileIn = CreateCurves();
- else
- hlcmsProfileIn = cmsOpenProfileFromFile(inICC, "r");
- if (outICC == NULL)
- hlcmsProfileOut = CreateCurves();
- else
- hlcmsProfileOut = cmsOpenProfileFromFile(outICC, "r");
- cmsFloat64Number n1 = fn1(ct1, hlcmsProfileIn, hlcmsProfileOut);
- if (inICC == NULL)
- hlcmsProfileIn = CreateCurves();
- else
- hlcmsProfileIn = cmsOpenProfileFromFile(inICC, "r");
- if (outICC == NULL)
- hlcmsProfileOut = CreateCurves();
- else
- hlcmsProfileOut = cmsOpenProfileFromFile(outICC, "r");
- cmsFloat64Number n2 = fn2(ct2, hlcmsProfileIn, hlcmsProfileOut);
- trace("%-30s: ", Title); fflush(stdout);
- trace("%-12.2f %-12.2f\n", n1, n2);
- }
- static
- void Comparative(const char* Title, perf_fn fn1, perf_fn fn2, const char* inICC, const char* outICC)
- {
- ComparativeCt(0, 0, Title, fn1, fn2, inICC, outICC);
- }
- // The worst case is used, no cache and all rgb combinations
- static
- cmsFloat64Number SpeedTest8bitsRGB(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_rgb8bits *In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGB_8, hlcmsProfileOut, TYPE_RGB_8, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgb8bits);
- In = (Scanline_rgb8bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsUInt8Number)r;
- In[j].g = (cmsUInt8Number)g;
- In[j].b = (cmsUInt8Number)b;
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- cmsFloat64Number SpeedTest8bitsRGBA(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_rgba8bits *In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGBA_8, hlcmsProfileOut, TYPE_RGBA_8, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgba8bits);
- In = (Scanline_rgba8bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsUInt8Number)r;
- In[j].g = (cmsUInt8Number)g;
- In[j].b = (cmsUInt8Number)b;
- In[j].a = 0;
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- // The worst case is used, no cache and all rgb combinations
- static
- cmsFloat64Number SpeedTest15bitsRGB(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_rgb15bits *In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGB_15, hlcmsProfileOut, TYPE_RGB_15, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgb15bits);
- In = (Scanline_rgb15bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsUInt16Number)r;
- In[j].g = (cmsUInt16Number)g;
- In[j].b = (cmsUInt16Number)b;
- j++;
- }
-
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
-
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- cmsFloat64Number SpeedTest15bitsRGBA(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_rgba15bits *In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGBA_15, hlcmsProfileOut, TYPE_RGBA_15, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgba15bits);
- In = (Scanline_rgba15bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsUInt16Number)r;
- In[j].g = (cmsUInt16Number)g;
- In[j].b = (cmsUInt16Number)b;
- In[j].a = 0;
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- cmsFloat64Number SpeedTest15bitsCMYK(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_cmyk15bits *In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_CMYK_15, hlcmsProfileOut, TYPE_CMYK_15, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_cmyk15bits);
- In = (Scanline_cmyk15bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsUInt16Number)r;
- In[j].g = (cmsUInt16Number)g;
- In[j].b = (cmsUInt16Number)b;
- In[j].a = (cmsUInt16Number)0;
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- // The worst case is used, no cache and all rgb combinations
- static
- cmsFloat64Number SpeedTest16bitsRGB(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_rgb16bits *In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGB_16, hlcmsProfileOut, TYPE_RGB_16, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_rgb16bits);
- In = (Scanline_rgb16bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsUInt16Number)FROM_8_TO_16(r);
- In[j].g = (cmsUInt16Number)FROM_8_TO_16(g);
- In[j].b = (cmsUInt16Number)FROM_8_TO_16(b);
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- cmsFloat64Number SpeedTest16bitsCMYK(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_cmyk16bits* In;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_CMYK_16, hlcmsProfileOut, TYPE_CMYK_16, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 256 * 256 * 256 * sizeof(Scanline_cmyk16bits);
- In = (Scanline_cmyk16bits*)malloc(Mb);
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].c = (cmsUInt16Number)r;
- In[j].m = (cmsUInt16Number)g;
- In[j].y = (cmsUInt16Number)b;
- In[j].k = (cmsUInt16Number)r;
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 256 * 256 * 256);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- void SpeedTest8(void)
- {
- cmsContext noPlugin = cmsCreateContext(0, 0);
- cmsFloat64Number t[10];
- trace("\n\n");
- trace("P E R F O R M A N C E T E S T S 8 B I T S (D E F A U L T)\n");
- trace("==============================================================\n\n");
- fflush(stdout);
- PerformanceHeader();
- t[0] = Performance("8 bits on CLUT profiles ", SpeedTest8bitsRGB, noPlugin, "test5.icc", "test3.icc", sizeof(Scanline_rgb8bits), 0);
- t[1] = Performance("8 bits on Matrix-Shaper ", SpeedTest8bitsRGB, noPlugin, "test5.icc", "test0.icc", sizeof(Scanline_rgb8bits), 0);
- t[2] = Performance("8 bits on same MatrixSh ", SpeedTest8bitsRGB, noPlugin, "test0.icc", "test0.icc", sizeof(Scanline_rgb8bits), 0);
- t[3] = Performance("8 bits on curves ", SpeedTest8bitsRGB, noPlugin, "*curves", "*curves", sizeof(Scanline_rgb8bits), 0);
- // Note that context 0 has the plug-in installed
- trace("\n\n");
- trace("P E R F O R M A N C E T E S T S 8 B I T S (P L U G I N)\n");
- trace("===========================================================\n\n");
- fflush(stdout);
- PerformanceHeader();
- Performance("8 bits on CLUT profiles ", SpeedTest8bitsRGB, 0, "test5.icc", "test3.icc", sizeof(Scanline_rgb8bits), t[0]);
- Performance("8 bits on Matrix-Shaper ", SpeedTest8bitsRGB, 0, "test5.icc", "test0.icc", sizeof(Scanline_rgb8bits), t[1]);
- Performance("8 bits on same MatrixSh ", SpeedTest8bitsRGB, 0, "test0.icc", "test0.icc", sizeof(Scanline_rgb8bits), t[2]);
- Performance("8 bits on curves ", SpeedTest8bitsRGB, 0, "*curves", "*curves", sizeof(Scanline_rgb8bits), t[3]);
- cmsDeleteContext(noPlugin);
- }
- static
- void SpeedTest15(void)
- {
- trace("\n\nP E R F O R M A N C E T E S T S 1 5 B I T S (P L U G I N)\n");
- trace( "===============================================================\n\n");
-
- PerformanceHeader();
- Performance("15 bits on CLUT profiles ", SpeedTest15bitsRGB, 0, "test5.icc", "test3.icc", sizeof(Scanline_rgb15bits), 0);
- Performance("15 bits on Matrix-Shaper profiles", SpeedTest15bitsRGB, 0, "test5.icc", "test0.icc", sizeof(Scanline_rgb15bits), 0);
- Performance("15 bits on same Matrix-Shaper ", SpeedTest15bitsRGB, 0, "test0.icc", "test0.icc", sizeof(Scanline_rgb15bits), 0);
- Performance("15 bits on curves ", SpeedTest15bitsRGB, 0, "*curves", "*curves", sizeof(Scanline_rgb15bits), 0);
- Performance("15 bits on CMYK CLUT profiles ", SpeedTest15bitsCMYK, 0, "test1.icc", "test2.icc", sizeof(Scanline_rgba15bits), 0);
- }
- static
- void SpeedTest16(void)
- {
- cmsContext noPlugin = cmsCreateContext(0, 0);
- trace("\n\n");
- trace("P E R F O R M A N C E T E S T S 1 6 B I T S (D E F A U L T)\n");
- trace("=================================================================\n\n");
-
- PerformanceHeader();
- Performance("16 bits on CLUT profiles ", SpeedTest16bitsRGB, noPlugin, "test5.icc", "test3.icc", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on Matrix-Shaper profiles", SpeedTest16bitsRGB, noPlugin, "test5.icc", "test0.icc", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on same Matrix-Shaper ", SpeedTest16bitsRGB, noPlugin, "test0.icc", "test0.icc", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on curves ", SpeedTest16bitsRGB, noPlugin, "*curves", "*curves", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on CMYK CLUT profiles ", SpeedTest16bitsCMYK, noPlugin, "test1.icc", "test2.icc", sizeof(Scanline_cmyk16bits), 0);
-
- trace("\n\n");
- trace("P E R F O R M A N C E T E S T S 1 6 B I T S (P L U G I N)\n");
- trace("===============================================================\n\n");
- PerformanceHeader();
- Performance("16 bits on CLUT profiles ", SpeedTest16bitsRGB, 0, "test5.icc", "test3.icc", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on Matrix-Shaper profiles", SpeedTest16bitsRGB, 0, "test5.icc", "test0.icc", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on same Matrix-Shaper ", SpeedTest16bitsRGB, 0, "test0.icc", "test0.icc", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on curves ", SpeedTest16bitsRGB, 0, "*curves", "*curves", sizeof(Scanline_rgb16bits), 0);
- Performance("16 bits on CMYK CLUT profiles ", SpeedTest16bitsCMYK, 0, "test1.icc", "test2.icc", sizeof(Scanline_cmyk16bits), 0);
- }
- // The worst case is used, no cache and all rgb combinations
- static
- cmsFloat64Number SpeedTestFloatRGB(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- void *In;
- cmsUInt32Number size, Mb;
- cmsUInt32Number inFormatter=0, outFormatter=0;
- cmsFloat64Number seconds;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- switch (cmsGetColorSpace(hlcmsProfileIn))
- {
- case cmsSigRgbData: inFormatter = TYPE_RGB_FLT; break;
- case cmsSigLabData: inFormatter = TYPE_Lab_FLT; break;
-
- default:
- Fail("Invalid colorspace");
- }
- switch (cmsGetColorSpace(hlcmsProfileOut))
- {
- case cmsSigRgbData: outFormatter = TYPE_RGB_FLT; break;
- case cmsSigLabData: outFormatter = TYPE_Lab_FLT; break;
- case cmsSigXYZData: outFormatter = TYPE_XYZ_FLT; break;
- default:
- Fail("Invalid colorspace");
- }
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, inFormatter, hlcmsProfileOut, outFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
-
- j = 0;
- if (inFormatter == TYPE_RGB_FLT)
- {
- cmsInt32Number r, g, b;
- Scanline_rgbFloat* fill;
-
- size = 256 * 256 * 256;
- Mb = size * sizeof(Scanline_rgbFloat);
- In = malloc(Mb);
- fill = (Scanline_rgbFloat*)In;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- fill[j].r = (cmsFloat32Number)r / 255.0f;
- fill[j].g = (cmsFloat32Number)g / 255.0f;
- fill[j].b = (cmsFloat32Number)b / 255.0f;
- j++;
- }
- }
- else
- {
- cmsFloat32Number L, a, b;
- Scanline_LabFloat* fill;
- size = 100 * 256 * 256;
- Mb = size * sizeof(Scanline_LabFloat);
- In = malloc(Mb);
- fill = (Scanline_LabFloat*)In;
- for (L = 0; L < 100; L++)
- for (a = -127.0; a < 127.0; a++)
- for (b = -127.0; b < +127.0; b++) {
- fill[j].L = L;
- fill[j].a = a;
- fill[j].b = b;
- j++;
- }
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, size);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
-
- seconds = (cmsFloat64Number)diff / (cmsFloat64Number)CLOCKS_PER_SEC;
- return ((cmsFloat64Number)size) / (1024.0 * 1024.0 * seconds);
- }
- static
- cmsFloat64Number SpeedTestFloatCMYK(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number c, m, y, k, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- Scanline_cmykFloat* In;
- cmsUInt32Number Mb;
-
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
-
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_CMYK_FLT, hlcmsProfileOut, TYPE_CMYK_FLT, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- Mb = 64 * 64 * 64 * 64 * sizeof(Scanline_cmykFloat);
- In = (Scanline_cmykFloat*)malloc(Mb);
- j = 0;
- for (c = 0; c < 256; c += 4)
- for (m = 0; m < 256; m += 4)
- for (y = 0; y < 256; y += 4)
- for (k = 0; k < 256; k += 4) {
- In[j].c = (cmsFloat32Number)c / 255.0f;
- In[j].m = (cmsFloat32Number)m / 255.0f;
- In[j].y = (cmsFloat32Number)y / 255.0f;
- In[j].k = (cmsFloat32Number)k / 255.0f;
- j++;
- }
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, 64 * 64 * 64 * 64);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- cmsFloat64Number SpeedTestFloatLab(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- void* In;
- cmsUInt32Number size, Mb;
- cmsUInt32Number outFormatter = 0;
- cmsFloat64Number seconds;
- cmsFloat32Number L, a, b;
- Scanline_LabFloat* fill;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- if (cmsGetColorSpace(hlcmsProfileIn) != cmsSigLabData)
- {
- Fail("Invalid colorspace");
- }
- switch (cmsGetColorSpace(hlcmsProfileOut))
- {
- case cmsSigRgbData: outFormatter = TYPE_RGB_FLT; break;
- case cmsSigLabData: outFormatter = TYPE_Lab_FLT; break;
- case cmsSigXYZData: outFormatter = TYPE_XYZ_FLT; break;
- default:
- Fail("Invalid colorspace");
- }
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_Lab_FLT, hlcmsProfileOut, outFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- j = 0;
- size = 100 * 256 * 256;
- Mb = size * sizeof(Scanline_LabFloat);
- In = malloc(Mb);
- fill = (Scanline_LabFloat*)In;
- for (L = 0; L < 100; L++)
- for (a = -127.0; a < 127.0; a++)
- for (b = -127.0; b < +127.0; b++) {
- fill[j].L = L;
- fill[j].a = a;
- fill[j].b = b;
- j++;
- }
-
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, size);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- seconds = (cmsFloat64Number)diff / (cmsFloat64Number)CLOCKS_PER_SEC;
- return ((cmsFloat64Number)size) / (1024.0 * 1024.0 * seconds);
- }
- static
- void SpeedTestFloat(void)
- {
- cmsContext noPlugin = cmsCreateContext(0, 0);
-
- cmsFloat64Number t[10] = { 0 };
- trace("\n\n");
- trace("P E R F O R M A N C E T E S T S F L O A T (D E F A U L T)\n");
- trace("==============================================================\n\n");
- fflush(stdout);
- PerformanceHeader();
- t[0] = Performance("Floating point on CLUT profiles ", SpeedTestFloatRGB, noPlugin, "test5.icc", "test3.icc", sizeof(Scanline_rgbFloat), 0);
- t[1] = Performance("Floating point on Matrix-Shaper ", SpeedTestFloatRGB, noPlugin, "test5.icc", "test0.icc", sizeof(Scanline_rgbFloat), 0);
- t[2] = Performance("Floating point on same MatrixSh ", SpeedTestFloatRGB, noPlugin, "test0.icc", "test0.icc", sizeof(Scanline_rgbFloat), 0);
- t[3] = Performance("Floating point on curves ", SpeedTestFloatRGB, noPlugin, "*curves", "*curves", sizeof(Scanline_rgbFloat), 0);
- t[4] = Performance("Floating point on RGB->Lab ", SpeedTestFloatRGB, noPlugin, "test5.icc", "*lab", sizeof(Scanline_rgbFloat), 0);
- t[5] = Performance("Floating point on RGB->XYZ ", SpeedTestFloatRGB, noPlugin, "test3.icc", "*xyz", sizeof(Scanline_rgbFloat), 0);
- t[6] = Performance("Floating point on CMYK->CMYK ", SpeedTestFloatCMYK, noPlugin, "test1.icc", "test2.icc",sizeof(Scanline_cmykFloat), 0);
- t[7] = Performance("Floating point on Lab->RGB ", SpeedTestFloatLab, noPlugin, "*lab", "test3.icc", sizeof(Scanline_LabFloat), 0);
- // Note that context 0 has the plug-in installed
- trace("\n\n");
- trace("P E R F O R M A N C E T E S T S F L O A T (P L U G I N)\n");
- trace("===========================================================\n\n");
- fflush(stdout);
- PerformanceHeader();
- Performance("Floating point on CLUT profiles ", SpeedTestFloatRGB, 0, "test5.icc", "test3.icc", sizeof(Scanline_rgbFloat), t[0]);
- Performance("Floating point on Matrix-Shaper ", SpeedTestFloatRGB, 0, "test5.icc", "test0.icc", sizeof(Scanline_rgbFloat), t[1]);
- Performance("Floating point on same MatrixSh ", SpeedTestFloatRGB, 0, "test0.icc", "test0.icc", sizeof(Scanline_rgbFloat), t[2]);
- Performance("Floating point on curves ", SpeedTestFloatRGB, 0, "*curves", "*curves", sizeof(Scanline_rgbFloat), t[3]);
- Performance("Floating point on RGB->Lab ", SpeedTestFloatRGB, 0, "test5.icc", "*lab", sizeof(Scanline_rgbFloat), t[4]);
- Performance("Floating point on RGB->XYZ ", SpeedTestFloatRGB, 0, "test3.icc", "*xyz", sizeof(Scanline_rgbFloat), t[5]);
- Performance("Floating point on CMYK->CMYK ", SpeedTestFloatCMYK, 0, "test1.icc", "test2.icc", sizeof(Scanline_cmykFloat), t[6]);
- Performance("Floating point on Lab->RGB ", SpeedTestFloatLab, 0, "*lab", "test3.icc", sizeof(Scanline_LabFloat), t[7]);
- cmsDeleteContext(noPlugin);
- }
- static
- cmsFloat64Number SpeedTestFloatByUsing16BitsRGB(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM xform16;
- Scanline_rgbFloat *In;
- Scanline_rgb16bits *tmp16;
- cmsUInt32Number MbFloat, Mb16;
- UNUSED_PARAMETER(ct);
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- xform16 = cmsCreateTransformTHR(0, hlcmsProfileIn, TYPE_RGB_16, hlcmsProfileOut, TYPE_RGB_16, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- MbFloat = 256 * 256 * 256 * sizeof(Scanline_rgbFloat);
- Mb16 = 256 * 256 * 256 * sizeof(Scanline_rgb16bits);
- In = (Scanline_rgbFloat*)malloc(MbFloat);
- tmp16 = (Scanline_rgb16bits*)malloc(Mb16);
-
- j = 0;
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In[j].r = (cmsFloat32Number)r / 255.0f;
- In[j].g = (cmsFloat32Number)g / 255.0f;
- In[j].b = (cmsFloat32Number)b / 255.0f;
- j++;
- }
-
- atime = clock();
-
- for (j = 0; j < 256 * 256 * 256; j++) {
- tmp16[j].r = (cmsUInt16Number)floor(In[j].r * 65535.0 + 0.5);
- tmp16[j].g = (cmsUInt16Number)floor(In[j].g * 65535.0 + 0.5);
- tmp16[j].b = (cmsUInt16Number)floor(In[j].b * 65535.0 + 0.5);
- j++;
- }
- cmsDoTransform(xform16, tmp16, tmp16, 256 * 256 * 256);
- for (j = 0; j < 256 * 256 * 256; j++) {
- In[j].r = (cmsFloat32Number) (tmp16[j].r / 65535.0 );
- In[j].g = (cmsFloat32Number) (tmp16[j].g / 65535.0);
- In[j].b = (cmsFloat32Number) (tmp16[j].b / 65535.0);
- j++;
- }
- diff = clock() - atime;
- free(In);
-
- cmsDeleteTransform(xform16);
- return MPixSec(diff);
- }
- static
- void ComparativeFloatVs16bits(void)
- {
- trace("\n\n");
- trace("C O M P A R A T I V E converting to 16 bit vs. using float plug-in.\n");
- trace(" values given in MegaPixels per second.\n");
- trace("====================================================================\n");
- trace(" 16 bits tmp. Float plugin\n");
- fflush(stdout);
- Comparative("Floating point on CLUT profiles ", SpeedTestFloatByUsing16BitsRGB, SpeedTestFloatRGB, "test5.icc", "test3.icc");
- Comparative("Floating point on Matrix-Shaper ", SpeedTestFloatByUsing16BitsRGB, SpeedTestFloatRGB, "test5.icc", "test0.icc");
- Comparative("Floating point on same MatrixSh ", SpeedTestFloatByUsing16BitsRGB, SpeedTestFloatRGB, "test0.icc", "test0.icc");
- Comparative("Floating point on curves ", SpeedTestFloatByUsing16BitsRGB, SpeedTestFloatRGB, NULL, NULL);
- }
- typedef struct
- {
- Scanline_rgba8bits pixels[256][256];
- cmsUInt8Number padding[4];
- } padded_line;
- typedef struct
- {
- padded_line line[256];
- } big_bitmap;
- static
- cmsFloat64Number SpeedTest8bitDoTransform(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b, j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- big_bitmap* In;
- big_bitmap* Out;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGBA_8, hlcmsProfileOut, TYPE_RGBA_8, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- // Our test bitmap is 256 x 256 padded lines
- Mb = sizeof(big_bitmap);
- In = (big_bitmap*)malloc(Mb);
- Out = (big_bitmap*)malloc(Mb);
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In->line[r].pixels[g][b].r = (cmsUInt8Number)r;
- In->line[r].pixels[g][b].g = (cmsUInt8Number)g;
- In->line[r].pixels[g][b].b = (cmsUInt8Number)b;
- In->line[r].pixels[g][b].a = 0;
- }
- atime = clock();
- for (j = 0; j < 256; j++) {
- cmsDoTransform(hlcmsxform, In->line[j].pixels, Out->line[j].pixels, 256 * 256);
- }
- diff = clock() - atime;
- free(In); free(Out);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- cmsFloat64Number SpeedTest8bitLineStride(cmsContext ct, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut)
- {
- cmsInt32Number r, g, b;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- big_bitmap* In;
- big_bitmap* Out;
- cmsUInt32Number Mb;
- if (hlcmsProfileIn == NULL || hlcmsProfileOut == NULL)
- Fail("Unable to open profiles");
- hlcmsxform = cmsCreateTransformTHR(ct, hlcmsProfileIn, TYPE_RGBA_8, hlcmsProfileOut, TYPE_RGBA_8, INTENT_PERCEPTUAL, cmsFLAGS_NOCACHE);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- // Our test bitmap is 256 x 256 padded lines
- Mb = sizeof(big_bitmap);
- In = (big_bitmap*)malloc(Mb);
- Out = (big_bitmap*)malloc(Mb);
- for (r = 0; r < 256; r++)
- for (g = 0; g < 256; g++)
- for (b = 0; b < 256; b++) {
- In->line[r].pixels[g][b].r = (cmsUInt8Number)r;
- In->line[r].pixels[g][b].g = (cmsUInt8Number)g;
- In->line[r].pixels[g][b].b = (cmsUInt8Number)b;
- In->line[r].pixels[g][b].a = 0;
- }
- atime = clock();
-
- cmsDoTransformLineStride(hlcmsxform, In, Out, 256*256, 256, sizeof(padded_line), sizeof(padded_line), 0, 0);
-
- diff = clock() - atime;
- free(In); free(Out);
- cmsDeleteTransform(hlcmsxform);
- return MPixSec(diff);
- }
- static
- void ComparativeLineStride8bits(void)
- {
- cmsContext NoPlugin, Plugin;
- trace("\n\n");
- trace("C O M P A R A T I V E cmsDoTransform() vs. cmsDoTransformLineStride()\n");
- trace(" values given in MegaPixels per second.\n");
- trace("====================================================================\n");
- fflush(stdout);
- NoPlugin = cmsCreateContext(NULL, NULL);
- Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL);
- ComparativeCt(NoPlugin, Plugin, "CLUT profiles ", SpeedTest8bitDoTransform, SpeedTest8bitLineStride, "test5.icc", "test3.icc");
- ComparativeCt(NoPlugin, Plugin, "CLUT 16 bits ", SpeedTest16bitsRGB, SpeedTest16bitsRGB, "test5.icc", "test3.icc");
- ComparativeCt(NoPlugin, Plugin, "Matrix-Shaper ", SpeedTest8bitDoTransform, SpeedTest8bitLineStride, "test5.icc", "test0.icc");
- ComparativeCt(NoPlugin, Plugin, "same MatrixSh ", SpeedTest8bitDoTransform, SpeedTest8bitLineStride, "test0.icc", "test0.icc");
- ComparativeCt(NoPlugin, Plugin, "curves ", SpeedTest8bitDoTransform, SpeedTest8bitLineStride, NULL, NULL);
- cmsDeleteContext(Plugin);
- cmsDeleteContext(NoPlugin);
- }
- static
- void TestGrayTransformPerformance()
- {
- cmsInt32Number j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- float *In;
- cmsInt32Number pixels;
- cmsUInt32Number Mb;
- cmsToneCurve* gamma18;
- cmsToneCurve* gamma22;
- cmsHPROFILE hlcmsProfileIn;
- cmsHPROFILE hlcmsProfileOut;
- gamma18 = cmsBuildGamma(0, 1.8);
- gamma22 = cmsBuildGamma(0, 2.2);
- hlcmsProfileIn = cmsCreateGrayProfile(NULL, gamma18);
- hlcmsProfileOut = cmsCreateGrayProfile(NULL, gamma22);
- cmsFreeToneCurve(gamma18);
- cmsFreeToneCurve(gamma22);
- hlcmsxform = cmsCreateTransform(hlcmsProfileIn, TYPE_GRAY_FLT | EXTRA_SH(1), hlcmsProfileOut, TYPE_GRAY_FLT|EXTRA_SH(1), INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- pixels = 256 * 256 * 256;
- Mb = pixels* 2*sizeof(float);
- In = (float*) malloc(Mb);
- for (j = 0; j < pixels*2; j++)
- In[j] = (j % 256) / 255.0f;
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, pixels);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- trace("Gray conversion using two gray profiles\t %-12.2f MPixels/Sec.\n", MPixSec(diff));
- }
- static
- void TestGrayTransformPerformance1()
- {
- cmsInt32Number j;
- clock_t atime;
- cmsFloat64Number diff;
- cmsHTRANSFORM hlcmsxform;
- float *In;
- cmsInt32Number pixels;
- cmsUInt32Number Mb;
- cmsToneCurve* gamma18;
- cmsToneCurve* gamma22;
- cmsHPROFILE hlcmsProfileIn;
- cmsHPROFILE hlcmsProfileOut;
- gamma18 = cmsBuildGamma(0, 1.8);
- gamma22 = cmsBuildGamma(0, 1./2.2);
- hlcmsProfileIn = cmsCreateLinearizationDeviceLink(cmsSigGrayData, &gamma18);
- hlcmsProfileOut = cmsCreateLinearizationDeviceLink(cmsSigGrayData, &gamma22);
- cmsFreeToneCurve(gamma18);
- cmsFreeToneCurve(gamma22);
- hlcmsxform = cmsCreateTransform(hlcmsProfileIn, TYPE_GRAY_FLT, hlcmsProfileOut, TYPE_GRAY_FLT, INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(hlcmsProfileIn);
- cmsCloseProfile(hlcmsProfileOut);
- pixels = 256 * 256 * 256;
- Mb = pixels* sizeof(float);
- In = (float*) malloc(Mb);
- for (j = 0; j < pixels; j++)
- In[j] = (j % 256) / 255.0f;
- atime = clock();
- cmsDoTransform(hlcmsxform, In, In, pixels);
- diff = clock() - atime;
- free(In);
- cmsDeleteTransform(hlcmsxform);
- trace("Gray conversion using two devicelinks\t %-12.2f MPixels/Sec.\n", MPixSec(diff));
- }
- // The harness test
- int main()
- {
- trace("FastFloating point extensions testbed - 1.5\n");
- trace("Copyright (c) 1998-2022 Marti Maria Saguer, all rights reserved\n");
-
- trace("\nInstalling error logger ... ");
- cmsSetLogErrorHandler(FatalErrorQuit);
- trace("done.\n");
- trace("Installing plug-in ... ");
- cmsPlugin(cmsFastFloatExtensions());
- trace("done.\n\n");
-
- CheckComputeIncrements();
- // 15 bit functionality
- CheckFormatters15();
- Check15bitsConversions();
-
- // 16 bits functionality
- CheckAccuracy16Bits();
- // Lab to whatever
- CheckLab2RGB();
- // Change format
- CheckChangeFormat();
- // Soft proofing
- CheckSoftProofing();
- // Floating point functionality
- CheckConversionFloat();
- trace("All floating point tests passed OK\n");
-
- SpeedTest8();
- SpeedTest16();
- SpeedTest15();
- SpeedTestFloat();
-
- ComparativeFloatVs16bits();
- ComparativeLineStride8bits();
- // Test gray performance
- trace("\n\n");
- trace("F L O A T G R A Y conversions performance.\n");
- trace("====================================================================\n");
- TestGrayTransformPerformance();
- TestGrayTransformPerformance1();
-
- trace("\nAll tests passed OK\n");
- return 0;
- }
|