| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089 |
- // ESENTHEL CHANGED: char -> signed char
- //// etcpack v2.74
- ////
- //// NO WARRANTY
- ////
- //// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE THE PROGRAM IS PROVIDED
- //// "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF ANY KIND, EXTENDS NO
- //// WARRANTIES OR CONDITIONS OF ANY KIND; EITHER EXPRESS, IMPLIED OR
- //// STATUTORY; INCLUDING, BUT NOT LIMITED TO, EXPRESS, IMPLIED OR
- //// STATUTORY WARRANTIES OR CONDITIONS OF TITLE, MERCHANTABILITY,
- //// SATISFACTORY QUALITY, SUITABILITY AND FITNESS FOR A PARTICULAR
- //// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
- //// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
- //// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
- //// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, OFFERING FOR SALE,
- //// DISTRIBUTION, LEASE, USE OR IMPORTATION UNDER THE LICENSE WILL BE FREE
- //// FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL
- //// PROPERTY RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE IS SUBJECT
- //// TO YOUR SOLE RESPONSIBILITY TO MAKE SUCH DETERMINATION AND ACQUIRE
- //// SUCH LICENSES AS MAY BE NECESSARY WITH RESPECT TO PATENTS, COPYRIGHT
- //// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES.
- ////
- //// FOR THE AVOIDANCE OF DOUBT THE PROGRAM (I) IS NOT LICENSED FOR; (II)
- //// IS NOT DESIGNED FOR OR INTENDED FOR; AND (III) MAY NOT BE USED FOR;
- //// ANY MISSION CRITICAL APPLICATIONS SUCH AS, BUT NOT LIMITED TO
- //// OPERATION OF NUCLEAR OR HEALTHCARE COMPUTER SYSTEMS AND/OR NETWORKS,
- //// AIRCRAFT OR TRAIN CONTROL AND/OR COMMUNICATION SYSTEMS OR ANY OTHER
- //// COMPUTER SYSTEMS AND/OR NETWORKS OR CONTROL AND/OR COMMUNICATION
- //// SYSTEMS ALL IN WHICH CASE THE FAILURE OF THE PROGRAM COULD LEAD TO
- //// DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL, MATERIAL OR ENVIRONMENTAL
- //// DAMAGE. YOUR RIGHTS UNDER THIS LICENSE WILL TERMINATE AUTOMATICALLY
- //// AND IMMEDIATELY WITHOUT NOTICE IF YOU FAIL TO COMPLY WITH THIS
- //// PARAGRAPH.
- ////
- //// IN NO EVENT WILL ERICSSON, BE LIABLE FOR ANY DAMAGES WHATSOEVER,
- //// INCLUDING BUT NOT LIMITED TO PERSONAL INJURY, ANY GENERAL, SPECIAL,
- //// INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
- //// CONNECTION WITH THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
- //// NOT LIMITED TO LOSS OF PROFITS, BUSINESS INTERUPTIONS, OR ANY OTHER
- //// COMMERCIAL DAMAGES OR LOSSES, LOSS OF DATA OR DATA BEING RENDERED
- //// INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
- //// THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) REGARDLESS OF THE
- //// THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE), EVEN IF SUCH HOLDER
- //// OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- ////
- //// (C) Ericsson AB 2005-2013. All Rights Reserved.
- ////
- /*#include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <sys/timeb.h>*/
- // Typedefs
- typedef unsigned char uint8;
- typedef unsigned short uint16;
- typedef short int16;
- // Functions needed for decrompession ---- in etcdec.cxx
- void read_big_endian_2byte_word(unsigned short *blockadr, FILE *f);
- void read_big_endian_4byte_word(unsigned int *blockadr, FILE *f);
- void unstuff57bits(unsigned int planar_word1, unsigned int planar_word2, unsigned int &planar57_word1, unsigned int &planar57_word2);
- void unstuff59bits(unsigned int thumbT_word1, unsigned int thumbT_word2, unsigned int &thumbT59_word1, unsigned int &thumbT59_word2);
- void unstuff58bits(unsigned int thumbH_word1, unsigned int thumbH_word2, unsigned int &thumbH58_word1, unsigned int &thumbH58_word2);
- void decompressColor(int R_B, int G_B, int B_B, uint8 (colors_RGB444)[2][3], uint8 (colors)[2][3]);
- void calculatePaintColors59T(uint8 d, uint8 p, uint8 (colors)[2][3], uint8 (possible_colors)[4][3]);
- void calculatePaintColors58H(uint8 d, uint8 p, uint8 (colors)[2][3], uint8 (possible_colors)[4][3]);
- void decompressBlockTHUMB59T(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty);
- void decompressBlockTHUMB58H(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty);
- void decompressBlockPlanar57(unsigned int compressed57_1, unsigned int compressed57_2, uint8 *img,int width,int height,int startx,int starty);
- void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty);
- void decompressBlockETC2(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty);
- void decompressBlockDifferentialWithAlpha(unsigned int block_part1,unsigned int block_part2, uint8* img, uint8* alpha, int width, int height, int startx, int starty);
- void decompressBlockETC21BitAlpha(unsigned int block_part1, unsigned int block_part2, uint8 *img, uint8* alphaimg, int width,int height,int startx,int starty);
- void decompressBlockTHUMB58HAlpha(unsigned int block_part1, unsigned int block_part2, uint8 *img, uint8* alpha,int width,int height,int startx,int starty);
- void decompressBlockTHUMB59TAlpha(unsigned int block_part1, unsigned int block_part2, uint8 *img, uint8* alpha,int width,int height,int startx,int starty);
- uint8 getbit(uint8 input, int frompos, int topos);
- int clamp(int val);
- void decompressBlockAlpha(uint8* data,uint8* img,int width,int height,int ix,int iy);
- uint16 get16bits11bits(int base, int table, int mul, int index);
- void decompressBlockAlpha16bit(uint8* data,uint8* img,int width,int height,int ix,int iy);
- int16 get16bits11signed(int base, int table, int mul, int index);
- void setupAlphaTable();
- // This source code is quite long. You can make it shorter by not including the
- // code doing the exhaustive code. Then the -slow modes will not work, but the
- // code will be approximately half the number of lines of code.
- // Then the lines between "exhaustive code starts here" and "exhaustive code ends here"
- // can then be removed.
- #ifndef EXHAUSTIVE_CODE_ACTIVE // ESENTHEL CHANGED
- #define EXHAUSTIVE_CODE_ACTIVE 1
- #endif
- // Remove warnings for unsafe functions such as strcpy
- #pragma warning(disable : 4996)
- // Remove warnings for conversions between different time variables
- #pragma warning(disable : 4244)
- // Remove warnings for negative or too big shifts
- //#pragma warning(disable : 4293)
-
- #define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x)))
- // The below code works as CLAMP(0, x, 255) if x < 255
- #define CLAMP_LEFT_ZERO(x) ((~(((int)(x))>>31))&(x))
- // The below code works as CLAMP(0, x, 255) if x is in [0,511]
- #define CLAMP_RIGHT_255(x) (((( ((((int)(x))<<23)>>31) ))|(x))&0x000000ff)
- #define SQUARE(x) ((x)*(x))
- #define JAS_ROUND(x) (((x) < 0.0 ) ? ((int)((x)-0.5)) : ((int)((x)+0.5)))
- #define JAS_MIN(a,b) ((a) < (b) ? (a) : (b))
- #define JAS_MAX(a,b) ((a) > (b) ? (a) : (b))
- // The error metric Wr Wg Wb should be definied so that Wr^2 + Wg^2 + Wb^2 = 1.
- // Hence it is easier to first define the squared values and derive the weights
- // as their square-roots.
- #define PERCEPTUAL_WEIGHT_R_SQUARED 0.299
- #define PERCEPTUAL_WEIGHT_G_SQUARED 0.587
- #define PERCEPTUAL_WEIGHT_B_SQUARED 0.114
- #define PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000 299
- #define PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000 587
- #define PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000 114
- #define RED(img,width,x,y) img[3*(y*width+x)+0]
- #define GREEN(img,width,x,y) img[3*(y*width+x)+1]
- #define BLUE(img,width,x,y) img[3*(y*width+x)+2]
- #define SHIFT(size,startpos) ((startpos)-(size)+1)
- #define MASK(size, startpos) (((2u<<(size-1u))-1u) << SHIFT(size,startpos)) // ESENTHEL CHANGED: converted to unsigned constants to silent compiler warnings on Android
- #define PUTBITS( dest, data, size, startpos) dest = ((dest & ~MASK(size, startpos)) | ((data << SHIFT(size, startpos)) & MASK(size,startpos)))
- #define SHIFTHIGH(size, startpos) (((startpos)-32)-(size)+1)
- #define MASKHIGH(size, startpos) (((1<<(size))-1) << SHIFTHIGH(size,startpos))
- #define PUTBITSHIGH(dest, data, size, startpos) dest = ((dest & ~MASKHIGH(size, startpos)) | ((data << SHIFTHIGH(size, startpos)) & MASKHIGH(size,startpos)))
- #define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1))
- #define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1))
- // Thumb macros and definitions
- #define R_BITS59T 4
- #define G_BITS59T 4
- #define B_BITS59T 4
- #define R_BITS58H 4
- #define G_BITS58H 4
- #define B_BITS58H 4
- #define MAXIMUM_ERROR (255*255*16*1000)
- #define R 0
- #define G 1
- #define B 2
- #define BLOCKHEIGHT 4
- #define BLOCKWIDTH 4
- #define BINPOW(power) (1<<(power))
- //#define RADIUS 2
- #define TABLE_BITS_59T 3
- #define TABLE_BITS_58H 3
- // Global tables
- //static const uint8 table59T[8] = {3,6,11,16,23,32,41,64}; // 3-bit table for the 59 bit T-mode
- //static const uint8 table58H[8] = {3,6,11,16,23,32,41,64}; // 3-bit table for the 58 bit H-mode
- static const uint8 weight[3] = {1,1,1}; // Color weight
- // Enums
- /*enum{PATTERN_H = 0,
- PATTERN_T = 1};*/
- enum{MODE_ETC1, MODE_THUMB_T, MODE_THUMB_H, MODE_PLANAR};
- // The ETC2 package of codecs includes the following codecs:
- //
- // codec enum
- // --------------------------------------------------------
- // GL_COMPRESSED_R11_EAC 0x9270
- // GL_COMPRESSED_SIGNED_R11_EAC 0x9271
- // GL_COMPRESSED_RG11_EAC 0x9272
- // GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
- // GL_COMPRESSED_RGB8_ETC2 0x9274
- // GL_COMPRESSED_SRGB8_ETC2 0x9275
- // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
- // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
- // GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
- // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
- //
- // The older codec ETC1 is not included in the package
- // GL_ETC1_RGB8_OES 0x8d64
- // but since ETC2 is backwards compatible an ETC1 texture can
- // be decoded using the RGB8_ETC2 enum (0x9274)
- //
- // In a PKM-file, the codecs are stored using the following identifiers
- //
- // identifier value codec
- // --------------------------------------------------------------------
- // ETC1_RGB_NO_MIPMAPS 0 GL_ETC1_RGB8_OES
- // ETC2PACKAGE_RGB_NO_MIPMAPS 1 GL_COMPRESSED_RGB8_ETC2
- // ETC2PACKAGE_RGBA_NO_MIPMAPS_OLD 2, not used -
- // ETC2PACKAGE_RGBA_NO_MIPMAPS 3 GL_COMPRESSED_RGBA8_ETC2_EAC
- // ETC2PACKAGE_RGBA1_NO_MIPMAPS 4 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
- // ETC2PACKAGE_R_NO_MIPMAPS 5 GL_COMPRESSED_R11_EAC
- // ETC2PACKAGE_RG_NO_MIPMAPS 6 GL_COMPRESSED_RG11_EAC
- // ETC2PACKAGE_R_SIGNED_NO_MIPMAPS 7 GL_COMPRESSED_SIGNED_R11_EAC
- // ETC2PACKAGE_RG_SIGNED_NO_MIPMAPS 8 GL_COMPRESSED_SIGNED_RG11_EAC
- //
- // In the code, the identifiers are not always used strictly. For instance, the
- // identifier ETC2PACKAGE_R_NO_MIPMAPS is sometimes used for both the unsigned
- // (GL_COMPRESSED_R11_EAC) and signed (GL_COMPRESSED_SIGNED_R11_EAC) version of
- // the codec.
- //
- enum{ETC1_RGB_NO_MIPMAPS,ETC2PACKAGE_RGB_NO_MIPMAPS,ETC2PACKAGE_RGBA_NO_MIPMAPS_OLD,ETC2PACKAGE_RGBA_NO_MIPMAPS,ETC2PACKAGE_RGBA1_NO_MIPMAPS,ETC2PACKAGE_R_NO_MIPMAPS,ETC2PACKAGE_RG_NO_MIPMAPS,ETC2PACKAGE_R_SIGNED_NO_MIPMAPS,ETC2PACKAGE_RG_SIGNED_NO_MIPMAPS,ETC2PACKAGE_sRGB_NO_MIPMAPS,ETC2PACKAGE_sRGBA_NO_MIPMAPS,ETC2PACKAGE_sRGBA1_NO_MIPMAPS};
- enum {MODE_COMPRESS, MODE_UNCOMPRESS, MODE_PSNR};
- enum {SPEED_SLOW, SPEED_FAST, SPEED_MEDIUM};
- enum {METRIC_PERCEPTUAL, METRIC_NONPERCEPTUAL};
- enum {CODEC_ETC, CODEC_ETC2};
- /*int mode = MODE_COMPRESS;
- int speed = SPEED_FAST;
- int metric = METRIC_PERCEPTUAL;
- int codec = CODEC_ETC2;
- int format = ETC2PACKAGE_RGB_NO_MIPMAPS;
- int verbose = true;
- extern int formatSigned;
- int ktxFile=0;
- bool first_time_message = true;*/
- static const int scramble[4] = {3, 2, 0, 1};
- //static const int unscramble[4] = {2, 3, 1, 0};
- /*typedef struct KTX_header_t
- {
- uint8 identifier[12];
- unsigned int endianness;
- unsigned int glType;
- unsigned int glTypeSize;
- unsigned int glFormat;
- unsigned int glInternalFormat;
- unsigned int glBaseInternalFormat;
- unsigned int pixelWidth;
- unsigned int pixelHeight;
- unsigned int pixelDepth;
- unsigned int numberOfArrayElements;
- unsigned int numberOfFaces;
- unsigned int numberOfMipmapLevels;
- unsigned int bytesOfKeyValueData;
- }
- KTX_header;
- #define KTX_IDENTIFIER_REF { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }
- #define KTX_ENDIAN_REF (0x04030201)
- #define KTX_ENDIAN_REF_REV (0x01020304)
- enum {GL_R=0x1903,GL_RG=0x8227,GL_RGB=0x1907,GL_RGBA=0x1908};
- #define GL_SRGB 0x8C40
- #define GL_SRGB8 0x8C41
- #define GL_SRGB8_ALPHA8 0x8C43
- #define GL_ETC1_RGB8_OES 0x8d64
- #define GL_COMPRESSED_R11_EAC 0x9270
- #define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
- #define GL_COMPRESSED_RG11_EAC 0x9272
- #define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
- #define GL_COMPRESSED_RGB8_ETC2 0x9274
- #define GL_COMPRESSED_SRGB8_ETC2 0x9275
- #define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
- #define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
- #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
- #define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
- int ktx_identifier[] = KTX_IDENTIFIER_REF;*/
- //converts indices from |a0|a1|e0|e1|i0|i1|m0|m1|b0|b1|f0|f1|j0|j1|n0|n1|c0|c1|g0|g1|k0|k1|o0|o1|d0|d1|h0|h1|l0|l1|p0|p1| previously used by T- and H-modes
- // into |p0|o0|n0|m0|l0|k0|j0|i0|h0|g0|f0|e0|d0|c0|b0|a0|p1|o1|n1|m1|l1|k1|j1|i1|h1|g1|f1|e1|d1|c1|b1|a1| which should be used for all modes.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int indexConversion(int pixelIndices)
- {
- int correctIndices = 0;
- int LSB[4][4];
- int MSB[4][4];
- int shift=0;
- for(int y=3; y>=0; y--)
- {
- for(int x=3; x>=0; x--)
- {
- LSB[x][y] = (pixelIndices>>shift)&1;
- shift++;
- MSB[x][y] = (pixelIndices>>shift)&1;
- shift++;
- }
- }
- shift=0;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- correctIndices|=(LSB[x][y]<<shift);
- correctIndices|=(MSB[x][y]<<(16+shift));
- shift++;
- }
- }
- return correctIndices;
- }
- // Tests if a file exists.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*bool fileExist(char *filename)
- {
- FILE *f=NULL;
- if((f=fopen(filename,"rb"))!=NULL)
- {
- fclose(f);
- return true;
- }
- return false;
- }
- // Expand source image so that it is divisible by a factor of four in the x-dimension.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- bool expandToWidthDivByFour(uint8 *&img, int width, int height, int &expandedwidth, int &expandedheight, int bitrate)
- {
- int wdiv4;
- int xx, yy;
- uint8 *newimg;
- wdiv4 = width /4;
- if( !(wdiv4 *4 == width) )
- {
- expandedwidth = (wdiv4 + 1)*4;
- expandedheight = height;
- newimg=(uint8*) malloc(3*expandedwidth*expandedheight*bitrate/8);
- if(!newimg)
- {
- printf("Could not allocate memory to expand width\n");
- return false;
- }
- // First copy image
- for(yy = 0; yy<height; yy++)
- {
- for(xx = 0; xx < width; xx++)
- {
- //we have 3*bitrate/8 bytes for each pixel..
- for(int i=0; i<3*bitrate/8; i++)
- {
- newimg[(yy * expandedwidth+ xx)*3*bitrate/8 + i] = img[(yy * width+xx)*3*bitrate/8 + i];
- }
- }
- }
- // Then make the last column of pixels the same as the previous column.
- for(yy = 0; yy< height; yy++)
- {
- for(xx = width; xx < expandedwidth; xx++)
- {
- for(int i=0; i<3*bitrate/8; i++)
- {
- newimg[(yy * expandedwidth+xx)*3*bitrate/8 + i] = img[(yy * width+(width-1))*3*bitrate/8 + i];
- }
- }
- }
- // Now free the old image
- free(img);
- // Use the new image
- img = newimg;
- return true;
- }
- else
- {
- printf("Image already of even width\n");
- expandedwidth = width;
- expandedheight = height;
- return false;
- }
- }
- // Expand source image so that it is divisible by a factor of four in the y-dimension.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- bool expandToHeightDivByFour(uint8 *&img, int width, int height, int &expandedwidth, int &expandedheight, int bitrate)
- {
- int hdiv4;
- int xx, yy;
- int numlinesmissing;
- uint8 *newimg;
- hdiv4 = height/4;
- if( !(hdiv4 * 4 == height) )
- {
- expandedwidth = width;
- expandedheight = (hdiv4 + 1) * 4;
- numlinesmissing = expandedheight - height;
- newimg=(uint8*)malloc(3*expandedwidth*expandedheight*bitrate/8);
- if(!newimg)
- {
- printf("Could not allocate memory to expand height\n");
- return false;
- }
-
- // First copy image. No need to reformat data.
- for(xx = 0; xx<3*width*height*bitrate/8; xx++)
- newimg[xx] = img[xx];
- // Then copy up to three lines.
- for(yy = height; yy < height + numlinesmissing; yy++)
- {
- for(xx = 0; xx<width; xx++)
- {
- for(int i=0; i<3*bitrate/8; i++)
- {
- newimg[(yy*width+xx)*3*bitrate/8 + i] = img[((height-1)*width+xx)*3*bitrate/8 + i];
- }
- }
- }
- // Now free the old image;
- free(img);
- // Use the new image:
- img = newimg;
- return true;
- }
- else
- {
- printf("Image height already divisible by four.\n");
- expandedwidth = width;
- expandedheight = height;
- return true;
- }
- }
- // Find the position of a file extension such as .ppm or .pkm
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int find_pos_of_extension(char *src)
- {
- int q=strlen(src);
- while(q>=0) // find file name extension
- {
- if(src[q]=='.') break;
- q--;
- }
- if(q<0)
- return -1;
- else
- return q;
- }
- // Read source file. Does conversion if file format is not .ppm.
- // Will expand file to be divisible by four in the x- and y- dimension.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*bool readSrcFile(char *filename,uint8 *&img,int &width,int &height, int &expandedwidth, int &expandedheight)
- {
- int w1,h1;
- int wdiv4, hdiv4;
- char str[255];
- // Delete temp file if it exists.
- if(fileExist("tmp.ppm"))
- {
- sprintf(str, "del tmp.ppm\n");
- system(str);
- }
- int q = find_pos_of_extension(filename);
- if(!strcmp(&filename[q],".ppm"))
- {
- // Already a .ppm file. Just copy.
- sprintf(str,"copy %s tmp.ppm \n", filename);
- printf("Copying source file to tmp.ppm\n", filename);
- }
- else
- {
- // Converting from other format to .ppm
- //
- // Use your favorite command line image converter program,
- // for instance Image Magick. Just make sure the syntax can
- // be written as below:
- //
- // C:\imconv source.jpg dest.ppm
- //
- sprintf(str,"imconv %s tmp.ppm\n", filename);
- printf("Converting source file from %s to .ppm\n", filename);
- }
- // Execute system call
- system(str);
- int bitrate=8;
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- bitrate=16;
- if(fReadPPM("tmp.ppm",w1,h1,img,bitrate))
- {
- width=w1;
- height=h1;
- system("del tmp.ppm");
- // Width must be divisible by 4 and height must be
- // divisible by 4. Otherwise, we will expand the image
- wdiv4 = width / 4;
- hdiv4 = height / 4;
- expandedwidth = width;
- expandedheight = height;
- if( !(wdiv4 * 4 == width) )
- {
- printf(" Width = %d is not divisible by four... ", width);
- printf(" expanding image in x-dir... ");
- if(expandToWidthDivByFour(img, width, height, expandedwidth, expandedheight,bitrate))
- {
- printf("OK.\n");
- }
- else
- {
- printf("\n Error: could not expand image\n");
- return false;
- }
- }
- if( !(hdiv4 * 4 == height))
- {
- printf(" Height = %d is not divisible by four... ", height);
- printf(" expanding image in y-dir...");
- if(expandToHeightDivByFour(img, expandedwidth, height, expandedwidth, expandedheight,bitrate))
- {
- printf("OK.\n");
- }
- else
- {
- printf("\n Error: could not expand image\n");
- return false;
- }
- }
- if(!(expandedwidth == width && expandedheight == height))
- printf("Active pixels: %dx%d. Expanded image: %dx%d\n",width,height,expandedwidth,expandedheight);
- return true;
- }
- else
- {
- printf("Could not read tmp.ppm file\n");
- exit(1);
- }
- return false;
- }
- // Reads a file without expanding it to be divisible by 4.
- // Is used when doing PSNR calculation between two files.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- bool readSrcFileNoExpand(char *filename,uint8 *&img,int &width,int &height)
- {
- int w1,h1;
- char str[255];
- // Delete temp file if it exists.
- if(fileExist("tmp.ppm"))
- {
- sprintf(str, "del tmp.ppm\n");
- system(str);
- }
- int q = find_pos_of_extension(filename);
- if(!strcmp(&filename[q],".ppm"))
- {
- // Already a .ppm file. Just copy.
- sprintf(str,"copy %s tmp.ppm \n", filename);
- printf("Copying source file to tmp.ppm\n", filename);
- }
- else
- {
- // Converting from other format to .ppm
- //
- // Use your favorite command line image converter program,
- // for instance Image Magick. Just make sure the syntax can
- // be written as below:
- //
- // C:\imconv source.jpg dest.ppm
- //
- sprintf(str,"imconv %s tmp.ppm\n", filename);
- // printf("Converting source file from %s to .ppm\n", filename);
- }
- // Execute system call
- system(str);
- if(fReadPPM("tmp.ppm",w1,h1,img,8))
- {
- width=w1;
- height=h1;
- system("del tmp.ppm");
- return true;
- }
- return false;
- }
- // Parses the arguments from the command line.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void readArguments(int argc,char *argv[],char* src,char *dst)
- {
- int q;
- //new code!! do this in a more nicer way!
- bool srcfound=false,dstfound=false;
- for(int i=1; i<argc; i++)
- {
- //loop through the arguments!
- //first check for flags..
- if(argv[i][0]=='-')
- {
- if(i==argc-1)
- {
- printf("flag missing argument: %s!\n");
- exit(1);
- }
- //handle speed flag
- if(!strcmp(argv[i],"-s"))
- {
- // We have argument -s. Now check for slow, medium or fast.
- if(!strcmp(argv[i+1],"slow"))
- speed = SPEED_SLOW;
- else if(!strcmp(argv[i+1],"medium"))
- speed = SPEED_MEDIUM;
- else if(!strcmp(argv[i+1],"fast"))
- speed = SPEED_FAST;
- else
- {
- printf("Error: %s not part of flag %s\n",argv[i+1], argv[i]);
- exit(1);
- }
- }
- //handle verbose flag
- else if(!strcmp(argv[i],"-v"))
- {
- // We have argument -s. Now check for slow, medium or fast.
- if(!strcmp(argv[i+1],"off"))
- verbose = false;
- else if(!strcmp(argv[i+1],"on"))
- verbose = true;
- else
- {
- printf("Error: %s not part of flag %s\n",argv[i+1], argv[i]);
- exit(1);
- }
- }
- //error metric flag
- else if(!strcmp(argv[i],"-e"))
- {
- // We have argument -e. Now check for perceptual or nonperceptual
- if(!strcmp(argv[i+1],"perceptual"))
- metric = METRIC_PERCEPTUAL;
- else if(!strcmp(argv[i+1],"nonperceptual"))
- metric = METRIC_NONPERCEPTUAL;
- else
- {
- printf("Error: %s not part of flag %s\n",argv[i+1], argv[i]);
- exit(1);
- }
- }
- //codec flag
- else if(!strcmp(argv[i],"-c"))
- {
- // We have argument -c. Now check for perceptual or nonperceptual
- if(!strcmp(argv[i+1],"etc") || !strcmp(argv[i+1],"etc1"))
- codec = CODEC_ETC;
- else if(!strcmp(argv[i+1],"etc2"))
- codec = CODEC_ETC2;
- else
- {
- printf("Error: %s not part of flag %s\n",argv[i+1], argv[i]);
- exit(1);
- }
- }
- //format flag
- else if(!strcmp(argv[i],"-f"))
- {
- if(!strcmp(argv[i+1],"R"))
- format=ETC2PACKAGE_R_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"RG"))
- format=ETC2PACKAGE_RG_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"R_signed"))
- {
- format=ETC2PACKAGE_R_NO_MIPMAPS;
- formatSigned=1;
- }
- else if(!strcmp(argv[i+1],"RG_signed"))
- {
- format=ETC2PACKAGE_RG_NO_MIPMAPS;
- formatSigned=1;
- }
- else if(!strcmp(argv[i+1],"RGB"))
- format=ETC2PACKAGE_RGB_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"sRGB"))
- format=ETC2PACKAGE_sRGB_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"RGBA")||!strcmp(argv[i+1],"RGBA8"))
- format=ETC2PACKAGE_RGBA_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"sRGBA")||!strcmp(argv[i+1],"sRGBA8"))
- format=ETC2PACKAGE_sRGBA_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"RGBA1"))
- format=ETC2PACKAGE_RGBA1_NO_MIPMAPS;
- else if(!strcmp(argv[i+1],"sRGBA1"))
- format=ETC2PACKAGE_sRGBA1_NO_MIPMAPS;
- else
- {
- printf("Error: %s not part of flag %s\n",argv[i+1], argv[i]);
- exit(1);
- }
- }
- else if(!strcmp(argv[i],"-p"))
- {
- mode=MODE_PSNR;
- i--; //ugly way of negating the increment of i done later because -p doesn't have an argument.
- }
- else
- {
- printf("Error: cannot interpret flag %s %s\n",argv[i], argv[i+1]);
- exit(1);
- }
- //don't read the flag argument next iteration..
- i++;
- }
- //this isn't a flag, so must be src or dst
- else
- {
- if(srcfound&&dstfound)
- {
- printf("too many arguments! expecting src, dst; found %s, %s, %s\n",src,dst,argv[i]);
- exit(1);
- }
- else if(srcfound)
- {
- strcpy(dst,argv[i]);
- dstfound=true;
- }
- else
- {
- strcpy(src,argv[i]);
- srcfound=true;
- }
- }
- }
- if(!srcfound&&dstfound)
- {
- printf("too few arguments! expecting src, dst\n");
- exit(1);
- }
- if(mode==MODE_PSNR)
- return;
- //check source/destination.. is this compression or decompression?
- q = find_pos_of_extension(src);
- if(q<0)
- {
- printf("invalid source file: %s\n",src);
- exit(1);
- }
- // If we have etcpack img.pkm img.any
- if(!strncmp(&src[q],".pkm",4))
- {
- // First argument is .pkm. Decompress.
- mode = MODE_UNCOMPRESS; // uncompress from binary file format .pkm
- }
- else if(!strncmp(&src[q],".ktx",4))
- {
- // First argument is .ktx. Decompress.
- mode = MODE_UNCOMPRESS; // uncompress from binary file format .pkm
- ktxFile=true;
- printf("decompressing ktx\n");
- }
- else
- {
- // The first argument was not .pkm. The second argument must then be .pkm.
- q = find_pos_of_extension(dst);
- if(q<0)
- {
- printf("invalid destination file: %s\n",src);
- exit(1);
- }
- if(!strncmp(&dst[q],".pkm",4))
- {
- // Second argument is .pkm. Compress.
- mode = MODE_COMPRESS; // compress to binary file format .pkm
- }
- else if(!strncmp(&dst[q],".ktx",4))
- {
- // Second argument is .ktx. Compress.
- ktxFile=true;
- mode = MODE_COMPRESS; // compress to binary file format .pkm
- printf("compressing to ktx\n");
- }
- else
- {
- printf("source or destination must be a .pkm or .ktx file\n");
- exit(1);
- }
- }
- //do some sanity check stuff..
- if(codec==CODEC_ETC&&format!=ETC2PACKAGE_RGB_NO_MIPMAPS)
- {
- printf("ETC1 codec only supports RGB format\n");
- exit(1);
- }
- else if(codec==CODEC_ETC)
- format=ETC1_RGB_NO_MIPMAPS;
- }*/
- //static int compressParams[16][4];
- const int compressParamsFast[32] = { -8, -2, 2, 8,
- -17, -5, 5, 17,
- -29, -9, 9, 29,
- -42, -13, 13, 42,
- -60, -18, 18, 60,
- -80, -24, 24, 80,
- -106, -33, 33, 106,
- -183, -47, 47, 183};
- /*bool readCompressParams(void)
- {
- compressParams[0][0] = -8; compressParams[0][1] = -2; compressParams[0][2] = 2; compressParams[0][3] = 8;
- compressParams[1][0] = -8; compressParams[1][1] = -2; compressParams[1][2] = 2; compressParams[1][3] = 8;
- compressParams[2][0] = -17; compressParams[2][1] = -5; compressParams[2][2] = 5; compressParams[2][3] = 17;
- compressParams[3][0] = -17; compressParams[3][1] = -5; compressParams[3][2] = 5; compressParams[3][3] = 17;
- compressParams[4][0] = -29; compressParams[4][1] = -9; compressParams[4][2] = 9; compressParams[4][3] = 29;
- compressParams[5][0] = -29; compressParams[5][1] = -9; compressParams[5][2] = 9; compressParams[5][3] = 29;
- compressParams[6][0] = -42; compressParams[6][1] = -13; compressParams[6][2] = 13; compressParams[6][3] = 42;
- compressParams[7][0] = -42; compressParams[7][1] = -13; compressParams[7][2] = 13; compressParams[7][3] = 42;
- compressParams[8][0] = -60; compressParams[8][1] = -18; compressParams[8][2] = 18; compressParams[8][3] = 60;
- compressParams[9][0] = -60; compressParams[9][1] = -18; compressParams[9][2] = 18; compressParams[9][3] = 60;
- compressParams[10][0] = -80; compressParams[10][1] = -24; compressParams[10][2] = 24; compressParams[10][3] = 80;
- compressParams[11][0] = -80; compressParams[11][1] = -24; compressParams[11][2] = 24; compressParams[11][3] = 80;
- compressParams[12][0] =-106; compressParams[12][1] = -33; compressParams[12][2] = 33; compressParams[12][3] = 106;
- compressParams[13][0] =-106; compressParams[13][1] = -33; compressParams[13][2] = 33; compressParams[13][3] = 106;
- compressParams[14][0] =-183; compressParams[14][1] = -47; compressParams[14][2] = 47; compressParams[14][3] = 183;
- compressParams[15][0] =-183; compressParams[15][1] = -47; compressParams[15][2] = 47; compressParams[15][3] = 183;
-
- return true;
- }*/
- // Computes the average color in a 2x4 area and returns the average color as a float.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeAverageColor2x4noQuantFloat(uint8 *img,int width,int height,int startx,int starty,float *avg_color)
- {
- int r=0,g=0,b=0;
- for(int y=starty; y<starty+4; y++)
- {
- for(int x=startx; x<startx+2; x++)
- {
- r+=RED(img,width,x,y);
- g+=GREEN(img,width,x,y);
- b+=BLUE(img,width,x,y);
- }
- }
- avg_color[0]=(float)(r/8.0);
- avg_color[1]=(float)(g/8.0);
- avg_color[2]=(float)(b/8.0);
- }
- // Computes the average color in a 4x2 area and returns the average color as a float.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeAverageColor4x2noQuantFloat(uint8 *img,int width,int height,int startx,int starty,float *avg_color)
- {
- int r=0,g=0,b=0;
- for(int y=starty; y<starty+2; y++)
- {
- for(int x=startx; x<startx+4; x++)
- {
- r+=RED(img,width,x,y);
- g+=GREEN(img,width,x,y);
- b+=BLUE(img,width,x,y);
- }
- }
- avg_color[0]=(float)(r/8.0);
- avg_color[1]=(float)(g/8.0);
- avg_color[2]=(float)(b/8.0);
- }
- // Finds all pixel indices for a 2x4 block.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int compressBlockWithTable2x4(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp)
- {
- uint8 orig[3],approx[3];
- unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0;
- int sum_error=0;
- int q, i;
- i = 0;
- for(int x=startx; x<startx+2; x++)
- {
- for(int y=starty; y<starty+4; y++)
- {
- int err;
- int best=0;
- int min_error=255*255*3*16;
- orig[0]=RED(img,width,x,y);
- orig[1]=GREEN(img,width,x,y);
- orig[2]=BLUE(img,width,x,y);
- for(q=0;q<4;q++)
- {
- approx[0]=CLAMP(0, avg_color[0]+compressParams[table][q],255);
- approx[1]=CLAMP(0, avg_color[1]+compressParams[table][q],255);
- approx[2]=CLAMP(0, avg_color[2]+compressParams[table][q],255);
- // Here we just use equal weights to R, G and B. Although this will
- // give visually worse results, it will give a better PSNR score.
- err=SQUARE(approx[0]-orig[0]) + SQUARE(approx[1]-orig[1]) + SQUARE(approx[2]-orig[2]);
- if(err<min_error)
- {
- min_error=err;
- best=q;
- }
- }
- pixel_indices = scramble[best];
- PUTBITS( pixel_indices_MSB, (pixel_indices >> 1), 1, i);
- PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i);
- i++;
- // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01}
- // so that first bit is sign bit and the other bit is size bit (4 or 12).
- // This means that we have to scramble the bits before storing them.
- sum_error+=min_error;
- }
- }
- *pixel_indices_MSBp = pixel_indices_MSB;
- *pixel_indices_LSBp = pixel_indices_LSB;
- return sum_error;
- }
- #define MAXERR1000 1000*255*255*16
- // Finds all pixel indices for a 2x4 block using perceptual weighting of error.
- // Done using fixed poinit arithmetics where weights are multiplied by 1000.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockWithTable2x4percep1000(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp)
- {
- uint8 orig[3],approx[3];
- unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0;
- unsigned int sum_error=0;
- int q, i;
- i = 0;
- for(int x=startx; x<startx+2; x++)
- {
- for(int y=starty; y<starty+4; y++)
- {
- unsigned int err;
- int best=0;
- unsigned int min_error=MAXERR1000;
- orig[0]=RED(img,width,x,y);
- orig[1]=GREEN(img,width,x,y);
- orig[2]=BLUE(img,width,x,y);
- for(q=0;q<4;q++)
- {
- approx[0]=CLAMP(0, avg_color[0]+compressParams[table][q],255);
- approx[1]=CLAMP(0, avg_color[1]+compressParams[table][q],255);
- approx[2]=CLAMP(0, avg_color[2]+compressParams[table][q],255);
- // Here we just use equal weights to R, G and B. Although this will
- // give visually worse results, it will give a better PSNR score.
- err = (PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE((approx[0]-orig[0]))
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE((approx[1]-orig[1]))
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*SQUARE((approx[2]-orig[2])));
- if(err<min_error)
- {
- min_error=err;
- best=q;
- }
- }
- pixel_indices = scramble[best];
- PUTBITS( pixel_indices_MSB, (pixel_indices >> 1), 1, i);
- PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i);
- i++;
- // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01}
- // so that first bit is sign bit and the other bit is size bit (4 or 12).
- // This means that we have to scramble the bits before storing them.
-
- sum_error+=min_error;
- }
- }
- *pixel_indices_MSBp = pixel_indices_MSB;
- *pixel_indices_LSBp = pixel_indices_LSB;
- return sum_error;
- }
- // Finds all pixel indices for a 2x4 block using perceptual weighting of error.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- float compressBlockWithTable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp)
- {
- uint8 orig[3],approx[3];
- unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0;
- float sum_error=0;
- int q, i;
- double wR2 = PERCEPTUAL_WEIGHT_R_SQUARED;
- double wG2 = PERCEPTUAL_WEIGHT_G_SQUARED;
- double wB2 = PERCEPTUAL_WEIGHT_B_SQUARED;
- i = 0;
- for(int x=startx; x<startx+2; x++)
- {
- for(int y=starty; y<starty+4; y++)
- {
- float err;
- int best=0;
- float min_error=255*255*3*16;
- orig[0]=RED(img,width,x,y);
- orig[1]=GREEN(img,width,x,y);
- orig[2]=BLUE(img,width,x,y);
- for(q=0;q<4;q++)
- {
- approx[0]=CLAMP(0, avg_color[0]+compressParams[table][q],255);
- approx[1]=CLAMP(0, avg_color[1]+compressParams[table][q],255);
- approx[2]=CLAMP(0, avg_color[2]+compressParams[table][q],255);
- // Here we just use equal weights to R, G and B. Although this will
- // give visually worse results, it will give a better PSNR score.
- err=(float)(wR2*SQUARE((approx[0]-orig[0])) + (float)wG2*SQUARE((approx[1]-orig[1])) + (float)wB2*SQUARE((approx[2]-orig[2])));
- if(err<min_error)
- {
- min_error=err;
- best=q;
- }
- }
- pixel_indices = scramble[best];
- PUTBITS( pixel_indices_MSB, (pixel_indices >> 1), 1, i);
- PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i);
- i++;
- // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01}
- // so that first bit is sign bit and the other bit is size bit (4 or 12).
- // This means that we have to scramble the bits before storing them.
-
- sum_error+=min_error;
- }
- }
- *pixel_indices_MSBp = pixel_indices_MSB;
- *pixel_indices_LSBp = pixel_indices_LSB;
- return sum_error;
- }
- // Finds all pixel indices for a 4x2 block.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int compressBlockWithTable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp)
- {
- uint8 orig[3],approx[3];
- unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0;
- int sum_error=0;
- int q;
- int i;
- i = 0;
- for(int x=startx; x<startx+4; x++)
- {
- for(int y=starty; y<starty+2; y++)
- {
- int err;
- int best=0;
- int min_error=255*255*3*16;
- orig[0]=RED(img,width,x,y);
- orig[1]=GREEN(img,width,x,y);
- orig[2]=BLUE(img,width,x,y);
- for(q=0;q<4;q++)
- {
- approx[0]=CLAMP(0, avg_color[0]+compressParams[table][q],255);
- approx[1]=CLAMP(0, avg_color[1]+compressParams[table][q],255);
- approx[2]=CLAMP(0, avg_color[2]+compressParams[table][q],255);
- // Here we just use equal weights to R, G and B. Although this will
- // give visually worse results, it will give a better PSNR score.
- err=SQUARE(approx[0]-orig[0]) + SQUARE(approx[1]-orig[1]) + SQUARE(approx[2]-orig[2]);
- if(err<min_error)
- {
- min_error=err;
- best=q;
- }
- }
- pixel_indices = scramble[best];
- PUTBITS( pixel_indices_MSB, (pixel_indices >> 1), 1, i);
- PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i);
- i++;
- // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01}
- // so that first bit is sign bit and the other bit is size bit (4 or 12).
- // This means that we have to scramble the bits before storing them.
- sum_error+=min_error;
- }
- i+=2;
- }
- *pixel_indices_MSBp = pixel_indices_MSB;
- *pixel_indices_LSBp = pixel_indices_LSB;
- return sum_error;
- }
- // Finds all pixel indices for a 4x2 block using perceptual weighting of error.
- // Done using fixed point arithmetics where 1000 corresponds to 1.0.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockWithTable4x2percep1000(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp)
- {
- uint8 orig[3],approx[3];
- unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0;
- unsigned int sum_error=0;
- int q;
- int i;
- i = 0;
- for(int x=startx; x<startx+4; x++)
- {
- for(int y=starty; y<starty+2; y++)
- {
- unsigned int err;
- int best=0;
- unsigned int min_error=MAXERR1000;
- orig[0]=RED(img,width,x,y);
- orig[1]=GREEN(img,width,x,y);
- orig[2]=BLUE(img,width,x,y);
- for(q=0;q<4;q++)
- {
- approx[0]=CLAMP(0, avg_color[0]+compressParams[table][q],255);
- approx[1]=CLAMP(0, avg_color[1]+compressParams[table][q],255);
- approx[2]=CLAMP(0, avg_color[2]+compressParams[table][q],255);
- // Here we just use equal weights to R, G and B. Although this will
- // give visually worse results, it will give a better PSNR score.
- err = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(approx[0]-orig[0])
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(approx[1]-orig[1])
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*SQUARE(approx[2]-orig[2]);
- if(err<min_error)
- {
- min_error=err;
- best=q;
- }
- }
- pixel_indices = scramble[best];
- PUTBITS( pixel_indices_MSB, (pixel_indices >> 1), 1, i);
- PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i);
- i++;
- // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01}
- // so that first bit is sign bit and the other bit is size bit (4 or 12).
- // This means that we have to scramble the bits before storing them.
- sum_error+=min_error;
- }
- i+=2;
- }
- *pixel_indices_MSBp = pixel_indices_MSB;
- *pixel_indices_LSBp = pixel_indices_LSB;
- return sum_error;
- }
- // Finds all pixel indices for a 4x2 block using perceptual weighting of error.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- float compressBlockWithTable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp)
- {
- uint8 orig[3],approx[3];
- unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0;
- float sum_error=0;
- int q;
- int i;
- float wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED;
- float wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED;
- float wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED;
- i = 0;
- for(int x=startx; x<startx+4; x++)
- {
- for(int y=starty; y<starty+2; y++)
- {
- float err;
- int best=0;
- float min_error=255*255*3*16;
- orig[0]=RED(img,width,x,y);
- orig[1]=GREEN(img,width,x,y);
- orig[2]=BLUE(img,width,x,y);
- for(q=0;q<4;q++)
- {
- approx[0]=CLAMP(0, avg_color[0]+compressParams[table][q],255);
- approx[1]=CLAMP(0, avg_color[1]+compressParams[table][q],255);
- approx[2]=CLAMP(0, avg_color[2]+compressParams[table][q],255);
- // Here we just use equal weights to R, G and B. Although this will
- // give visually worse results, it will give a better PSNR score.
- err=(float) wR2*SQUARE(approx[0]-orig[0]) + (float)wG2*SQUARE(approx[1]-orig[1]) + (float)wB2*SQUARE(approx[2]-orig[2]);
- if(err<min_error)
- {
- min_error=err;
- best=q;
- }
- }
- pixel_indices = scramble[best];
- PUTBITS( pixel_indices_MSB, (pixel_indices >> 1), 1, i);
- PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i);
- i++;
- // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01}
- // so that first bit is sign bit and the other bit is size bit (4 or 12).
- // This means that we have to scramble the bits before storing them.
- sum_error+=min_error;
- }
- i+=2;
- }
- *pixel_indices_MSBp = pixel_indices_MSB;
- *pixel_indices_LSBp = pixel_indices_LSB;
- return sum_error;
- }
- // Table for fast implementation of clamping to the interval [0,255] followed by addition of 255.
- const int clamp_table_plus_255[768] = {0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255, 0+255,
- 0+255, 1+255, 2+255, 3+255, 4+255, 5+255, 6+255, 7+255, 8+255, 9+255, 10+255, 11+255, 12+255, 13+255, 14+255, 15+255, 16+255, 17+255, 18+255, 19+255, 20+255, 21+255, 22+255, 23+255, 24+255, 25+255, 26+255, 27+255, 28+255, 29+255, 30+255, 31+255, 32+255, 33+255, 34+255, 35+255, 36+255, 37+255, 38+255, 39+255, 40+255, 41+255, 42+255, 43+255, 44+255, 45+255, 46+255, 47+255, 48+255, 49+255, 50+255, 51+255, 52+255, 53+255, 54+255, 55+255, 56+255, 57+255, 58+255, 59+255, 60+255, 61+255, 62+255, 63+255, 64+255, 65+255, 66+255, 67+255, 68+255, 69+255, 70+255, 71+255, 72+255, 73+255, 74+255, 75+255, 76+255, 77+255, 78+255, 79+255, 80+255, 81+255, 82+255, 83+255, 84+255, 85+255, 86+255, 87+255, 88+255, 89+255, 90+255, 91+255, 92+255, 93+255, 94+255, 95+255, 96+255, 97+255, 98+255, 99+255, 100+255, 101+255, 102+255, 103+255, 104+255, 105+255, 106+255, 107+255, 108+255, 109+255, 110+255, 111+255, 112+255, 113+255, 114+255, 115+255, 116+255, 117+255, 118+255, 119+255, 120+255, 121+255, 122+255, 123+255, 124+255, 125+255, 126+255, 127+255, 128+255, 129+255, 130+255, 131+255, 132+255, 133+255, 134+255, 135+255, 136+255, 137+255, 138+255, 139+255, 140+255, 141+255, 142+255, 143+255, 144+255, 145+255, 146+255, 147+255, 148+255, 149+255, 150+255, 151+255, 152+255, 153+255, 154+255, 155+255, 156+255, 157+255, 158+255, 159+255, 160+255, 161+255, 162+255, 163+255, 164+255, 165+255, 166+255, 167+255, 168+255, 169+255, 170+255, 171+255, 172+255, 173+255, 174+255, 175+255, 176+255, 177+255, 178+255, 179+255, 180+255, 181+255, 182+255, 183+255, 184+255, 185+255, 186+255, 187+255, 188+255, 189+255, 190+255, 191+255, 192+255, 193+255, 194+255, 195+255, 196+255, 197+255, 198+255, 199+255, 200+255, 201+255, 202+255, 203+255, 204+255, 205+255, 206+255, 207+255, 208+255, 209+255, 210+255, 211+255,
- 212+255, 213+255, 214+255, 215+255, 216+255, 217+255, 218+255, 219+255, 220+255, 221+255, 222+255, 223+255, 224+255, 225+255, 226+255, 227+255, 228+255, 229+255, 230+255, 231+255, 232+255, 233+255, 234+255, 235+255, 236+255, 237+255, 238+255, 239+255, 240+255, 241+255, 242+255, 243+255, 244+255, 245+255, 246+255, 247+255, 248+255, 249+255, 250+255, 251+255, 252+255, 253+255, 254+255, 255+255,
- 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255,
- 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255, 255+255};
- // Table for fast implementationi of clamping to the interval [0,255]
- const int clamp_table[768] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
- // Table for fast implementation of squaring for numbers in the interval [-255, 255]
- const unsigned int square_table[511] = {65025, 64516, 64009, 63504, 63001, 62500, 62001, 61504, 61009, 60516, 60025, 59536, 59049, 58564, 58081, 57600,
- 57121, 56644, 56169, 55696, 55225, 54756, 54289, 53824, 53361, 52900, 52441, 51984, 51529, 51076, 50625, 50176,
- 49729, 49284, 48841, 48400, 47961, 47524, 47089, 46656, 46225, 45796, 45369, 44944, 44521, 44100, 43681, 43264,
- 42849, 42436, 42025, 41616, 41209, 40804, 40401, 40000, 39601, 39204, 38809, 38416, 38025, 37636, 37249, 36864,
- 36481, 36100, 35721, 35344, 34969, 34596, 34225, 33856, 33489, 33124, 32761, 32400, 32041, 31684, 31329, 30976,
- 30625, 30276, 29929, 29584, 29241, 28900, 28561, 28224, 27889, 27556, 27225, 26896, 26569, 26244, 25921, 25600,
- 25281, 24964, 24649, 24336, 24025, 23716, 23409, 23104, 22801, 22500, 22201, 21904, 21609, 21316, 21025, 20736,
- 20449, 20164, 19881, 19600, 19321, 19044, 18769, 18496, 18225, 17956, 17689, 17424, 17161, 16900, 16641, 16384,
- 16129, 15876, 15625, 15376, 15129, 14884, 14641, 14400, 14161, 13924, 13689, 13456, 13225, 12996, 12769, 12544,
- 12321, 12100, 11881, 11664, 11449, 11236, 11025, 10816, 10609, 10404, 10201, 10000, 9801, 9604, 9409, 9216,
- 9025, 8836, 8649, 8464, 8281, 8100, 7921, 7744, 7569, 7396, 7225, 7056, 6889, 6724, 6561, 6400,
- 6241, 6084, 5929, 5776, 5625, 5476, 5329, 5184, 5041, 4900, 4761, 4624, 4489, 4356, 4225, 4096,
- 3969, 3844, 3721, 3600, 3481, 3364, 3249, 3136, 3025, 2916, 2809, 2704, 2601, 2500, 2401, 2304,
- 2209, 2116, 2025, 1936, 1849, 1764, 1681, 1600, 1521, 1444, 1369, 1296, 1225, 1156, 1089, 1024,
- 961, 900, 841, 784, 729, 676, 625, 576, 529, 484, 441, 400, 361, 324, 289, 256,
- 225, 196, 169, 144, 121, 100, 81, 64, 49, 36, 25, 16, 9, 4, 1,
- 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225,
- 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961,
- 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209,
- 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969,
- 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241,
- 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025,
- 9216, 9409, 9604, 9801, 10000, 10201, 10404, 10609, 10816, 11025, 11236, 11449, 11664, 11881, 12100, 12321,
- 12544, 12769, 12996, 13225, 13456, 13689, 13924, 14161, 14400, 14641, 14884, 15129, 15376, 15625, 15876, 16129,
- 16384, 16641, 16900, 17161, 17424, 17689, 17956, 18225, 18496, 18769, 19044, 19321, 19600, 19881, 20164, 20449,
- 20736, 21025, 21316, 21609, 21904, 22201, 22500, 22801, 23104, 23409, 23716, 24025, 24336, 24649, 24964, 25281,
- 25600, 25921, 26244, 26569, 26896, 27225, 27556, 27889, 28224, 28561, 28900, 29241, 29584, 29929, 30276, 30625,
- 30976, 31329, 31684, 32041, 32400, 32761, 33124, 33489, 33856, 34225, 34596, 34969, 35344, 35721, 36100, 36481,
- 36864, 37249, 37636, 38025, 38416, 38809, 39204, 39601, 40000, 40401, 40804, 41209, 41616, 42025, 42436, 42849,
- 43264, 43681, 44100, 44521, 44944, 45369, 45796, 46225, 46656, 47089, 47524, 47961, 48400, 48841, 49284, 49729,
- 50176, 50625, 51076, 51529, 51984, 52441, 52900, 53361, 53824, 54289, 54756, 55225, 55696, 56169, 56644, 57121,
- 57600, 58081, 58564, 59049, 59536, 60025, 60516, 61009, 61504, 62001, 62500, 63001, 63504, 64009, 64516, 65025};
- // Abbreviated variable names to make below tables smaller in source code size
- #define KR PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000
- #define KG PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000
- #define KB PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000
- // Table for fast implementation of squaring for numbers in the interval [-255, 255] multiplied by the perceptual weight for red.
- const unsigned int square_table_percep_red[511] = {
- 65025*KR, 64516*KR, 64009*KR, 63504*KR, 63001*KR, 62500*KR, 62001*KR, 61504*KR, 61009*KR, 60516*KR, 60025*KR, 59536*KR, 59049*KR, 58564*KR, 58081*KR, 57600*KR,
- 57121*KR, 56644*KR, 56169*KR, 55696*KR, 55225*KR, 54756*KR, 54289*KR, 53824*KR, 53361*KR, 52900*KR, 52441*KR, 51984*KR, 51529*KR, 51076*KR, 50625*KR, 50176*KR,
- 49729*KR, 49284*KR, 48841*KR, 48400*KR, 47961*KR, 47524*KR, 47089*KR, 46656*KR, 46225*KR, 45796*KR, 45369*KR, 44944*KR, 44521*KR, 44100*KR, 43681*KR, 43264*KR,
- 42849*KR, 42436*KR, 42025*KR, 41616*KR, 41209*KR, 40804*KR, 40401*KR, 40000*KR, 39601*KR, 39204*KR, 38809*KR, 38416*KR, 38025*KR, 37636*KR, 37249*KR, 36864*KR,
- 36481*KR, 36100*KR, 35721*KR, 35344*KR, 34969*KR, 34596*KR, 34225*KR, 33856*KR, 33489*KR, 33124*KR, 32761*KR, 32400*KR, 32041*KR, 31684*KR, 31329*KR, 30976*KR,
- 30625*KR, 30276*KR, 29929*KR, 29584*KR, 29241*KR, 28900*KR, 28561*KR, 28224*KR, 27889*KR, 27556*KR, 27225*KR, 26896*KR, 26569*KR, 26244*KR, 25921*KR, 25600*KR,
- 25281*KR, 24964*KR, 24649*KR, 24336*KR, 24025*KR, 23716*KR, 23409*KR, 23104*KR, 22801*KR, 22500*KR, 22201*KR, 21904*KR, 21609*KR, 21316*KR, 21025*KR, 20736*KR,
- 20449*KR, 20164*KR, 19881*KR, 19600*KR, 19321*KR, 19044*KR, 18769*KR, 18496*KR, 18225*KR, 17956*KR, 17689*KR, 17424*KR, 17161*KR, 16900*KR, 16641*KR, 16384*KR,
- 16129*KR, 15876*KR, 15625*KR, 15376*KR, 15129*KR, 14884*KR, 14641*KR, 14400*KR, 14161*KR, 13924*KR, 13689*KR, 13456*KR, 13225*KR, 12996*KR, 12769*KR, 12544*KR,
- 12321*KR, 12100*KR, 11881*KR, 11664*KR, 11449*KR, 11236*KR, 11025*KR, 10816*KR, 10609*KR, 10404*KR, 10201*KR, 10000*KR, 9801*KR, 9604*KR, 9409*KR, 9216*KR,
- 9025*KR, 8836*KR, 8649*KR, 8464*KR, 8281*KR, 8100*KR, 7921*KR, 7744*KR, 7569*KR, 7396*KR, 7225*KR, 7056*KR, 6889*KR, 6724*KR, 6561*KR, 6400*KR,
- 6241*KR, 6084*KR, 5929*KR, 5776*KR, 5625*KR, 5476*KR, 5329*KR, 5184*KR, 5041*KR, 4900*KR, 4761*KR, 4624*KR, 4489*KR, 4356*KR, 4225*KR, 4096*KR,
- 3969*KR, 3844*KR, 3721*KR, 3600*KR, 3481*KR, 3364*KR, 3249*KR, 3136*KR, 3025*KR, 2916*KR, 2809*KR, 2704*KR, 2601*KR, 2500*KR, 2401*KR, 2304*KR,
- 2209*KR, 2116*KR, 2025*KR, 1936*KR, 1849*KR, 1764*KR, 1681*KR, 1600*KR, 1521*KR, 1444*KR, 1369*KR, 1296*KR, 1225*KR, 1156*KR, 1089*KR, 1024*KR,
- 961*KR, 900*KR, 841*KR, 784*KR, 729*KR, 676*KR, 625*KR, 576*KR, 529*KR, 484*KR, 441*KR, 400*KR, 361*KR, 324*KR, 289*KR, 256*KR,
- 225*KR, 196*KR, 169*KR, 144*KR, 121*KR, 100*KR, 81*KR, 64*KR, 49*KR, 36*KR, 25*KR, 16*KR, 9*KR, 4*KR, 1*KR,
- 0*KR, 1*KR, 4*KR, 9*KR, 16*KR, 25*KR, 36*KR, 49*KR, 64*KR, 81*KR, 100*KR, 121*KR, 144*KR, 169*KR, 196*KR, 225*KR,
- 256*KR, 289*KR, 324*KR, 361*KR, 400*KR, 441*KR, 484*KR, 529*KR, 576*KR, 625*KR, 676*KR, 729*KR, 784*KR, 841*KR, 900*KR, 961*KR,
- 1024*KR, 1089*KR, 1156*KR, 1225*KR, 1296*KR, 1369*KR, 1444*KR, 1521*KR, 1600*KR, 1681*KR, 1764*KR, 1849*KR, 1936*KR, 2025*KR, 2116*KR, 2209*KR,
- 2304*KR, 2401*KR, 2500*KR, 2601*KR, 2704*KR, 2809*KR, 2916*KR, 3025*KR, 3136*KR, 3249*KR, 3364*KR, 3481*KR, 3600*KR, 3721*KR, 3844*KR, 3969*KR,
- 4096*KR, 4225*KR, 4356*KR, 4489*KR, 4624*KR, 4761*KR, 4900*KR, 5041*KR, 5184*KR, 5329*KR, 5476*KR, 5625*KR, 5776*KR, 5929*KR, 6084*KR, 6241*KR,
- 6400*KR, 6561*KR, 6724*KR, 6889*KR, 7056*KR, 7225*KR, 7396*KR, 7569*KR, 7744*KR, 7921*KR, 8100*KR, 8281*KR, 8464*KR, 8649*KR, 8836*KR, 9025*KR,
- 9216*KR, 9409*KR, 9604*KR, 9801*KR, 10000*KR, 10201*KR, 10404*KR, 10609*KR, 10816*KR, 11025*KR, 11236*KR, 11449*KR, 11664*KR, 11881*KR, 12100*KR, 12321*KR,
- 12544*KR, 12769*KR, 12996*KR, 13225*KR, 13456*KR, 13689*KR, 13924*KR, 14161*KR, 14400*KR, 14641*KR, 14884*KR, 15129*KR, 15376*KR, 15625*KR, 15876*KR, 16129*KR,
- 16384*KR, 16641*KR, 16900*KR, 17161*KR, 17424*KR, 17689*KR, 17956*KR, 18225*KR, 18496*KR, 18769*KR, 19044*KR, 19321*KR, 19600*KR, 19881*KR, 20164*KR, 20449*KR,
- 20736*KR, 21025*KR, 21316*KR, 21609*KR, 21904*KR, 22201*KR, 22500*KR, 22801*KR, 23104*KR, 23409*KR, 23716*KR, 24025*KR, 24336*KR, 24649*KR, 24964*KR, 25281*KR,
- 25600*KR, 25921*KR, 26244*KR, 26569*KR, 26896*KR, 27225*KR, 27556*KR, 27889*KR, 28224*KR, 28561*KR, 28900*KR, 29241*KR, 29584*KR, 29929*KR, 30276*KR, 30625*KR,
- 30976*KR, 31329*KR, 31684*KR, 32041*KR, 32400*KR, 32761*KR, 33124*KR, 33489*KR, 33856*KR, 34225*KR, 34596*KR, 34969*KR, 35344*KR, 35721*KR, 36100*KR, 36481*KR,
- 36864*KR, 37249*KR, 37636*KR, 38025*KR, 38416*KR, 38809*KR, 39204*KR, 39601*KR, 40000*KR, 40401*KR, 40804*KR, 41209*KR, 41616*KR, 42025*KR, 42436*KR, 42849*KR,
- 43264*KR, 43681*KR, 44100*KR, 44521*KR, 44944*KR, 45369*KR, 45796*KR, 46225*KR, 46656*KR, 47089*KR, 47524*KR, 47961*KR, 48400*KR, 48841*KR, 49284*KR, 49729*KR,
- 50176*KR, 50625*KR, 51076*KR, 51529*KR, 51984*KR, 52441*KR, 52900*KR, 53361*KR, 53824*KR, 54289*KR, 54756*KR, 55225*KR, 55696*KR, 56169*KR, 56644*KR, 57121*KR,
- 57600*KR, 58081*KR, 58564*KR, 59049*KR, 59536*KR, 60025*KR, 60516*KR, 61009*KR, 61504*KR, 62001*KR, 62500*KR, 63001*KR, 63504*KR, 64009*KR, 64516*KR, 65025*KR};
- // Table for fast implementation of squaring for numbers in the interval [-255, 255] multiplied by the perceptual weight for green.
- const unsigned int square_table_percep_green[511] = {
- 65025*KG, 64516*KG, 64009*KG, 63504*KG, 63001*KG, 62500*KG, 62001*KG, 61504*KG, 61009*KG, 60516*KG, 60025*KG, 59536*KG, 59049*KG, 58564*KG, 58081*KG, 57600*KG,
- 57121*KG, 56644*KG, 56169*KG, 55696*KG, 55225*KG, 54756*KG, 54289*KG, 53824*KG, 53361*KG, 52900*KG, 52441*KG, 51984*KG, 51529*KG, 51076*KG, 50625*KG, 50176*KG,
- 49729*KG, 49284*KG, 48841*KG, 48400*KG, 47961*KG, 47524*KG, 47089*KG, 46656*KG, 46225*KG, 45796*KG, 45369*KG, 44944*KG, 44521*KG, 44100*KG, 43681*KG, 43264*KG,
- 42849*KG, 42436*KG, 42025*KG, 41616*KG, 41209*KG, 40804*KG, 40401*KG, 40000*KG, 39601*KG, 39204*KG, 38809*KG, 38416*KG, 38025*KG, 37636*KG, 37249*KG, 36864*KG,
- 36481*KG, 36100*KG, 35721*KG, 35344*KG, 34969*KG, 34596*KG, 34225*KG, 33856*KG, 33489*KG, 33124*KG, 32761*KG, 32400*KG, 32041*KG, 31684*KG, 31329*KG, 30976*KG,
- 30625*KG, 30276*KG, 29929*KG, 29584*KG, 29241*KG, 28900*KG, 28561*KG, 28224*KG, 27889*KG, 27556*KG, 27225*KG, 26896*KG, 26569*KG, 26244*KG, 25921*KG, 25600*KG,
- 25281*KG, 24964*KG, 24649*KG, 24336*KG, 24025*KG, 23716*KG, 23409*KG, 23104*KG, 22801*KG, 22500*KG, 22201*KG, 21904*KG, 21609*KG, 21316*KG, 21025*KG, 20736*KG,
- 20449*KG, 20164*KG, 19881*KG, 19600*KG, 19321*KG, 19044*KG, 18769*KG, 18496*KG, 18225*KG, 17956*KG, 17689*KG, 17424*KG, 17161*KG, 16900*KG, 16641*KG, 16384*KG,
- 16129*KG, 15876*KG, 15625*KG, 15376*KG, 15129*KG, 14884*KG, 14641*KG, 14400*KG, 14161*KG, 13924*KG, 13689*KG, 13456*KG, 13225*KG, 12996*KG, 12769*KG, 12544*KG,
- 12321*KG, 12100*KG, 11881*KG, 11664*KG, 11449*KG, 11236*KG, 11025*KG, 10816*KG, 10609*KG, 10404*KG, 10201*KG, 10000*KG, 9801*KG, 9604*KG, 9409*KG, 9216*KG,
- 9025*KG, 8836*KG, 8649*KG, 8464*KG, 8281*KG, 8100*KG, 7921*KG, 7744*KG, 7569*KG, 7396*KG, 7225*KG, 7056*KG, 6889*KG, 6724*KG, 6561*KG, 6400*KG,
- 6241*KG, 6084*KG, 5929*KG, 5776*KG, 5625*KG, 5476*KG, 5329*KG, 5184*KG, 5041*KG, 4900*KG, 4761*KG, 4624*KG, 4489*KG, 4356*KG, 4225*KG, 4096*KG,
- 3969*KG, 3844*KG, 3721*KG, 3600*KG, 3481*KG, 3364*KG, 3249*KG, 3136*KG, 3025*KG, 2916*KG, 2809*KG, 2704*KG, 2601*KG, 2500*KG, 2401*KG, 2304*KG,
- 2209*KG, 2116*KG, 2025*KG, 1936*KG, 1849*KG, 1764*KG, 1681*KG, 1600*KG, 1521*KG, 1444*KG, 1369*KG, 1296*KG, 1225*KG, 1156*KG, 1089*KG, 1024*KG,
- 961*KG, 900*KG, 841*KG, 784*KG, 729*KG, 676*KG, 625*KG, 576*KG, 529*KG, 484*KG, 441*KG, 400*KG, 361*KG, 324*KG, 289*KG, 256*KG,
- 225*KG, 196*KG, 169*KG, 144*KG, 121*KG, 100*KG, 81*KG, 64*KG, 49*KG, 36*KG, 25*KG, 16*KG, 9*KG, 4*KG, 1*KG,
- 0*KG, 1*KG, 4*KG, 9*KG, 16*KG, 25*KG, 36*KG, 49*KG, 64*KG, 81*KG, 100*KG, 121*KG, 144*KG, 169*KG, 196*KG, 225*KG,
- 256*KG, 289*KG, 324*KG, 361*KG, 400*KG, 441*KG, 484*KG, 529*KG, 576*KG, 625*KG, 676*KG, 729*KG, 784*KG, 841*KG, 900*KG, 961*KG,
- 1024*KG, 1089*KG, 1156*KG, 1225*KG, 1296*KG, 1369*KG, 1444*KG, 1521*KG, 1600*KG, 1681*KG, 1764*KG, 1849*KG, 1936*KG, 2025*KG, 2116*KG, 2209*KG,
- 2304*KG, 2401*KG, 2500*KG, 2601*KG, 2704*KG, 2809*KG, 2916*KG, 3025*KG, 3136*KG, 3249*KG, 3364*KG, 3481*KG, 3600*KG, 3721*KG, 3844*KG, 3969*KG,
- 4096*KG, 4225*KG, 4356*KG, 4489*KG, 4624*KG, 4761*KG, 4900*KG, 5041*KG, 5184*KG, 5329*KG, 5476*KG, 5625*KG, 5776*KG, 5929*KG, 6084*KG, 6241*KG,
- 6400*KG, 6561*KG, 6724*KG, 6889*KG, 7056*KG, 7225*KG, 7396*KG, 7569*KG, 7744*KG, 7921*KG, 8100*KG, 8281*KG, 8464*KG, 8649*KG, 8836*KG, 9025*KG,
- 9216*KG, 9409*KG, 9604*KG, 9801*KG, 10000*KG, 10201*KG, 10404*KG, 10609*KG, 10816*KG, 11025*KG, 11236*KG, 11449*KG, 11664*KG, 11881*KG, 12100*KG, 12321*KG,
- 12544*KG, 12769*KG, 12996*KG, 13225*KG, 13456*KG, 13689*KG, 13924*KG, 14161*KG, 14400*KG, 14641*KG, 14884*KG, 15129*KG, 15376*KG, 15625*KG, 15876*KG, 16129*KG,
- 16384*KG, 16641*KG, 16900*KG, 17161*KG, 17424*KG, 17689*KG, 17956*KG, 18225*KG, 18496*KG, 18769*KG, 19044*KG, 19321*KG, 19600*KG, 19881*KG, 20164*KG, 20449*KG,
- 20736*KG, 21025*KG, 21316*KG, 21609*KG, 21904*KG, 22201*KG, 22500*KG, 22801*KG, 23104*KG, 23409*KG, 23716*KG, 24025*KG, 24336*KG, 24649*KG, 24964*KG, 25281*KG,
- 25600*KG, 25921*KG, 26244*KG, 26569*KG, 26896*KG, 27225*KG, 27556*KG, 27889*KG, 28224*KG, 28561*KG, 28900*KG, 29241*KG, 29584*KG, 29929*KG, 30276*KG, 30625*KG,
- 30976*KG, 31329*KG, 31684*KG, 32041*KG, 32400*KG, 32761*KG, 33124*KG, 33489*KG, 33856*KG, 34225*KG, 34596*KG, 34969*KG, 35344*KG, 35721*KG, 36100*KG, 36481*KG,
- 36864*KG, 37249*KG, 37636*KG, 38025*KG, 38416*KG, 38809*KG, 39204*KG, 39601*KG, 40000*KG, 40401*KG, 40804*KG, 41209*KG, 41616*KG, 42025*KG, 42436*KG, 42849*KG,
- 43264*KG, 43681*KG, 44100*KG, 44521*KG, 44944*KG, 45369*KG, 45796*KG, 46225*KG, 46656*KG, 47089*KG, 47524*KG, 47961*KG, 48400*KG, 48841*KG, 49284*KG, 49729*KG,
- 50176*KG, 50625*KG, 51076*KG, 51529*KG, 51984*KG, 52441*KG, 52900*KG, 53361*KG, 53824*KG, 54289*KG, 54756*KG, 55225*KG, 55696*KG, 56169*KG, 56644*KG, 57121*KG,
- 57600*KG, 58081*KG, 58564*KG, 59049*KG, 59536*KG, 60025*KG, 60516*KG, 61009*KG, 61504*KG, 62001*KG, 62500*KG, 63001*KG, 63504*KG, 64009*KG, 64516*KG, 65025*KG};
- // Table for fast implementation of squaring for numbers in the interval [-255, 255] multiplied by the perceptual weight for blue.
- const unsigned int square_table_percep_blue[511] = {
- 65025*KB, 64516*KB, 64009*KB, 63504*KB, 63001*KB, 62500*KB, 62001*KB, 61504*KB, 61009*KB, 60516*KB, 60025*KB, 59536*KB, 59049*KB, 58564*KB, 58081*KB, 57600*KB,
- 57121*KB, 56644*KB, 56169*KB, 55696*KB, 55225*KB, 54756*KB, 54289*KB, 53824*KB, 53361*KB, 52900*KB, 52441*KB, 51984*KB, 51529*KB, 51076*KB, 50625*KB, 50176*KB,
- 49729*KB, 49284*KB, 48841*KB, 48400*KB, 47961*KB, 47524*KB, 47089*KB, 46656*KB, 46225*KB, 45796*KB, 45369*KB, 44944*KB, 44521*KB, 44100*KB, 43681*KB, 43264*KB,
- 42849*KB, 42436*KB, 42025*KB, 41616*KB, 41209*KB, 40804*KB, 40401*KB, 40000*KB, 39601*KB, 39204*KB, 38809*KB, 38416*KB, 38025*KB, 37636*KB, 37249*KB, 36864*KB,
- 36481*KB, 36100*KB, 35721*KB, 35344*KB, 34969*KB, 34596*KB, 34225*KB, 33856*KB, 33489*KB, 33124*KB, 32761*KB, 32400*KB, 32041*KB, 31684*KB, 31329*KB, 30976*KB,
- 30625*KB, 30276*KB, 29929*KB, 29584*KB, 29241*KB, 28900*KB, 28561*KB, 28224*KB, 27889*KB, 27556*KB, 27225*KB, 26896*KB, 26569*KB, 26244*KB, 25921*KB, 25600*KB,
- 25281*KB, 24964*KB, 24649*KB, 24336*KB, 24025*KB, 23716*KB, 23409*KB, 23104*KB, 22801*KB, 22500*KB, 22201*KB, 21904*KB, 21609*KB, 21316*KB, 21025*KB, 20736*KB,
- 20449*KB, 20164*KB, 19881*KB, 19600*KB, 19321*KB, 19044*KB, 18769*KB, 18496*KB, 18225*KB, 17956*KB, 17689*KB, 17424*KB, 17161*KB, 16900*KB, 16641*KB, 16384*KB,
- 16129*KB, 15876*KB, 15625*KB, 15376*KB, 15129*KB, 14884*KB, 14641*KB, 14400*KB, 14161*KB, 13924*KB, 13689*KB, 13456*KB, 13225*KB, 12996*KB, 12769*KB, 12544*KB,
- 12321*KB, 12100*KB, 11881*KB, 11664*KB, 11449*KB, 11236*KB, 11025*KB, 10816*KB, 10609*KB, 10404*KB, 10201*KB, 10000*KB, 9801*KB, 9604*KB, 9409*KB, 9216*KB,
- 9025*KB, 8836*KB, 8649*KB, 8464*KB, 8281*KB, 8100*KB, 7921*KB, 7744*KB, 7569*KB, 7396*KB, 7225*KB, 7056*KB, 6889*KB, 6724*KB, 6561*KB, 6400*KB,
- 6241*KB, 6084*KB, 5929*KB, 5776*KB, 5625*KB, 5476*KB, 5329*KB, 5184*KB, 5041*KB, 4900*KB, 4761*KB, 4624*KB, 4489*KB, 4356*KB, 4225*KB, 4096*KB,
- 3969*KB, 3844*KB, 3721*KB, 3600*KB, 3481*KB, 3364*KB, 3249*KB, 3136*KB, 3025*KB, 2916*KB, 2809*KB, 2704*KB, 2601*KB, 2500*KB, 2401*KB, 2304*KB,
- 2209*KB, 2116*KB, 2025*KB, 1936*KB, 1849*KB, 1764*KB, 1681*KB, 1600*KB, 1521*KB, 1444*KB, 1369*KB, 1296*KB, 1225*KB, 1156*KB, 1089*KB, 1024*KB,
- 961*KB, 900*KB, 841*KB, 784*KB, 729*KB, 676*KB, 625*KB, 576*KB, 529*KB, 484*KB, 441*KB, 400*KB, 361*KB, 324*KB, 289*KB, 256*KB,
- 225*KB, 196*KB, 169*KB, 144*KB, 121*KB, 100*KB, 81*KB, 64*KB, 49*KB, 36*KB, 25*KB, 16*KB, 9*KB, 4*KB, 1*KB,
- 0*KB, 1*KB, 4*KB, 9*KB, 16*KB, 25*KB, 36*KB, 49*KB, 64*KB, 81*KB, 100*KB, 121*KB, 144*KB, 169*KB, 196*KB, 225*KB,
- 256*KB, 289*KB, 324*KB, 361*KB, 400*KB, 441*KB, 484*KB, 529*KB, 576*KB, 625*KB, 676*KB, 729*KB, 784*KB, 841*KB, 900*KB, 961*KB,
- 1024*KB, 1089*KB, 1156*KB, 1225*KB, 1296*KB, 1369*KB, 1444*KB, 1521*KB, 1600*KB, 1681*KB, 1764*KB, 1849*KB, 1936*KB, 2025*KB, 2116*KB, 2209*KB,
- 2304*KB, 2401*KB, 2500*KB, 2601*KB, 2704*KB, 2809*KB, 2916*KB, 3025*KB, 3136*KB, 3249*KB, 3364*KB, 3481*KB, 3600*KB, 3721*KB, 3844*KB, 3969*KB,
- 4096*KB, 4225*KB, 4356*KB, 4489*KB, 4624*KB, 4761*KB, 4900*KB, 5041*KB, 5184*KB, 5329*KB, 5476*KB, 5625*KB, 5776*KB, 5929*KB, 6084*KB, 6241*KB,
- 6400*KB, 6561*KB, 6724*KB, 6889*KB, 7056*KB, 7225*KB, 7396*KB, 7569*KB, 7744*KB, 7921*KB, 8100*KB, 8281*KB, 8464*KB, 8649*KB, 8836*KB, 9025*KB,
- 9216*KB, 9409*KB, 9604*KB, 9801*KB, 10000*KB, 10201*KB, 10404*KB, 10609*KB, 10816*KB, 11025*KB, 11236*KB, 11449*KB, 11664*KB, 11881*KB, 12100*KB, 12321*KB,
- 12544*KB, 12769*KB, 12996*KB, 13225*KB, 13456*KB, 13689*KB, 13924*KB, 14161*KB, 14400*KB, 14641*KB, 14884*KB, 15129*KB, 15376*KB, 15625*KB, 15876*KB, 16129*KB,
- 16384*KB, 16641*KB, 16900*KB, 17161*KB, 17424*KB, 17689*KB, 17956*KB, 18225*KB, 18496*KB, 18769*KB, 19044*KB, 19321*KB, 19600*KB, 19881*KB, 20164*KB, 20449*KB,
- 20736*KB, 21025*KB, 21316*KB, 21609*KB, 21904*KB, 22201*KB, 22500*KB, 22801*KB, 23104*KB, 23409*KB, 23716*KB, 24025*KB, 24336*KB, 24649*KB, 24964*KB, 25281*KB,
- 25600*KB, 25921*KB, 26244*KB, 26569*KB, 26896*KB, 27225*KB, 27556*KB, 27889*KB, 28224*KB, 28561*KB, 28900*KB, 29241*KB, 29584*KB, 29929*KB, 30276*KB, 30625*KB,
- 30976*KB, 31329*KB, 31684*KB, 32041*KB, 32400*KB, 32761*KB, 33124*KB, 33489*KB, 33856*KB, 34225*KB, 34596*KB, 34969*KB, 35344*KB, 35721*KB, 36100*KB, 36481*KB,
- 36864*KB, 37249*KB, 37636*KB, 38025*KB, 38416*KB, 38809*KB, 39204*KB, 39601*KB, 40000*KB, 40401*KB, 40804*KB, 41209*KB, 41616*KB, 42025*KB, 42436*KB, 42849*KB,
- 43264*KB, 43681*KB, 44100*KB, 44521*KB, 44944*KB, 45369*KB, 45796*KB, 46225*KB, 46656*KB, 47089*KB, 47524*KB, 47961*KB, 48400*KB, 48841*KB, 49284*KB, 49729*KB,
- 50176*KB, 50625*KB, 51076*KB, 51529*KB, 51984*KB, 52441*KB, 52900*KB, 53361*KB, 53824*KB, 54289*KB, 54756*KB, 55225*KB, 55696*KB, 56169*KB, 56644*KB, 57121*KB,
- 57600*KB, 58081*KB, 58564*KB, 59049*KB, 59536*KB, 60025*KB, 60516*KB, 61009*KB, 61504*KB, 62001*KB, 62500*KB, 63001*KB, 63504*KB, 64009*KB, 64516*KB, 65025*KB};
- // Find the best table to use for a 2x4 area by testing all.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int tryalltables_3bittable2x4(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB)
- {
- int min_error = 3*255*255*16;
- int q;
- int err;
- unsigned int pixel_indices_MSB, pixel_indices_LSB;
- for(q=0;q<16;q+=2) // try all the 8 tables.
- {
- err=compressBlockWithTable2x4(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB);
- if(err<min_error)
- {
- min_error=err;
- best_pixel_indices_MSB = pixel_indices_MSB;
- best_pixel_indices_LSB = pixel_indices_LSB;
- best_table=q >> 1;
- }
- }
- return min_error;
- }
- // Find the best table to use for a 2x4 area by testing all.
- // Uses perceptual weighting.
- // Uses fixed point implementation where 1000 equals 1.0
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int tryalltables_3bittable2x4percep1000(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB)
- {
- unsigned int min_error = MAXERR1000;
- int q;
- unsigned int err;
- unsigned int pixel_indices_MSB, pixel_indices_LSB;
- for(q=0;q<16;q+=2) // try all the 8 tables.
- {
- err=compressBlockWithTable2x4percep1000(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB);
- if(err<min_error)
- {
- min_error=err;
- best_pixel_indices_MSB = pixel_indices_MSB;
- best_pixel_indices_LSB = pixel_indices_LSB;
- best_table=q >> 1;
- }
- }
- return min_error;
- }
- // Find the best table to use for a 2x4 area by testing all.
- // Uses perceptual weighting.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int tryalltables_3bittable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB)
- {
- float min_error = 3*255*255*16;
- int q;
- float err;
- unsigned int pixel_indices_MSB, pixel_indices_LSB;
- for(q=0;q<16;q+=2) // try all the 8 tables.
- {
- err=compressBlockWithTable2x4percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB);
- if(err<min_error)
- {
- min_error=err;
- best_pixel_indices_MSB = pixel_indices_MSB;
- best_pixel_indices_LSB = pixel_indices_LSB;
- best_table=q >> 1;
- }
- }
- return (int) min_error;
- }
- // Find the best table to use for a 4x2 area by testing all.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int tryalltables_3bittable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB)
- {
- int min_error = 3*255*255*16;
- int q;
- int err;
- unsigned int pixel_indices_MSB, pixel_indices_LSB;
- for(q=0;q<16;q+=2) // try all the 8 tables.
- {
- err=compressBlockWithTable4x2(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB);
- if(err<min_error)
- {
- min_error=err;
- best_pixel_indices_MSB = pixel_indices_MSB;
- best_pixel_indices_LSB = pixel_indices_LSB;
- best_table=q >> 1;
- }
- }
- return min_error;
- }
- // Find the best table to use for a 4x2 area by testing all.
- // Uses perceptual weighting.
- // Uses fixed point implementation where 1000 equals 1.0
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int tryalltables_3bittable4x2percep1000(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB)
- {
- unsigned int min_error = MAXERR1000;
- int q;
- unsigned int err;
- unsigned int pixel_indices_MSB, pixel_indices_LSB;
- for(q=0;q<16;q+=2) // try all the 8 tables.
- {
- err=compressBlockWithTable4x2percep1000(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB);
- if(err<min_error)
- {
- min_error=err;
- best_pixel_indices_MSB = pixel_indices_MSB;
- best_pixel_indices_LSB = pixel_indices_LSB;
- best_table=q >> 1;
- }
- }
- return min_error;
- }
- // Find the best table to use for a 4x2 area by testing all.
- // Uses perceptual weighting.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int tryalltables_3bittable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB)
- {
- float min_error = 3*255*255*16;
- int q;
- float err;
- unsigned int pixel_indices_MSB, pixel_indices_LSB;
- for(q=0;q<16;q+=2) // try all the 8 tables.
- {
- err=compressBlockWithTable4x2percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB);
- if(err<min_error)
- {
- min_error=err;
- best_pixel_indices_MSB = pixel_indices_MSB;
- best_pixel_indices_LSB = pixel_indices_LSB;
- best_table=q >> 1;
- }
- }
- return (int) min_error;
- }
- // The below code quantizes a float RGB value to RGB444.
- //
- // The format often allows a pixel to completely compensate an intensity error of the base
- // color. Hence the closest RGB444 point may not be the best, and the code below uses
- // this fact to find a better RGB444 color as the base color.
- //
- // (See the presentation http://www.jacobstrom.com/publications/PACKMAN.ppt for more info.)
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void quantize444ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color)
- {
- float dr, dg, db;
- float kr, kg, kb;
- float wR2, wG2, wB2;
- uint8 low_color[3];
- uint8 high_color[3];
- float min_error=255*255*8*3;
- float lowhightable[8];
- unsigned int best_table=0;
- unsigned int best_index=0;
- int q;
- float kval = (float) (255.0/15.0);
- // These are the values that we want to have:
- float red_average, green_average, blue_average;
- int red_4bit_low, green_4bit_low, blue_4bit_low;
- int red_4bit_high, green_4bit_high, blue_4bit_high;
-
- // These are the values that we approximate with:
- int red_low, green_low, blue_low;
- int red_high, green_high, blue_high;
- red_average = avg_col_in[0];
- green_average = avg_col_in[1];
- blue_average = avg_col_in[2];
- // Find the 5-bit reconstruction levels red_low, red_high
- // so that red_average is in interval [red_low, red_high].
- // (The same with green and blue.)
- red_4bit_low = (int) (red_average/kval);
- green_4bit_low = (int) (green_average/kval);
- blue_4bit_low = (int) (blue_average/kval);
- red_4bit_high = CLAMP(0, red_4bit_low + 1, 15);
- green_4bit_high = CLAMP(0, green_4bit_low + 1, 15);
- blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15);
- red_low = (red_4bit_low << 4) | (red_4bit_low >> 0);
- green_low = (green_4bit_low << 4) | (green_4bit_low >> 0);
- blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0);
- red_high = (red_4bit_high << 4) | (red_4bit_high >> 0);
- green_high = (green_4bit_high << 4) | (green_4bit_high >> 0);
- blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0);
- kr = (float)red_high - (float)red_low;
- kg = (float)green_high - (float)green_low;
- kb = (float)blue_high - (float)blue_low;
- // Note that dr, dg, and db are all negative.
- dr = red_low - red_average;
- dg = green_low - green_average;
- db = blue_low - blue_average;
- // Use straight (nonperceptive) weights.
- wR2 = (float) 1.0;
- wG2 = (float) 1.0;
- wB2 = (float) 1.0;
- lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- float min_value = lowhightable[0];
- int min_index = 0;
- for(q = 1; q<8; q++)
- {
- if(lowhightable[q] < min_value)
- {
- min_value = lowhightable[q];
- min_index = q;
- }
- }
- float drh = red_high-red_average;
- float dgh = green_high-green_average;
- float dbh = blue_high-blue_average;
- low_color[0] = red_4bit_low;
- low_color[1] = green_4bit_low;
- low_color[2] = blue_4bit_low;
- high_color[0] = red_4bit_high;
- high_color[1] = green_4bit_high;
- high_color[2] = blue_4bit_high;
- switch(min_index)
- {
- case 0:
- // Since the step size is always 17 in RGB444 format (15*17=255),
- // kr = kg = kb = 17, which means that case 0 and case 7 will
- // always have equal projected error. Choose the one that is
- // closer to the desired color.
- if(dr*dr + dg*dg + db*db > 3*8*8)
- {
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- }
- else
- {
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- }
- break;
- case 1:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 2:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 3:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 4:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 5:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 6:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- case 7:
- if(dr*dr + dg*dg + db*db > 3*8*8)
- {
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- }
- else
- {
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- }
- break;
- }
- // Expand 5-bit encoded color to 8-bit color
- avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2);
- avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2);
- avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2);
- }
- // The below code quantizes a float RGB value to RGB555.
- //
- // The format often allows a pixel to completely compensate an intensity error of the base
- // color. Hence the closest RGB555 point may not be the best, and the code below uses
- // this fact to find a better RGB555 color as the base color.
- //
- // (See the presentation http://www.jacobstrom.com/publications/PACKMAN.ppt for more info.)
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void quantize555ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color)
- {
- float dr, dg, db;
- float kr, kg, kb;
- float wR2, wG2, wB2;
- uint8 low_color[3];
- uint8 high_color[3];
- float min_error=255*255*8*3;
- float lowhightable[8];
- unsigned int best_table=0;
- unsigned int best_index=0;
- int q;
- float kval = (float) (255.0/31.0);
- // These are the values that we want to have:
- float red_average, green_average, blue_average;
- int red_5bit_low, green_5bit_low, blue_5bit_low;
- int red_5bit_high, green_5bit_high, blue_5bit_high;
-
- // These are the values that we approximate with:
- int red_low, green_low, blue_low;
- int red_high, green_high, blue_high;
- red_average = avg_col_in[0];
- green_average = avg_col_in[1];
- blue_average = avg_col_in[2];
- // Find the 5-bit reconstruction levels red_low, red_high
- // so that red_average is in interval [red_low, red_high].
- // (The same with green and blue.)
- red_5bit_low = (int) (red_average/kval);
- green_5bit_low = (int) (green_average/kval);
- blue_5bit_low = (int) (blue_average/kval);
- red_5bit_high = CLAMP(0, red_5bit_low + 1, 31);
- green_5bit_high = CLAMP(0, green_5bit_low + 1, 31);
- blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31);
- red_low = (red_5bit_low << 3) | (red_5bit_low >> 2);
- green_low = (green_5bit_low << 3) | (green_5bit_low >> 2);
- blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2);
- red_high = (red_5bit_high << 3) | (red_5bit_high >> 2);
- green_high = (green_5bit_high << 3) | (green_5bit_high >> 2);
- blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2);
- kr = (float)red_high - (float)red_low;
- kg = (float)green_high - (float)green_low;
- kb = (float)blue_high - (float)blue_low;
- // Note that dr, dg, and db are all negative.
- dr = red_low - red_average;
- dg = green_low - green_average;
- db = blue_low - blue_average;
- // Use straight (nonperceptive) weights.
- wR2 = (float) 1.0;
- wG2 = (float) 1.0;
- wB2 = (float) 1.0;
- lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- float min_value = lowhightable[0];
- int min_index = 0;
- for(q = 1; q<8; q++)
- {
- if(lowhightable[q] < min_value)
- {
- min_value = lowhightable[q];
- min_index = q;
- }
- }
- float drh = red_high-red_average;
- float dgh = green_high-green_average;
- float dbh = blue_high-blue_average;
- low_color[0] = red_5bit_low;
- low_color[1] = green_5bit_low;
- low_color[2] = blue_5bit_low;
- high_color[0] = red_5bit_high;
- high_color[1] = green_5bit_high;
- high_color[2] = blue_5bit_high;
- switch(min_index)
- {
- case 0:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 1:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 2:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 3:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 4:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 5:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 6:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- case 7:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- }
- // Expand 5-bit encoded color to 8-bit color
- avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2);
- avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2);
- avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2);
-
- }
- // The below code quantizes a float RGB value to RGB444.
- //
- // The format often allows a pixel to completely compensate an intensity error of the base
- // color. Hence the closest RGB444 point may not be the best, and the code below uses
- // this fact to find a better RGB444 color as the base color.
- //
- // (See the presentation http://www.jacobstrom.com/publications/PACKMAN.ppt for more info.)
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void quantize444ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color)
- {
- float dr, dg, db;
- float kr, kg, kb;
- float wR2, wG2, wB2;
- uint8 low_color[3];
- uint8 high_color[3];
- float min_error=255*255*8*3;
- float lowhightable[8];
- unsigned int best_table=0;
- unsigned int best_index=0;
- int q;
- float kval = (float) (255.0/15.0);
- // These are the values that we want to have:
- float red_average, green_average, blue_average;
- int red_4bit_low, green_4bit_low, blue_4bit_low;
- int red_4bit_high, green_4bit_high, blue_4bit_high;
-
- // These are the values that we approximate with:
- int red_low, green_low, blue_low;
- int red_high, green_high, blue_high;
- red_average = avg_col_in[0];
- green_average = avg_col_in[1];
- blue_average = avg_col_in[2];
- // Find the 5-bit reconstruction levels red_low, red_high
- // so that red_average is in interval [red_low, red_high].
- // (The same with green and blue.)
- red_4bit_low = (int) (red_average/kval);
- green_4bit_low = (int) (green_average/kval);
- blue_4bit_low = (int) (blue_average/kval);
- red_4bit_high = CLAMP(0, red_4bit_low + 1, 15);
- green_4bit_high = CLAMP(0, green_4bit_low + 1, 15);
- blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15);
- red_low = (red_4bit_low << 4) | (red_4bit_low >> 0);
- green_low = (green_4bit_low << 4) | (green_4bit_low >> 0);
- blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0);
- red_high = (red_4bit_high << 4) | (red_4bit_high >> 0);
- green_high = (green_4bit_high << 4) | (green_4bit_high >> 0);
- blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0);
- low_color[0] = red_4bit_low;
- low_color[1] = green_4bit_low;
- low_color[2] = blue_4bit_low;
- high_color[0] = red_4bit_high;
- high_color[1] = green_4bit_high;
- high_color[2] = blue_4bit_high;
- kr = (float)red_high - (float)red_low;
- kg = (float)green_high - (float)green_low;
- kb = (float)blue_high- (float)blue_low;
- // Note that dr, dg, and db are all negative.
- dr = red_low - red_average;
- dg = green_low - green_average;
- db = blue_low - blue_average;
- // Perceptual weights to use
- wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED;
- wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED;
- wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED;
- lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- float min_value = lowhightable[0];
- int min_index = 0;
- for(q = 1; q<8; q++)
- {
- if(lowhightable[q] < min_value)
- {
- min_value = lowhightable[q];
- min_index = q;
- }
- }
- float drh = red_high-red_average;
- float dgh = green_high-green_average;
- float dbh = blue_high-blue_average;
- switch(min_index)
- {
- case 0:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 1:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 2:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 3:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 4:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 5:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 6:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- case 7:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- }
- // Expand encoded color to eight bits
- avg_color[0] = (enc_color[0] << 4) | enc_color[0];
- avg_color[1] = (enc_color[1] << 4) | enc_color[1];
- avg_color[2] = (enc_color[2] << 4) | enc_color[2];
- }
- // The below code quantizes a float RGB value to RGB555.
- //
- // The format often allows a pixel to completely compensate an intensity error of the base
- // color. Hence the closest RGB555 point may not be the best, and the code below uses
- // this fact to find a better RGB555 color as the base color.
- //
- // (See the presentation http://www.jacobstrom.com/publications/PACKMAN.ppt for more info.)
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void quantize555ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color)
- {
- float dr, dg, db;
- float kr, kg, kb;
- float wR2, wG2, wB2;
- uint8 low_color[3];
- uint8 high_color[3];
- float min_error=255*255*8*3;
- float lowhightable[8];
- unsigned int best_table=0;
- unsigned int best_index=0;
- int q;
- float kval = (float) (255.0/31.0);
- // These are the values that we want to have:
- float red_average, green_average, blue_average;
- int red_5bit_low, green_5bit_low, blue_5bit_low;
- int red_5bit_high, green_5bit_high, blue_5bit_high;
-
- // These are the values that we approximate with:
- int red_low, green_low, blue_low;
- int red_high, green_high, blue_high;
- red_average = avg_col_in[0];
- green_average = avg_col_in[1];
- blue_average = avg_col_in[2];
- // Find the 5-bit reconstruction levels red_low, red_high
- // so that red_average is in interval [red_low, red_high].
- // (The same with green and blue.)
- red_5bit_low = (int) (red_average/kval);
- green_5bit_low = (int) (green_average/kval);
- blue_5bit_low = (int) (blue_average/kval);
- red_5bit_high = CLAMP(0, red_5bit_low + 1, 31);
- green_5bit_high = CLAMP(0, green_5bit_low + 1, 31);
- blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31);
- red_low = (red_5bit_low << 3) | (red_5bit_low >> 2);
- green_low = (green_5bit_low << 3) | (green_5bit_low >> 2);
- blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2);
- red_high = (red_5bit_high << 3) | (red_5bit_high >> 2);
- green_high = (green_5bit_high << 3) | (green_5bit_high >> 2);
- blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2);
- low_color[0] = red_5bit_low;
- low_color[1] = green_5bit_low;
- low_color[2] = blue_5bit_low;
- high_color[0] = red_5bit_high;
- high_color[1] = green_5bit_high;
- high_color[2] = blue_5bit_high;
- kr = (float)red_high - (float)red_low;
- kg = (float)green_high - (float)green_low;
- kb = (float)blue_high - (float)blue_low;
- // Note that dr, dg, and db are all negative.
- dr = red_low - red_average;
- dg = green_low - green_average;
- db = blue_low - blue_average;
- // Perceptual weights to use
- wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED;
- wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED;
- wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED;
- lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) );
- lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) );
- lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) );
- lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) );
- float min_value = lowhightable[0];
- int min_index = 0;
- for(q = 1; q<8; q++)
- {
- if(lowhightable[q] < min_value)
- {
- min_value = lowhightable[q];
- min_index = q;
- }
- }
- float drh = red_high-red_average;
- float dgh = green_high-green_average;
- float dbh = blue_high-blue_average;
- switch(min_index)
- {
- case 0:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 1:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = low_color[2];
- break;
- case 2:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 3:
- enc_color[0] = low_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 4:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = low_color[2];
- break;
- case 5:
- enc_color[0] = high_color[0];
- enc_color[1] = low_color[1];
- enc_color[2] = high_color[2];
- break;
- case 6:
- enc_color[0] = low_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- case 7:
- enc_color[0] = high_color[0];
- enc_color[1] = high_color[1];
- enc_color[2] = high_color[2];
- break;
- }
- // Expand 5-bit encoded color to 8-bit color
- avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2);
- avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2);
- avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2);
- }
- // Compresses the block using only the individual mode in ETC1/ETC2 using the average color as the base color.
- // Uses a perceptual error metric.
- // Uses fixed point arithmetics where 1000 equals 1.0
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockOnlyIndividualAveragePerceptual1000(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, int *best_enc_color1, int*best_enc_color2, int &best_flip, unsigned int &best_err_upper, unsigned int &best_err_lower, unsigned int &best_err_left, unsigned int &best_err_right, int *best_color_upper, int *best_color_lower, int *best_color_left, int *best_color_right)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3];
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- unsigned int norm_err=0;
- unsigned int flip_err=0;
- unsigned int best_err;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- enc_color1[0] = int( JAS_ROUND(15.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(15.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(15.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(15.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(15.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(15.0*avg_color_float2[2]/255.0) );
- diffbit = 0;
- avg_color_quant1[0] = enc_color1[0] << 4 | (enc_color1[0] );
- avg_color_quant1[1] = enc_color1[1] << 4 | (enc_color1[1] );
- avg_color_quant1[2] = enc_color1[2] << 4 | (enc_color1[2] );
- avg_color_quant2[0] = enc_color2[0] << 4 | (enc_color2[0] );
- avg_color_quant2[1] = enc_color2[1] << 4 | (enc_color2[1] );
- avg_color_quant2[2] = enc_color2[2] << 4 | (enc_color2[2] );
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
-
- best_color_left[0] = enc_color1[0];
- best_color_left[1] = enc_color1[1];
- best_color_left[2] = enc_color1[2];
- best_color_right[0] = enc_color2[0];
- best_color_right[1] = enc_color2[1];
- best_color_right[2] = enc_color2[2];
- norm_err = 0;
- // left part of block
- best_err_left = tryalltables_3bittable2x4percep1000(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- norm_err = best_err_left;
- // right part of block
- best_err_right = tryalltables_3bittable2x4percep1000(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- norm_err += best_err_right;
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(15.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(15.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(15.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(15.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(15.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(15.0*avg_color_float2[2]/255.0) );
- best_color_upper[0] = enc_color1[0];
- best_color_upper[1] = enc_color1[1];
- best_color_upper[2] = enc_color1[2];
- best_color_lower[0] = enc_color2[0];
- best_color_lower[1] = enc_color2[1];
- best_color_lower[2] = enc_color2[2];
- diffbit = 0;
- avg_color_quant1[0] = enc_color1[0] << 4 | (enc_color1[0] );
- avg_color_quant1[1] = enc_color1[1] << 4 | (enc_color1[1] );
- avg_color_quant1[2] = enc_color1[2] << 4 | (enc_color1[2] );
- avg_color_quant2[0] = enc_color2[0] << 4 | (enc_color2[0] );
- avg_color_quant2[1] = enc_color2[1] << 4 | (enc_color2[1] );
- avg_color_quant2[2] = enc_color2[2] << 4 | (enc_color2[2] );
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 49);
- PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43);
- // upper part of block
- best_err_upper = tryalltables_3bittable4x2percep1000(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- flip_err = best_err_upper;
- // lower part of block
- best_err_lower = tryalltables_3bittable4x2percep1000(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- flip_err += best_err_lower;
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- // Now lets see which is the best table to use. Only 8 tables are possible.
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- best_err = norm_err;
- best_flip = 0;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- best_err = flip_err;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- best_flip = 1;
- }
- return best_err;
- }
- // Compresses the block using only the individual mode in ETC1/ETC2 using the average color as the base color.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int compressBlockOnlyIndividualAverage(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, int *best_enc_color1, int*best_enc_color2, int &best_flip, unsigned int &best_err_upper, unsigned int &best_err_lower, unsigned int &best_err_left, unsigned int &best_err_right, int *best_color_upper, int *best_color_lower, int *best_color_left, int *best_color_right)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3];
- int min_error=255*255*8*3;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- int best_err;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- enc_color1[0] = int( JAS_ROUND(15.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(15.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(15.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(15.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(15.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(15.0*avg_color_float2[2]/255.0) );
- diffbit = 0;
- avg_color_quant1[0] = enc_color1[0] << 4 | (enc_color1[0] );
- avg_color_quant1[1] = enc_color1[1] << 4 | (enc_color1[1] );
- avg_color_quant1[2] = enc_color1[2] << 4 | (enc_color1[2] );
- avg_color_quant2[0] = enc_color2[0] << 4 | (enc_color2[0] );
- avg_color_quant2[1] = enc_color2[1] << 4 | (enc_color2[1] );
- avg_color_quant2[2] = enc_color2[2] << 4 | (enc_color2[2] );
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- best_color_left[0] = enc_color1[0];
- best_color_left[1] = enc_color1[1];
- best_color_left[2] = enc_color1[2];
- best_color_right[0] = enc_color2[0];
- best_color_right[1] = enc_color2[1];
- best_color_right[2] = enc_color2[2];
- norm_err = 0;
- // left part of block
- best_err_left = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- norm_err = best_err_left;
- // right part of block
- best_err_right = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- norm_err += best_err_right;
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(15.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(15.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(15.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(15.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(15.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(15.0*avg_color_float2[2]/255.0) );
- best_color_upper[0] = enc_color1[0];
- best_color_upper[1] = enc_color1[1];
- best_color_upper[2] = enc_color1[2];
- best_color_lower[0] = enc_color2[0];
- best_color_lower[1] = enc_color2[1];
- best_color_lower[2] = enc_color2[2];
- diffbit = 0;
- avg_color_quant1[0] = enc_color1[0] << 4 | (enc_color1[0] );
- avg_color_quant1[1] = enc_color1[1] << 4 | (enc_color1[1] );
- avg_color_quant1[2] = enc_color1[2] << 4 | (enc_color1[2] );
- avg_color_quant2[0] = enc_color2[0] << 4 | (enc_color2[0] );
- avg_color_quant2[1] = enc_color2[1] << 4 | (enc_color2[1] );
- avg_color_quant2[2] = enc_color2[2] << 4 | (enc_color2[2] );
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 49);
- PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43);
- // upper part of block
- best_err_upper = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- flip_err = best_err_upper;
- // lower part of block
- best_err_lower = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- flip_err += best_err_lower;
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- // Now lets see which is the best table to use. Only 8 tables are possible.
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- best_err = norm_err;
- best_flip = 0;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- best_err = flip_err;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- best_flip = 1;
- }
- return best_err;
- }
- // Compresses the block using either the individual or differential mode in ETC1/ETC2
- // Uses the average color as the base color in each half-block.
- // Tries both flipped and unflipped.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockDiffFlipAverage(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int min_error=255*255*8*3;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- float eps;
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_norm, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_norm, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_norm, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- norm_err = 0;
- // left part of block
- norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps);
- enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps);
- enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps);
- enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps);
- enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps);
- enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
- // Pack bits into the first word.
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
-
- // left part of block
- norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_flip, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_flip, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_flip, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps);
- enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps);
- enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps);
- enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps);
- enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps);
- enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- // Now lets see which is the best table to use. Only 8 tables are possible.
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- }
- }
- // Compresses the block using only the differential mode in ETC1/ETC2
- // Uses the average color as the base color in each half-block.
- // If average colors are too different, use the average color of the entire block in both half-blocks.
- // Tries both flipped and unflipped.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int compressBlockOnlyDiffFlipAverage(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, int *best_enc_color1, int*best_enc_color2, int &best_flip)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int min_error=255*255*8*3;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- int best_err;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( !((diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3)) )
- {
- // The colors are too different. Use the same color in both blocks.
- enc_color1[0] = int( JAS_ROUND(31.0*((avg_color_float1[0]+avg_color_float2[0])/2.0)/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*((avg_color_float1[1]+avg_color_float2[1])/2.0)/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*((avg_color_float1[2]+avg_color_float2[2])/2.0)/255.0) );
- enc_color2[0] = enc_color1[0];
- enc_color2[1] = enc_color1[1];
- enc_color2[2] = enc_color1[2];
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- }
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_norm, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_norm, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_norm, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- norm_err = 0;
- // left part of block
- norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( !((diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3)) )
- {
- // The colors are too different. Use the same color in both blocks.
- enc_color1[0] = int( JAS_ROUND(31.0*((avg_color_float1[0]+avg_color_float2[0])/2.0)/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*((avg_color_float1[1]+avg_color_float2[1])/2.0)/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*((avg_color_float1[2]+avg_color_float2[2])/2.0)/255.0) );
- enc_color2[0] = enc_color1[0];
- enc_color2[1] = enc_color1[1];
- enc_color2[2] = enc_color1[2];
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- }
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_flip, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_flip, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_flip, diff[2], 3, 42);
- // upper part of block
- flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- // Now lets see which is the best table to use. Only 8 tables are possible.
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- best_err = norm_err;
- best_flip = 0;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- best_err = flip_err;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- best_flip = 1;
- }
- return best_err;
- }
- // Compresses the block using only the differential mode in ETC1/ETC2
- // Uses the average color as the base color in each half-block.
- // If average colors are too different, use the average color of the entire block in both half-blocks.
- // Tries both flipped and unflipped.
- // Uses fixed point arithmetics where 1000 represents 1.0.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockOnlyDiffFlipAveragePerceptual1000(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- unsigned int min_error=MAXERR1000;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( !((diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3)) )
- {
- enc_color1[0] = (enc_color1[0] + enc_color2[0]) >> 1;
- enc_color1[1] = (enc_color1[1] + enc_color2[1]) >> 1;
- enc_color1[2] = (enc_color1[2] + enc_color2[2]) >> 1;
- enc_color2[0] = enc_color1[0];
- enc_color2[1] = enc_color1[1];
- enc_color2[2] = enc_color1[2];
- }
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_norm, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_norm, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_norm, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- norm_err = 0;
- // left part of block
- norm_err = tryalltables_3bittable2x4percep1000(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4percep1000(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( !((diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3)) )
- {
- enc_color1[0] = (enc_color1[0] + enc_color2[0]) >> 1;
- enc_color1[1] = (enc_color1[1] + enc_color2[1]) >> 1;
- enc_color1[2] = (enc_color1[2] + enc_color2[2]) >> 1;
- enc_color2[0] = enc_color1[0];
- enc_color2[1] = enc_color1[1];
- enc_color2[2] = enc_color1[2];
- }
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_flip, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_flip, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_flip, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2percep1000(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2percep1000(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- unsigned int best_err;
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- best_err = norm_err;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- best_err = flip_err;
- }
- return best_err;
- }
- // Compresses the block using both the individual and the differential mode in ETC1/ETC2
- // Uses the average color as the base color in each half-block.
- // Uses a perceptual error metric.
- // Tries both flipped and unflipped.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockDiffFlipAveragePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int min_error=255*255*8*3;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- float eps;
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_norm, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_norm, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_norm, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- norm_err = 0;
- // left part of block
- norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps);
- enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps);
- enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps);
- enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps);
- enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps);
- enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
-
- // Pack bits into the first word.
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
-
- // left part of block
- norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) );
- enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) );
- enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) );
- enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) );
- enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) );
- enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) );
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_flip, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_flip, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_flip, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps);
- enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps);
- enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps);
- enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps);
- enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps);
- enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- // Now lets see which is the best table to use. Only 8 tables are possible.
-
- double best_err;
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- best_err = norm_err;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- best_err = flip_err;
- }
- return best_err;
- }
- // This is our structure for matrix data
- struct dMatrix
- {
- int width; // The number of coloumns in the matrix
- int height; // The number of rows in the matrix
- double *data; // The matrix data in row order
- };
- // Multiplies two matrices
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- dMatrix *multiplyMatrices( dMatrix *Amat, dMatrix *Bmat)
- {
- int xx,yy, q;
- dMatrix *resmatrix;
- if(Amat->width != Bmat->height)
- {
- printf("Cannot multiply matrices -- dimensions do not agree.\n");
- exit(1);
- }
- // Allocate space for result
- resmatrix = (dMatrix*) malloc(sizeof(dMatrix));
- resmatrix->width = Bmat->width;
- resmatrix->height = Amat->height;
- resmatrix->data = (double*) malloc(sizeof(double)*(resmatrix->width)*(resmatrix->height));
- for(yy = 0; yy<resmatrix->height; yy++)
- for(xx = 0; xx<resmatrix->width; xx++)
- for(q=0, resmatrix->data[yy*resmatrix->width+xx] = 0.0; q<Amat->width; q++)
- resmatrix->data[yy*resmatrix->width+xx] += Amat->data[yy*Amat->width + q] * Bmat->data[q*Bmat->width+xx];
- return(resmatrix);
- }
- // Transposes a matrix
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void transposeMatrix( dMatrix *mat)
- {
- int xx, yy, zz;
- double *temp;
- int newwidth, newheight;
- temp = (double*) malloc (sizeof(double)*(mat->width)*(mat->height));
- for(zz = 0; zz<((mat->width)*(mat->height)); zz++)
- temp[zz] = mat->data[zz];
- newwidth = mat->height;
- newheight= mat->width;
- for(yy = 0; yy<newheight; yy++)
- for(xx = 0; xx<newwidth; xx++)
- mat->data[yy*newwidth+xx] = temp[xx*(mat->width)+yy];
- mat->height = newheight;
- mat->width = newwidth;
- free(temp);
- }
- // In the planar mode in ETC2, the block can be partitioned as follows:
- //
- // O A A A H
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- // V
- // Here A-pixels, B-pixels and C-pixels only depend on two values. For instance, B-pixels only depend on O and V.
- // This can be used to quickly rule out combinations of colors.
- // Here we calculate the minimum error for the block if we know the red component for O and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcBBBred(uint8 *block, int colorO, int colorV)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error = 0;
-
- // Now first column: B B B
- /* unroll loop for( yy=0; (yy<4) && (error <= best_error_sofar); yy++)*/
- {
- error = error + square_table[(block[4*4 + 0] - clamp_table[ ((((colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 0] - clamp_table[ (((((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*3 + 0] - clamp_table[ (((3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- return error;
- }
- // Calculating the minimum error for the block if we know the red component for H and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcCCCred(uint8 *block, int colorH, int colorV)
- {
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error=0;
- error = error + square_table[(block[4*4*3 + 4 + 0] - clamp_table[ (((colorH + 3*colorV)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 4*2 + 0] - clamp_table[ (((2*colorH + 2*colorV)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4 + 4*3 + 0] - clamp_table[ (((3*colorH + colorV)+2)>>2) + 255])+255];
-
- return error;
- }
- // Calculating the minimum error for the block if we know the red component for O and H.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcLowestPossibleRedOHperceptual(uint8 *block, int colorO, int colorH, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- unsigned int error;
- error = square_table_percep_red[(block[0] - colorO) + 255];
- error = error + square_table_percep_red[(block[4] - clamp_table[ ((( (colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table_percep_red[(block[4*2] - clamp_table[ ((( ((colorH-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_red[(block[4*3] - clamp_table[ ((( 3*(colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the red component for O and H.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcLowestPossibleRedOH(uint8 *block, int colorO, int colorH, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- unsigned int error;
- error = square_table[(block[0] - colorO) + 255];
- error = error + square_table[(block[4] - clamp_table[ ((( (colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table[(block[4*2] - clamp_table[ ((( ((colorH-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*3] - clamp_table[ ((( 3*(colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the red component for O and H and V.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcErrorPlanarOnlyRedPerceptual(uint8 *block, int colorO, int colorH, int colorV, unsigned int lowest_possible_error, unsigned int BBBvalue, unsigned int CCCvalue, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error;
- // The block can be partitioned into: O A A A
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- int xpart_times_4;
- // The first part: O A A A. It equals lowest_possible_error previously calculated.
- // lowest_possible_error is OAAA, BBBvalue is BBB and CCCvalue is C1C2C3.
- error = lowest_possible_error + BBBvalue + CCCvalue;
- // The remaining pixels to cover are D1 through D6.
- if(error <= best_error_sofar)
- {
- // Second column: D1 D2 but not C1
- xpart_times_4 = (colorH-colorO);
- error = error + square_table_percep_red[(block[4*4 + 4 + 0] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_red[(block[4*4*2 + 4 + 0] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- // Third column: D3 notC2 D4
- xpart_times_4 = (colorH-colorO) << 1;
- error = error + square_table_percep_red[(block[4*4 + 4*2 + 0] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table_percep_red[(block[4*4*3 + 4*2 + 0] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- // Forth column: notC3 D5 D6
- xpart_times_4 = 3*(colorH-colorO);
- error = error + square_table_percep_red[(block[4*4*2 + 4*3 + 0] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_red[(block[4*4*3 + 4*3 + 0] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the red component for O and H and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcErrorPlanarOnlyRed(uint8 *block, int colorO, int colorH, int colorV, unsigned int lowest_possible_error, unsigned int BBBvalue, unsigned int CCCvalue, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error;
- // The block can be partitioned into: O A A A
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- int xpart_times_4;
- // The first part: O A A A. It equals lowest_possible_error previously calculated.
- // lowest_possible_error is OAAA, BBBvalue is BBB and CCCvalue is C1C2C3.
- error = lowest_possible_error + BBBvalue + CCCvalue;
- // The remaining pixels to cover are D1 through D6.
- if(error <= best_error_sofar)
- {
- // Second column: D1 D2 but not C1
- xpart_times_4 = (colorH-colorO);
- error = error + square_table[(block[4*4 + 4 + 0] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 4 + 0] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- // Third column: D3 notC2 D4
- xpart_times_4 = (colorH-colorO) << 1;
- error = error + square_table[(block[4*4 + 4*2 + 0] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table[(block[4*4*3 + 4*2 + 0] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- // Forth column: notC3 D5 D6
- xpart_times_4 = 3*(colorH-colorO);
- error = error + square_table[(block[4*4*2 + 4*3 + 0] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*3 + 4*3 + 0] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the red component for O and H.
- // Uses perceptual error metrics.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcLowestPossibleGreenOHperceptual(uint8 *block, int colorO, int colorH, unsigned int best_error_sofar)
- {
- colorO = (colorO << 1) | (colorO >> 6);
- colorH = (colorH << 1) | (colorH >> 6);
- unsigned int error;
- error = square_table_percep_green[(block[1] - colorO) + 255];
- error = error + square_table_percep_green[(block[4 + 1] - clamp_table[ ((( (colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table_percep_green[(block[4*2 + 1] - clamp_table[ ((( ((colorH-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_green[(block[4*3 + 1] - clamp_table[ ((( 3*(colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the red component for O and H.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcLowestPossibleGreenOH(uint8 *block, int colorO, int colorH, unsigned int best_error_sofar)
- {
- colorO = (colorO << 1) | (colorO >> 6);
- colorH = (colorH << 1) | (colorH >> 6);
- unsigned int error;
- error = square_table[(block[1] - colorO) + 255];
- error = error + square_table[(block[4 + 1] - clamp_table[ ((( (colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table[(block[4*2 + 1] - clamp_table[ ((( ((colorH-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*3 + 1] - clamp_table[ ((( 3*(colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the green component for O and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcBBBgreen(uint8 *block, int colorO, int colorV)
- {
- colorO = (colorO << 1) | (colorO >> 6);
- colorV = (colorV << 1) | (colorV >> 6);
- unsigned int error = 0;
-
- // Now first column: B B B
- /* unroll loop for( yy=0; (yy<4) && (error <= best_error_sofar); yy++)*/
- {
- error = error + square_table[(block[4*4 + 1] - clamp_table[ ((((colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 1] - clamp_table[ (((((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*3 + 1] - clamp_table[ (((3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the green component for H and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcCCCgreen(uint8 *block, int colorH, int colorV)
- {
- colorH = (colorH << 1) | (colorH >> 6);
- colorV = (colorV << 1) | (colorV >> 6);
- unsigned int error=0;
- error = error + square_table[(block[4*4*3 + 4 + 1] - clamp_table[ (((colorH + 3*colorV)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 4*2 + 1] - clamp_table[ (((2*colorH + 2*colorV)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4 + 4*3 + 1] - clamp_table[ (((3*colorH + colorV)+2)>>2) + 255])+255];
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the green component for H V and O.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcErrorPlanarOnlyGreenPerceptual(uint8 *block, int colorO, int colorH, int colorV, unsigned int lowest_possible_error, unsigned int BBBvalue, unsigned int CCCvalue, unsigned int best_error_sofar)
- {
- colorO = (colorO << 1) | (colorO >> 6);
- colorH = (colorH << 1) | (colorH >> 6);
- colorV = (colorV << 1) | (colorV >> 6);
- unsigned int error;
- // The block can be partitioned into: O A A A
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- int xpart_times_4;
- // The first part: O A A A. It equals lowest_possible_error previously calculated.
- // lowest_possible_error is OAAA, BBBvalue is BBB and CCCvalue is C1C2C3.
- error = lowest_possible_error + BBBvalue + CCCvalue;
- // The remaining pixels to cover are D1 through D6.
- if(error <= best_error_sofar)
- {
- // Second column: D1 D2 but not C1
- xpart_times_4 = (colorH-colorO);
- error = error + square_table_percep_green[(block[4*4 + 4 + 1] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_green[(block[4*4*2 + 4 + 1] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- // Third column: D3 notC2 D4
- xpart_times_4 = (colorH-colorO) << 1;
- error = error + square_table_percep_green[(block[4*4 + 4*2 + 1] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table_percep_green[(block[4*4*3 + 4*2 + 1] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- // Forth column: notC3 D5 D6
- xpart_times_4 = 3*(colorH-colorO);
- error = error + square_table_percep_green[(block[4*4*2 + 4*3 + 1] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_green[(block[4*4*3 + 4*3 + 1] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the green component for H V and O.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcErrorPlanarOnlyGreen(uint8 *block, int colorO, int colorH, int colorV, unsigned int lowest_possible_error, unsigned int BBBvalue, unsigned int CCCvalue, unsigned int best_error_sofar)
- {
- colorO = (colorO << 1) | (colorO >> 6);
- colorH = (colorH << 1) | (colorH >> 6);
- colorV = (colorV << 1) | (colorV >> 6);
- unsigned int error;
- // The block can be partitioned into: O A A A
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- int xpart_times_4;
- // The first part: O A A A. It equals lowest_possible_error previously calculated.
- // lowest_possible_error is OAAA, BBBvalue is BBB and CCCvalue is C1C2C3.
- error = lowest_possible_error + BBBvalue + CCCvalue;
- // The remaining pixels to cover are D1 through D6.
- if(error <= best_error_sofar)
- {
- // Second column: D1 D2 but not C1
- xpart_times_4 = (colorH-colorO);
- error = error + square_table[(block[4*4 + 4 + 1] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 4 + 1] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- // Third column: D3 notC2 D4
- xpart_times_4 = (colorH-colorO) << 1;
- error = error + square_table[(block[4*4 + 4*2 + 1] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table[(block[4*4*3 + 4*2 + 1] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- // Forth column: notC3 D5 D6
- xpart_times_4 = 3*(colorH-colorO);
- error = error + square_table[(block[4*4*2 + 4*3 + 1] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*3 + 4*3 + 1] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O and V.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcBBBbluePerceptual(uint8 *block, int colorO, int colorV)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error = 0;
-
- // Now first column: B B B
- /* unroll loop for( yy=0; (yy<4) && (error <= best_error_sofar); yy++)*/
- {
- error = error + square_table_percep_blue[(block[4*4 + 2] - clamp_table[ ((((colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*4*2 + 2] - clamp_table[ (((((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*4*3 + 2] - clamp_table[ (((3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcBBBblue(uint8 *block, int colorO, int colorV)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error = 0;
-
- // Now first column: B B B
- /* unroll loop for( yy=0; (yy<4) && (error <= best_error_sofar); yy++)*/
- {
- error = error + square_table[(block[4*4 + 2] - clamp_table[ ((((colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 2] - clamp_table[ (((((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*3 + 2] - clamp_table[ (((3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for H and V.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcCCCbluePerceptual(uint8 *block, int colorH, int colorV)
- {
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error=0;
- error = error + square_table_percep_blue[(block[4*4*3 + 4 + 2] - clamp_table[ (((colorH + 3*colorV)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*4*2 + 4*2 + 2] - clamp_table[ (((2*colorH + 2*colorV)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*4 + 4*3 + 2] - clamp_table[ (((3*colorH + colorV)+2)>>2) + 255])+255];
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O and V.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcCCCblue(uint8 *block, int colorH, int colorV)
- {
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error=0;
- error = error + square_table[(block[4*4*3 + 4 + 2] - clamp_table[ (((colorH + 3*colorV)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 4*2 + 2] - clamp_table[ (((2*colorH + 2*colorV)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4 + 4*3 + 2] - clamp_table[ (((3*colorH + colorV)+2)>>2) + 255])+255];
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O and H.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcLowestPossibleBlueOHperceptual(uint8 *block, int colorO, int colorH, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- unsigned int error;
- error = square_table_percep_blue[(block[2] - colorO) + 255];
- error = error + square_table_percep_blue[(block[4+2] - clamp_table[ ((( (colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table_percep_blue[(block[4*2+2] - clamp_table[ ((( ((colorH-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*3+2] - clamp_table[ ((( 3*(colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O and H.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcLowestPossibleBlueOH(uint8 *block, int colorO, int colorH, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- unsigned int error;
- error = square_table[(block[2] - colorO) + 255];
- error = error + square_table[(block[4+2] - clamp_table[ ((( (colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table[(block[4*2+2] - clamp_table[ ((( ((colorH-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*3+2] - clamp_table[ ((( 3*(colorH-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O, V and H.
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcErrorPlanarOnlyBluePerceptual(uint8 *block, int colorO, int colorH, int colorV, unsigned int lowest_possible_error, unsigned int BBBvalue, unsigned int CCCvalue, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error;
- // The block can be partitioned into: O A A A
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- int xpart_times_4;
- // The first part: O A A A. It equals lowest_possible_error previously calculated.
- // lowest_possible_error is OAAA, BBBvalue is BBB and CCCvalue is C1C2C3.
- error = lowest_possible_error + BBBvalue + CCCvalue;
- // The remaining pixels to cover are D1 through D6.
- if(error <= best_error_sofar)
- {
- // Second column: D1 D2 but not C1
- xpart_times_4 = (colorH-colorO);
- error = error + square_table_percep_blue[(block[4*4 + 4 + 2] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*4*2 + 4 + 2] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- // Third column: D3 notC2 D4
- xpart_times_4 = (colorH-colorO) << 1;
- error = error + square_table_percep_blue[(block[4*4 + 4*2 + 2] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table_percep_blue[(block[4*4*3 + 4*2 + 2] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- // Forth column: notC3 D5 D6
- xpart_times_4 = 3*(colorH-colorO);
- error = error + square_table_percep_blue[(block[4*4*2 + 4*3 + 2] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table_percep_blue[(block[4*4*3 + 4*3 + 2] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- }
-
- return error;
- }
- // Calculating the minimum error for the block (in planar mode) if we know the blue component for O, V and H.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calcErrorPlanarOnlyBlue(uint8 *block, int colorO, int colorH, int colorV, unsigned int lowest_possible_error, unsigned int BBBvalue, unsigned int CCCvalue, unsigned int best_error_sofar)
- {
- colorO = (colorO << 2) | (colorO >> 4);
- colorH = (colorH << 2) | (colorH >> 4);
- colorV = (colorV << 2) | (colorV >> 4);
- unsigned int error;
- // The block can be partitioned into: O A A A
- // B D1 D3 C3
- // B D2 C2 D5
- // B C1 D4 D6
- int xpart_times_4;
- // The first part: O A A A. It equals lowest_possible_error previously calculated.
- // lowest_possible_error is OAAA, BBBvalue is BBB and CCCvalue is C1C2C3.
- error = lowest_possible_error + BBBvalue + CCCvalue;
- // The remaining pixels to cover are D1 through D6.
- if(error <= best_error_sofar)
- {
- // Second column: D1 D2 but not C1
- xpart_times_4 = (colorH-colorO);
- error = error + square_table[(block[4*4 + 4 + 2] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*2 + 4 + 2] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- // Third column: D3 notC2 D4
- xpart_times_4 = (colorH-colorO) << 1;
- error = error + square_table[(block[4*4 + 4*2 + 2] - clamp_table[ (((xpart_times_4 + (colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- if(error <= best_error_sofar)
- {
- error = error + square_table[(block[4*4*3 + 4*2 + 2] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- // Forth column: notC3 D5 D6
- xpart_times_4 = 3*(colorH-colorO);
- error = error + square_table[(block[4*4*2 + 4*3 + 2] - clamp_table[ (((xpart_times_4 + ((colorV-colorO)<<1) + 4*colorO)+2)>>2) + 255])+255];
- error = error + square_table[(block[4*4*3 + 4*3 + 2] - clamp_table[ (((xpart_times_4 + 3*(colorV-colorO) + 4*colorO)+2)>>2) + 255])+255];
- }
- }
- return error;
- }
- // This function uses least squares in order to determine the best values of the plane.
- // This is close to optimal, but not quite, due to nonlinearities in the expantion from 6 and 7 bits to 8, and
- // in the clamping to a number between 0 and the maximum.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockPlanar57(uint8 *img, int width,int height,int startx,int starty, unsigned int &compressed57_1, unsigned int &compressed57_2)
- {
- // Use least squares to find the solution with the smallest error.
- // That is, find the vector x so that |Ax-b|^2 is minimized, where
- // x = [Ro Rr Rv]';
- // A = [1 3/4 2/4 1/4 3/4 2/4 1/4 0 2/4 1/4 0 -1/4 1/4 0 -1/4 -2/4 ;
- // 0 1/4 2/4 3/4 0 1/4 2/4 3/4 0 1/4 2/4 3/4 0 1/4 2/4 3/4 ;
- // 0 0 0 0 1/4 1/4 1/4 1/4 2/4 2/4 2/4 2/4; 3/4 3/4 3/4 3/4]';
- // b = [r11 r12 r13 r14 r21 r22 r23 r24 r31 r32 r33 r34 r41 r42 r43 r44];
- //
- // That is, find solution x = inv(A' * A) * A' * b
- // = C * A' * b;
- // C is always the same, so we have calculated it off-line here.
- // = C * D
- int xx,yy, cc;
- double coeffsA[48]= { 1.00, 0.00, 0.00,
- 0.75, 0.25, 0.00,
- 0.50, 0.50, 0.00,
- 0.25, 0.75, 0.00,
- 0.75, 0.00, 0.25,
- 0.50, 0.25, 0.25,
- 0.25, 0.50, 0.25,
- 0.00, 0.75, 0.25,
- 0.50, 0.00, 0.50,
- 0.25, 0.25, 0.50,
- 0.00, 0.50, 0.50,
- -0.25, 0.75, 0.50,
- 0.25, 0.00, 0.75,
- 0.00, 0.25, 0.75,
- -0.25, 0.50, 0.75,
- -0.50, 0.75, 0.75};
- double coeffsC[9] = {0.2875, -0.0125, -0.0125, -0.0125, 0.4875, -0.3125, -0.0125, -0.3125, 0.4875};
- double colorO[3], colorH[3], colorV[3];
- uint8 colorO8[3], colorH8[3], colorV8[3];
-
- dMatrix *D_matrix;
- dMatrix *x_vector;
- dMatrix A_matrix; A_matrix.width = 3; A_matrix.height = 16;
- A_matrix.data = coeffsA;
- dMatrix C_matrix; C_matrix.width = 3; C_matrix.height = 3;
- C_matrix.data = coeffsC;
- dMatrix b_vector; b_vector.width = 1; b_vector.height = 16;
- b_vector.data = (double*) malloc(sizeof(double)*b_vector.width*b_vector.height);
- transposeMatrix(&A_matrix);
- // Red component
- // Load color data into vector b:
- for(cc = 0, yy = 0; yy<4; yy++)
- for(xx = 0; xx<4; xx++)
- b_vector.data[cc++] = img[3*width*(starty+yy) + 3*(startx+xx) + 0];
- D_matrix = multiplyMatrices(&A_matrix, &b_vector);
- x_vector = multiplyMatrices(&C_matrix, D_matrix);
- colorO[0] = CLAMP(0.0, x_vector->data[0], 255.0);
- colorH[0] = CLAMP(0.0, x_vector->data[1], 255.0);
- colorV[0] = CLAMP(0.0, x_vector->data[2], 255.0);
- free(D_matrix->data); free(D_matrix);
- free(x_vector->data); free(x_vector);
- // Green component
- // Load color data into vector b:
- for(cc = 0, yy = 0; yy<4; yy++)
- for(xx = 0; xx<4; xx++)
- b_vector.data[cc++] = img[3*width*(starty+yy) + 3*(startx+xx) + 1];
- D_matrix = multiplyMatrices(&A_matrix, &b_vector);
- x_vector = multiplyMatrices(&C_matrix, D_matrix);
- colorO[1] = CLAMP(0.0, x_vector->data[0], 255.0);
- colorH[1] = CLAMP(0.0, x_vector->data[1], 255.0);
- colorV[1] = CLAMP(0.0, x_vector->data[2], 255.0);
- free(D_matrix->data); free(D_matrix);
- free(x_vector->data); free(x_vector);
- // Blue component
- // Load color data into vector b:
- for(cc = 0, yy = 0; yy<4; yy++)
- for(xx = 0; xx<4; xx++)
- b_vector.data[cc++] = img[3*width*(starty+yy) + 3*(startx+xx) + 2];
- D_matrix = multiplyMatrices(&A_matrix, &b_vector);
- x_vector = multiplyMatrices(&C_matrix, D_matrix);
- colorO[2] = CLAMP(0.0, x_vector->data[0], 255.0);
- colorH[2] = CLAMP(0.0, x_vector->data[1], 255.0);
- colorV[2] = CLAMP(0.0, x_vector->data[2], 255.0);
- free(D_matrix->data); free(D_matrix);
- free(x_vector->data); free(x_vector);
- // Quantize to 6 bits
- double D = 255*(1.0/((1<<6)-1.0) );
- colorO8[0] = JAS_ROUND((1.0*colorO[0])/D);
- colorO8[2] = JAS_ROUND((1.0*colorO[2])/D);
- colorH8[0] = JAS_ROUND((1.0*colorH[0])/D);
- colorH8[2] = JAS_ROUND((1.0*colorH[2])/D);
- colorV8[0] = JAS_ROUND((1.0*colorV[0])/D);
- colorV8[2] = JAS_ROUND((1.0*colorV[2])/D);
- // Quantize to 7 bits
- D = 255*(1.0/((1<<7)-1.0) );
- colorO8[1] = JAS_ROUND((1.0*colorO[1])/D);
- colorH8[1] = JAS_ROUND((1.0*colorH[1])/D);
- colorV8[1] = JAS_ROUND((1.0*colorV[1])/D);
- // Pack bits in 57 bits
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ------------------------------------------------------------------------------------------------
- // | R0 | G0 | B0 | RH | GH |
- // ------------------------------------------------------------------------------------------------
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // ------------------------------------------------------------------------------------------------
- // | BH | RV | GV | BV | not used |
- // ------------------------------------------------------------------------------------------------
- compressed57_1 = 0;
- compressed57_2 = 0;
- PUTBITSHIGH( compressed57_1, colorO8[0], 6, 63);
- PUTBITSHIGH( compressed57_1, colorO8[1], 7, 57);
- PUTBITSHIGH( compressed57_1, colorO8[2], 6, 50);
- PUTBITSHIGH( compressed57_1, colorH8[0], 6, 44);
- PUTBITSHIGH( compressed57_1, colorH8[1], 7, 38);
- PUTBITS( compressed57_2, colorH8[2], 6, 31);
- PUTBITS( compressed57_2, colorV8[0], 6, 25);
- PUTBITS( compressed57_2, colorV8[1], 7, 19);
- PUTBITS( compressed57_2, colorV8[2], 6, 12);
- }
- // During search it is not convenient to store the bits the way they are stored in the
- // file format. Hence, after search, it is converted to this format.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void stuff57bits(unsigned int planar57_word1, unsigned int planar57_word2, unsigned int &planar_word1, unsigned int &planar_word2)
- {
- // Put bits in twotimer configuration for 57 bits (red and green dont overflow, green does)
- //
- // Go from this bit layout:
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // |R0 |G01G02 |B01B02 ;B03 |RH1 |RH2|GH |
- // -----------------------------------------------------------------------------------------------
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // -----------------------------------------------------------------------------------------------
- // |BH |RV |GV |BV | not used |
- // -----------------------------------------------------------------------------------------------
- //
- // To this:
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ------------------------------------------------------------------------------------------------
- // |//|R0 |G01|/|G02 |B01|/ // //|B02 |//|B03 |RH1 |df|RH2|
- // ------------------------------------------------------------------------------------------------
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // -----------------------------------------------------------------------------------------------
- // |GH |BH |RV |GV |BV |
- // -----------------------------------------------------------------------------------------------
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- uint8 RO, GO1, GO2, BO1, BO2, BO3, RH1, RH2, GH, BH, RV, GV, BV;
- uint8 bit, a, b, c, d, bits;
- RO = GETBITSHIGH( planar57_word1, 6, 63);
- GO1= GETBITSHIGH( planar57_word1, 1, 57);
- GO2= GETBITSHIGH( planar57_word1, 6, 56);
- BO1= GETBITSHIGH( planar57_word1, 1, 50);
- BO2= GETBITSHIGH( planar57_word1, 2, 49);
- BO3= GETBITSHIGH( planar57_word1, 3, 47);
- RH1= GETBITSHIGH( planar57_word1, 5, 44);
- RH2= GETBITSHIGH( planar57_word1, 1, 39);
- GH = GETBITSHIGH( planar57_word1, 7, 38);
- BH = GETBITS( planar57_word2, 6, 31);
- RV = GETBITS( planar57_word2, 6, 25);
- GV = GETBITS( planar57_word2, 7, 19);
- BV = GETBITS( planar57_word2, 6, 12);
- planar_word1 = 0; planar_word2 = 0;
- PUTBITSHIGH( planar_word1, RO, 6, 62);
- PUTBITSHIGH( planar_word1, GO1, 1, 56);
- PUTBITSHIGH( planar_word1, GO2, 6, 54);
- PUTBITSHIGH( planar_word1, BO1, 1, 48);
- PUTBITSHIGH( planar_word1, BO2, 2, 44);
- PUTBITSHIGH( planar_word1, BO3, 3, 41);
- PUTBITSHIGH( planar_word1, RH1, 5, 38);
- PUTBITSHIGH( planar_word1, RH2, 1, 32);
- PUTBITS( planar_word2, GH, 7, 31);
- PUTBITS( planar_word2, BH, 6, 24);
- PUTBITS( planar_word2, RV, 6, 18);
- PUTBITS( planar_word2, GV, 7, 12);
- PUTBITS( planar_word2, BV, 6, 5);
- // Make sure that red does not overflow:
- bit = GETBITSHIGH( planar_word1, 1, 62);
- PUTBITSHIGH( planar_word1, !bit, 1, 63);
- // Make sure that green does not overflow:
- bit = GETBITSHIGH( planar_word1, 1, 54);
- PUTBITSHIGH( planar_word1, !bit, 1, 55);
- // Make sure that blue overflows:
- a = GETBITSHIGH( planar_word1, 1, 44);
- b = GETBITSHIGH( planar_word1, 1, 43);
- c = GETBITSHIGH( planar_word1, 1, 41);
- d = GETBITSHIGH( planar_word1, 1, 40);
- // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
- // The following logical expression checks for the presence of any of those:
- bit = (a & c) | (!a & b & c & d) | (a & b & !c & d);
- bits = 0xf*bit;
- PUTBITSHIGH( planar_word1, bits, 3, 47);
- PUTBITSHIGH( planar_word1, !bit, 1, 42);
- // Set diffbit
- PUTBITSHIGH( planar_word1, 1, 1, 33);
- }
- // During search it is not convenient to store the bits the way they are stored in the
- // file format. Hence, after search, it is converted to this format.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void stuff58bits(unsigned int thumbH58_word1, unsigned int thumbH58_word2, unsigned int &thumbH_word1, unsigned int &thumbH_word2)
- {
- // Put bits in twotimer configuration for 58 (red doesn't overflow, green does)
- //
- // Go from this bit layout:
- //
- //
- // |63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- // |-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- // |---------------------------------------index bits----------------------------------------------|
- //
- // To this:
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // |//|R0 |G0 |// // //|G0|B0|//|B0b |R1 |G1 |B0 |d2|df|d1|
- // -----------------------------------------------------------------------------------------------
- //
- // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- // |---------------------------------------index bits----------------------------------------------|
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt|
- // -----------------------------------------------------------------------------------------------
- //
- //
- // Thus, what we are really doing is going from this bit layout:
- //
- //
- // |63 62 61 60 59 58|57 56 55 54 53 52 51|50 49|48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33|32 |
- // |-------empty-----|part0---------------|part1|part2------------------------------------------|part3|
- //
- // To this:
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // --------------------------------------------------------------------------------------------------|
- // |//|part0 |// // //|part1|//|part2 |df|part3|
- // --------------------------------------------------------------------------------------------------|
- unsigned int part0, part1, part2, part3;
- uint8 bit, a, b, c, d, bits;
- // move parts
- part0 = GETBITSHIGH( thumbH58_word1, 7, 57);
- part1 = GETBITSHIGH( thumbH58_word1, 2, 50);
- part2 = GETBITSHIGH( thumbH58_word1,16, 48);
- part3 = GETBITSHIGH( thumbH58_word1, 1, 32);
- thumbH_word1 = 0;
- PUTBITSHIGH( thumbH_word1, part0, 7, 62);
- PUTBITSHIGH( thumbH_word1, part1, 2, 52);
- PUTBITSHIGH( thumbH_word1, part2, 16, 49);
- PUTBITSHIGH( thumbH_word1, part3, 1, 32);
- // Make sure that red does not overflow:
- bit = GETBITSHIGH( thumbH_word1, 1, 62);
- PUTBITSHIGH( thumbH_word1, !bit, 1, 63);
- // Make sure that green overflows:
- a = GETBITSHIGH( thumbH_word1, 1, 52);
- b = GETBITSHIGH( thumbH_word1, 1, 51);
- c = GETBITSHIGH( thumbH_word1, 1, 49);
- d = GETBITSHIGH( thumbH_word1, 1, 48);
- // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
- // The following logical expression checks for the presence of any of those:
- bit = (a & c) | (!a & b & c & d) | (a & b & !c & d);
- bits = 0xf*bit;
- PUTBITSHIGH( thumbH_word1, bits, 3, 55);
- PUTBITSHIGH( thumbH_word1, !bit, 1, 50);
- // Set diffbit
- PUTBITSHIGH( thumbH_word1, 1, 1, 33);
- thumbH_word2 = thumbH58_word2;
- }
- // copy of above, but diffbit is 0
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void stuff58bitsDiffFalse(unsigned int thumbH58_word1, unsigned int thumbH58_word2, unsigned int &thumbH_word1, unsigned int &thumbH_word2)
- {
- unsigned int part0, part1, part2, part3;
- uint8 bit, a, b, c, d, bits;
- // move parts
- part0 = GETBITSHIGH( thumbH58_word1, 7, 57);
- part1 = GETBITSHIGH( thumbH58_word1, 2, 50);
- part2 = GETBITSHIGH( thumbH58_word1,16, 48);
- part3 = GETBITSHIGH( thumbH58_word1, 1, 32);
- thumbH_word1 = 0;
- PUTBITSHIGH( thumbH_word1, part0, 7, 62);
- PUTBITSHIGH( thumbH_word1, part1, 2, 52);
- PUTBITSHIGH( thumbH_word1, part2, 16, 49);
- PUTBITSHIGH( thumbH_word1, part3, 1, 32);
- // Make sure that red does not overflow:
- bit = GETBITSHIGH( thumbH_word1, 1, 62);
- PUTBITSHIGH( thumbH_word1, !bit, 1, 63);
- // Make sure that green overflows:
- a = GETBITSHIGH( thumbH_word1, 1, 52);
- b = GETBITSHIGH( thumbH_word1, 1, 51);
- c = GETBITSHIGH( thumbH_word1, 1, 49);
- d = GETBITSHIGH( thumbH_word1, 1, 48);
- // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
- // The following logical expression checks for the presence of any of those:
- bit = (a & c) | (!a & b & c & d) | (a & b & !c & d);
- bits = 0xf*bit;
- PUTBITSHIGH( thumbH_word1, bits, 3, 55);
- PUTBITSHIGH( thumbH_word1, !bit, 1, 50);
- // Set diffbit
- PUTBITSHIGH( thumbH_word1, 0, 1, 33);
- thumbH_word2 = thumbH58_word2;
- }
- // During search it is not convenient to store the bits the way they are stored in the
- // file format. Hence, after search, it is converted to this format.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void stuff59bits(unsigned int thumbT59_word1, unsigned int thumbT59_word2, unsigned int &thumbT_word1, unsigned int &thumbT_word2)
- {
- // Put bits in twotimer configuration for 59 (red overflows)
- //
- // Go from this bit layout:
- //
- // |63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- // |----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- // |----------------------------------------index bits---------------------------------------------|
- //
- //
- // To this:
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // |// // //|R0a |//|R0b |G0 |B0 |R1 |G1 |B1 |da |df|db|
- // -----------------------------------------------------------------------------------------------
- //
- // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- // |----------------------------------------index bits---------------------------------------------|
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt|
- // ------------------------------------------------------------------------------------------------
- uint8 R0a;
- uint8 bit, a, b, c, d, bits;
- R0a = GETBITSHIGH( thumbT59_word1, 2, 58);
- // Fix middle part
- thumbT_word1 = thumbT59_word1 << 1;
- // Fix R0a (top two bits of R0)
- PUTBITSHIGH( thumbT_word1, R0a, 2, 60);
- // Fix db (lowest bit of d)
- PUTBITSHIGH( thumbT_word1, thumbT59_word1, 1, 32);
- //
- // Make sure that red overflows:
- a = GETBITSHIGH( thumbT_word1, 1, 60);
- b = GETBITSHIGH( thumbT_word1, 1, 59);
- c = GETBITSHIGH( thumbT_word1, 1, 57);
- d = GETBITSHIGH( thumbT_word1, 1, 56);
- // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
- // The following logical expression checks for the presence of any of those:
- bit = (a & c) | (!a & b & c & d) | (a & b & !c & d);
- bits = 0xf*bit;
- PUTBITSHIGH( thumbT_word1, bits, 3, 63);
- PUTBITSHIGH( thumbT_word1, !bit, 1, 58);
- // Set diffbit
- PUTBITSHIGH( thumbT_word1, 1, 1, 33);
- thumbT_word2 = thumbT59_word2;
- }
- // Decompress the planar mode and calculate the error per component compared to original image.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void decompressBlockPlanar57errorPerComponent(unsigned int compressed57_1, unsigned int compressed57_2, uint8 *img,int width,int height,int startx,int starty, uint8 *srcimg, unsigned int &error_red, unsigned int &error_green, unsigned int &error_blue)
- {
- uint8 colorO[3], colorH[3], colorV[3];
- colorO[0] = GETBITSHIGH( compressed57_1, 6, 63);
- colorO[1] = GETBITSHIGH( compressed57_1, 7, 57);
- colorO[2] = GETBITSHIGH( compressed57_1, 6, 50);
- colorH[0] = GETBITSHIGH( compressed57_1, 6, 44);
- colorH[1] = GETBITSHIGH( compressed57_1, 7, 38);
- colorH[2] = GETBITS( compressed57_2, 6, 31);
- colorV[0] = GETBITS( compressed57_2, 6, 25);
- colorV[1] = GETBITS( compressed57_2, 7, 19);
- colorV[2] = GETBITS( compressed57_2, 6, 12);
- colorO[0] = (colorO[0] << 2) | (colorO[0] >> 4);
- colorO[1] = (colorO[1] << 1) | (colorO[1] >> 6);
- colorO[2] = (colorO[2] << 2) | (colorO[2] >> 4);
- colorH[0] = (colorH[0] << 2) | (colorH[0] >> 4);
- colorH[1] = (colorH[1] << 1) | (colorH[1] >> 6);
- colorH[2] = (colorH[2] << 2) | (colorH[2] >> 4);
- colorV[0] = (colorV[0] << 2) | (colorV[0] >> 4);
- colorV[1] = (colorV[1] << 1) | (colorV[1] >> 6);
- colorV[2] = (colorV[2] << 2) | (colorV[2] >> 4);
-
- int xx, yy;
- for( xx=0; xx<4; xx++)
- {
- for( yy=0; yy<4; yy++)
- {
- img[3*width*(starty+yy) + 3*(startx+xx) + 0] = (int)CLAMP(0, JAS_ROUND((xx*(colorH[0]-colorO[0])/4.0 + yy*(colorV[0]-colorO[0])/4.0 + colorO[0])), 255);
- img[3*width*(starty+yy) + 3*(startx+xx) + 1] = (int)CLAMP(0, JAS_ROUND((xx*(colorH[1]-colorO[1])/4.0 + yy*(colorV[1]-colorO[1])/4.0 + colorO[1])), 255);
- img[3*width*(starty+yy) + 3*(startx+xx) + 2] = (int)CLAMP(0, JAS_ROUND((xx*(colorH[2]-colorO[2])/4.0 + yy*(colorV[2]-colorO[2])/4.0 + colorO[2])), 255);
- }
- }
- error_red = 0;
- error_green= 0;
- error_blue = 0;
- for( xx=0; xx<4; xx++)
- {
- for( yy=0; yy<4; yy++)
- {
- error_red = error_red + SQUARE(srcimg[3*width*(starty+yy) + 3*(startx+xx) + 0] - img[3*width*(starty+yy) + 3*(startx+xx) + 0]);
- error_green = error_green + SQUARE(srcimg[3*width*(starty+yy) + 3*(startx+xx) + 1] - img[3*width*(starty+yy) + 3*(startx+xx) + 1]);
- error_blue = error_blue + SQUARE(srcimg[3*width*(starty+yy) + 3*(startx+xx) + 2] - img[3*width*(starty+yy) + 3*(startx+xx) + 2]);
- }
- }
- }
- // Compress using both individual and differential mode in ETC1/ETC2 using combined color
- // quantization. Both flip modes are tried.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockDiffFlipCombined(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int min_error=255*255*8*3;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- float eps;
- uint8 dummy[3];
- quantize555ColorCombined(avg_color_float1, enc_color1, dummy);
- quantize555ColorCombined(avg_color_float2, enc_color2, dummy);
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_norm, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_norm, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_norm, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- norm_err = 0;
- // left part of block
- norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- uint8 dummy[3];
- quantize444ColorCombined(avg_color_float1, enc_color1, dummy);
- quantize444ColorCombined(avg_color_float2, enc_color2, dummy);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
-
- // Pack bits into the first word.
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // left part of block
- norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- quantize555ColorCombined(avg_color_float1, enc_color1, dummy);
- quantize555ColorCombined(avg_color_float2, enc_color2, dummy);
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_flip, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_flip, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_flip, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- uint8 dummy[3];
- quantize444ColorCombined(avg_color_float1, enc_color1, dummy);
- quantize444ColorCombined(avg_color_float2, enc_color2, dummy);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- // Now lets see which is the best table to use. Only 8 tables are possible.
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- }
- }
- // Calculation of the two block colors using the LBG-algorithm
- // The following method scales down the intensity, since this can be compensated for anyway by both the H and T mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeColorLBGHalfIntensityFast(uint8 *img,int width,int startx,int starty, uint8 (LBG_colors)[2][3])
- {
- uint8 block_mask[4][4];
- // reset rand so that we get predictable output per block
- srand(10000);
- //LBG-algorithm
- double D = 0, oldD, bestD = MAXIMUM_ERROR, eps = 0.0000000001;
- double error_a, error_b;
- int number_of_iterations = 10;
- double t_color[2][3];
- double original_colors[4][4][3];
- double current_colors[2][3];
- double best_colors[2][3];
- double max_v[3];
- double min_v[3];
- int x,y,i;
- double red, green, blue;
- bool continue_seeding;
- int maximum_number_of_seedings = 10;
- int seeding;
- bool continue_iterate;
- max_v[R] = -512.0; max_v[G] = -512.0; max_v[B] = -512.0;
- min_v[R] = 512.0; min_v[G] = 512.0; min_v[B] = 512.0;
- // resolve trainingdata
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (x = 0; x < BLOCKWIDTH; ++x)
- {
- red = img[3*((starty+y)*width+startx+x)+R];
- green = img[3*((starty+y)*width+startx+x)+G];
- blue = img[3*((starty+y)*width+startx+x)+B];
- // Use qrs representation instead of rgb
- // qrs = Q * rgb where Q = [a a a ; b -b 0 ; c c -2c]; a = 1/sqrt(3), b= 1/sqrt(2), c = 1/sqrt(6);
- // rgb = inv(Q)*qrs = Q' * qrs where ' denotes transpose.
- // The q variable holds intensity. r and s hold chrominance.
- // q = [0, sqrt(3)*255], r = [-255/sqrt(2), 255/sqrt(2)], s = [-2*255/sqrt(6), 2*255/sqrt(6)];
- //
- // The LGB algorithm will only act on the r and s variables and not on q.
- //
- original_colors[x][y][R] = (1.0/sqrt(1.0*3))*red + (1.0/sqrt(1.0*3))*green + (1.0/sqrt(1.0*3))*blue;
- original_colors[x][y][G] = (1.0/sqrt(1.0*2))*red - (1.0/sqrt(1.0*2))*green;
- original_colors[x][y][B] = (1.0/sqrt(1.0*6))*red + (1.0/sqrt(1.0*6))*green - (2.0/sqrt(1.0*6))*blue;
-
- // find max
- if (original_colors[x][y][R] > max_v[R]) max_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] > max_v[G]) max_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] > max_v[B]) max_v[B] = original_colors[x][y][B];
- // find min
- if (original_colors[x][y][R] < min_v[R]) min_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] < min_v[G]) min_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] < min_v[B]) min_v[B] = original_colors[x][y][B];
- }
- }
- D = 512*512*3*16.0;
- bestD = 512*512*3*16.0;
- continue_seeding = true;
- // loop seeds
- for (seeding = 0; (seeding < maximum_number_of_seedings) && continue_seeding; seeding++)
- {
- // hopefully we will not need more seedings:
- continue_seeding = false;
- // calculate seeds
- for (uint8 s = 0; s < 2; ++s)
- {
- for (uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = double((double(rand())/RAND_MAX)*(max_v[c]-min_v[c])) + min_v[c];
- }
- }
-
- // divide into two quantization sets and calculate distortion
- continue_iterate = true;
- for(i = 0; (i < number_of_iterations) && continue_iterate; i++)
- {
- oldD = D;
- D = 0;
- int n = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- error_a = 0.5*SQUARE(original_colors[x][y][R] - current_colors[0][R]) +
- SQUARE(original_colors[x][y][G] - current_colors[0][G]) +
- SQUARE(original_colors[x][y][B] - current_colors[0][B]);
- error_b = 0.5*SQUARE(original_colors[x][y][R] - current_colors[1][R]) +
- SQUARE(original_colors[x][y][G] - current_colors[1][G]) +
- SQUARE(original_colors[x][y][B] - current_colors[1][B]);
- if (error_a < error_b)
- {
- block_mask[x][y] = 0;
- D += error_a;
- ++n;
- }
- else
- {
- block_mask[x][y] = 1;
- D += error_b;
- }
- }
- }
- // compare with old distortion
- if (D == 0)
- {
- // Perfect score -- we dont need to go further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D == oldD)
- {
- // Same score as last round -- no need to go for further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D < bestD)
- {
- bestD = D;
- for(uint8 s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- best_colors[s][c] = current_colors[s][c];
- }
- }
- }
- if (n == 0 || n == BLOCKWIDTH*BLOCKHEIGHT)
- {
- // All colors end up in the same voroni region. We need to reseed.
- continue_iterate = false;
- continue_seeding = true;
- }
- else
- {
- // Calculate new reconstruction points using the centroids
- // Find new construction values from average
- t_color[0][R] = 0;
- t_color[0][G] = 0;
- t_color[0][B] = 0;
- t_color[1][R] = 0;
- t_color[1][G] = 0;
- t_color[1][B] = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- // use dummy value for q-parameter
- t_color[block_mask[x][y]][R] += original_colors[x][y][R];
- t_color[block_mask[x][y]][G] += original_colors[x][y][G];
- t_color[block_mask[x][y]][B] += original_colors[x][y][B];
- }
- }
- current_colors[0][R] = t_color[0][R] / n;
- current_colors[1][R] = t_color[1][R] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][G] = t_color[0][G] / n;
- current_colors[1][G] = t_color[1][G] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][B] = t_color[0][B] / n;
- current_colors[1][B] = t_color[1][B] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- }
- }
- }
- for(x=0;x<2;x++)
- {
- double qq, rr, ss;
- qq = best_colors[x][0];
- rr = best_colors[x][1];
- ss = best_colors[x][2];
- current_colors[x][0] = CLAMP(0, (1.0/sqrt(1.0*3))*qq + (1.0/sqrt(1.0*2))*rr + (1.0/sqrt(1.0*6))*ss, 255);
- current_colors[x][1] = CLAMP(0, (1.0/sqrt(1.0*3))*qq - (1.0/sqrt(1.0*2))*rr + (1.0/sqrt(1.0*6))*ss, 255);
- current_colors[x][2] = CLAMP(0, (1.0/sqrt(1.0*3))*qq + (0.0 )*rr - (2.0/sqrt(1.0*6))*ss, 255);
- }
- for(x=0;x<2;x++)
- for(y=0;y<3;y++)
- LBG_colors[x][y] = JAS_ROUND(current_colors[x][y]);
- }
- // Calculation of the two block colors using the LBG-algorithm
- // The following method scales down the intensity, since this can be compensated for anyway by both the H and T mode.
- // Faster version
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeColorLBGNotIntensityFast(uint8 *img,int width,int startx,int starty, uint8 (LBG_colors)[2][3])
- {
- uint8 block_mask[4][4];
- // reset rand so that we get predictable output per block
- srand(10000);
- //LBG-algorithm
- double D = 0, oldD, bestD = MAXIMUM_ERROR, eps = 0.0000000001;
- double error_a, error_b;
- int number_of_iterations = 10;
- double t_color[2][3];
- double original_colors[4][4][3];
- double current_colors[2][3];
- double best_colors[2][3];
- double max_v[3];
- double min_v[3];
- int x,y,i;
- double red, green, blue;
- bool continue_seeding;
- int maximum_number_of_seedings = 10;
- int seeding;
- bool continue_iterate;
- max_v[R] = -512.0; max_v[G] = -512.0; max_v[B] = -512.0;
- min_v[R] = 512.0; min_v[G] = 512.0; min_v[B] = 512.0;
- // resolve trainingdata
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (x = 0; x < BLOCKWIDTH; ++x)
- {
- red = img[3*((starty+y)*width+startx+x)+R];
- green = img[3*((starty+y)*width+startx+x)+G];
- blue = img[3*((starty+y)*width+startx+x)+B];
- // Use qrs representation instead of rgb
- // qrs = Q * rgb where Q = [a a a ; b -b 0 ; c c -2c]; a = 1/sqrt(1.0*3), b= 1/sqrt(1.0*2), c = 1/sqrt(1.0*6);
- // rgb = inv(Q)*qrs = Q' * qrs where ' denotes transpose.
- // The q variable holds intensity. r and s hold chrominance.
- // q = [0, sqrt(1.0*3)*255], r = [-255/sqrt(1.0*2), 255/sqrt(1.0*2)], s = [-2*255/sqrt(1.0*6), 2*255/sqrt(1.0*6)];
- //
- // The LGB algorithm will only act on the r and s variables and not on q.
- //
- original_colors[x][y][R] = (1.0/sqrt(1.0*3))*red + (1.0/sqrt(1.0*3))*green + (1.0/sqrt(1.0*3))*blue;
- original_colors[x][y][G] = (1.0/sqrt(1.0*2))*red - (1.0/sqrt(1.0*2))*green;
- original_colors[x][y][B] = (1.0/sqrt(1.0*6))*red + (1.0/sqrt(1.0*6))*green - (2.0/sqrt(1.0*6))*blue;
-
- // find max
- if (original_colors[x][y][R] > max_v[R]) max_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] > max_v[G]) max_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] > max_v[B]) max_v[B] = original_colors[x][y][B];
- // find min
- if (original_colors[x][y][R] < min_v[R]) min_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] < min_v[G]) min_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] < min_v[B]) min_v[B] = original_colors[x][y][B];
- }
- }
- D = 512*512*3*16.0;
- bestD = 512*512*3*16.0;
- continue_seeding = true;
- // loop seeds
- for (seeding = 0; (seeding < maximum_number_of_seedings) && continue_seeding; seeding++)
- {
- // hopefully we will not need more seedings:
- continue_seeding = false;
- // calculate seeds
- for (uint8 s = 0; s < 2; ++s)
- {
- for (uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = double((double(rand())/RAND_MAX)*(max_v[c]-min_v[c])) + min_v[c];
- }
- }
- // divide into two quantization sets and calculate distortion
- continue_iterate = true;
- for(i = 0; (i < number_of_iterations) && continue_iterate; i++)
- {
- oldD = D;
- D = 0;
- int n = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- error_a = 0.0*SQUARE(original_colors[x][y][R] - current_colors[0][R]) +
- SQUARE(original_colors[x][y][G] - current_colors[0][G]) +
- SQUARE(original_colors[x][y][B] - current_colors[0][B]);
- error_b = 0.0*SQUARE(original_colors[x][y][R] - current_colors[1][R]) +
- SQUARE(original_colors[x][y][G] - current_colors[1][G]) +
- SQUARE(original_colors[x][y][B] - current_colors[1][B]);
- if (error_a < error_b)
- {
- block_mask[x][y] = 0;
- D += error_a;
- ++n;
- }
- else
- {
- block_mask[x][y] = 1;
- D += error_b;
- }
- }
- }
- // compare with old distortion
- if (D == 0)
- {
- // Perfect score -- we dont need to go further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D == oldD)
- {
- // Same score as last round -- no need to go for further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D < bestD)
- {
- bestD = D;
- for(uint8 s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- best_colors[s][c] = current_colors[s][c];
- }
- }
- }
- if (n == 0 || n == BLOCKWIDTH*BLOCKHEIGHT)
- {
- // All colors end up in the same voroni region. We need to reseed.
- continue_iterate = false;
- continue_seeding = true;
- }
- else
- {
- // Calculate new reconstruction points using the centroids
- // Find new construction values from average
- t_color[0][R] = 0;
- t_color[0][G] = 0;
- t_color[0][B] = 0;
- t_color[1][R] = 0;
- t_color[1][G] = 0;
- t_color[1][B] = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- // use dummy value for q-parameter
- t_color[block_mask[x][y]][R] += original_colors[x][y][R];
- t_color[block_mask[x][y]][G] += original_colors[x][y][G];
- t_color[block_mask[x][y]][B] += original_colors[x][y][B];
- }
- }
- current_colors[0][R] = t_color[0][R] / n;
- current_colors[1][R] = t_color[1][R] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][G] = t_color[0][G] / n;
- current_colors[1][G] = t_color[1][G] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][B] = t_color[0][B] / n;
- current_colors[1][B] = t_color[1][B] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- }
- }
- }
- for(x=0;x<2;x++)
- {
- double qq, rr, ss;
- qq = best_colors[x][0];
- rr = best_colors[x][1];
- ss = best_colors[x][2];
- current_colors[x][0] = CLAMP(0, (1.0/sqrt(1.0*3))*qq + (1.0/sqrt(1.0*2))*rr + (1.0/sqrt(1.0*6))*ss, 255);
- current_colors[x][1] = CLAMP(0, (1.0/sqrt(1.0*3))*qq - (1.0/sqrt(1.0*2))*rr + (1.0/sqrt(1.0*6))*ss, 255);
- current_colors[x][2] = CLAMP(0, (1.0/sqrt(1.0*3))*qq + (0.0 )*rr - (2.0/sqrt(1.0*6))*ss, 255);
- }
- for(x=0;x<2;x++)
- for(y=0;y<3;y++)
- LBG_colors[x][y] = JAS_ROUND(current_colors[x][y]);
- }
- // Calculation of the two block colors using the LBG-algorithm
- // The following method completely ignores the intensity, since this can be compensated for anyway by both the H and T mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeColorLBGNotIntensity(uint8 *img,int width,int startx,int starty, uint8 (LBG_colors)[2][3])
- {
- uint8 block_mask[4][4];
- // reset rand so that we get predictable output per block
- srand(10000);
- //LBG-algorithm
- double D = 0, oldD, bestD = MAXIMUM_ERROR, eps = 0.0000000001;
- double error_a, error_b;
- int number_of_iterations = 10;
- double t_color[2][3];
- double original_colors[4][4][3];
- double current_colors[2][3];
- double best_colors[2][3];
- double max_v[3];
- double min_v[3];
- int x,y,i;
- double red, green, blue;
- bool continue_seeding;
- int maximum_number_of_seedings = 10;
- int seeding;
- bool continue_iterate;
- max_v[R] = -512.0; max_v[G] = -512.0; max_v[B] = -512.0;
- min_v[R] = 512.0; min_v[G] = 512.0; min_v[B] = 512.0;
- // resolve trainingdata
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (x = 0; x < BLOCKWIDTH; ++x)
- {
- red = img[3*((starty+y)*width+startx+x)+R];
- green = img[3*((starty+y)*width+startx+x)+G];
- blue = img[3*((starty+y)*width+startx+x)+B];
- // Use qrs representation instead of rgb
- // qrs = Q * rgb where Q = [a a a ; b -b 0 ; c c -2c]; a = 1/sqrt(1.0*3), b= 1/sqrt(1.0*2), c = 1/sqrt(1.0*6);
- // rgb = inv(Q)*qrs = Q' * qrs where ' denotes transpose.
- // The q variable holds intensity. r and s hold chrominance.
- // q = [0, sqrt(1.0*3)*255], r = [-255/sqrt(1.0*2), 255/sqrt(1.0*2)], s = [-2*255/sqrt(1.0*6), 2*255/sqrt(1.0*6)];
- //
- // The LGB algorithm will only act on the r and s variables and not on q.
- //
- original_colors[x][y][R] = (1.0/sqrt(1.0*3))*red + (1.0/sqrt(1.0*3))*green + (1.0/sqrt(1.0*3))*blue;
- original_colors[x][y][G] = (1.0/sqrt(1.0*2))*red - (1.0/sqrt(1.0*2))*green;
- original_colors[x][y][B] = (1.0/sqrt(1.0*6))*red + (1.0/sqrt(1.0*6))*green - (2.0/sqrt(1.0*6))*blue;
- // find max
- if (original_colors[x][y][R] > max_v[R]) max_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] > max_v[G]) max_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] > max_v[B]) max_v[B] = original_colors[x][y][B];
- // find min
- if (original_colors[x][y][R] < min_v[R]) min_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] < min_v[G]) min_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] < min_v[B]) min_v[B] = original_colors[x][y][B];
- }
- }
- D = 512*512*3*16.0;
- bestD = 512*512*3*16.0;
- continue_seeding = true;
- // loop seeds
- for (seeding = 0; (seeding < maximum_number_of_seedings) && continue_seeding; seeding++)
- {
- // hopefully we will not need more seedings:
- continue_seeding = false;
- // calculate seeds
- for (uint8 s = 0; s < 2; ++s)
- {
- for (uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = double((double(rand())/RAND_MAX)*(max_v[c]-min_v[c])) + min_v[c];
- }
- }
-
- // divide into two quantization sets and calculate distortion
- continue_iterate = true;
- for(i = 0; (i < number_of_iterations) && continue_iterate; i++)
- {
- oldD = D;
- D = 0;
- int n = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- error_a = 0.0*SQUARE(original_colors[x][y][R] - current_colors[0][R]) +
- SQUARE(original_colors[x][y][G] - current_colors[0][G]) +
- SQUARE(original_colors[x][y][B] - current_colors[0][B]);
- error_b = 0.0*SQUARE(original_colors[x][y][R] - current_colors[1][R]) +
- SQUARE(original_colors[x][y][G] - current_colors[1][G]) +
- SQUARE(original_colors[x][y][B] - current_colors[1][B]);
- if (error_a < error_b)
- {
- block_mask[x][y] = 0;
- D += error_a;
- ++n;
- }
- else
- {
- block_mask[x][y] = 1;
- D += error_b;
- }
- }
- }
- // compare with old distortion
- if (D == 0)
- {
- // Perfect score -- we dont need to go further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D == oldD)
- {
- // Same score as last round -- no need to go for further iterations.
- continue_iterate = false;
- continue_seeding = true;
- }
- if (D < bestD)
- {
- bestD = D;
- for(uint8 s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- best_colors[s][c] = current_colors[s][c];
- }
- }
- }
- if (n == 0 || n == BLOCKWIDTH*BLOCKHEIGHT)
- {
- // All colors end up in the same voroni region. We need to reseed.
- continue_iterate = false;
- continue_seeding = true;
- }
- else
- {
- // Calculate new reconstruction points using the centroids
- // Find new construction values from average
- t_color[0][R] = 0;
- t_color[0][G] = 0;
- t_color[0][B] = 0;
- t_color[1][R] = 0;
- t_color[1][G] = 0;
- t_color[1][B] = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- // use dummy value for q-parameter
- t_color[block_mask[x][y]][R] += original_colors[x][y][R];
- t_color[block_mask[x][y]][G] += original_colors[x][y][G];
- t_color[block_mask[x][y]][B] += original_colors[x][y][B];
- }
- }
- current_colors[0][R] = t_color[0][R] / n;
- current_colors[1][R] = t_color[1][R] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][G] = t_color[0][G] / n;
- current_colors[1][G] = t_color[1][G] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][B] = t_color[0][B] / n;
- current_colors[1][B] = t_color[1][B] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- }
- }
- }
- for(x=0;x<2;x++)
- {
- double qq, rr, ss;
- qq = best_colors[x][0];
- rr = best_colors[x][1];
- ss = best_colors[x][2];
- current_colors[x][0] = CLAMP(0, (1.0/sqrt(1.0*3))*qq + (1.0/sqrt(1.0*2))*rr + (1.0/sqrt(1.0*6))*ss, 255);
- current_colors[x][1] = CLAMP(0, (1.0/sqrt(1.0*3))*qq - (1.0/sqrt(1.0*2))*rr + (1.0/sqrt(1.0*6))*ss, 255);
- current_colors[x][2] = CLAMP(0, (1.0/sqrt(1.0*3))*qq + (0.0 )*rr - (2.0/sqrt(1.0*6))*ss, 255);
- }
- for(x=0;x<2;x++)
- for(y=0;y<3;y++)
- LBG_colors[x][y] = JAS_ROUND(current_colors[x][y]);
- }
- // Calculation of the two block colors using the LBG-algorithm
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeColorLBG(uint8 *img,int width,int startx,int starty, uint8 (LBG_colors)[2][3])
- {
- uint8 block_mask[4][4];
- // reset rand so that we get predictable output per block
- srand(10000);
- //LBG-algorithm
- double D = 0, oldD, bestD = MAXIMUM_ERROR, eps = 0.0000000001;
- double error_a, error_b;
- int number_of_iterations = 10;
- double t_color[2][3];
- double original_colors[4][4][3];
- double current_colors[2][3];
- double best_colors[2][3];
- double max_v[3];
- double min_v[3];
- int x,y,i;
- double red, green, blue;
- bool continue_seeding;
- int maximum_number_of_seedings = 10;
- int seeding;
- bool continue_iterate;
- max_v[R] = -512.0; max_v[G] = -512.0; max_v[B] = -512.0;
- min_v[R] = 512.0; min_v[G] = 512.0; min_v[B] = 512.0;
- // resolve trainingdata
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (x = 0; x < BLOCKWIDTH; ++x)
- {
- red = img[3*((starty+y)*width+startx+x)+R];
- green = img[3*((starty+y)*width+startx+x)+G];
- blue = img[3*((starty+y)*width+startx+x)+B];
- original_colors[x][y][R] = red;
- original_colors[x][y][G] = green;
- original_colors[x][y][B] = blue;
- // find max
- if (original_colors[x][y][R] > max_v[R]) max_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] > max_v[G]) max_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] > max_v[B]) max_v[B] = original_colors[x][y][B];
- // find min
- if (original_colors[x][y][R] < min_v[R]) min_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] < min_v[G]) min_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] < min_v[B]) min_v[B] = original_colors[x][y][B];
- }
- }
- D = 512*512*3*16.0;
- bestD = 512*512*3*16.0;
- continue_seeding = true;
- // loop seeds
- for (seeding = 0; (seeding < maximum_number_of_seedings) && continue_seeding; seeding++)
- {
- // hopefully we will not need more seedings:
- continue_seeding = false;
- // calculate seeds
- for (uint8 s = 0; s < 2; ++s)
- {
- for (uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = double((double(rand())/RAND_MAX)*(max_v[c]-min_v[c])) + min_v[c];
- }
- }
-
- // divide into two quantization sets and calculate distortion
- continue_iterate = true;
- for(i = 0; (i < number_of_iterations) && continue_iterate; i++)
- {
- oldD = D;
- D = 0;
- int n = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- error_a = SQUARE(original_colors[x][y][R] - JAS_ROUND(current_colors[0][R])) +
- SQUARE(original_colors[x][y][G] - JAS_ROUND(current_colors[0][G])) +
- SQUARE(original_colors[x][y][B] - JAS_ROUND(current_colors[0][B]));
- error_b = SQUARE(original_colors[x][y][R] - JAS_ROUND(current_colors[1][R])) +
- SQUARE(original_colors[x][y][G] - JAS_ROUND(current_colors[1][G])) +
- SQUARE(original_colors[x][y][B] - JAS_ROUND(current_colors[1][B]));
- if (error_a < error_b)
- {
- block_mask[x][y] = 0;
- D += error_a;
- ++n;
- }
- else
- {
- block_mask[x][y] = 1;
- D += error_b;
- }
- }
- }
- // compare with old distortion
- if (D == 0)
- {
- // Perfect score -- we dont need to go further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D == oldD)
- {
- // Same score as last round -- no need to go for further iterations.
- continue_iterate = false;
- continue_seeding = true;
- }
- if (D < bestD)
- {
- bestD = D;
- for(uint8 s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- best_colors[s][c] = current_colors[s][c];
- }
- }
- }
- if (n == 0 || n == BLOCKWIDTH*BLOCKHEIGHT)
- {
- // All colors end up in the same voroni region. We need to reseed.
- continue_iterate = false;
- continue_seeding = true;
- }
- else
- {
- // Calculate new reconstruction points using the centroids
- // Find new construction values from average
- t_color[0][R] = 0;
- t_color[0][G] = 0;
- t_color[0][B] = 0;
- t_color[1][R] = 0;
- t_color[1][G] = 0;
- t_color[1][B] = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- // use dummy value for q-parameter
- t_color[block_mask[x][y]][R] += original_colors[x][y][R];
- t_color[block_mask[x][y]][G] += original_colors[x][y][G];
- t_color[block_mask[x][y]][B] += original_colors[x][y][B];
- }
- }
- current_colors[0][R] = t_color[0][R] / n;
- current_colors[1][R] = t_color[1][R] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][G] = t_color[0][G] / n;
- current_colors[1][G] = t_color[1][G] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][B] = t_color[0][B] / n;
- current_colors[1][B] = t_color[1][B] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- }
- }
- }
- // Set the best colors as the final block colors
- for(int s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = best_colors[s][c];
- }
- }
- for(x=0;x<2;x++)
- for(y=0;y<3;y++)
- LBG_colors[x][y] = JAS_ROUND(current_colors[x][y]);
- }
- // Calculation of the two block colors using the LBG-algorithm
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void computeColorLBGfast(uint8 *img,int width,int startx,int starty, uint8 (LBG_colors)[2][3])
- {
- uint8 block_mask[4][4];
- // reset rand so that we get predictable output per block
- srand(10000);
- //LBG-algorithm
- double D = 0, oldD, bestD = MAXIMUM_ERROR, eps = 0.0000000001;
- double error_a, error_b;
- int number_of_iterations = 10;
- double t_color[2][3];
- uint8 original_colors[4][4][3];
- double current_colors[2][3];
- double best_colors[2][3];
- double max_v[3];
- double min_v[3];
- int x,y,i;
- bool continue_seeding;
- int maximum_number_of_seedings = 10;
- int seeding;
- bool continue_iterate;
- max_v[R] = -512.0; max_v[G] = -512.0; max_v[B] = -512.0;
- min_v[R] = 512.0; min_v[G] = 512.0; min_v[B] = 512.0;
- // resolve trainingdata
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (x = 0; x < BLOCKWIDTH; ++x)
- {
- original_colors[x][y][R] = img[3*((starty+y)*width+startx+x)+R];
- original_colors[x][y][G] = img[3*((starty+y)*width+startx+x)+G];
- original_colors[x][y][B] = img[3*((starty+y)*width+startx+x)+B];
-
- // find max
- if (original_colors[x][y][R] > max_v[R]) max_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] > max_v[G]) max_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] > max_v[B]) max_v[B] = original_colors[x][y][B];
- // find min
- if (original_colors[x][y][R] < min_v[R]) min_v[R] = original_colors[x][y][R];
- if (original_colors[x][y][G] < min_v[G]) min_v[G] = original_colors[x][y][G];
- if (original_colors[x][y][B] < min_v[B]) min_v[B] = original_colors[x][y][B];
- }
- }
- D = 512*512*3*16.0;
- bestD = 512*512*3*16.0;
- continue_seeding = true;
- // loop seeds
- for (seeding = 0; (seeding < maximum_number_of_seedings) && continue_seeding; seeding++)
- {
- // hopefully we will not need more seedings:
- continue_seeding = false;
- // calculate seeds
- for (uint8 s = 0; s < 2; ++s)
- {
- for (uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = double((double(rand())/RAND_MAX)*(max_v[c]-min_v[c])) + min_v[c];
- }
- }
-
- // divide into two quantization sets and calculate distortion
- continue_iterate = true;
- for(i = 0; (i < number_of_iterations) && continue_iterate; i++)
- {
- oldD = D;
- D = 0;
- int n = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- error_a = SQUARE(original_colors[x][y][R] - JAS_ROUND(current_colors[0][R])) +
- SQUARE(original_colors[x][y][G] - JAS_ROUND(current_colors[0][G])) +
- SQUARE(original_colors[x][y][B] - JAS_ROUND(current_colors[0][B]));
- error_b = SQUARE(original_colors[x][y][R] - JAS_ROUND(current_colors[1][R])) +
- SQUARE(original_colors[x][y][G] - JAS_ROUND(current_colors[1][G])) +
- SQUARE(original_colors[x][y][B] - JAS_ROUND(current_colors[1][B]));
- if (error_a < error_b)
- {
- block_mask[x][y] = 0;
- D += error_a;
- ++n;
- }
- else
- {
- block_mask[x][y] = 1;
- D += error_b;
- }
- }
- }
- // compare with old distortion
- if (D == 0)
- {
- // Perfect score -- we dont need to go further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D == oldD)
- {
- // Same score as last round -- no need to go for further iterations.
- continue_iterate = false;
- continue_seeding = false;
- }
- if (D < bestD)
- {
- bestD = D;
- for(uint8 s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- best_colors[s][c] = current_colors[s][c];
- }
- }
- }
- if (n == 0 || n == BLOCKWIDTH*BLOCKHEIGHT)
- {
- // All colors end up in the same voroni region. We need to reseed.
- continue_iterate = false;
- continue_seeding = true;
- }
- else
- {
- // Calculate new reconstruction points using the centroids
- // Find new construction values from average
- t_color[0][R] = 0;
- t_color[0][G] = 0;
- t_color[0][B] = 0;
- t_color[1][R] = 0;
- t_color[1][G] = 0;
- t_color[1][B] = 0;
- for (y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (int x = 0; x < BLOCKWIDTH; ++x)
- {
- // use dummy value for q-parameter
- t_color[block_mask[x][y]][R] += original_colors[x][y][R];
- t_color[block_mask[x][y]][G] += original_colors[x][y][G];
- t_color[block_mask[x][y]][B] += original_colors[x][y][B];
- }
- }
- current_colors[0][R] = t_color[0][R] / n;
- current_colors[1][R] = t_color[1][R] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][G] = t_color[0][G] / n;
- current_colors[1][G] = t_color[1][G] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- current_colors[0][B] = t_color[0][B] / n;
- current_colors[1][B] = t_color[1][B] / (BLOCKWIDTH*BLOCKHEIGHT - n);
- }
- }
- }
- // Set the best colors as the final block colors
- for(int s = 0; s < 2; ++s)
- {
- for(uint8 c = 0; c < 3; ++c)
- {
- current_colors[s][c] = best_colors[s][c];
- }
- }
- for(x=0;x<2;x++)
- for(y=0;y<3;y++)
- LBG_colors[x][y] = JAS_ROUND(current_colors[x][y]);
- }
- // Each color component is compressed to fit in its specified number of bits
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressColor(int R_B, int G_B, int B_B, uint8 (current_color)[2][3], uint8 (quantized_color)[2][3])
- {
- //
- // The color is calculated as:
- //
- // c = (c + (2^(8-b))/2) / (255 / (2^b - 1)) where b is the number of bits
- // to code color c with
- // For instance, if b = 3:
- //
- // c = (c + 16) / (255 / 7) = 7 * (c + 16) / 255
- //
- quantized_color[0][R] = CLAMP(0,(BINPOW(R_B)-1) * (current_color[0][R] + BINPOW(8-R_B-1)) / 255,255);
- quantized_color[0][G] = CLAMP(0,(BINPOW(G_B)-1) * (current_color[0][G] + BINPOW(8-G_B-1)) / 255,255);
- quantized_color[0][B] = CLAMP(0,(BINPOW(B_B)-1) * (current_color[0][B] + BINPOW(8-B_B-1)) / 255,255);
- quantized_color[1][R] = CLAMP(0,(BINPOW(R_B)-1) * (current_color[1][R] + BINPOW(8-R_B-1)) / 255,255);
- quantized_color[1][G] = CLAMP(0,(BINPOW(G_B)-1) * (current_color[1][G] + BINPOW(8-G_B-1)) / 255,255);
- quantized_color[1][B] = CLAMP(0,(BINPOW(B_B)-1) * (current_color[1][B] + BINPOW(8-B_B-1)) / 255,255);
- }
- // Swapping two RGB-colors
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void swapColors(uint8 (colors)[2][3])
- {
- uint8 temp = colors[0][R];
- colors[0][R] = colors[1][R];
- colors[1][R] = temp;
- temp = colors[0][G];
- colors[0][G] = colors[1][G];
- colors[1][G] = temp;
- temp = colors[0][B];
- colors[0][B] = colors[1][B];
- colors[1][B] = temp;
- }
- // Calculate the paint colors from the block colors
- // using a distance d and one of the H- or T-patterns.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- // Calculate the error for the block at position (startx,starty)
- // The parameters needed for reconstruction are calculated as well
- //
- // Please note that the function can change the order between the two colors in colorsRGB444
- //
- // In the 59T bit mode, we only have pattern T.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59Tperceptual1000(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff[3];
- uint8 best_sw;
- unsigned int pixel_colors;
- uint8 colors[2][3];
- uint8 possible_colors[4][3];
- // First use the colors as they are, then swap them
- for (uint8 sw = 0; sw <2; ++sw)
- {
- if (sw == 1)
- {
- swapColors(colorsRGB444);
- }
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_59T); ++d)
- {
- calculatePaintColors59T(d,PATTERN_T, colors, possible_colors);
-
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXERR1000;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
-
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) +
- PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]) +
- PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- }
- }
- block_error += best_pixel_error;
- }
- }
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- best_sw = sw;
- }
- }
-
- if (sw == 1 && best_sw == 0)
- {
- swapColors(colorsRGB444);
- }
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- }
- return best_block_error;
- }
- // Calculate the error for the block at position (startx,starty)
- // The parameters needed for reconstruction is calculated as well
- //
- // Please note that the function can change the order between the two colors in colorsRGB444
- //
- // In the 59T bit mode, we only have pattern T.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculateError59T(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- uint8 best_sw;
- unsigned int pixel_colors;
- uint8 colors[2][3];
- uint8 possible_colors[4][3];
- // First use the colors as they are, then swap them
- for (uint8 sw = 0; sw <2; ++sw)
- {
- if (sw == 1)
- {
- swapColors(colorsRGB444);
- }
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_59T); ++d)
- {
- calculatePaintColors59T(d,PATTERN_T, colors, possible_colors);
-
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXIMUM_ERROR;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
-
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = weight[R]*SQUARE(diff[R]) +
- weight[G]*SQUARE(diff[G]) +
- weight[B]*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- }
- }
- block_error += best_pixel_error;
- }
- }
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- best_sw = sw;
- }
- }
-
- if (sw == 1 && best_sw == 0)
- {
- swapColors(colorsRGB444);
- }
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- }
- return best_block_error;
- }
- // Calculate the error for the block at position (startx,starty)
- // The parameters needed for reconstruction is calculated as well
- //
- // In the 59T bit mode, we only have pattern T.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TnoSwapPerceptual1000(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 colors[2][3];
- uint8 possible_colors[4][3];
- int thebestintheworld;
- // First use the colors as they are, then swap them
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_59T); ++d)
- {
- calculatePaintColors59T(d,PATTERN_T, colors, possible_colors);
-
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXERR1000;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
-
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) +
- PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]) +
- PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- thebestintheworld = c;
- }
- }
- block_error += best_pixel_error;
- }
- }
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- }
- }
-
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- return best_block_error;
- }
- // Calculate the error for the block at position (startx,starty)
- // The parameters needed for reconstruction is calculated as well
- //
- // In the 59T bit mode, we only have pattern T.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculateError59TnoSwap(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 colors[2][3];
- uint8 possible_colors[4][3];
- int thebestintheworld;
- // First use the colors as they are, then swap them
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_59T); ++d)
- {
- calculatePaintColors59T(d,PATTERN_T, colors, possible_colors);
-
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXIMUM_ERROR;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = weight[R]*SQUARE(diff[R]) +
- weight[G]*SQUARE(diff[G]) +
- weight[B]*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- thebestintheworld = c;
- }
- }
- block_error += best_pixel_error;
- }
- }
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- }
- }
-
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- return best_block_error;
- }
- // Put the compress params into the compression block
- //
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void packBlock59T(uint8 (colors)[2][3], uint8 d, unsigned int pixel_indices, unsigned int &compressed1, unsigned int &compressed2)
- {
-
- compressed1 = 0;
- PUTBITSHIGH( compressed1, colors[0][R], 4, 58);
- PUTBITSHIGH( compressed1, colors[0][G], 4, 54);
- PUTBITSHIGH( compressed1, colors[0][B], 4, 50);
- PUTBITSHIGH( compressed1, colors[1][R], 4, 46);
- PUTBITSHIGH( compressed1, colors[1][G], 4, 42);
- PUTBITSHIGH( compressed1, colors[1][B], 4, 38);
- PUTBITSHIGH( compressed1, d, TABLE_BITS_59T, 34);
- pixel_indices=indexConversion(pixel_indices);
- compressed2 = 0;
- PUTBITS( compressed2, pixel_indices, 32, 31);
- }
- // Copy colors from source to dest
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void copyColors(uint8 (source)[2][3], uint8 (dest)[2][3])
- {
- int x,y;
- for (x=0; x<2; x++)
- for (y=0; y<3; y++)
- dest[x][y] = source[x][y];
- }
- // The below code should compress the block to 59 bits.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockTHUMB59TFastestOnlyColorPerceptual1000(uint8 *img,int width,int height,int startx,int starty, int (best_colorsRGB444_packed)[2])
- {
- unsigned int best_error = MAXERR1000;
- unsigned int best_pixel_indices;
- uint8 best_distance;
- unsigned int error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
- // Calculate average color using the LBG-algorithm
- computeColorLBGHalfIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_no_i);
- // Determine the parameters for the lowest error
- error_no_i = calculateError59Tperceptual1000(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- best_colorsRGB444_packed[0] = (colorsRGB444_no_i[0][0] << 8) + (colorsRGB444_no_i[0][1] << 4) + (colorsRGB444_no_i[0][2] << 0);
- best_colorsRGB444_packed[1] = (colorsRGB444_no_i[1][0] << 8) + (colorsRGB444_no_i[1][1] << 4) + (colorsRGB444_no_i[1][2] << 0);
- return best_error;
- }
- // The below code should compress the block to 59 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB59TFastestOnlyColor(uint8 *img,int width,int height,int startx,int starty, int (best_colorsRGB444_packed)[2])
- {
- double best_error = MAXIMUM_ERROR;
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
- // Calculate average color using the LBG-algorithm
- computeColorLBGHalfIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_no_i);
- // Determine the parameters for the lowest error
- error_no_i = calculateError59T(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- best_colorsRGB444_packed[0] = (colorsRGB444_no_i[0][0] << 8) + (colorsRGB444_no_i[0][1] << 4) + (colorsRGB444_no_i[0][2] << 0);
- best_colorsRGB444_packed[1] = (colorsRGB444_no_i[1][0] << 8) + (colorsRGB444_no_i[1][1] << 4) + (colorsRGB444_no_i[1][2] << 0);
- return best_error;
- }
- // The below code should compress the block to 59 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB59TFastestPerceptual1000(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
- // Calculate average color using the LBG-algorithm
- computeColorLBGHalfIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_no_i);
- // Determine the parameters for the lowest error
- error_no_i = calculateError59Tperceptual1000(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- // Put the compress params into the compression block
- packBlock59T(best_colorsRGB444, best_distance, best_pixel_indices, compressed1, compressed2);
- return best_error;
- }
- // The below code should compress the block to 59 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB59TFastest(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
- // Calculate average color using the LBG-algorithm
- computeColorLBGHalfIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_no_i);
- // Determine the parameters for the lowest error
- error_no_i = calculateError59T(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- // Put the compress params into the compression block
- packBlock59T(best_colorsRGB444, best_distance, best_pixel_indices, compressed1, compressed2);
- return best_error;
- }
- // The below code should compress the block to 59 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB59TFast(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- double error_half_i;
- uint8 colorsRGB444_half_i[2][3];
- unsigned int pixel_indices_half_i;
- uint8 distance_half_i;
-
- double error;
- uint8 colorsRGB444[2][3];
- unsigned int pixel_indices;
- uint8 distance;
- uint8 colors[2][3];
- // Calculate average color using the LBG-algorithm
- computeColorLBGNotIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_no_i);
- // Determine the parameters for the lowest error
- error_no_i = calculateError59T(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- // Calculate average color using the LBG-algorithm
- computeColorLBGHalfIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_half_i);
- // Determine the parameters for the lowest error
- error_half_i = calculateError59T(img, width, startx, starty, colorsRGB444_half_i, distance_half_i, pixel_indices_half_i);
- // Calculate average color using the LBG-algorithm
- computeColorLBGfast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444);
- // Determine the parameters for the lowest error
- error = calculateError59T(img, width, startx, starty, colorsRGB444, distance, pixel_indices);
-
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- if(error_half_i < best_error)
- {
- best_error = error_half_i;
- best_distance = distance_half_i;
- best_pixel_indices = pixel_indices_half_i;
- copyColors (colorsRGB444_half_i, best_colorsRGB444);
- }
- if(error < best_error)
- {
- best_error = error;
- best_distance = distance;
- best_pixel_indices = pixel_indices;
- copyColors (colorsRGB444, best_colorsRGB444);
- }
- // Put the compress params into the compression block
- packBlock59T(best_colorsRGB444, best_distance, best_pixel_indices, compressed1, compressed2);
- return best_error;
- }
- // Calculate the error for the block at position (startx,starty)
- // The parameters needed for reconstruction is calculated as well
- //
- // In the 58H bit mode, we only have pattern H.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorAndCompress58Hperceptual1000(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[4][3];
- uint8 colors[2][3];
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- calculatePaintColors58H(d, PATTERN_H, colors, possible_colors);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXERR1000;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) +
- PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]) +
- PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- }
- }
- block_error += best_pixel_error;
- }
- }
-
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- }
- }
- return best_block_error;
- }
- // The H-mode but with punchthrough alpha
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculateErrorAndCompress58HAlpha(uint8* srcimg, uint8* alphaimg,int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[4][3];
- uint8 colors[2][3];
- int alphaindex;
- int colorsRGB444_packed[2];
- colorsRGB444_packed[0] = (colorsRGB444[0][R] << 8) + (colorsRGB444[0][G] << 4) + colorsRGB444[0][B];
- colorsRGB444_packed[1] = (colorsRGB444[1][R] << 8) + (colorsRGB444[1][G] << 4) + colorsRGB444[1][B];
-
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
-
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- alphaindex=2;
- if( (colorsRGB444_packed[0] >= colorsRGB444_packed[1]) ^ ((d & 1)==1) )
- {
- //we're going to have to swap the colors to be able to choose this distance.. that means
- //that the indices will be swapped as well, so C1 will be the one with alpha instead of C3..
- alphaindex=0;
- }
- calculatePaintColors58H(d, PATTERN_H, colors, possible_colors);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- int alpha=0;
- if(alphaimg[((starty+y)*width+startx+x)]>0)
- alpha=1;
- if(alphaimg[((starty+y)*width+startx+x)]>0&&alphaimg[((starty+y)*width+startx+x)]<255)
- printf("INVALID ALPHA DATA!!\n");
- best_pixel_error = MAXIMUM_ERROR;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
- if(c==alphaindex&&alpha)
- {
- pixel_error=0;
- }
- else if(c==alphaindex||alpha)
- {
- pixel_error=MAXIMUM_ERROR;
- }
- else
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = weight[R]*SQUARE(diff[R]) +
- weight[G]*SQUARE(diff[G]) +
- weight[B]*SQUARE(diff[B]);
- }
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- }
- }
- block_error += best_pixel_error;
- }
- }
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- }
- }
- return best_block_error;
- }
- // Calculate the error for the block at position (startx,starty)
- // The parameters needed for reconstruction is calculated as well
- //
- // In the 58H bit mode, we only have pattern H.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculateErrorAndCompress58H(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[4][3];
- uint8 colors[2][3];
-
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- calculatePaintColors58H(d, PATTERN_H, colors, possible_colors);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXIMUM_ERROR;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- for (uint8 c = 0; c < 4; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = weight[R]*SQUARE(diff[R]) +
- weight[G]*SQUARE(diff[G]) +
- weight[B]*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c;
- }
- }
- block_error += best_pixel_error;
- }
- }
-
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- }
- }
-
- return best_block_error;
- }
- // Makes sure that col0 < col1;
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void sortColorsRGB444(uint8 (colorsRGB444)[2][3])
- {
- unsigned int col0, col1, tcol;
- // sort colors
- col0 = 16*16*colorsRGB444[0][R] + 16*colorsRGB444[0][G] + colorsRGB444[0][B];
- col1 = 16*16*colorsRGB444[1][R] + 16*colorsRGB444[1][G] + colorsRGB444[1][B];
- // After this, col0 should be smaller than col1 (col0 < col1)
- if( col0 > col1)
- {
- tcol = col0;
- col0 = col1;
- col1 = tcol;
- }
- else
- {
- if(col0 == col1)
- {
- // Both colors are the same. That is useless. If they are both black,
- // col1 can just as well be (0,0,1). Else, col0 can be col1 - 1.
- if(col0 == 0)
- col1 = col0+1;
- else
- col0 = col1-1;
- }
- }
-
- colorsRGB444[0][R] = GETBITS(col0, 4, 11);
- colorsRGB444[0][G] = GETBITS(col0, 4, 7);
- colorsRGB444[0][B] = GETBITS(col0, 4, 3);
- colorsRGB444[1][R] = GETBITS(col1, 4, 11);
- colorsRGB444[1][G] = GETBITS(col1, 4, 7);
- colorsRGB444[1][B] = GETBITS(col1, 4, 3);
- }
- // The below code should compress the block to 58 bits.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockTHUMB58HFastestPerceptual1000(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int best_error = MAXERR1000;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- unsigned int error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
-
- // Calculate average color using the LBG-algorithm but discarding the intensity in the error function
- computeColorLBGHalfIntensityFast(img, width, startx, starty, colors);
- compressColor(R_BITS58H, G_BITS58H, B_BITS58H, colors, colorsRGB444_no_i);
- sortColorsRGB444(colorsRGB444_no_i);
- error_no_i = calculateErrorAndCompress58Hperceptual1000(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- // | col0 >= col1 col0 < col1
- //------------------------------------------------------
- // (dist & 1) = 1 | no need to swap | need to swap
- // |-----------------+----------------
- // (dist & 1) = 0 | need to swap | no need to swap
- //
- // This can be done with an xor test.
- int best_colorsRGB444_packed[2];
- best_colorsRGB444_packed[0] = (best_colorsRGB444[0][R] << 8) + (best_colorsRGB444[0][G] << 4) + best_colorsRGB444[0][B];
- best_colorsRGB444_packed[1] = (best_colorsRGB444[1][R] << 8) + (best_colorsRGB444[1][G] << 4) + best_colorsRGB444[1][B];
- if( (best_colorsRGB444_packed[0] >= best_colorsRGB444_packed[1]) ^ ((best_distance & 1)==1) )
- {
- swapColors(best_colorsRGB444);
- // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
- best_pixel_indices = (0x55555555 & best_pixel_indices) | (0xaaaaaaaa & (~best_pixel_indices));
- }
-
- // Put the compress params into the compression block
- compressed1 = 0;
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][R], 4, 57);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][G], 4, 53);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][B], 4, 49);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][R], 4, 45);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][G], 4, 41);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][B], 4, 37);
- PUTBITSHIGH( compressed1, (best_distance >> 1), 2, 33);
- compressed2 = 0;
- best_pixel_indices=indexConversion(best_pixel_indices);
- PUTBITS( compressed2, best_pixel_indices, 32, 31);
- return best_error;
- }
- // The below code should compress the block to 58 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB58HFastest(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
-
- // Calculate average color using the LBG-algorithm but discarding the intensity in the error function
- computeColorLBGHalfIntensityFast(img, width, startx, starty, colors);
- compressColor(R_BITS58H, G_BITS58H, B_BITS58H, colors, colorsRGB444_no_i);
- sortColorsRGB444(colorsRGB444_no_i);
- error_no_i = calculateErrorAndCompress58H(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- // | col0 >= col1 col0 < col1
- //------------------------------------------------------
- // (dist & 1) = 1 | no need to swap | need to swap
- // |-----------------+----------------
- // (dist & 1) = 0 | need to swap | no need to swap
- //
- // This can be done with an xor test.
- int best_colorsRGB444_packed[2];
- best_colorsRGB444_packed[0] = (best_colorsRGB444[0][R] << 8) + (best_colorsRGB444[0][G] << 4) + best_colorsRGB444[0][B];
- best_colorsRGB444_packed[1] = (best_colorsRGB444[1][R] << 8) + (best_colorsRGB444[1][G] << 4) + best_colorsRGB444[1][B];
- if( (best_colorsRGB444_packed[0] >= best_colorsRGB444_packed[1]) ^ ((best_distance & 1)==1) )
- {
- swapColors(best_colorsRGB444);
- // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
- best_pixel_indices = (0x55555555 & best_pixel_indices) | (0xaaaaaaaa & (~best_pixel_indices));
- }
- // Put the compress params into the compression block
- compressed1 = 0;
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][R], 4, 57);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][G], 4, 53);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][B], 4, 49);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][R], 4, 45);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][G], 4, 41);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][B], 4, 37);
- PUTBITSHIGH( compressed1, (best_distance >> 1), 2, 33);
- best_pixel_indices=indexConversion(best_pixel_indices);
- compressed2 = 0;
- PUTBITS( compressed2, best_pixel_indices, 32, 31);
- return best_error;
- }
- //same as above, but with 1-bit alpha
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB58HAlpha(uint8 *img, uint8* alphaimg, int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
-
- // Calculate average color using the LBG-algorithm but discarding the intensity in the error function
- computeColorLBGHalfIntensityFast(img, width, startx, starty, colors);
- compressColor(R_BITS58H, G_BITS58H, B_BITS58H, colors, colorsRGB444_no_i);
- sortColorsRGB444(colorsRGB444_no_i);
- error_no_i = calculateErrorAndCompress58HAlpha(img, alphaimg,width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- // | col0 >= col1 col0 < col1
- //------------------------------------------------------
- // (dist & 1) = 1 | no need to swap | need to swap
- // |-----------------+----------------
- // (dist & 1) = 0 | need to swap | no need to swap
- //
- // This can be done with an xor test.
- int best_colorsRGB444_packed[2];
- best_colorsRGB444_packed[0] = (best_colorsRGB444[0][R] << 8) + (best_colorsRGB444[0][G] << 4) + best_colorsRGB444[0][B];
- best_colorsRGB444_packed[1] = (best_colorsRGB444[1][R] << 8) + (best_colorsRGB444[1][G] << 4) + best_colorsRGB444[1][B];
- if( (best_colorsRGB444_packed[0] >= best_colorsRGB444_packed[1]) ^ ((best_distance & 1)==1) )
- {
- swapColors(best_colorsRGB444);
- // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
- best_pixel_indices = (0x55555555 & best_pixel_indices) | (0xaaaaaaaa & (~best_pixel_indices));
- }
- // Put the compress params into the compression block
- compressed1 = 0;
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][R], 4, 57);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][G], 4, 53);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][B], 4, 49);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][R], 4, 45);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][G], 4, 41);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][B], 4, 37);
- PUTBITSHIGH( compressed1, (best_distance >> 1), 2, 33);
- best_pixel_indices=indexConversion(best_pixel_indices);
- compressed2 = 0;
- PUTBITS( compressed2, best_pixel_indices, 32, 31);
- return best_error;
- }
- // The below code should compress the block to 58 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB58HFast(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- double error_half_i;
- uint8 colorsRGB444_half_i[2][3];
- unsigned int pixel_indices_half_i;
- uint8 distance_half_i;
- double error;
- uint8 colorsRGB444[2][3];
- unsigned int pixel_indices;
- uint8 distance;
- uint8 colors[2][3];
-
- // Calculate average color using the LBG-algorithm but discarding the intensity in the error function
- computeColorLBGNotIntensity(img, width, startx, starty, colors);
- compressColor(R_BITS58H, G_BITS58H, B_BITS58H, colors, colorsRGB444_no_i);
- sortColorsRGB444(colorsRGB444_no_i);
- error_no_i = calculateErrorAndCompress58H(img, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- // Calculate average color using the LBG-algorithm but halfing the influence of the intensity in the error function
- computeColorLBGNotIntensity(img, width, startx, starty, colors);
- compressColor(R_BITS58H, G_BITS58H, B_BITS58H, colors, colorsRGB444_half_i);
- sortColorsRGB444(colorsRGB444_half_i);
- error_half_i = calculateErrorAndCompress58H(img, width, startx, starty, colorsRGB444_half_i, distance_half_i, pixel_indices_half_i);
- // Calculate average color using the LBG-algorithm
- computeColorLBG(img, width, startx, starty, colors);
- compressColor(R_BITS58H, G_BITS58H, B_BITS58H, colors, colorsRGB444);
- sortColorsRGB444(colorsRGB444);
- error = calculateErrorAndCompress58H(img, width, startx, starty, colorsRGB444, distance, pixel_indices);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- if(error_half_i < best_error)
- {
- best_error = error_half_i;
- best_distance = distance_half_i;
- best_pixel_indices = pixel_indices_half_i;
- copyColors(colorsRGB444_half_i, best_colorsRGB444);
- }
- if(error < best_error)
- {
- best_error = error;
- best_distance = distance;
- best_pixel_indices = pixel_indices;
- copyColors(colorsRGB444, best_colorsRGB444);
- }
- // | col0 >= col1 col0 < col1
- //------------------------------------------------------
- // (dist & 1) = 1 | no need to swap | need to swap
- // |-----------------+----------------
- // (dist & 1) = 0 | need to swap | no need to swap
- //
- // This can be done with an xor test.
- int best_colorsRGB444_packed[2];
- best_colorsRGB444_packed[0] = (best_colorsRGB444[0][R] << 8) + (best_colorsRGB444[0][G] << 4) + best_colorsRGB444[0][B];
- best_colorsRGB444_packed[1] = (best_colorsRGB444[1][R] << 8) + (best_colorsRGB444[1][G] << 4) + best_colorsRGB444[1][B];
- if( (best_colorsRGB444_packed[0] >= best_colorsRGB444_packed[1]) ^ ((best_distance & 1)==1) )
- {
- swapColors(best_colorsRGB444);
- // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
- best_pixel_indices = (0x55555555 & best_pixel_indices) | (0xaaaaaaaa & (~best_pixel_indices));
- }
- // Put the compress params into the compression block
- compressed1 = 0;
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][R], 4, 57);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][G], 4, 53);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][B], 4, 49);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][R], 4, 45);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][G], 4, 41);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][B], 4, 37);
- PUTBITSHIGH( compressed1, (best_distance >> 1), 2, 33);
- best_pixel_indices=indexConversion(best_pixel_indices);
- compressed2 = 0;
- PUTBITS( compressed2, best_pixel_indices, 32, 31);
- return best_error;
- }
- // Compress block testing both individual and differential mode.
- // Perceptual error metric.
- // Combined quantization for colors.
- // Both flipped and unflipped tested.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockDiffFlipCombinedPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int min_error=255*255*8*3;
- unsigned int best_table_indices1=0, best_table_indices2=0;
- unsigned int best_table1=0, best_table2=0;
- int diffbit;
- int norm_err=0;
- int flip_err=0;
- // First try normal blocks 2x4:
- computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- float eps;
- uint8 dummy[3];
- quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy);
- quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy);
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_norm, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_norm, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_norm, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- norm_err = 0;
- // left part of block
- norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy);
- quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
- // Pack bits into the first word.
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- compressed1_norm = 0;
- PUTBITSHIGH( compressed1_norm, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
-
- // left part of block
- norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // right part of block
- norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_norm, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_norm, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_norm, 0, 1, 32);
- compressed2_norm = 0;
- PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15);
- }
- // Now try flipped blocks 4x2:
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1);
- computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2);
- // First test if avg_color1 is similar enough to avg_color2 so that
- // we can use differential coding of colors.
- quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy);
- quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy);
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) )
- {
- diffbit = 1;
- // The difference to be coded:
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_flip, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_flip, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_flip, diff[2], 3, 42);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- else
- {
- diffbit = 0;
- // The difference is bigger than what fits in 555 plus delta-333, so we will have
- // to deal with 444 444.
- eps = (float) 0.0001;
- quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy);
- quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy);
- avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0];
- avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1];
- avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2];
- avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0];
- avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1];
- avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2];
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- // Pack bits into the first word.
- compressed1_flip = 0;
- PUTBITSHIGH( compressed1_flip, diffbit, 1, 33);
- PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43);
- unsigned int best_pixel_indices1_MSB;
- unsigned int best_pixel_indices1_LSB;
- unsigned int best_pixel_indices2_MSB;
- unsigned int best_pixel_indices2_LSB;
- // upper part of block
- flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- // lower part of block
- flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- PUTBITSHIGH( compressed1_flip, best_table1, 3, 39);
- PUTBITSHIGH( compressed1_flip, best_table2, 3, 36);
- PUTBITSHIGH( compressed1_flip, 1, 1, 32);
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
-
- compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- // Now lets see which is the best table to use. Only 8 tables are possible.
- if(norm_err <= flip_err)
- {
- compressed1 = compressed1_norm | 0;
- compressed2 = compressed2_norm;
- }
- else
- {
- compressed1 = compressed1_flip | 1;
- compressed2 = compressed2_flip;
- }
- }
- // Calculate the error of a block
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calcBlockErrorRGB(uint8 *img, uint8 *imgdec, int width, int height, int startx, int starty)
- {
- int xx,yy;
- double err;
- err = 0;
- for(xx = startx; xx< startx+4; xx++)
- {
- for(yy = starty; yy<starty+4; yy++)
- {
- err += SQUARE(1.0*RED(img,width,xx,yy) - 1.0*RED(imgdec, width, xx,yy));
- err += SQUARE(1.0*GREEN(img,width,xx,yy)- 1.0*GREEN(imgdec, width, xx,yy));
- err += SQUARE(1.0*BLUE(img,width,xx,yy) - 1.0*BLUE(imgdec, width, xx,yy));
- }
- }
- return err;
- }
- // Calculate the perceptually weighted error of a block
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calcBlockPerceptualErrorRGB(uint8 *img, uint8 *imgdec, int width, int height, int startx, int starty)
- {
- int xx,yy;
- double err;
- err = 0;
- for(xx = startx; xx< startx+4; xx++)
- {
- for(yy = starty; yy<starty+4; yy++)
- {
- err += PERCEPTUAL_WEIGHT_R_SQUARED*SQUARE(1.0*RED(img,width,xx,yy) - 1.0*RED(imgdec, width, xx,yy));
- err += PERCEPTUAL_WEIGHT_G_SQUARED*SQUARE(1.0*GREEN(img,width,xx,yy)- 1.0*GREEN(imgdec, width, xx,yy));
- err += PERCEPTUAL_WEIGHT_B_SQUARED*SQUARE(1.0*BLUE(img,width,xx,yy) - 1.0*BLUE(imgdec, width, xx,yy));
- }
- }
- return err;
- }
- // Compress an ETC1 block (or the individual and differential modes of an ETC2 block)
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockDiffFlipFast(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int average_block1;
- unsigned int average_block2;
- double error_average;
- unsigned int combined_block1;
- unsigned int combined_block2;
- double error_combined;
- double best_error;
- // First quantize the average color to the nearest neighbor.
- compressBlockDiffFlipAverage(img, width, height, startx, starty, average_block1, average_block2);
- decompressBlockDiffFlip(average_block1, average_block2, imgdec, width, height, startx, starty);
- error_average = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- // Then quantize the average color taking into consideration that intensity can change
- compressBlockDiffFlipCombined(img, width, height, startx, starty, combined_block1, combined_block2);
- decompressBlockDiffFlip(combined_block1, combined_block2, imgdec, width, height, startx, starty);
- error_combined = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- if(error_combined < error_average)
- {
- compressed1 = combined_block1;
- compressed2 = combined_block2;
- best_error = error_combined;
- }
- else
- {
- compressed1 = average_block1;
- compressed2 = average_block2;
- best_error = error_average;
- }
- return best_error;
- }
- // Compress an ETC1 block (or the individual and differential modes of an ETC2 block)
- // Uses perceptual error metric.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockDiffFlipFastPerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int average_block1;
- unsigned int average_block2;
- double error_average;
- unsigned int combined_block1;
- unsigned int combined_block2;
- double error_combined;
- // First quantize the average color to the nearest neighbor.
- compressBlockDiffFlipAveragePerceptual(img, width, height, startx, starty, average_block1, average_block2);
- decompressBlockDiffFlip(average_block1, average_block2, imgdec, width, height, startx, starty);
- error_average = calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- // Then quantize the average color taking into consideration that intensity can change
- compressBlockDiffFlipCombinedPerceptual(img, width, height, startx, starty, combined_block1, combined_block2);
- decompressBlockDiffFlip(combined_block1, combined_block2, imgdec, width, height, startx, starty);
- error_combined = calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- if(error_combined < error_average)
- {
- compressed1 = combined_block1;
- compressed2 = combined_block2;
- }
- else
- {
- compressed1 = average_block1;
- compressed2 = average_block2;
- }
- }
- // Compresses the differential mode of an ETC2 block with punchthrough alpha
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int compressBlockDifferentialWithAlpha(bool isTransparent, uint8* img, uint8* alphaimg, uint8* imgdec, int width, int height, int startx, int starty, unsigned int &etc1_word1, unsigned int &etc1_word2)
- {
- unsigned int compressed1_norm, compressed2_norm;
- unsigned int compressed1_flip, compressed2_flip;
- unsigned int compressed1_temp, compressed2_temp;
- uint8 avg_color_quant1[3], avg_color_quant2[3];
- float avg_color_float1[3],avg_color_float2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int min_error=255*255*8*3;
-
- int norm_err=0;
- int flip_err=0;
- int temp_err=0;
- for(int flipbit=0; flipbit<2; flipbit++)
- {
- //compute average color for each half.
- for(int c=0; c<3; c++)
- {
- avg_color_float1[c]=0;
- avg_color_float2[c]=0;
- float sum1=0;
- float sum2=0;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- float fac=1;
- int index = x+startx+(y+starty)*width;
- //transparent pixels are only barely figured into the average. This ensures that they DO matter if we have only
- //transparent pixels in one half of the block, and not otherwise. A bit ugly perhaps.
- if(alphaimg[index]<128)
- fac=0.0001f;
- float col = fac*img[index*3+c];
- if( (flipbit==0&&x<2) || (flipbit==1&&y<2) )
- {
- sum1+=fac;
- avg_color_float1[c]+=col;
- }
- else
- {
- sum2+=fac;
- avg_color_float2[c]+=col;
- }
- }
- }
- avg_color_float1[c]/=sum1;
- avg_color_float2[c]/=sum2;
- }
- uint8 dummy[3];
- quantize555ColorCombined(avg_color_float1, enc_color1, dummy);
- quantize555ColorCombined(avg_color_float2, enc_color2, dummy);
- diff[0] = enc_color2[0]-enc_color1[0];
- diff[1] = enc_color2[1]-enc_color1[1];
- diff[2] = enc_color2[2]-enc_color1[2];
- //make sure diff is small enough for diff-coding
- for(int c=0; c<3; c++)
- {
- if(diff[c]<-4)
- diff[c]=-4;
- if(diff[c]>3)
- diff[c]=3;
- enc_color2[c]=enc_color1[c]+diff[c];
- }
- avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2);
- avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2);
- avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2);
- // Pack bits into the first word.
- // see regular compressblockdiffflipfast for details
- compressed1_temp = 0;
- PUTBITSHIGH( compressed1_temp, !isTransparent, 1, 33);
- PUTBITSHIGH( compressed1_temp, enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1_temp, enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1_temp, enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1_temp, diff[0], 3, 58);
- PUTBITSHIGH( compressed1_temp, diff[1], 3, 50);
- PUTBITSHIGH( compressed1_temp, diff[2], 3, 42);
- temp_err = 0;
-
- int besterror[2];
- besterror[0]=255*255*3*16;
- besterror[1]=255*255*3*16;
- int besttable[2];
- int best_indices_LSB[16];
- int best_indices_MSB[16];
- //for each table, we're going to compute the indices required to get minimum error in each half.
- //then we'll check if this was the best table for either half, and set besterror/besttable accordingly.
- for(int table=0; table<8; table++)
- {
- int taberror[2];//count will be sort of an index of each pixel within a half, determining where the index will be placed in the bitstream.
-
- int pixel_indices_LSB[16],pixel_indices_MSB[16];
-
- for(int i=0; i<2; i++)
- {
- taberror[i]=0;
- }
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- int index = x+startx+(y+starty)*width;
- uint8 basecol[3];
- bool transparentPixel=alphaimg[index]<128;
- //determine which half of the block this pixel is in, based on the flipbit.
- int half=0;
- if( (flipbit==0&&x<2) || (flipbit&&y<2) )
- {
- basecol[0]=avg_color_quant1[0];
- basecol[1]=avg_color_quant1[1];
- basecol[2]=avg_color_quant1[2];
- }
- else
- {
- half=1;
- basecol[0]=avg_color_quant2[0];
- basecol[1]=avg_color_quant2[1];
- basecol[2]=avg_color_quant2[2];
- }
- int besterri=255*255*3*2;
- int besti=0;
- int erri;
- for(int i=0; i<4; i++)
- {
- if(i==1&&isTransparent)
- continue;
- erri=0;
- for(int c=0; c<3; c++)
- {
- int col=CLAMP(0,((int)basecol[c])+compressParams[table*2][i],255);
- if(i==2&&isTransparent)
- {
- col=(int)basecol[c];
- }
- int errcol=col-((int)(img[index*3+c]));
- erri=erri+(errcol*errcol);
- }
- if(erri<besterri)
- {
- besterri=erri;
- besti=i;
- }
- }
- if(transparentPixel)
- {
- besterri=0;
- besti=1;
- }
- //the best index for this pixel using this table for its half is known.
- //add its error to error for this table and half.
- taberror[half]+=besterri;
- //store the index! we might toss it later though if this was a bad table.
- int pixel_index = scramble[besti];
- pixel_indices_MSB[x*4+y]=(pixel_index >> 1);
- pixel_indices_LSB[x*4+y]=(pixel_index & 1);
- }
- }
- for(int half=0; half<2; half++)
- {
- if(taberror[half]<besterror[half])
- {
- besterror[half]=taberror[half];
- besttable[half]=table;
- for(int i=0; i<16; i++)
- {
- int thishalf=0;
- int y=i%4;
- int x=i/4;
- if( !(flipbit==0&&x<2) && !(flipbit&&y<2) )
- thishalf=1;
- if(half!=thishalf) //this pixel is not in given half, don't update best index!
- continue;
- best_indices_MSB[i]=pixel_indices_MSB[i];
- best_indices_LSB[i]=pixel_indices_LSB[i];
- }
- }
- }
- }
- PUTBITSHIGH( compressed1_temp, besttable[0], 3, 39);
- PUTBITSHIGH( compressed1_temp, besttable[1], 3, 36);
- PUTBITSHIGH( compressed1_temp, 0, 1, 32);
- compressed2_temp = 0;
- for(int i=0; i<16; i++)
- {
- PUTBITS( compressed2_temp, (best_indices_MSB[i] ), 1, 16+i);
- PUTBITS( compressed2_temp, (best_indices_LSB[i] ), 1, i);
- }
-
- if(flipbit)
- {
- flip_err=besterror[0]+besterror[1];
- compressed1_flip=compressed1_temp;
- compressed2_flip=compressed2_temp;
- }
- else
- {
- norm_err=besterror[0]+besterror[1];
- compressed1_norm=compressed1_temp;
- compressed2_norm=compressed2_temp;
- }
- }
- // Now to find out if flipping was a good idea or not
- if(norm_err <= flip_err)
- {
- etc1_word1 = compressed1_norm | 0;
- etc1_word2 = compressed2_norm;
- return norm_err;
- }
- else
- {
- etc1_word1 = compressed1_flip | 1;
- etc1_word2 = compressed2_flip;
- return flip_err;
- }
- }
- // Calculate RGBA error --- only count non-transparent pixels (alpha > 128)
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calcBlockErrorRGBA(uint8 *img, uint8 *imgdec, uint8* alpha, int width, int height, int startx, int starty)
- {
- int xx,yy;
- double err;
- err = 0;
- for(xx = startx; xx< startx+4; xx++)
- {
- for(yy = starty; yy<starty+4; yy++)
- {
- //only count non-transparent pixels.
- if(alpha[yy*width+xx]>128)
- {
- err += SQUARE(1.0*RED(img,width,xx,yy) - 1.0*RED(imgdec, width, xx,yy));
- err += SQUARE(1.0*GREEN(img,width,xx,yy)- 1.0*GREEN(imgdec, width, xx,yy));
- err += SQUARE(1.0*BLUE(img,width,xx,yy) - 1.0*BLUE(imgdec, width, xx,yy));
- }
- }
- }
- return err;
- }
- //calculates the error for a block using the given colors, and the paremeters required to obtain the error. This version uses 1-bit punch-through alpha.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculateError59TAlpha(uint8* srcimg, uint8* alpha,int width, int startx, int starty, uint8 (colorsRGB444)[2][3], uint8 &distance, unsigned int &pixel_indices)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- uint8 best_sw;
- unsigned int pixel_colors;
- uint8 colors[2][3];
- uint8 possible_colors[4][3];
- // First use the colors as they are, then swap them
- for (uint8 sw = 0; sw <2; ++sw)
- {
- if (sw == 1)
- {
- swapColors(colorsRGB444);
- }
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_59T); ++d)
- {
- calculatePaintColors59T(d,PATTERN_T, colors, possible_colors);
-
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXIMUM_ERROR;
- pixel_colors <<=2; // Make room for next value
- // Loop possible block colors
- if(alpha[x+startx+(y+starty)*width]==0)
- {
- best_pixel_error=0;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= 2; //insert the index for this pixel, two meaning transparent.
- }
- else
- {
- for (uint8 c = 0; c < 4; ++c)
- {
-
- if(c==2)
- continue; //don't use this, because we don't have alpha here and index 2 means transparent.
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- diff[B] = srcimg[3*((starty+y)*width+startx+x)+B] - CLAMP(0,possible_colors[c][B],255);
- pixel_error = weight[R]*SQUARE(diff[R]) +
- weight[G]*SQUARE(diff[G]) +
- weight[B]*SQUARE(diff[B]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- pixel_colors ^= (pixel_colors & 3); // Reset the two first bits
- pixel_colors |= c; //insert the index for this pixel
- }
- }
- }
- block_error += best_pixel_error;
- }
- }
- if (block_error < best_block_error)
- {
- best_block_error = block_error;
- distance = d;
- pixel_indices = pixel_colors;
- best_sw = sw;
- }
- }
-
- if (sw == 1 && best_sw == 0)
- {
- swapColors(colorsRGB444);
- }
- decompressColor(R_BITS59T, G_BITS59T, B_BITS59T, colorsRGB444, colors);
- }
- return best_block_error;
- }
- // same as fastest t-mode compressor above, but here one of the colors (the central one in the T) is used to also signal that the pixel is transparent.
- // the only difference is that calculateError has been swapped out to one that considers alpha.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double compressBlockTHUMB59TAlpha(uint8 *img, uint8* alpha, int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- double best_error = MAXIMUM_ERROR;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- double error_no_i;
- uint8 colorsRGB444_no_i[2][3];
- unsigned int pixel_indices_no_i;
- uint8 distance_no_i;
- uint8 colors[2][3];
- // Calculate average color using the LBG-algorithm
- computeColorLBGHalfIntensityFast(img,width,startx,starty, colors);
- compressColor(R_BITS59T, G_BITS59T, B_BITS59T, colors, colorsRGB444_no_i);
- // Determine the parameters for the lowest error
- error_no_i = calculateError59TAlpha(img, alpha, width, startx, starty, colorsRGB444_no_i, distance_no_i, pixel_indices_no_i);
- best_error = error_no_i;
- best_distance = distance_no_i;
- best_pixel_indices = pixel_indices_no_i;
- copyColors(colorsRGB444_no_i, best_colorsRGB444);
- // Put the compress params into the compression block
- packBlock59T(best_colorsRGB444, best_distance, best_pixel_indices, compressed1, compressed2);
- return best_error;
- }
- // Put bits in order for the format.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void stuff59bitsDiffFalse(unsigned int thumbT59_word1, unsigned int thumbT59_word2, unsigned int &thumbT_word1, unsigned int &thumbT_word2)
- {
- // Put bits in twotimer configuration for 59 (red overflows)
- //
- // Go from this bit layout:
- //
- // |63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- // |----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- // |----------------------------------------index bits---------------------------------------------|
- //
- //
- // To this:
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // |// // //|R0a |//|R0b |G0 |B0 |R1 |G1 |B1 |da |df|db|
- // -----------------------------------------------------------------------------------------------
- //
- // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- // |----------------------------------------index bits---------------------------------------------|
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // -----------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt|
- // ------------------------------------------------------------------------------------------------
- uint8 R0a;
- uint8 bit, a, b, c, d, bits;
- R0a = GETBITSHIGH( thumbT59_word1, 2, 58);
- // Fix middle part
- thumbT_word1 = thumbT59_word1 << 1;
- // Fix R0a (top two bits of R0)
- PUTBITSHIGH( thumbT_word1, R0a, 2, 60);
- // Fix db (lowest bit of d)
- PUTBITSHIGH( thumbT_word1, thumbT59_word1, 1, 32);
- //
- // Make sure that red overflows:
- a = GETBITSHIGH( thumbT_word1, 1, 60);
- b = GETBITSHIGH( thumbT_word1, 1, 59);
- c = GETBITSHIGH( thumbT_word1, 1, 57);
- d = GETBITSHIGH( thumbT_word1, 1, 56);
- // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
- // The following logical expression checks for the presence of any of those:
- bit = (a & c) | (!a & b & c & d) | (a & b & !c & d);
- bits = 0xf*bit;
- PUTBITSHIGH( thumbT_word1, bits, 3, 63);
- PUTBITSHIGH( thumbT_word1, !bit, 1, 58);
- // Set diffbit
- PUTBITSHIGH( thumbT_word1, 0, 1, 33);
- thumbT_word2 = thumbT59_word2;
- }
- // Tests if there is at least one pixel in the image which would get alpha = 0 in punchtrough mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- bool hasAlpha(uint8* alphaimg, int ix, int iy, int width)
- {
- for(int x=ix; x<ix+4; x++)
- {
- for(int y=iy; y<iy+4; y++)
- {
- int index = x+y*width;
- if(alphaimg[index]<128)
- {
- return true;
- }
- }
- }
- return false;
- }
- // Compress a block with ETC2 RGB
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockETC2Fast(uint8 *img, uint8* alphaimg, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, int format)
- {
- unsigned int etc1_word1;
- unsigned int etc1_word2;
- double error_etc1;
- unsigned int planar57_word1;
- unsigned int planar57_word2;
- unsigned int planar_word1;
- unsigned int planar_word2;
- double error_planar;
- unsigned int thumbT59_word1;
- unsigned int thumbT59_word2;
- unsigned int thumbT_word1;
- unsigned int thumbT_word2;
- double error_thumbT;
-
- unsigned int thumbH58_word1;
- unsigned int thumbH58_word2;
- unsigned int thumbH_word1;
- unsigned int thumbH_word2;
- double error_thumbH;
- double error_best;
- signed char best_char;
- int best_mode;
-
- if(format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- /* if we have one-bit alpha, we never use the individual mode,
- instead that bit flags that one of our four offsets will instead
- mean transparent (with 0 offset for color channels) */
- /* the regular ETC individual mode is disabled, but the old T, H and planar modes
- are kept unchanged and may be used for blocks without transparency.
- Introduced are old ETC with only differential coding,
- ETC differential but with 3 offsets and transparent,
- and T-mode with 3 colors plus transparent.*/
- /* in a fairly hackish manner, error_etc1, etc1_word1 and etc1_word2 will
- represent the best out of the three introduced modes, to be compared
- with the three kept modes in the old code*/
- unsigned int tempword1, tempword2;
- double temperror;
- //try regular differential transparent mode
- int testerr= compressBlockDifferentialWithAlpha(true,img,alphaimg, imgdec,width,height,startx,starty,etc1_word1,etc1_word2);
- uint8* alphadec = new uint8[width*height];
- decompressBlockDifferentialWithAlpha(etc1_word1, etc1_word2, imgdec, alphadec,width, height, startx, starty);
- error_etc1 = calcBlockErrorRGBA(img, imgdec, alphaimg,width, height, startx, starty);
- if(error_etc1!=testerr)
- {
- printf("testerr: %d, etcerr: %lf\n",testerr,error_etc1);
- }
- //try T-mode with transparencies
- //for now, skip this...
- compressBlockTHUMB59TAlpha(img,alphaimg,width,height,startx,starty,tempword1,tempword2);
- decompressBlockTHUMB59TAlpha(tempword1,tempword2,imgdec, alphadec, width,height,startx,starty);
- temperror=calcBlockErrorRGBA(img, imgdec, alphaimg, width, height, startx, starty);
- if(temperror<error_etc1)
- {
- error_etc1=temperror;
- stuff59bitsDiffFalse(tempword1,tempword2,etc1_word1,etc1_word2);
- }
- compressBlockTHUMB58HAlpha(img,alphaimg,width,height,startx,starty,tempword1,tempword2);
- decompressBlockTHUMB58HAlpha(tempword1,tempword2,imgdec, alphadec, width,height,startx,starty);
- temperror=calcBlockErrorRGBA(img, imgdec, alphaimg, width, height, startx, starty);
- if(temperror<error_etc1)
- {
- error_etc1=temperror;
- stuff58bitsDiffFalse(tempword1,tempword2,etc1_word1,etc1_word2);
- }
- //if we have transparency in this pixel, we know that one of these two modes was best..
- if(hasAlpha(alphaimg,startx,starty,width))
- {
- compressed1=etc1_word1;
- compressed2=etc1_word2;
- delete[] alphadec; // ESENTHEL CHANGED
- return;
- }
- //error_etc1=255*255*1000;
- //otherwise, they MIGHT have been the best, although that's unlikely.. anyway, try old differential mode now
-
- compressBlockDifferentialWithAlpha(false,img,alphaimg,imgdec,width,height,startx,starty,tempword1,tempword2);
- decompressBlockDiffFlip(tempword1, tempword2, imgdec, width, height, startx, starty);
- temperror = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- decompressBlockDifferentialWithAlpha(tempword1,tempword2,imgdec,alphadec,width,height,startx,starty);
- if(temperror<error_etc1)
- {
- error_etc1=temperror;
- etc1_word1=tempword1;
- etc1_word2=tempword2;
- }
- delete[] alphadec; // ESENTHEL CHANGED
- //drop out of this if, and test old T, H and planar modes (we have already returned if there are transparent pixels in this block)
- }
- else
- {
- //this includes individual mode, and therefore doesn't apply in case of punch-through alpha.
- compressBlockDiffFlipFast(img, imgdec, width, height, startx, starty, etc1_word1, etc1_word2);
- decompressBlockDiffFlip(etc1_word1, etc1_word2, imgdec, width, height, startx, starty);
- error_etc1 = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- }
- //these modes apply regardless of whether we want punch-through alpha or not.
- //error etc_1 and etc1_word1/etc1_word2 contain previous best candidate.
- compressBlockPlanar57(img, width, height, startx, starty, planar57_word1, planar57_word2);
- decompressBlockPlanar57(planar57_word1, planar57_word2, imgdec, width, height, startx, starty);
- error_planar = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff57bits(planar57_word1, planar57_word2, planar_word1, planar_word2);
- compressBlockTHUMB59TFastest(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2);
- decompressBlockTHUMB59T(thumbT59_word1, thumbT59_word2, imgdec, width, height, startx, starty);
- error_thumbT = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- compressBlockTHUMB58HFastest(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2);
- decompressBlockTHUMB58H(thumbH58_word1, thumbH58_word2, imgdec, width, height, startx, starty);
- error_thumbH = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- error_best = error_etc1;
- compressed1 = etc1_word1;
- compressed2 = etc1_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- if(error_planar < error_best)
- {
- compressed1 = planar_word1;
- compressed2 = planar_word2;
- best_char = 'p';
- error_best = error_planar;
- best_mode = MODE_PLANAR;
- }
- if(error_thumbT < error_best)
- {
- compressed1 = thumbT_word1;
- compressed2 = thumbT_word2;
- best_char = 'T';
- error_best = error_thumbT;
- best_mode = MODE_THUMB_T;
- }
- if(error_thumbH < error_best)
- {
- compressed1 = thumbH_word1;
- compressed2 = thumbH_word2;
- best_char = 'H';
- error_best = error_thumbH;
- best_mode = MODE_THUMB_H;
- }
-
- switch(best_mode)
- {
- // Now see which mode won and compress that a little bit harder
- case MODE_THUMB_T:
- compressBlockTHUMB59TFast(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2);
- decompressBlockTHUMB59T(thumbT59_word1, thumbT59_word2, imgdec, width, height, startx, starty);
- error_thumbT = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- if(error_thumbT < error_best)
- {
- compressed1 = thumbT_word1;
- compressed2 = thumbT_word2;
- }
- break;
- case MODE_THUMB_H:
- compressBlockTHUMB58HFast(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2);
- decompressBlockTHUMB58H(thumbH58_word1, thumbH58_word2, imgdec, width, height, startx, starty);
- error_thumbH = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- if(error_thumbH < error_best)
- {
- compressed1 = thumbH_word1;
- compressed2 = thumbH_word2;
- }
- break;
- default:
- break;
- }
- }
- // Compress an ETC2 RGB block using perceptual error metric
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockETC2FastPerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int etc1_word1;
- unsigned int etc1_word2;
- double error_etc1;
- unsigned int planar57_word1;
- unsigned int planar57_word2;
- unsigned int planar_word1;
- unsigned int planar_word2;
- double error_planar;
- unsigned int thumbT59_word1;
- unsigned int thumbT59_word2;
- unsigned int thumbT_word1;
- unsigned int thumbT_word2;
- double error_thumbT;
-
- unsigned int thumbH58_word1;
- unsigned int thumbH58_word2;
- unsigned int thumbH_word1;
- unsigned int thumbH_word2;
- double error_thumbH;
- double error_best;
- signed char best_char;
- int best_mode;
- compressBlockDiffFlipFastPerceptual(img, imgdec, width, height, startx, starty, etc1_word1, etc1_word2);
- decompressBlockDiffFlip(etc1_word1, etc1_word2, imgdec, width, height, startx, starty);
- error_etc1 = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- compressBlockPlanar57(img, width, height, startx, starty, planar57_word1, planar57_word2);
- decompressBlockPlanar57(planar57_word1, planar57_word2, imgdec, width, height, startx, starty);
- error_planar = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- stuff57bits(planar57_word1, planar57_word2, planar_word1, planar_word2);
- compressBlockTHUMB59TFastestPerceptual1000(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2);
- decompressBlockTHUMB59T(thumbT59_word1, thumbT59_word2, imgdec, width, height, startx, starty);
- error_thumbT = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- compressBlockTHUMB58HFastestPerceptual1000(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2);
- decompressBlockTHUMB58H(thumbH58_word1, thumbH58_word2, imgdec, width, height, startx, starty);
- error_thumbH = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- error_best = error_etc1;
- compressed1 = etc1_word1;
- compressed2 = etc1_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- if(error_planar < error_best)
- {
- compressed1 = planar_word1;
- compressed2 = planar_word2;
- best_char = 'p';
- error_best = error_planar;
- best_mode = MODE_PLANAR;
- }
- if(error_thumbT < error_best)
- {
- compressed1 = thumbT_word1;
- compressed2 = thumbT_word2;
- best_char = 'T';
- error_best = error_thumbT;
- best_mode = MODE_THUMB_T;
- }
- if(error_thumbH < error_best)
- {
- compressed1 = thumbH_word1;
- compressed2 = thumbH_word2;
- best_char = 'H';
- error_best = error_thumbH;
- best_mode = MODE_THUMB_H;
- }
-
- switch(best_mode)
- {
- // Now see which mode won and compress that a little bit harder
- case MODE_THUMB_T:
- compressBlockTHUMB59TFast(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2);
- decompressBlockTHUMB59T(thumbT59_word1, thumbT59_word2, imgdec, width, height, startx, starty);
- error_thumbT = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- if(error_thumbT < error_best)
- {
- compressed1 = thumbT_word1;
- compressed2 = thumbT_word2;
- }
- break;
- case MODE_THUMB_H:
- compressBlockTHUMB58HFast(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2);
- decompressBlockTHUMB58H(thumbH58_word1, thumbH58_word2, imgdec, width, height, startx, starty);
- error_thumbH = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- if(error_thumbH < error_best)
- {
- compressed1 = thumbH_word1;
- compressed2 = thumbH_word2;
- }
- break;
- default:
- break;
- }
- }
- // Write a word in big endian style
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*void write_big_endian_2byte_word(unsigned short *blockadr, FILE *f)
- {
- uint8 bytes[2];
- unsigned short block;
- block = blockadr[0];
- bytes[0] = (block >> 8) & 0xff;
- bytes[1] = (block >> 0) & 0xff;
- fwrite(&bytes[0],1,1,f);
- fwrite(&bytes[1],1,1,f);
- }*/
- // Write a word in big endian style
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*void write_big_endian_4byte_word(unsigned int *blockadr, FILE *f)
- {
- uint8 bytes[4];
- unsigned int block;
- block = blockadr[0];
- bytes[0] = (block >> 24) & 0xff;
- bytes[1] = (block >> 16) & 0xff;
- bytes[2] = (block >> 8) & 0xff;
- bytes[3] = (block >> 0) & 0xff;
- fwrite(&bytes[0],1,1,f);
- fwrite(&bytes[1],1,1,f);
- fwrite(&bytes[2],1,1,f);
- fwrite(&bytes[3],1,1,f);
- }*/
- extern int alphaTable[256][8];
- extern int alphaBase[16][4];
- // valtab holds precalculated data used for compressing using EAC2.
- // Note that valtab is constructed using get16bits11bits, which means
- // that it already is expanded to 16 bits.
- // Note also that it its contents will depend on the value of formatSigned.
- /*int *valtab;
- void setupAlphaTableAndValtab()
- {
- setupAlphaTable();
- //fix precomputation table..!
- valtab = new int[1024*512];
- int16 val16;
- int count=0;
- for(int base=0; base<256; base++)
- {
- for(int tab=0; tab<16; tab++)
- {
- for(int mul=0; mul<16; mul++)
- {
- for(int index=0; index<8; index++)
- {
- if(formatSigned)
- {
- val16=get16bits11signed(base,tab,mul,index);
- valtab[count] = val16 + 256*128;
- }
- else
- valtab[count]=get16bits11bits(base,tab,mul,index);
- count++;
- }
- }
- }
- }
- }
- // Reads alpha data
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void readAlpha(uint8* &data, int &width, int &height, int &extendedwidth, int &extendedheight)
- {
- //width and height are already known..?
- uint8* tempdata;
- int wantedBitDepth;
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- wantedBitDepth=8;
- }
- else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- wantedBitDepth=16;
- }
- else
- {
- printf("invalid format for alpha reading!\n");
- exit(1);
- }
- fReadPGM("alpha.pgm",width,height,tempdata,wantedBitDepth);
- extendedwidth=4*((width+3)/4);
- extendedheight=4*((height+3)/4);
- if(width==extendedwidth&&height==extendedheight)
- {
- data=tempdata;
- }
- else
- {
- data = (uint8*)malloc(extendedwidth*extendedheight*wantedBitDepth/8);
- uint8 last=0;
- uint8 lastlast=0;
- for(int x=0; x<extendedwidth; x++)
- {
- for(int y=0; y<extendedheight; y++)
- {
- if(wantedBitDepth==8)
- {
- if(x<width&&y<height)
- {
- last = tempdata[x+y*width];
- }
- data[x+y*extendedwidth]=last;
- }
- else
- {
- if(x<width&&y<height)
- {
- last = tempdata[(x+y*width)*2];
- lastlast = tempdata[(x+y*width)*2+1];
- }
- data[(x+y*extendedwidth)*2]=last;
- data[(x+y*extendedwidth)*2+1]=lastlast;
- }
- }
- }
- }
- if(format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- for(int x=0; x<extendedwidth; x++)
- {
- for(int y=0; y<extendedheight; y++)
- {
- if(data[x+y*extendedwidth]<128)
- data[x+y*extendedwidth]=0;
- else
- data[x+y*extendedwidth]=255;
- }
- }
- }
- }*/
- // Compresses the alpha part of a GL_COMPRESSED_RGBA8_ETC2_EAC block.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockAlphaFast(uint8 * data, int ix, int iy, int width, int height, uint8* returnData)
- {
- int alphasum=0;
- int maxdist=-2;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- alphasum+=data[ix+x+(iy+y)*width];
- }
- }
- int alpha = (int)( ((float)alphasum)/16.0f+0.5f); //average pixel value, used as guess for base value.
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- if(abs(alpha-data[ix+x+(iy+y)*width])>maxdist)
- maxdist=abs(alpha-data[ix+x+(iy+y)*width]); //maximum distance from average
- }
- }
- int approxPos = (maxdist*255)/160-4; //experimentally derived formula for calculating approximate table position given a max distance from average
- if(approxPos>255)
- approxPos=255;
- int startTable=approxPos-15; //first table to be tested
- if(startTable<0)
- startTable=0;
- int endTable=clamp(approxPos+15); //last table to be tested
- int bestsum=1000000000;
- int besttable=-3;
- int bestalpha=128;
- int prevalpha=alpha;
- //main loop: determine best base alpha value and offset table to use for compression
- //try some different alpha tables.
- for(int table = startTable; table<endTable&&bestsum>0; table++)
- {
- int tablealpha=prevalpha;
- int tablebestsum=1000000000;
- //test some different alpha values, trying to find the best one for the given table.
- for(int alphascale=16; alphascale>0; alphascale/=4)
- {
- int startalpha;
- int endalpha;
- if(alphascale==16)
- {
- startalpha = clamp(tablealpha-alphascale*4);
- endalpha = clamp(tablealpha+alphascale*4);
- }
- else
- {
- startalpha = clamp(tablealpha-alphascale*2);
- endalpha = clamp(tablealpha+alphascale*2);
- }
- for(alpha=startalpha; alpha<=endalpha; alpha+=alphascale)
- {
- int sum=0;
- int val,diff,bestdiff=10000000,index;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- //compute best offset here, add square difference to sum..
- val=data[ix+x+(iy+y)*width];
- bestdiff=1000000000;
- //the values are always ordered from small to large, with the first 4 being negative and the last 4 positive
- //search is therefore made in the order 0-1-2-3 or 7-6-5-4, stopping when error increases compared to the previous entry tested.
- if(val>alpha)
- {
- for(index=7; index>3; index--)
- {
- diff=clamp_table[alpha+(int)(alphaTable[table][index])+255]-val;
- diff*=diff;
- if(diff<=bestdiff)
- {
- bestdiff=diff;
- }
- else
- break;
- }
- }
- else
- {
- for(index=0; index<4; index++)
- {
- diff=clamp_table[alpha+(int)(alphaTable[table][index])+255]-val;
- diff*=diff;
- if(diff<bestdiff)
- {
- bestdiff=diff;
- }
- else
- break;
- }
- }
- //best diff here is bestdiff, add it to sum!
- sum+=bestdiff;
- //if the sum here is worse than previously best already, there's no use in continuing the count..
- //note that tablebestsum could be used for more precise estimation, but the speedup gained here is deemed more important.
- if(sum>bestsum)
- {
- x=9999; //just to make it large and get out of the x<4 loop
- break;
- }
- }
- }
- if(sum<tablebestsum)
- {
- tablebestsum=sum;
- tablealpha=alpha;
- }
- if(sum<bestsum)
- {
- bestsum=sum;
- besttable=table;
- bestalpha=alpha;
- }
- }
- if(alphascale<=2)
- alphascale=0;
- }
- }
- alpha=bestalpha;
- //"good" alpha value and table are known!
- //store them, then loop through the pixels again and print indices.
- returnData[0]=alpha;
- returnData[1]=besttable;
- for(int pos=2; pos<8; pos++)
- {
- returnData[pos]=0;
- }
- int byte=2;
- int bit=0;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- //find correct index
- int besterror=1000000;
- int bestindex=99;
- for(int index=0; index<8; index++) //no clever ordering this time, as this loop is only run once per block anyway
- {
- int error= (clamp(alpha +(int)(alphaTable[besttable][index]))-data[ix+x+(iy+y)*width])*(clamp(alpha +(int)(alphaTable[besttable][index]))-data[ix+x+(iy+y)*width]);
- if(error<besterror)
- {
- besterror=error;
- bestindex=index;
- }
- }
- //best table index has been determined.
- //pack 3-bit index into compressed data, one bit at a time
- for(int numbit=0; numbit<3; numbit++)
- {
- returnData[byte]|=getbit(bestindex,2-numbit,7-bit);
- bit++;
- if(bit>7)
- {
- bit=0;
- byte++;
- }
- }
- }
- }
- }
- // Helper function for the below function
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*int getPremulIndex(int base, int tab, int mul, int index)
- {
- return (base<<11)+(tab<<7)+(mul<<3)+index;
- }
- // Calculates the error used in compressBlockAlpha16()
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calcError(uint8* data, int ix, int iy, int width, int height, int base, int tab, int mul, double prevbest)
- {
- int offset = getPremulIndex(base,tab,mul,0);
- double error=0;
- for (int y=0; y<4; y++)
- {
- for(int x=0; x<4; x++)
- {
- double besthere = (1<<20);
- besthere*=besthere;
- uint8 byte1 = data[2*(x+ix+(y+iy)*width)];
- uint8 byte2 = data[2*(x+ix+(y+iy)*width)+1];
- int alpha = (byte1<<8)+byte2;
- for(int index=0; index<8; index++)
- {
- double indexError;
- indexError = alpha-valtab[offset+index];
- indexError*=indexError;
- if(indexError<besthere)
- besthere=indexError;
- }
- error+=besthere;
- if(error>=prevbest)
- return prevbest+(1<<30);
- }
- }
- return error;
- }
- // compressBlockAlpha16
- //
- // Compresses a block using the 11-bit EAC formats.
- // Depends on the global variable formatSigned.
- //
- // COMPRESSED_R11_EAC (if formatSigned = 0)
- // This is an 11-bit unsigned format. Since we do not have a good 11-bit file format, we use 16-bit pgm instead.
- // Here we assume that, in the input 16-bit pgm file, 0 represents 0.0 and 65535 represents 1.0. The function compressBlockAlpha16
- // will find the compressed block which best matches the data. In detail, it will find the compressed block, which
- // if decompressed, will generate an 11-bit block that after bit replication to 16-bits will generate the closest
- // block to the original 16-bit pgm block.
- //
- // COMPRESSED_SIGNED_R11_EAC (if formatSigned = 1)
- // This is an 11-bit signed format. Since we do not have any signed file formats, we use unsigned 16-bit pgm instead.
- // Hence we assume that, in the input 16-bit pgm file, 1 represents -1.0, 32768 represents 0.0 and 65535 represents 1.0.
- // The function compresseBlockAlpha16 will find the compressed block, which if decompressed, will generate a signed
- // 11-bit block that after bit replication to 16-bits and conversion to unsigned (1 equals -1.0, 32768 equals 0.0 and
- // 65535 equals 1.0) will generate the closest block to the original 16-bit pgm block.
- //
- // COMPRESSED_RG11_EAC is compressed by calling the function twice, dito for COMPRESSED_SIGNED_RG11_EAC.
- //
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockAlpha16(uint8* data, int ix, int iy, int width, int height, uint8* returnData)
- {
- unsigned int bestbase, besttable, bestmul;
- double besterror;
- besterror=1<<20;
- besterror*=besterror;
- for(int base=0; base<256; base++)
- {
- for(int table=0; table<16; table++)
- {
- for(int mul=0; mul<16; mul++)
- {
- double e = calcError(data, ix, iy, width, height,base,table,mul,besterror);
- if(e<besterror)
- {
- bestbase=base;
- besttable=table;
- bestmul=mul;
- besterror=e;
- }
- }
- }
- }
- returnData[0]=bestbase;
- returnData[1]=(bestmul<<4)+besttable;
- if(formatSigned)
- {
- //if we have a signed format, the base value should be given as a signed byte.
- signed char signedbase = bestbase-128;
- returnData[0]=*((uint8*)(&signedbase));
- }
-
- for(int i=2; i<8; i++)
- {
- returnData[i]=0;
- }
- int byte=2;
- int bit=0;
- for (int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- double besterror=255*255;
- besterror*=besterror;
- int bestindex=99;
- uint8 byte1 = data[2*(x+ix+(y+iy)*width)];
- uint8 byte2 = data[2*(x+ix+(y+iy)*width)+1];
- int alpha = (byte1<<8)+byte2;
- for(unsigned int index=0; index<8; index++)
- {
- double indexError;
- if(formatSigned)
- {
- int16 val16;
- int val;
- val16 = get16bits11signed(bestbase,besttable,bestmul,index);
- val = val16 + 256*128;
- indexError = alpha-val;
- }
- else
- indexError = alpha-get16bits11bits(bestbase,besttable,bestmul,index);
- indexError*=indexError;
- if(indexError<besterror)
- {
- besterror=indexError;
- bestindex=index;
- }
- }
-
- for(int numbit=0; numbit<3; numbit++)
- {
- returnData[byte]|=getbit(bestindex,2-numbit,7-bit);
- bit++;
- if(bit>7)
- {
- bit=0;
- byte++;
- }
- }
- }
- }
- }*/
- // Exhaustive compression of alpha compression in a GL_COMPRESSED_RGB8_ETC2 block
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockAlphaSlow(uint8* data, int ix, int iy, int width, int height, uint8* returnData)
- {
- //determine the best table and base alpha value for this block using MSE
- int alphasum=0;
- int maxdist=-2;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- alphasum+=data[ix+x+(iy+y)*width];
- }
- }
- int alpha = (int)( ((float)alphasum)/16.0f+0.5f); //average pixel value, used as guess for base value.
- int bestsum=1000000000;
- int besttable=-3;
- int bestalpha=128;
- int prevalpha=alpha;
- //main loop: determine best base alpha value and offset table to use for compression
- //try some different alpha tables.
- for(int table = 0; table<256&&bestsum>0; table++)
- {
- int tablealpha=prevalpha;
- int tablebestsum=1000000000;
- //test some different alpha values, trying to find the best one for the given table.
- for(int alphascale=32; alphascale>0; alphascale/=8)
- {
-
- int startalpha = clamp(tablealpha-alphascale*4);
- int endalpha = clamp(tablealpha+alphascale*4);
-
- for(alpha=startalpha; alpha<=endalpha; alpha+=alphascale) {
- int sum=0;
- int val,diff,bestdiff=10000000,index;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- //compute best offset here, add square difference to sum..
- val=data[ix+x+(iy+y)*width];
- bestdiff=1000000000;
- //the values are always ordered from small to large, with the first 4 being negative and the last 4 positive
- //search is therefore made in the order 0-1-2-3 or 7-6-5-4, stopping when error increases compared to the previous entry tested.
- if(val>alpha)
- {
- for(index=7; index>3; index--)
- {
- diff=clamp_table[alpha+(alphaTable[table][index])+255]-val;
- diff*=diff;
- if(diff<=bestdiff)
- {
- bestdiff=diff;
- }
- else
- break;
- }
- }
- else
- {
- for(index=0; index<5; index++)
- {
- diff=clamp_table[alpha+(alphaTable[table][index])+255]-val;
- diff*=diff;
- if(diff<bestdiff)
- {
- bestdiff=diff;
- }
- else
- break;
- }
- }
- //best diff here is bestdiff, add it to sum!
- sum+=bestdiff;
- //if the sum here is worse than previously best already, there's no use in continuing the count..
- if(sum>tablebestsum)
- {
- x=9999; //just to make it large and get out of the x<4 loop
- break;
- }
- }
- }
- if(sum<tablebestsum)
- {
- tablebestsum=sum;
- tablealpha=alpha;
- }
- if(sum<bestsum)
- {
- bestsum=sum;
- besttable=table;
- bestalpha=alpha;
- }
- }
- if(alphascale==4)
- alphascale=8;
- }
- }
- alpha=bestalpha;
- //the best alpha value and table are known!
- //store them, then loop through the pixels again and print indices.
- returnData[0]=alpha;
- returnData[1]=besttable;
- for(int pos=2; pos<8; pos++)
- {
- returnData[pos]=0;
- }
- int byte=2;
- int bit=0;
- for(int x=0; x<4; x++)
- {
- for(int y=0; y<4; y++)
- {
- //find correct index
- int besterror=1000000;
- int bestindex=99;
- for(int index=0; index<8; index++) //no clever ordering this time, as this loop is only run once per block anyway
- {
- int error= (clamp(alpha +(int)(alphaTable[besttable][index]))-data[ix+x+(iy+y)*width])*(clamp(alpha +(int)(alphaTable[besttable][index]))-data[ix+x+(iy+y)*width]);
- if(error<besterror)
- {
- besterror=error;
- bestindex=index;
- }
- }
- //best table index has been determined.
- //pack 3-bit index into compressed data, one bit at a time
- for(int numbit=0; numbit<3; numbit++)
- {
- returnData[byte]|=getbit(bestindex,2-numbit,7-bit);
- bit++;
- if(bit>7)
- {
- bit=0;
- byte++;
- }
- }
- }
- }
- }
- // Calculate weighted PSNR
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*double calculateWeightedPSNR(uint8 *lossyimg, uint8 *origimg, int width, int height, double w1, double w2, double w3)
- {
- // Note: This calculation of PSNR uses the formula
- //
- // PSNR = 10 * log_10 ( 255^2 / wMSE )
- //
- // where the wMSE is calculated as
- //
- // 1/(N*M) * sum ( ( w1*(R' - R)^2 + w2*(G' - G)^2 + w3*(B' - B)^2) )
- //
- // typical weights are 0.299, 0.587, 0.114 for perceptually weighted PSNR and
- // 1.0/3.0, 1.0/3.0, 1.0/3.0 for nonweighted PSNR
- int x,y;
- double wMSE;
- double PSNR;
- double err;
- wMSE = 0;
- for(y=0;y<height;y++)
- {
- for(x=0;x<width;x++)
- {
- err = lossyimg[y*width*3+x*3+0] - origimg[y*width*3+x*3+0];
- wMSE = wMSE + (w1*(err * err));
- err = lossyimg[y*width*3+x*3+1] - origimg[y*width*3+x*3+1];
- wMSE = wMSE + (w2*(err * err));
- err = lossyimg[y*width*3+x*3+2] - origimg[y*width*3+x*3+2];
- wMSE = wMSE + (w3*(err * err));
- }
- }
- wMSE = wMSE / (width * height);
- if(wMSE == 0)
- {
- printf("********************************************************************\n");
- printf("There is no difference at all between image files --- infinite PSNR.\n");
- printf("********************************************************************\n");
- }
- PSNR = 10*log((1.0*255*255)/wMSE)/log(10.0);
- return PSNR;
- }
- // Calculate unweighted PSNR (weights are (1,1,1))
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculatePSNR(uint8 *lossyimg, uint8 *origimg, int width, int height)
- {
- // Note: This calculation of PSNR uses the formula
- //
- // PSNR = 10 * log_10 ( 255^2 / MSE )
- //
- // where the MSE is calculated as
- //
- // 1/(N*M) * sum ( 1/3 * ((R' - R)^2 + (G' - G)^2 + (B' - B)^2) )
- //
- // The reason for having the 1/3 factor is the following:
- // Presume we have a grayscale image, that is acutally just the red component
- // of a color image.. The squared error is then (R' - R)^2.
- // Assume that we have a certain signal to noise ratio, say 30 dB. If we add
- // another two components (say green and blue) with the same signal to noise
- // ratio, we want the total signal to noise ratio be the same. For the
- // squared error to remain constant we must divide by three after adding
- // together the squared errors of the components.
- return calculateWeightedPSNR(lossyimg, origimg, width, height, (1.0/3.0), (1.0/3.0), (1.0/3.0));
- }
- // Decompresses a file
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void uncompressFile(char *srcfile, uint8* &img, uint8 *&alphaimg, int& active_width, int& active_height)
- {
- FILE *f;
- int width,height;
- unsigned int block_part1, block_part2;
- uint8 *newimg, *newalphaimg, *alphaimg2;
- unsigned short w, h;
- int xx, yy;
- unsigned char magic[4];
- unsigned char version[2];
- unsigned short texture_type;
- if(f=fopen(srcfile,"rb"))
- {
- // Load table
- readCompressParams();
- if(ktxFile)
- {
- //read ktx header..
- KTX_header header;
- fread(&header,sizeof(KTX_header),1,f);
- //read size parameter, which we don't actually need..
- unsigned int bitsize;
- fread(&bitsize,sizeof(unsigned int),1,f);
-
- active_width=header.pixelWidth;
- active_height = header.pixelHeight;
- w = ((active_width+3)/4)*4;
- h = ((active_height+3)/4)*4;
- width=w;
- height=h;
- if(header.glInternalFormat==GL_COMPRESSED_SIGNED_R11_EAC)
- {
- format=ETC2PACKAGE_R_NO_MIPMAPS;
- formatSigned=1;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_R11_EAC)
- {
- format=ETC2PACKAGE_R_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_SIGNED_RG11_EAC)
- {
- format=ETC2PACKAGE_RG_NO_MIPMAPS;
- formatSigned=1;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_RG11_EAC)
- {
- format=ETC2PACKAGE_RG_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_RGB8_ETC2)
- {
- format=ETC2PACKAGE_RGB_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_SRGB8_ETC2)
- {
- format=ETC2PACKAGE_sRGB_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_RGBA8_ETC2_EAC)
- {
- format=ETC2PACKAGE_RGBA_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC)
- {
- format=ETC2PACKAGE_sRGBA_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2)
- {
- format=ETC2PACKAGE_RGBA1_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2)
- {
- format=ETC2PACKAGE_sRGBA1_NO_MIPMAPS;
- }
- else if(header.glInternalFormat==GL_ETC1_RGB8_OES)
- {
- format=ETC1_RGB_NO_MIPMAPS;
- codec=CODEC_ETC;
- }
- else
- {
- printf("ktx file has unknown glInternalFormat (not etc compressed)!\n");
- exit(1);
- }
- }
- else
- {
- // Read magic nunmber
- fread(&magic[0], sizeof(unsigned char), 1, f);
- fread(&magic[1], sizeof(unsigned char), 1, f);
- fread(&magic[2], sizeof(unsigned char), 1, f);
- fread(&magic[3], sizeof(unsigned char), 1, f);
- if(!(magic[0] == 'P' && magic[1] == 'K' && magic[2] == 'M' && magic[3] == ' '))
- {
- printf("\n\n The file %s is not a .pkm file.\n",srcfile);
- exit(1);
- }
-
- // Read version
- fread(&version[0], sizeof(unsigned char), 1, f);
- fread(&version[1], sizeof(unsigned char), 1, f);
- if( version[0] == '1' && version[1] == '0' )
- {
- // Read texture type
- read_big_endian_2byte_word(&texture_type, f);
- if(!(texture_type == ETC1_RGB_NO_MIPMAPS))
- {
- printf("\n\n The file %s (of version %c.%c) does not contain a texture of known format.\n", srcfile, version[0],version[1]);
- printf("Known formats: ETC1_RGB_NO_MIPMAPS.\n", srcfile);
- exit(1);
- }
- }
- else if( version[0] == '2' && version[1] == '0' )
- {
- // Read texture type
- read_big_endian_2byte_word(&texture_type, f);
- if(texture_type==ETC2PACKAGE_RG_SIGNED_NO_MIPMAPS)
- {
- texture_type=ETC2PACKAGE_RG_NO_MIPMAPS;
- formatSigned=1;
- //printf("Decompressing 2-channel signed data\n");
- }
- if(texture_type==ETC2PACKAGE_R_SIGNED_NO_MIPMAPS)
- {
- texture_type=ETC2PACKAGE_R_NO_MIPMAPS;
- formatSigned=1;
- //printf("Decompressing 1-channel signed data\n");
- }
- if(texture_type==ETC2PACKAGE_sRGB_NO_MIPMAPS)
- {
- // The SRGB formats are decoded just as RGB formats -- use RGB format for decompression.
- texture_type=ETC2PACKAGE_RGB_NO_MIPMAPS;
- }
- if(texture_type==ETC2PACKAGE_sRGBA_NO_MIPMAPS)
- {
- // The SRGB formats are decoded just as RGB formats -- use RGB format for decompression.
- texture_type=ETC2PACKAGE_RGBA_NO_MIPMAPS;
- }
- if(texture_type==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- // The SRGB formats are decoded just as RGB formats -- use RGB format for decompression.
- texture_type=ETC2PACKAGE_sRGBA1_NO_MIPMAPS;
- }
- if(texture_type==ETC2PACKAGE_RGBA_NO_MIPMAPS_OLD)
- {
- printf("\n\nThe file %s contains a compressed texture created using an old version of ETCPACK.\n",srcfile);
- printf("decompression is not supported in this version.\n");
- exit(1);
- }
- if(!(texture_type==ETC2PACKAGE_RGB_NO_MIPMAPS||texture_type==ETC2PACKAGE_sRGB_NO_MIPMAPS||texture_type==ETC2PACKAGE_RGBA_NO_MIPMAPS||texture_type==ETC2PACKAGE_sRGBA_NO_MIPMAPS||texture_type==ETC2PACKAGE_R_NO_MIPMAPS||texture_type==ETC2PACKAGE_RG_NO_MIPMAPS||texture_type==ETC2PACKAGE_RGBA1_NO_MIPMAPS||texture_type==ETC2PACKAGE_sRGBA1_NO_MIPMAPS))
- {
- printf("\n\n The file %s does not contain a texture of known format.\n", srcfile);
- printf("Known formats: ETC2PACKAGE_RGB_NO_MIPMAPS.\n", srcfile);
- exit(1);
- }
- }
- else
- {
- printf("\n\n The file %s is not of version 1.0 or 2.0 but of version %c.%c.\n",srcfile, version[0], version[1]);
- printf("Aborting.\n");
- exit(1);
- }
- format=texture_type;
- printf("textype: %d\n",texture_type);
- // ETC2 is backwards compatible, which means that an ETC2-capable decompressor can also handle
- // old ETC1 textures without any problems. Thus a version 1.0 file with ETC1_RGB_NO_MIPMAPS and a
- // version 2.0 file with ETC2PACKAGE_RGB_NO_MIPMAPS can be handled by the same ETC2-capable decompressor
- // Read how many pixels the blocks make up
- read_big_endian_2byte_word(&w, f);
- read_big_endian_2byte_word(&h, f);
- width = w;
- height = h;
- // Read how many pixels contain active data (the rest are just
- // for making sure we have a 4*a x 4*b size).
- read_big_endian_2byte_word(&w, f);
- read_big_endian_2byte_word(&h, f);
- active_width = w;
- active_height = h;
- }
- printf("Width = %d, Height = %d\n",width, height);
- printf("active pixel area: top left %d x %d area.\n",active_width, active_height);
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- img=(uint8*)malloc(3*width*height*2);
- else
- img=(uint8*)malloc(3*width*height);
- if(!img)
- {
- printf("Error: could not allocate memory\n");
- exit(0);
- }
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_R_NO_MIPMAPS||format==ETC2PACKAGE_RG_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- //printf("alpha channel decompression\n");
- alphaimg=(uint8*)malloc(width*height*2);
- setupAlphaTableAndValtab();
- if(!alphaimg)
- {
- printf("Error: could not allocate memory for alpha\n");
- exit(0);
- }
- }
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- alphaimg2=(uint8*)malloc(width*height*2);
- if(!alphaimg2)
- {
- printf("Error: could not allocate memory\n");
- exit(0);
- }
- }
- for(int y=0;y<height/4;y++)
- {
- for(int x=0;x<width/4;x++)
- {
- //decode alpha channel for RGBA
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS)
- {
- uint8 alphablock[8];
- fread(alphablock,1,8,f);
- decompressBlockAlpha(alphablock,alphaimg,width,height,4*x,4*y);
- }
- //color channels for most normal modes
- if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- //we have normal ETC2 color channels, decompress these
- read_big_endian_4byte_word(&block_part1,f);
- read_big_endian_4byte_word(&block_part2,f);
- if(format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- decompressBlockETC21BitAlpha(block_part1, block_part2,img,alphaimg,width,height,4*x,4*y);
- else
- decompressBlockETC2(block_part1, block_part2,img,width,height,4*x,4*y);
- }
- //one or two 11-bit alpha channels for R or RG.
- if(format==ETC2PACKAGE_R_NO_MIPMAPS||format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- uint8 alphablock[8];
- fread(alphablock,1,8,f);
- decompressBlockAlpha16bit(alphablock,alphaimg,width,height,4*x,4*y);
- }
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- uint8 alphablock[8];
- fread(alphablock,1,8,f);
- decompressBlockAlpha16bit(alphablock,alphaimg2,width,height,4*x,4*y);
- }
- }
- }
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- for(int y=0;y<height;y++)
- {
- for(int x=0;x<width;x++)
- {
- img[6*(y*width+x)]=alphaimg[2*(y*width+x)];
- img[6*(y*width+x)+1]=alphaimg[2*(y*width+x)+1];
- img[6*(y*width+x)+2]=alphaimg2[2*(y*width+x)];
- img[6*(y*width+x)+3]=alphaimg2[2*(y*width+x)+1];
- img[6*(y*width+x)+4]=0;
- img[6*(y*width+x)+5]=0;
- }
- }
- }
- // Ok, and now only write out the active pixels to the .ppm file.
- // (But only if the active pixels differ from the total pixels)
- if( !(height == active_height && width == active_width) )
- {
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- newimg=(uint8*)malloc(3*active_width*active_height*2);
- else
- newimg=(uint8*)malloc(3*active_width*active_height);
-
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_R_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- newalphaimg = (uint8*)malloc(active_width*active_height*2);
- }
- if(!newimg)
- {
- printf("Error: could not allocate memory\n");
- exit(0);
- }
-
- // Convert from total area to active area:
- for(yy = 0; yy<active_height; yy++)
- {
- for(xx = 0; xx< active_width; xx++)
- {
- if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- newimg[ (yy*active_width)*3 + xx*3 + 0 ] = img[ (yy*width)*3 + xx*3 + 0];
- newimg[ (yy*active_width)*3 + xx*3 + 1 ] = img[ (yy*width)*3 + xx*3 + 1];
- newimg[ (yy*active_width)*3 + xx*3 + 2 ] = img[ (yy*width)*3 + xx*3 + 2];
- }
- else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- newimg[ (yy*active_width)*6 + xx*6 + 0 ] = img[ (yy*width)*6 + xx*6 + 0];
- newimg[ (yy*active_width)*6 + xx*6 + 1 ] = img[ (yy*width)*6 + xx*6 + 1];
- newimg[ (yy*active_width)*6 + xx*6 + 2 ] = img[ (yy*width)*6 + xx*6 + 2];
- newimg[ (yy*active_width)*6 + xx*6 + 3 ] = img[ (yy*width)*6 + xx*6 + 3];
- newimg[ (yy*active_width)*6 + xx*6 + 4 ] = img[ (yy*width)*6 + xx*6 + 4];
- newimg[ (yy*active_width)*6 + xx*6 + 5 ] = img[ (yy*width)*6 + xx*6 + 5];
- }
- if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- newalphaimg[ ((yy*active_width) + xx)*2] = alphaimg[2*((yy*width) + xx)];
- newalphaimg[ ((yy*active_width) + xx)*2+1] = alphaimg[2*((yy*width) + xx)+1];
- }
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- newalphaimg[ ((yy*active_width) + xx)] = alphaimg[((yy*width) + xx)];
- }
- }
- }
- free(img);
- img = newimg;
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_R_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- free(alphaimg);
- alphaimg=newalphaimg;
- }
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- free(alphaimg);
- free(alphaimg2);
- alphaimg = NULL;
- alphaimg2 = NULL;
- }
- }
- }
- else
- {
- printf("Error: could not open <%s>.\n",srcfile);
- exit(1);
- }
- height=active_height;
- width=active_width;
- fclose(f);
- }
- // Writes output file
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void writeOutputFile(char *dstfile, uint8* img, uint8* alphaimg, int width, int height)
- {
- char str[300];
- if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- fWritePPM("tmp.ppm",width,height,img,8,false);
- printf("Saved file tmp.ppm \n\n");
- }
- else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- fWritePPM("tmp.ppm",width,height,img,16,false);
- }
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- fWritePGM("alphaout.pgm",width,height,alphaimg,false,8);
- if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- fWritePGM("alphaout.pgm",width,height,alphaimg,false,16);
- // Delete destination file if it exists
- if(fileExist(dstfile))
- {
- sprintf(str, "del %s\n",dstfile);
- system(str);
- }
- int q = find_pos_of_extension(dstfile);
- if(!strcmp(&dstfile[q],".ppm")&&format!=ETC2PACKAGE_R_NO_MIPMAPS)
- {
- // Already a .ppm file. Just rename.
- sprintf(str,"move tmp.ppm %s\n",dstfile);
- printf("Renaming destination file to %s\n",dstfile);
- }
- else
- {
- // Converting from .ppm to other file format
- //
- // Use your favorite command line image converter program,
- // for instance Image Magick. Just make sure the syntax can
- // be written as below:
- //
- // C:\imconv source.ppm dest.jpg
- //
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- // Somewhere after version 6.7.1-2 of ImageMagick the following command gives the wrong result due to a bug.
- // sprintf(str,"composite -compose CopyOpacity alphaout.pgm tmp.ppm %s\n",dstfile);
- // Instead we read the file and write a tga.
- printf("Converting destination file from .ppm/.pgm to %s with alpha\n",dstfile);
- int rw, rh;
- unsigned char *pixelsRGB;
- unsigned char *pixelsA;
- fReadPPM("tmp.ppm", rw, rh, pixelsRGB, 8);
- fReadPGM("alphaout.pgm", rw, rh, pixelsA, 8);
- fWriteTGAfromRGBandA(dstfile, rw, rh, pixelsRGB, pixelsA, true);
- free(pixelsRGB);
- free(pixelsA);
- sprintf(str,""); // Nothing to execute.
- }
- else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- sprintf(str,"imconv alphaout.pgm %s\n",dstfile);
- printf("Converting destination file from .pgm to %s\n",dstfile);
- }
- else
- {
- sprintf(str,"imconv tmp.ppm %s\n",dstfile);
- printf("Converting destination file from .ppm to %s\n",dstfile);
- }
- }
- // Execute system call
- system(str);
-
- free(img);
- if(alphaimg!=NULL)
- free(alphaimg);
- }
- // Calculates the PSNR between two files
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculatePSNRfile(char *srcfile, uint8 *origimg, uint8* origalpha)
- {
- uint8 *alphaimg, *img;
- int active_width, active_height;
- uncompressFile(srcfile,img,alphaimg,active_width,active_height);
- // calculate Mean Square Error (MSE)
- double MSER=0,MSEG=0,MSEB=0,MSEA, PSNRR,PSNRG,PSNRA;
- double MSE;
- double wMSE;
- double PSNR=0;
- double wPSNR;
- double err;
- MSE = 0;
- MSEA=0;
- wMSE = 0;
- int width=((active_width+3)/4)*4;
- int height=((active_height+3)/4)*4;
- int numpixels = 0;
- for(int y=0;y<active_height;y++)
- {
- for(int x=0;x<active_width;x++)
- {
- if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- //we have regular color channels..
- if((format != ETC2PACKAGE_RGBA1_NO_MIPMAPS && format != ETC2PACKAGE_sRGBA1_NO_MIPMAPS) || alphaimg[y*width + x] > 0)
- {
- err = img[y*active_width*3+x*3+0] - origimg[y*width*3+x*3+0];
- MSE += ((err * err)/3.0);
- wMSE += PERCEPTUAL_WEIGHT_R_SQUARED * (err*err);
- err = img[y*active_width*3+x*3+1] - origimg[y*width*3+x*3+1];
- MSE += ((err * err)/3.0);
- wMSE += PERCEPTUAL_WEIGHT_G_SQUARED * (err*err);
- err = img[y*active_width*3+x*3+2] - origimg[y*width*3+x*3+2];
- MSE += ((err * err)/3.0);
- wMSE += PERCEPTUAL_WEIGHT_B_SQUARED * (err*err);
- numpixels++;
- }
- }
- else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- int rorig = (origimg[6*(y*width+x)+0]<<8)+origimg[6*(y*width+x)+1];
- int rnew = ( img[6*(y*active_width+x)+0]<<8)+ img[6*(y*active_width+x)+1];
- int gorig = (origimg[6*(y*width+x)+2]<<8)+origimg[6*(y*width+x)+3];
- int gnew = ( img[6*(y*active_width+x)+2]<<8)+ img[6*(y*active_width+x)+3];
- err=rorig-rnew;
- MSER+=(err*err);
- err=gorig-gnew;
- MSEG+=(err*err);
- }
- else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- int aorig = (((int)origalpha[2*(y*width+x)+0])<<8)+origalpha[2*(y*width+x)+1];
- int anew = (((int)alphaimg[2*(y*active_width+x)+0])<<8)+alphaimg[2*(y*active_width+x)+1];
- err=aorig-anew;
- MSEA+=(err*err);
- }
- }
- }
- if(format == ETC2PACKAGE_RGBA1_NO_MIPMAPS || format == ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- MSE = MSE / (1.0 * numpixels);
- wMSE = wMSE / (1.0 * numpixels);
- PSNR = 10*log((1.0*255*255)/MSE)/log(10.0);
- wPSNR = 10*log((1.0*255*255)/wMSE)/log(10.0);
- printf("PSNR only calculated on pixels where compressed alpha > 0\n");
- printf("color PSNR: %lf\nweighted PSNR: %lf\n",PSNR,wPSNR);
- }
- else if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- MSE = MSE / (active_width * active_height);
- wMSE = wMSE / (active_width * active_height);
- PSNR = 10*log((1.0*255*255)/MSE)/log(10.0);
- wPSNR = 10*log((1.0*255*255)/wMSE)/log(10.0);
- if(format == ETC2PACKAGE_RGBA_NO_MIPMAPS || format == ETC2PACKAGE_sRGBA_NO_MIPMAPS)
- printf("PSNR only calculated on RGB, not on alpha\n");
- printf("color PSNR: %lf\nweighted PSNR: %lf\n",PSNR,wPSNR);
- }
- else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- MSER = MSER / (active_width * active_height);
- MSEG = MSEG / (active_width * active_height);
- PSNRR = 10*log((1.0*65535*65535)/MSER)/log(10.0);
- PSNRG = 10*log((1.0*65535*65535)/MSEG)/log(10.0);
- printf("red PSNR: %lf\ngreen PSNR: %lf\n",PSNRR,PSNRG);
- }
- else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- MSEA = MSEA / (active_width * active_height);
- PSNRA = 10*log((1.0*65535.0*65535.0)/MSEA)/log(10.0);
- printf("PSNR: %lf\n",PSNRA);
- }
- free(img);
- return PSNR;
- }*/
- //// Exhaustive code starts here.
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precomutes a table that is used when compressing a block exhaustively
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- inline unsigned int precompute_3bittable_all_subblocksRG_withtest_perceptual1000(uint8 *block,uint8 *avg_color, unsigned int *precalc_err_UL_R, unsigned int *precalc_err_UR_R, unsigned int *precalc_err_LL_R, unsigned int *precalc_err_LR_R,unsigned int *precalc_err_UL_RG, unsigned int *precalc_err_UR_RG, unsigned int *precalc_err_LL_RG, unsigned int *precalc_err_LR_RG, unsigned int best_err)
- {
- int table;
- int index;
- int orig[3],approx[3][4];
- int x;
- int intensity_modifier;
- const int *table_indices;
- int good_enough_to_test;
- unsigned int err[4];
- unsigned int err_this_table_upper;
- unsigned int err_this_table_lower;
- unsigned int err_this_table_left;
- unsigned int err_this_table_right;
- // If the error in the red and green component is already larger than best_err for all 8 tables in
- // all of upper, lower, left and right, this combination of red and green will never be used in
- // the optimal color configuration. Therefore we can avoid testing all the blue colors for this
- // combination.
- good_enough_to_test = false;
- for(table=0;table<8;table++) // try all the 8 tables.
- {
- table_indices = &compressParamsFast[table*4];
- intensity_modifier = table_indices[0];
- approx[1][0]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- intensity_modifier = table_indices[1];
- approx[1][1]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- intensity_modifier = table_indices[2];
- approx[1][2]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- intensity_modifier = table_indices[3];
- approx[1][3]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- err_this_table_upper = 0;
- err_this_table_lower = 0;
- err_this_table_left = 0;
- err_this_table_right = 0;
- for(x=0; x<4; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_UL_R[table*4*4+x*4+index]
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000 * SQUARE(approx[1][index]-orig[1]);
- precalc_err_UL_RG[table*4*4+x*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_left+=err[0];
- }
- for(x=4; x<8; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_UR_R[table*4*4+(x-4)*4+index]
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000 * SQUARE(approx[1][index]-orig[1]);
- precalc_err_UR_RG[table*4*4+(x-4)*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_right+=err[0];
- }
- for(x=8; x<12; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_LL_R[table*4*4+(x-8)*4+index]
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000 * SQUARE(approx[1][index]-orig[1]);
- precalc_err_LL_RG[table*4*4+(x-8)*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_left+=err[0];
- }
- for(x=12; x<16; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_LR_R[table*4*4+(x-12)*4+index]
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000 * SQUARE(approx[1][index]-orig[1]);
- precalc_err_LR_RG[table*4*4+(x-12)*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_right+=err[0];
- }
- if(err_this_table_upper < best_err)
- good_enough_to_test = true;
- if(err_this_table_lower < best_err)
- good_enough_to_test = true;
- if(err_this_table_left < best_err)
- good_enough_to_test = true;
- if(err_this_table_right < best_err)
- good_enough_to_test = true;
- }
- return good_enough_to_test;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precomutes a table that is used when compressing a block exhaustively
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- inline int precompute_3bittable_all_subblocksRG_withtest(uint8 *block,uint8 *avg_color, unsigned int *precalc_err_UL_R, unsigned int *precalc_err_UR_R, unsigned int *precalc_err_LL_R, unsigned int *precalc_err_LR_R,unsigned int *precalc_err_UL_RG, unsigned int *precalc_err_UR_RG, unsigned int *precalc_err_LL_RG, unsigned int *precalc_err_LR_RG, unsigned int best_err)
- {
- int table;
- int index;
- int orig[3],approx[3][4];
- int x;
- int intensity_modifier;
- const int *table_indices;
- int good_enough_to_test;
- unsigned int err[4];
- unsigned int err_this_table_upper;
- unsigned int err_this_table_lower;
- unsigned int err_this_table_left;
- unsigned int err_this_table_right;
- // If the error in the red and green component is already larger than best_err for all 8 tables in
- // all of upper, lower, left and right, this combination of red and green will never be used in
- // the optimal color configuration. Therefore we can avoid testing all the blue colors for this
- // combination.
- good_enough_to_test = false;
- for(table=0;table<8;table++) // try all the 8 tables.
- {
- table_indices = &compressParamsFast[table*4];
- intensity_modifier = table_indices[0];
- approx[1][0]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- intensity_modifier = table_indices[1];
- approx[1][1]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- intensity_modifier = table_indices[2];
- approx[1][2]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- intensity_modifier = table_indices[3];
- approx[1][3]=CLAMP(0, avg_color[1]+intensity_modifier,255);
- err_this_table_upper = 0;
- err_this_table_lower = 0;
- err_this_table_left = 0;
- err_this_table_right = 0;
- for(x=0; x<4; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_UL_R[table*4*4+x*4+index]+SQUARE(approx[1][index]-orig[1]);
- precalc_err_UL_RG[table*4*4+x*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_left+=err[0];
- }
- for(x=4; x<8; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_UR_R[table*4*4+(x-4)*4+index]+SQUARE(approx[1][index]-orig[1]);
- precalc_err_UR_RG[table*4*4+(x-4)*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_right+=err[0];
- }
- for(x=8; x<12; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_LL_R[table*4*4+(x-8)*4+index]+SQUARE(approx[1][index]-orig[1]);
- precalc_err_LL_RG[table*4*4+(x-8)*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_left+=err[0];
- }
- for(x=12; x<16; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index] = precalc_err_LR_R[table*4*4+(x-12)*4+index]+SQUARE(approx[1][index]-orig[1]);
- precalc_err_LR_RG[table*4*4+(x-12)*4+index] = err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_right+=err[0];
- }
- if(err_this_table_upper < best_err)
- good_enough_to_test = true;
- if(err_this_table_lower < best_err)
- good_enough_to_test = true;
- if(err_this_table_left < best_err)
- good_enough_to_test = true;
- if(err_this_table_right < best_err)
- good_enough_to_test = true;
- }
- return good_enough_to_test;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precomutes a table that is used when compressing a block exhaustively
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- inline unsigned int precompute_3bittable_all_subblocksR_with_test_perceptual1000(uint8 *block,uint8 *avg_color, unsigned int *precalc_err_UL_R, unsigned int *precalc_err_UR_R, unsigned int *precalc_err_LL_R, unsigned int *precalc_err_LR_R, unsigned int best_err)
- {
- int table;
- int index;
- int orig[3],approx[3][4];
- int x;
- int intensity_modifier;
- const int *table_indices;
- unsigned int err[4];
- unsigned int err_this_table_upper;
- unsigned int err_this_table_lower;
- unsigned int err_this_table_left;
- unsigned int err_this_table_right;
- int good_enough_to_test;
- good_enough_to_test = false;
- for(table=0;table<8;table++) // try all the 8 tables.
- {
- err_this_table_upper = 0;
- err_this_table_lower = 0;
- err_this_table_left = 0;
- err_this_table_right = 0;
- table_indices = &compressParamsFast[table*4];
- intensity_modifier = table_indices[0];
- approx[0][0]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- intensity_modifier = table_indices[1];
- approx[0][1]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- intensity_modifier = table_indices[2];
- approx[0][2]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- intensity_modifier = table_indices[3];
- approx[0][3]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- for(x=0; x<4; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(approx[0][index]-orig[0]);
- precalc_err_UL_R[table*4*4+x*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_left+=err[0];
- }
- for(x=4; x<8; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(approx[0][index]-orig[0]);
- precalc_err_UR_R[table*4*4+(x-4)*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_right+=err[0];
- }
- for(x=8; x<12; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(approx[0][index]-orig[0]);
- precalc_err_LL_R[table*4*4+(x-8)*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_left+=err[0];
-
- }
- for(x=12; x<16; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(approx[0][index]-orig[0]);
- precalc_err_LR_R[table*4*4+(x-12)*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_right+=err[0];
- }
- if(err_this_table_upper < best_err)
- good_enough_to_test = true;
- if(err_this_table_lower < best_err)
- good_enough_to_test = true;
- if(err_this_table_left < best_err)
- good_enough_to_test = true;
- if(err_this_table_right < best_err)
- good_enough_to_test = true;
- }
- return good_enough_to_test;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precomutes a table that is used when compressing a block exhaustively
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- inline int precompute_3bittable_all_subblocksR_with_test(uint8 *block,uint8 *avg_color, unsigned int *precalc_err_UL_R, unsigned int *precalc_err_UR_R, unsigned int *precalc_err_LL_R, unsigned int *precalc_err_LR_R, unsigned int best_err)
- {
- int table;
- int index;
- int orig[3],approx[3][4];
- int x;
- int intensity_modifier;
- const int *table_indices;
- unsigned int err[4];
- unsigned int err_this_table_upper;
- unsigned int err_this_table_lower;
- unsigned int err_this_table_left;
- unsigned int err_this_table_right;
- int good_enough_to_test;
- good_enough_to_test = false;
- for(table=0;table<8;table++) // try all the 8 tables.
- {
- err_this_table_upper = 0;
- err_this_table_lower = 0;
- err_this_table_left = 0;
- err_this_table_right = 0;
- table_indices = &compressParamsFast[table*4];
- intensity_modifier = table_indices[0];
- approx[0][0]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- intensity_modifier = table_indices[1];
- approx[0][1]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- intensity_modifier = table_indices[2];
- approx[0][2]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- intensity_modifier = table_indices[3];
- approx[0][3]=CLAMP(0, avg_color[0]+intensity_modifier,255);
- for(x=0; x<4; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=SQUARE(approx[0][index]-orig[0]);
- precalc_err_UL_R[table*4*4+x*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_left+=err[0];
- }
- for(x=4; x<8; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=SQUARE(approx[0][index]-orig[0]);
- precalc_err_UR_R[table*4*4+(x-4)*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_upper+=err[0];
- err_this_table_right+=err[0];
- }
- for(x=8; x<12; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=SQUARE(approx[0][index]-orig[0]);
- precalc_err_LL_R[table*4*4+(x-8)*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_left+=err[0];
-
- }
- for(x=12; x<16; x++)
- {
- orig[0]=block[x*4];
- orig[1]=block[x*4+1];
- orig[2]=block[x*4+2];
- for(index=0;index<4;index++)
- {
- err[index]=SQUARE(approx[0][index]-orig[0]);
- precalc_err_LR_R[table*4*4+(x-12)*4+index]=err[index];
- }
- if(err[0] > err[1])
- err[0] = err[1];
- if(err[2] > err[3])
- err[2] = err[3];
- if(err[0] > err[2])
- err[0] = err[2];
- err_this_table_lower+=err[0];
- err_this_table_right+=err[0];
- }
- if(err_this_table_upper < best_err)
- good_enough_to_test = true;
- if(err_this_table_lower < best_err)
- good_enough_to_test = true;
- if(err_this_table_left < best_err)
- good_enough_to_test = true;
- if(err_this_table_right < best_err)
- good_enough_to_test = true;
- }
- return good_enough_to_test;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Tries all index-tables, used when compressing a block exhaustively
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- inline void tryalltables_3bittable_all_subblocks_using_precalc(uint8 *block_2x2,uint8 *color_quant1, unsigned int *precalc_err_UL_RG, unsigned int *precalc_err_UR_RG, unsigned int *precalc_err_LL_RG, unsigned int *precalc_err_LR_RG, unsigned int &err_upper, unsigned int &err_lower, unsigned int &err_left, unsigned int &err_right, unsigned int best_err)
- {
- unsigned int err_this_table_upper;
- unsigned int err_this_table_lower;
- unsigned int err_this_table_left;
- unsigned int err_this_table_right;
- int orig[3],approx[4];
- int err[4];
- err_upper = 3*255*255*16;
- err_lower = 3*255*255*16;
- err_left = 3*255*255*16;
- err_right = 3*255*255*16;
- #define ONE_PIXEL_UL(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_UL_RG[table_nbr*4*4+xx*4+0] + square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_UL_RG[table_nbr*4*4+xx*4+1] + square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_UL_RG[table_nbr*4*4+xx*4+2] + square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_UL_RG[table_nbr*4*4+xx*4+3] + square_table[approx[3]-orig[2]];\
- /* end unrolled loop*/\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_upper+=err[0];\
- err_this_table_left+=err[0];\
- #define ONE_PIXEL_UR(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+0] + square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+1] + square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+2] + square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+3] + square_table[approx[3]-orig[2]];\
- /* end unrolled loop */\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_upper+=err[0];\
- err_this_table_right+=err[0];
- #define ONE_PIXEL_LL(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+0] + square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+1] + square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+2] + square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+3] + square_table[approx[3]-orig[2]];\
- /* end unrolled loop*/\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_lower+=err[0];\
- err_this_table_left+=err[0];\
- #define ONE_PIXEL_LR(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+0] + square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+1] + square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+2] + square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+3] + square_table[approx[3]-orig[2]];\
- /* end unrolled loop*/\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_lower+=err[0];\
- err_this_table_right+=err[0];\
- #define ONE_TABLE_3(table_nbr)\
- err_this_table_upper = 0;\
- err_this_table_lower = 0;\
- err_this_table_left = 0;\
- err_this_table_right = 0;\
- approx[0]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+0]+255];\
- approx[1]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+1]+255];\
- approx[2]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+2]+255];\
- approx[3]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+3]+255];\
- /* unroll loop for(xx=0; xx<4; xx++) */\
- ONE_PIXEL_UL(table_nbr,0)\
- ONE_PIXEL_UL(table_nbr,1)\
- ONE_PIXEL_UL(table_nbr,2)\
- ONE_PIXEL_UL(table_nbr,3)\
- /* end unroll loop */\
- /* unroll loop for(xx=4; xx<8; xx++) */\
- ONE_PIXEL_LR(table_nbr,12)\
- ONE_PIXEL_LR(table_nbr,13)\
- ONE_PIXEL_LR(table_nbr,14)\
- ONE_PIXEL_LR(table_nbr,15)\
- /* end unroll loop */\
- /* If error in the top left 2x2 pixel area is already larger than the best error, and */\
- /* The same is true for the bottom right 2x2 pixel area, this combination of table and color */\
- /* can never be part of an optimal solution and therefore we do not need to test the other */\
- /* two 2x2 pixel areas */\
- if((err_this_table_upper<best_err)||(err_this_table_lower<best_err))\
- {\
- /* unroll loop for(xx=4; xx<8; xx++) */\
- ONE_PIXEL_UR(table_nbr,4)\
- ONE_PIXEL_UR(table_nbr,5)\
- ONE_PIXEL_UR(table_nbr,6)\
- ONE_PIXEL_UR(table_nbr,7)\
- /* end unroll loop */\
- /* unroll loop for(xx=4; xx<8; xx++) */\
- ONE_PIXEL_LL(table_nbr,8)\
- ONE_PIXEL_LL(table_nbr,9)\
- ONE_PIXEL_LL(table_nbr,10)\
- ONE_PIXEL_LL(table_nbr,11)\
- /* end unroll loop */\
- if(err_this_table_upper<err_upper)\
- err_upper = err_this_table_upper;\
- if(err_this_table_lower<err_lower)\
- err_lower = err_this_table_lower;\
- if(err_this_table_left<err_left)\
- err_left = err_this_table_left;\
- if(err_this_table_right<err_right)\
- err_right = err_this_table_right;\
- }\
- /*unroll loop for(table_nbr=0;table_nbr<8;table_nbr++)*/
- ONE_TABLE_3(0);
- ONE_TABLE_3(1);
- ONE_TABLE_3(2);
- ONE_TABLE_3(3);
- ONE_TABLE_3(4);
- ONE_TABLE_3(5);
- ONE_TABLE_3(6);
- ONE_TABLE_3(7);
- /*end unroll loop*/
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Tries all index-tables, used when compressing a block exhaustively using perceptual error measure
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- inline void tryalltables_3bittable_all_subblocks_using_precalc_perceptual1000(uint8 *block_2x2,uint8 *color_quant1, unsigned int *precalc_err_UL_RG, unsigned int *precalc_err_UR_RG, unsigned int *precalc_err_LL_RG, unsigned int *precalc_err_LR_RG, unsigned int &err_upper, unsigned int &err_lower, unsigned int &err_left, unsigned int &err_right, unsigned int best_err)
- {
- unsigned int err_this_table_upper;
- unsigned int err_this_table_lower;
- unsigned int err_this_table_left;
- unsigned int err_this_table_right;
- int orig[3],approx[4];
- int err[4];
- err_upper = MAXERR1000;
- err_lower = MAXERR1000;
- err_left = MAXERR1000;
- err_right =MAXERR1000;
- #define ONE_PIXEL_UL_PERCEP(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_UL_RG[table_nbr*4*4+xx*4+0] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_UL_RG[table_nbr*4*4+xx*4+1] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_UL_RG[table_nbr*4*4+xx*4+2] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_UL_RG[table_nbr*4*4+xx*4+3] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[3]-orig[2]];\
- /* end unrolled loop*/\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_upper+=err[0];\
- err_this_table_left+=err[0];\
- #define ONE_PIXEL_UR_PERCEP(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+0] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+1] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+2] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_UR_RG[table_nbr*4*4+(xx-4)*4+3] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[3]-orig[2]];\
- /* end unrolled loop */\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_upper+=err[0];\
- err_this_table_right+=err[0];
- #define ONE_PIXEL_LL_PERCEP(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+0] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+1] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+2] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_LL_RG[table_nbr*4*4+(xx-8)*4+3] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[3]-orig[2]];\
- /* end unrolled loop*/\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_lower+=err[0];\
- err_this_table_left+=err[0];\
- #define ONE_PIXEL_LR_PERCEP(table_nbr,xx)\
- orig[0]=block_2x2[xx*4];\
- orig[1]=block_2x2[xx*4+1];\
- orig[2]=block_2x2[xx*4+2];\
- /* unrolled loop for(index=0;index<4;index++)*/\
- err[0]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+0] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[0]-orig[2]];\
- err[1]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+1] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[1]-orig[2]];\
- err[2]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+2] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[2]-orig[2]];\
- err[3]=precalc_err_LR_RG[table_nbr*4*4+(xx-12)*4+3] + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[approx[3]-orig[2]];\
- /* end unrolled loop*/\
- if(err[0] > err[1])\
- err[0] = err[1];\
- if(err[2] > err[3])\
- err[2] = err[3];\
- if(err[0] > err[2])\
- err[0] = err[2];\
- err_this_table_lower+=err[0];\
- err_this_table_right+=err[0];\
- #define ONE_TABLE_3_PERCEP(table_nbr)\
- err_this_table_upper = 0;\
- err_this_table_lower = 0;\
- err_this_table_left = 0;\
- err_this_table_right = 0;\
- approx[0]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+0]+255];\
- approx[1]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+1]+255];\
- approx[2]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+2]+255];\
- approx[3]=clamp_table_plus_255[color_quant1[2]+compressParamsFast[table_nbr*4+3]+255];\
- /* unroll loop for(xx=0; xx<4; xx++) */\
- ONE_PIXEL_UL_PERCEP(table_nbr,0)\
- ONE_PIXEL_UL_PERCEP(table_nbr,1)\
- ONE_PIXEL_UL_PERCEP(table_nbr,2)\
- ONE_PIXEL_UL_PERCEP(table_nbr,3)\
- /* end unroll loop */\
- /* unroll loop for(xx=4; xx<8; xx++) */\
- ONE_PIXEL_LR_PERCEP(table_nbr,12)\
- ONE_PIXEL_LR_PERCEP(table_nbr,13)\
- ONE_PIXEL_LR_PERCEP(table_nbr,14)\
- ONE_PIXEL_LR_PERCEP(table_nbr,15)\
- /* end unroll loop */\
- /* If error in the top left 2x2 pixel area is already larger than the best error, and */\
- /* The same is true for the bottom right 2x2 pixel area, this combination of table and color */\
- /* can never be part of an optimal solution and therefore we do not need to test the other */\
- /* two 2x2 pixel areas */\
- if((err_this_table_upper<best_err)||(err_this_table_lower<best_err))\
- {\
- /* unroll loop for(xx=4; xx<8; xx++) */\
- ONE_PIXEL_UR_PERCEP(table_nbr,4)\
- ONE_PIXEL_UR_PERCEP(table_nbr,5)\
- ONE_PIXEL_UR_PERCEP(table_nbr,6)\
- ONE_PIXEL_UR_PERCEP(table_nbr,7)\
- /* end unroll loop */\
- /* unroll loop for(xx=4; xx<8; xx++) */\
- ONE_PIXEL_LL_PERCEP(table_nbr,8)\
- ONE_PIXEL_LL_PERCEP(table_nbr,9)\
- ONE_PIXEL_LL_PERCEP(table_nbr,10)\
- ONE_PIXEL_LL_PERCEP(table_nbr,11)\
- /* end unroll loop */\
- if(err_this_table_upper<err_upper)\
- err_upper = err_this_table_upper;\
- if(err_this_table_lower<err_lower)\
- err_lower = err_this_table_lower;\
- if(err_this_table_left<err_left)\
- err_left = err_this_table_left;\
- if(err_this_table_right<err_right)\
- err_right = err_this_table_right;\
- }\
- /*unroll loop for(table_nbr=0;table_nbr<8;table_nbr++)*/
- ONE_TABLE_3_PERCEP(0);
- ONE_TABLE_3_PERCEP(1);
- ONE_TABLE_3_PERCEP(2);
- ONE_TABLE_3_PERCEP(3);
- ONE_TABLE_3_PERCEP(4);
- ONE_TABLE_3_PERCEP(5);
- ONE_TABLE_3_PERCEP(6);
- ONE_TABLE_3_PERCEP(7);
- /*end unroll loop*/
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compresses the individual mode exhaustively (perecptual error metric).
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockIndividualExhaustivePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int total_best_err)
- {
- unsigned int best_err_norm_diff = MAXERR1000;
- unsigned int best_err_norm_444 = MAXERR1000;
- unsigned int best_err_flip_diff = MAXERR1000;
- unsigned int best_err_flip_444 = MAXERR1000;
- uint8 color_quant1[3], color_quant2[3];
- int enc_color1[3];
- int best_enc_color1[3], best_enc_color2[3];
-
- int min_error=MAXERR1000;
- unsigned int best_pixel_indices1_MSB=0;
- unsigned int best_pixel_indices1_LSB=0;
- unsigned int best_pixel_indices2_MSB=0;
- unsigned int best_pixel_indices2_LSB=0;
- unsigned int pixel_indices1_MSB=0;
- unsigned int pixel_indices1_LSB=0;
- unsigned int pixel_indices2_MSB=0;
- unsigned int err_upper, err_lower;
- unsigned int err_left, err_right;
- unsigned int pixel_indices2_LSB=0;
- unsigned int best_err_upper = MAXERR1000;
- unsigned int best_err_lower = MAXERR1000;
- unsigned int best_err_left = MAXERR1000;
- unsigned int best_err_right = MAXERR1000;
- int best_upper_col[3];
- int best_lower_col[3];
- int best_left_col[3];
- int best_right_col[3];
- unsigned int table1=0, table2=0;
- unsigned int best_table1=0, best_table2=0;
- unsigned int precalc_err_UL_R[8*4*4];
- unsigned int precalc_err_UR_R[8*4*4];
- unsigned int precalc_err_LL_R[8*4*4];
- unsigned int precalc_err_LR_R[8*4*4];
- unsigned int precalc_err_UL_RG[8*4*4];
- unsigned int precalc_err_UR_RG[8*4*4];
- unsigned int precalc_err_LL_RG[8*4*4];
- unsigned int precalc_err_LR_RG[8*4*4];
- int diffbit;
- uint8 block_2x2[4*4*4];
- unsigned int best_err;
- int best_flip;
- int xx,yy,count = 0;
- // Reshuffle pixels so that the top left 2x2 pixels arrive first, then the top right 2x2 pixels etc. Also put use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<2; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 0; xx<2; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- unsigned int test1, test2;
- best_err = (unsigned int)compressBlockOnlyIndividualAveragePerceptual1000(img, width, height, startx, starty, test1, test2, best_enc_color1, best_enc_color2, best_flip, best_err_upper, best_err_lower, best_err_left, best_err_right, best_upper_col, best_lower_col, best_left_col, best_right_col);
- if(best_err < total_best_err)
- total_best_err = best_err;
- unsigned int tryblocks = 0;
- unsigned int allblocks = 0;
- int needtest;
- for(enc_color1[0]=0; enc_color1[0]<16; enc_color1[0]++)
- {
- color_quant1[0] = enc_color1[0] << 4 | (enc_color1[0]);
- if(precompute_3bittable_all_subblocksR_with_test_perceptual1000(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, total_best_err))
- {
- for(enc_color1[1]=0; enc_color1[1]<16; enc_color1[1]++)
- {
- color_quant1[1] = enc_color1[1] << 4 | (enc_color1[1]);
- if(precompute_3bittable_all_subblocksRG_withtest_perceptual1000(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, total_best_err))
- {
- needtest = false;
- for(enc_color1[2]=0; enc_color1[2]<16; enc_color1[2]++)
- {
- color_quant1[2] = enc_color1[2] << 4 | (enc_color1[2]);
- tryalltables_3bittable_all_subblocks_using_precalc_perceptual1000(block_2x2, color_quant1, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, err_upper, err_lower, err_left, err_right, total_best_err);
- if(err_upper<best_err_upper)
- {
- best_err_upper = err_upper;
- best_upper_col[0] = enc_color1[0];
- best_upper_col[1] = enc_color1[1];
- best_upper_col[2] = enc_color1[2];
- needtest = true;
- }
- if(err_lower<best_err_lower)
- {
- best_err_lower = err_lower;
- best_lower_col[0] = enc_color1[0];
- best_lower_col[1] = enc_color1[1];
- best_lower_col[2] = enc_color1[2];
- needtest=true;
- }
- if(err_left<best_err_left)
- {
- best_err_left = err_left;
- best_left_col[0] = enc_color1[0];
- best_left_col[1] = enc_color1[1];
- best_left_col[2] = enc_color1[2];
- needtest=true;
- }
- if(err_right<best_err_right)
- {
- best_err_right = err_right;
- best_right_col[0] = enc_color1[0];
- best_right_col[1] = enc_color1[1];
- best_right_col[2] = enc_color1[2];
- needtest = true;
- }
- }
- if(needtest)
- {
- if(best_err_upper+best_err_lower < best_err_left+best_err_right)
- {
- best_err = best_err_upper+best_err_lower;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- else
- {
- best_err = best_err_left+best_err_right;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- }
- }
- }
- }
- }
-
- if(best_err_upper+best_err_lower < best_err_left+best_err_right)
- {
- best_flip = 1;
- best_enc_color1[0] = best_upper_col[0];
- best_enc_color1[1] = best_upper_col[1];
- best_enc_color1[2] = best_upper_col[2];
- best_enc_color2[0] = best_lower_col[0];
- best_enc_color2[1] = best_lower_col[1];
- best_enc_color2[2] = best_lower_col[2];
- best_err = best_err_upper+best_err_lower;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- else
- {
- best_flip = 0;
- best_enc_color1[0] = best_left_col[0];
- best_enc_color1[1] = best_left_col[1];
- best_enc_color1[2] = best_left_col[2];
- best_enc_color2[0] = best_right_col[0];
- best_enc_color2[1] = best_right_col[1];
- best_enc_color2[2] = best_right_col[2];
- best_err = best_err_left+best_err_right;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- color_quant1[0] = best_enc_color1[0] << 4 | (best_enc_color1[0]);
- color_quant1[1] = best_enc_color1[1] << 4 | (best_enc_color1[1]);
- color_quant1[2] = best_enc_color1[2] << 4 | (best_enc_color1[2]);
- if(best_flip == 0)
- tryalltables_3bittable2x4percep1000(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- else
- tryalltables_3bittable4x2percep1000(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- color_quant2[0] = best_enc_color2[0] << 4 | (best_enc_color2[0]);
- color_quant2[1] = best_enc_color2[1] << 4 | (best_enc_color2[1]);
- color_quant2[2] = best_enc_color2[2] << 4 | (best_enc_color2[2]);
- if(best_flip == 0)
- tryalltables_3bittable2x4percep1000(img,width,height,startx+2,starty,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- else
- tryalltables_3bittable4x2percep1000(img,width,height,startx,starty+2,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- diffbit = 1;
- compressed1 = 0;
- PUTBITSHIGH( compressed1, diffbit, 0, 33);
- PUTBITSHIGH( compressed1, best_enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1, best_enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1, best_enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1, best_enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1, best_enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1, best_enc_color2[2], 4, 43);
- PUTBITSHIGH( compressed1, best_table1, 3, 39);
- PUTBITSHIGH( compressed1, best_table2, 3, 36);
- PUTBITSHIGH( compressed1, best_flip, 1, 32);
- if(best_flip == 0)
- {
- compressed2 = 0;
- PUTBITS( compressed2, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
- compressed2 = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- return best_err;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compresses the individual mode exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockIndividualExhaustive(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int total_best_err)
- {
- unsigned int best_err_norm_diff = 255*255*16*3;
- unsigned int best_err_norm_444 = 255*255*16*3;
- unsigned int best_err_flip_diff = 255*255*16*3;
- unsigned int best_err_flip_444 = 255*255*16*3;
- uint8 color_quant1[3], color_quant2[3];
- int enc_color1[3];
- int best_enc_color1[3], best_enc_color2[3];
-
- int min_error=255*255*8*3;
- unsigned int best_pixel_indices1_MSB=0;
- unsigned int best_pixel_indices1_LSB=0;
- unsigned int best_pixel_indices2_MSB=0;
- unsigned int best_pixel_indices2_LSB=0;
- unsigned int pixel_indices1_MSB=0;
- unsigned int pixel_indices1_LSB=0;
- unsigned int pixel_indices2_MSB=0;
- unsigned int err_upper, err_lower;
- unsigned int err_left, err_right;
- unsigned int pixel_indices2_LSB=0;
- unsigned int best_err_upper = 255*255*16*3;
- unsigned int best_err_lower = 255*255*16*3;
- unsigned int best_err_left = 255*255*16*3;
- unsigned int best_err_right = 255*255*16*3;
- int best_upper_col[3];
- int best_lower_col[3];
- int best_left_col[3];
- int best_right_col[3];
- unsigned int table1=0, table2=0;
- unsigned int best_table1=0, best_table2=0;
- unsigned int precalc_err_UL_R[8*4*4];
- unsigned int precalc_err_UR_R[8*4*4];
- unsigned int precalc_err_LL_R[8*4*4];
- unsigned int precalc_err_LR_R[8*4*4];
- unsigned int precalc_err_UL_RG[8*4*4];
- unsigned int precalc_err_UR_RG[8*4*4];
- unsigned int precalc_err_LL_RG[8*4*4];
- unsigned int precalc_err_LR_RG[8*4*4];
- int diffbit;
- uint8 block_2x2[4*4*4];
- unsigned int best_err;
- int best_flip;
- int xx,yy,count = 0;
- // Reshuffle pixels so that the top left 2x2 pixels arrive first, then the top right 2x2 pixels etc. Also put use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<2; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 0; xx<2; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- unsigned int test1, test2;
- best_err = (unsigned int)compressBlockOnlyIndividualAverage(img, width, height, startx, starty, test1, test2, best_enc_color1, best_enc_color2, best_flip, best_err_upper, best_err_lower, best_err_left, best_err_right, best_upper_col, best_lower_col, best_left_col, best_right_col);
- if(best_err < total_best_err)
- total_best_err = best_err;
- unsigned int tryblocks = 0;
- unsigned int allblocks = 0;
- int needtest;
- for(enc_color1[0]=0; enc_color1[0]<16; enc_color1[0]++)
- {
- color_quant1[0] = enc_color1[0] << 4 | (enc_color1[0]);
- if(precompute_3bittable_all_subblocksR_with_test(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, total_best_err))
- {
- for(enc_color1[1]=0; enc_color1[1]<16; enc_color1[1]++)
- {
- color_quant1[1] = enc_color1[1] << 4 | (enc_color1[1]);
- if(precompute_3bittable_all_subblocksRG_withtest(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, total_best_err))
- {
- needtest = false;
- for(enc_color1[2]=0; enc_color1[2]<16; enc_color1[2]++)
- {
- color_quant1[2] = enc_color1[2] << 4 | (enc_color1[2]);
- tryalltables_3bittable_all_subblocks_using_precalc(block_2x2, color_quant1, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, err_upper, err_lower, err_left, err_right, total_best_err);
- if(err_upper<best_err_upper)
- {
- best_err_upper = err_upper;
- best_upper_col[0] = enc_color1[0];
- best_upper_col[1] = enc_color1[1];
- best_upper_col[2] = enc_color1[2];
- needtest = true;
- }
- if(err_lower<best_err_lower)
- {
- best_err_lower = err_lower;
- best_lower_col[0] = enc_color1[0];
- best_lower_col[1] = enc_color1[1];
- best_lower_col[2] = enc_color1[2];
- needtest=true;
- }
- if(err_left<best_err_left)
- {
- best_err_left = err_left;
- best_left_col[0] = enc_color1[0];
- best_left_col[1] = enc_color1[1];
- best_left_col[2] = enc_color1[2];
- needtest=true;
- }
- if(err_right<best_err_right)
- {
- best_err_right = err_right;
- best_right_col[0] = enc_color1[0];
- best_right_col[1] = enc_color1[1];
- best_right_col[2] = enc_color1[2];
- needtest = true;
- }
- }
- if(needtest)
- {
- if(best_err_upper+best_err_lower < best_err_left+best_err_right)
- {
- best_err = best_err_upper+best_err_lower;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- else
- {
- best_err = best_err_left+best_err_right;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- }
- }
- }
- }
- }
- if(best_err_upper+best_err_lower < best_err_left+best_err_right)
- {
- best_flip = 1;
- best_enc_color1[0] = best_upper_col[0];
- best_enc_color1[1] = best_upper_col[1];
- best_enc_color1[2] = best_upper_col[2];
- best_enc_color2[0] = best_lower_col[0];
- best_enc_color2[1] = best_lower_col[1];
- best_enc_color2[2] = best_lower_col[2];
- best_err = best_err_upper+best_err_lower;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- else
- {
- best_flip = 0;
- best_enc_color1[0] = best_left_col[0];
- best_enc_color1[1] = best_left_col[1];
- best_enc_color1[2] = best_left_col[2];
- best_enc_color2[0] = best_right_col[0];
- best_enc_color2[1] = best_right_col[1];
- best_enc_color2[2] = best_right_col[2];
- best_err = best_err_left+best_err_right;
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- color_quant1[0] = best_enc_color1[0] << 4 | (best_enc_color1[0]);
- color_quant1[1] = best_enc_color1[1] << 4 | (best_enc_color1[1]);
- color_quant1[2] = best_enc_color1[2] << 4 | (best_enc_color1[2]);
- if(best_flip == 0)
- tryalltables_3bittable2x4(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- else
- tryalltables_3bittable4x2(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- color_quant2[0] = best_enc_color2[0] << 4 | (best_enc_color2[0]);
- color_quant2[1] = best_enc_color2[1] << 4 | (best_enc_color2[1]);
- color_quant2[2] = best_enc_color2[2] << 4 | (best_enc_color2[2]);
- if(best_flip == 0)
- tryalltables_3bittable2x4(img,width,height,startx+2,starty,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- else
- tryalltables_3bittable4x2(img,width,height,startx,starty+2,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- diffbit = 1;
- compressed1 = 0;
- PUTBITSHIGH( compressed1, diffbit, 0, 33);
- PUTBITSHIGH( compressed1, best_enc_color1[0], 4, 63);
- PUTBITSHIGH( compressed1, best_enc_color1[1], 4, 55);
- PUTBITSHIGH( compressed1, best_enc_color1[2], 4, 47);
- PUTBITSHIGH( compressed1, best_enc_color2[0], 4, 59);
- PUTBITSHIGH( compressed1, best_enc_color2[1], 4, 51);
- PUTBITSHIGH( compressed1, best_enc_color2[2], 4, 43);
- PUTBITSHIGH( compressed1, best_table1, 3, 39);
- PUTBITSHIGH( compressed1, best_table2, 3, 36);
- PUTBITSHIGH( compressed1, best_flip, 1, 32);
- if(best_flip == 0)
- {
- compressed2 = 0;
- PUTBITS( compressed2, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
- compressed2 = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- return best_err;
- }
- #endif
-
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compresses the differential mode exhaustively (perecptual error metric).
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockDifferentialExhaustivePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int best_error_so_far)
- {
- unsigned int best_err_norm_diff = MAXERR1000;
- unsigned int best_err_norm_444 = MAXERR1000;
- unsigned int best_err_flip_diff = MAXERR1000;
- unsigned int best_err_flip_444 = MAXERR1000;
- uint8 color_quant1[3], color_quant2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int best_enc_color1[3], best_enc_color2[3];
- signed char bytediff[3];
-
- unsigned int best_pixel_indices1_MSB=0;
- unsigned int best_pixel_indices1_LSB=0;
- unsigned int best_pixel_indices2_MSB=0;
- unsigned int best_pixel_indices2_LSB=0;
- unsigned int pixel_indices1_MSB=0;
- unsigned int pixel_indices1_LSB=0;
- unsigned int pixel_indices2_MSB=0;
- unsigned int *err_upper, *err_lower;
- unsigned int *err_left, *err_right;
- unsigned int pixel_indices2_LSB=0;
- unsigned int table1=0, table2=0;
- unsigned int best_table1=0, best_table2=0;
- unsigned int precalc_err_UL_R[8*4*4];
- unsigned int precalc_err_UR_R[8*4*4];
- unsigned int precalc_err_LL_R[8*4*4];
- unsigned int precalc_err_LR_R[8*4*4];
- unsigned int precalc_err_UL_RG[8*4*4];
- unsigned int precalc_err_UR_RG[8*4*4];
- unsigned int precalc_err_LL_RG[8*4*4];
- unsigned int precalc_err_LR_RG[8*4*4];
- unsigned int best_error_using_diff_mode;
- int diffbit;
- uint8 block_2x2[4*4*4];
- unsigned int error, error_lying, error_standing;
- unsigned int *err_lower_adr;
- int best_flip;
- unsigned int *err_right_adr;
- int xx,yy,count = 0;
- // Reshuffle pixels so that the top left 2x2 pixels arrive first, then the top right 2x2 pixels etc. Also put use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<2; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 0; xx<2; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- unsigned int test1, test2;
- best_error_using_diff_mode = compressBlockOnlyDiffFlipAveragePerceptual1000(img, width, height, startx, starty, test1, test2);
- if(best_error_using_diff_mode < best_error_so_far)
- best_error_so_far = best_error_using_diff_mode;
- // Decode the parameters so that we have a worst case color pair and a flip status
- best_flip = test1 & 1;
- best_enc_color1[0] = GETBITSHIGH( test1, 5, 63);
- best_enc_color1[1] = GETBITSHIGH( test1, 5, 55);
- best_enc_color1[2] = GETBITSHIGH( test1, 5, 47);
- bytediff[0] = GETBITSHIGH( test1, 3, 58);
- bytediff[1] = GETBITSHIGH( test1, 3, 50);
- bytediff[2] = GETBITSHIGH( test1, 3, 42);
- bytediff[0] = (bytediff[0] << 5);
- bytediff[1] = (bytediff[1] << 5);
- bytediff[2] = (bytediff[2] << 5);
- bytediff[0] = bytediff[0] >> 5;
- bytediff[1] = bytediff[1] >> 5;
- bytediff[2] = bytediff[2] >> 5;
- best_enc_color2[0]= best_enc_color1[0] + bytediff[0];
- best_enc_color2[1]= best_enc_color1[1] + bytediff[1];
- best_enc_color2[2]= best_enc_color1[2] + bytediff[2];
- // allocate memory for errors:
- err_upper = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_upper){printf("Out of memory allocating \n");exit(1);}
- err_lower = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_lower){printf("Out of memory allocating \n");exit(1);}
- err_left = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_left){printf("Out of memory allocating \n");exit(1);}
- err_right = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_right){printf("Out of memory allocating \n");exit(1);}
- int q;
- // Calculate all errors
- for(enc_color1[0]=0; enc_color1[0]<32; enc_color1[0]++)
- {
- color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- if(precompute_3bittable_all_subblocksR_with_test_perceptual1000(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, best_error_so_far))
- {
- for(enc_color1[1]=0; enc_color1[1]<32; enc_color1[1]++)
- {
- color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- if(precompute_3bittable_all_subblocksRG_withtest_perceptual1000(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, best_error_so_far))
- {
- for(enc_color1[2]=0; enc_color1[2]<32; enc_color1[2]++)
- {
- color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- tryalltables_3bittable_all_subblocks_using_precalc_perceptual1000(block_2x2, color_quant1, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], err_lower[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], err_right[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], best_error_so_far);
- }
- }
- else
- {
- for(q=0;q<32;q++)
- {
- err_upper[32*32*enc_color1[0]+32*enc_color1[1]+q] = MAXERR1000;
- err_lower[32*32*enc_color1[0]+32*enc_color1[1]+q] = MAXERR1000;
- err_left[32*32*enc_color1[0]+32*enc_color1[1]+q] = MAXERR1000;
- err_right[32*32*enc_color1[0]+32*enc_color1[1]+q] = MAXERR1000;
- }
- }
- }
- }
- else
- {
- for(q=0;q<32*32;q++)
- {
- err_upper[32*32*enc_color1[0]+q] = MAXERR1000;
- err_lower[32*32*enc_color1[0]+q] = MAXERR1000;
- err_left[32*32*enc_color1[0]+q] = MAXERR1000;
- err_right[32*32*enc_color1[0]+q] = MAXERR1000;
- }
- }
- }
- for(enc_color1[0]=0; enc_color1[0]<32; enc_color1[0]++)
- {
- for(enc_color1[1]=0; enc_color1[1]<32; enc_color1[1]++)
- {
- for(enc_color1[2]=0; enc_color1[2]<4; enc_color1[2]++)
- {
- error_lying = err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- error_standing = err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- if(error_lying < best_error_so_far || error_standing < best_error_so_far)
- {
- for(enc_color2[0]=JAS_MAX(0,enc_color1[0]-4); enc_color2[0]<JAS_MIN(enc_color1[0]+4,32); enc_color2[0]++)
- {
- for(enc_color2[1]=JAS_MAX(0,enc_color1[1]-4); enc_color2[1]<JAS_MIN(enc_color1[1]+4,32); enc_color2[1]++)
- {
- err_lower_adr = &err_lower[32*32*enc_color2[0]+32*enc_color2[1]];
- err_right_adr = &err_right[32*32*enc_color2[0]+32*enc_color2[1]];
- for(enc_color2[2]=JAS_MAX(0,enc_color1[2]-4); enc_color2[2]<JAS_MIN(enc_color1[2]+4,32); enc_color2[2]++)
- {
- error = error_lying+err_lower_adr[enc_color2[2]];
- if(error<best_error_so_far)
- {
- best_flip = 1;
- best_error_so_far = error;
- best_error_using_diff_mode = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- error = error_standing+err_right_adr[enc_color2[2]];
- if(error<best_error_so_far)
- {
- best_flip = 0;
- best_error_so_far = error;
- best_error_using_diff_mode = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- }
- }
- }
- }
- }
- for(enc_color1[2]=4; enc_color1[2]<28; enc_color1[2]++)
- {
- error_lying = err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- error_standing = err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- if(error_lying < best_error_so_far || error_standing < best_error_so_far)
- {
- for(enc_color2[0]=JAS_MAX(0,enc_color1[0]-4); enc_color2[0]<JAS_MIN(enc_color1[0]+4,32); enc_color2[0]++)
- {
- for(enc_color2[1]=JAS_MAX(0,enc_color1[1]-4); enc_color2[1]<JAS_MIN(enc_color1[1]+4,32); enc_color2[1]++)
- {
- err_lower_adr = &err_lower[32*32*enc_color2[0]+32*enc_color2[1]];
- err_right_adr = &err_right[32*32*enc_color2[0]+32*enc_color2[1]];
- // since enc_color[2] is between 4 and 29 we do not need to clamp the loop on the next line
- for(enc_color2[2]=enc_color1[2]-4; enc_color2[2]<enc_color1[2]+4; enc_color2[2]++)
- {
- error = error_lying+err_lower_adr[enc_color2[2]];
- if(error<best_error_so_far)
- {
- best_flip = 1;
- best_error_so_far = error;
- best_error_using_diff_mode = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- error = error_standing+err_right_adr[enc_color2[2]];
- if(error<best_error_so_far)
- {
- best_flip = 0;
- best_error_so_far = error;
- best_error_using_diff_mode = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- }
- }
- }
- }
- }
- for(enc_color1[2]=28; enc_color1[2]<32; enc_color1[2]++)
- {
- error_lying = err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- error_standing = err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- if(error_lying < best_error_so_far || error_standing < best_error_so_far)
- {
- for(enc_color2[0]=JAS_MAX(0,enc_color1[0]-4); enc_color2[0]<JAS_MIN(enc_color1[0]+4,32); enc_color2[0]++)
- {
- for(enc_color2[1]=JAS_MAX(0,enc_color1[1]-4); enc_color2[1]<JAS_MIN(enc_color1[1]+4,32); enc_color2[1]++)
- {
- err_lower_adr = &err_lower[32*32*enc_color2[0]+32*enc_color2[1]];
- err_right_adr = &err_right[32*32*enc_color2[0]+32*enc_color2[1]];
- for(enc_color2[2]=JAS_MAX(0,enc_color1[2]-4); enc_color2[2]<JAS_MIN(enc_color1[2]+4,32); enc_color2[2]++)
- {
- error = error_lying+err_lower_adr[enc_color2[2]];
- if(error<best_error_so_far)
- {
- best_flip = 1;
- best_error_so_far = error;
- best_error_using_diff_mode = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- error = error_standing+err_right_adr[enc_color2[2]];
- if(error<best_error_so_far)
- {
- best_flip = 0;
- best_error_so_far = error;
- best_error_using_diff_mode = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- }
- }
- }
- }
- }
- }
- }
- free(err_upper);
- free(err_lower);
- free(err_left);
- free(err_right);
- color_quant1[0] = best_enc_color1[0] << 3 | (best_enc_color1[0] >> 2);
- color_quant1[1] = best_enc_color1[1] << 3 | (best_enc_color1[1] >> 2);
- color_quant1[2] = best_enc_color1[2] << 3 | (best_enc_color1[2] >> 2);
- if(best_flip == 0)
- tryalltables_3bittable2x4percep1000(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- else
- tryalltables_3bittable4x2percep1000(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- color_quant2[0] = best_enc_color2[0] << 3 | (best_enc_color2[0] >> 2);
- color_quant2[1] = best_enc_color2[1] << 3 | (best_enc_color2[1] >> 2);
- color_quant2[2] = best_enc_color2[2] << 3 | (best_enc_color2[2] >> 2);
- if(best_flip == 0)
- tryalltables_3bittable2x4percep1000(img,width,height,startx+2,starty,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- else
- tryalltables_3bittable4x2percep1000(img,width,height,startx,starty+2,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- diff[0] = best_enc_color2[0]-best_enc_color1[0];
- diff[1] = best_enc_color2[1]-best_enc_color1[1];
- diff[2] = best_enc_color2[2]-best_enc_color1[2];
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- diffbit = 1;
- compressed1 = 0;
- PUTBITSHIGH( compressed1, diffbit, 1, 33);
- PUTBITSHIGH( compressed1, best_enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1, best_enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1, best_enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1, diff[0], 3, 58);
- PUTBITSHIGH( compressed1, diff[1], 3, 50);
- PUTBITSHIGH( compressed1, diff[2], 3, 42);
- PUTBITSHIGH( compressed1, best_table1, 3, 39);
- PUTBITSHIGH( compressed1, best_table2, 3, 36);
- PUTBITSHIGH( compressed1, best_flip, 1, 32);
- if(best_flip == 0)
- {
- compressed2 = 0;
- PUTBITS( compressed2, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
- compressed2 = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- return best_error_using_diff_mode;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compresses the differential mode exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockDifferentialExhaustive(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int previous_best_err)
- {
- unsigned int best_err_norm_diff = 255*255*16*3;
- unsigned int best_err_norm_444 = 255*255*16*3;
- unsigned int best_err_flip_diff = 255*255*16*3;
- unsigned int best_err_flip_444 = 255*255*16*3;
- uint8 color_quant1[3], color_quant2[3];
- int enc_color1[3], enc_color2[3], diff[3];
- int best_enc_color1[3], best_enc_color2[3];
-
- int min_error=255*255*8*3;
- unsigned int best_pixel_indices1_MSB=0;
- unsigned int best_pixel_indices1_LSB=0;
- unsigned int best_pixel_indices2_MSB=0;
- unsigned int best_pixel_indices2_LSB=0;
- unsigned int pixel_indices1_MSB=0;
- unsigned int pixel_indices1_LSB=0;
- unsigned int pixel_indices2_MSB=0;
- unsigned int *err_upper, *err_lower;
- unsigned int *err_left, *err_right;
- unsigned int pixel_indices2_LSB=0;
- unsigned int table1=0, table2=0;
- unsigned int best_table1=0, best_table2=0;
- unsigned int precalc_err_UL_R[8*4*4];
- unsigned int precalc_err_UR_R[8*4*4];
- unsigned int precalc_err_LL_R[8*4*4];
- unsigned int precalc_err_LR_R[8*4*4];
- unsigned int precalc_err_UL_RG[8*4*4];
- unsigned int precalc_err_UR_RG[8*4*4];
- unsigned int precalc_err_LL_RG[8*4*4];
- unsigned int precalc_err_LR_RG[8*4*4];
- int diffbit;
- uint8 block_2x2[4*4*4];
- unsigned int error, error_lying, error_standing, best_err, total_best_err;
- unsigned int *err_lower_adr;
- int best_flip;
- unsigned int *err_right_adr;
- int xx,yy,count = 0;
- // Reshuffle pixels so that the top left 2x2 pixels arrive first, then the top right 2x2 pixels etc. Also put use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<2; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=0; yy<2; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 0; xx<2; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- for(xx = 2; xx<4; xx++)
- {
- for(yy=2; yy<4; yy++)
- {
- block_2x2[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block_2x2[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block_2x2[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block_2x2[(count)*4+3] = 0;
- count++;
- }
- }
- unsigned int test1, test2;
- best_err = (unsigned int)compressBlockOnlyDiffFlipAverage(img, width, height, startx, starty, test1, test2, best_enc_color1, best_enc_color2, best_flip);
- if(previous_best_err < best_err)
- total_best_err = previous_best_err;
- else
- total_best_err = best_err;
- // allocate memory for errors:
- err_upper = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_upper){printf("Out of memory allocating \n");exit(1);}
- err_lower = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_lower){printf("Out of memory allocating \n");exit(1);}
- err_left = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_left){printf("Out of memory allocating \n");exit(1);}
- err_right = (unsigned int*) malloc(32*32*32*sizeof(unsigned int));
- if(!err_right){printf("Out of memory allocating \n");exit(1);}
- int q;
- // Calculate all errors
- for(enc_color1[0]=0; enc_color1[0]<32; enc_color1[0]++)
- {
- color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2);
- if(precompute_3bittable_all_subblocksR_with_test(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, total_best_err))
- {
- for(enc_color1[1]=0; enc_color1[1]<32; enc_color1[1]++)
- {
- color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2);
- if(precompute_3bittable_all_subblocksRG_withtest(block_2x2, color_quant1, precalc_err_UL_R, precalc_err_UR_R, precalc_err_LL_R, precalc_err_LR_R, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, total_best_err))
- {
- for(enc_color1[2]=0; enc_color1[2]<32; enc_color1[2]++)
- {
- color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2);
- tryalltables_3bittable_all_subblocks_using_precalc(block_2x2, color_quant1, precalc_err_UL_RG, precalc_err_UR_RG, precalc_err_LL_RG, precalc_err_LR_RG, err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], err_lower[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], err_right[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]], total_best_err);
- }
- }
- else
- {
- for(q=0;q<32;q++)
- {
- err_upper[32*32*enc_color1[0]+32*enc_color1[1]+q] = 255*255*16*3;
- err_lower[32*32*enc_color1[0]+32*enc_color1[1]+q] = 255*255*16*3;
- err_left[32*32*enc_color1[0]+32*enc_color1[1]+q] = 255*255*16*3;
- err_right[32*32*enc_color1[0]+32*enc_color1[1]+q] = 255*255*16*3;
- }
- }
- }
- }
- else
- {
- for(q=0;q<32*32;q++)
- {
- err_upper[32*32*enc_color1[0]+q] = 255*255*16*3;
- err_lower[32*32*enc_color1[0]+q] = 255*255*16*3;
- err_left[32*32*enc_color1[0]+q] = 255*255*16*3;
- err_right[32*32*enc_color1[0]+q] = 255*255*16*3;
- }
- }
- }
- for(enc_color1[0]=0; enc_color1[0]<32; enc_color1[0]++)
- {
- for(enc_color1[1]=0; enc_color1[1]<32; enc_color1[1]++)
- {
- for(enc_color1[2]=0; enc_color1[2]<4; enc_color1[2]++)
- {
- error_lying = err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- error_standing = err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- if(error_lying < total_best_err || error_standing < total_best_err)
- {
- for(enc_color2[0]=JAS_MAX(0,enc_color1[0]-4); enc_color2[0]<JAS_MIN(enc_color1[0]+4,32); enc_color2[0]++)
- {
- for(enc_color2[1]=JAS_MAX(0,enc_color1[1]-4); enc_color2[1]<JAS_MIN(enc_color1[1]+4,32); enc_color2[1]++)
- {
- err_lower_adr = &err_lower[32*32*enc_color2[0]+32*enc_color2[1]];
- err_right_adr = &err_right[32*32*enc_color2[0]+32*enc_color2[1]];
- for(enc_color2[2]=JAS_MAX(0,enc_color1[2]-4); enc_color2[2]<JAS_MIN(enc_color1[2]+4,32); enc_color2[2]++)
- {
- error = error_lying+err_lower_adr[enc_color2[2]];
- if(error<best_err)
- {
- best_flip = 1;
- best_err = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- error = error_standing+err_right_adr[enc_color2[2]];
- if(error<best_err)
- {
- best_flip = 0;
- best_err = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- }
- }
- }
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- }
- for(enc_color1[2]=4; enc_color1[2]<28; enc_color1[2]++)
- {
- error_lying = err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- error_standing = err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- if(error_lying < total_best_err || error_standing < total_best_err)
- {
- for(enc_color2[0]=JAS_MAX(0,enc_color1[0]-4); enc_color2[0]<JAS_MIN(enc_color1[0]+4,32); enc_color2[0]++)
- {
- for(enc_color2[1]=JAS_MAX(0,enc_color1[1]-4); enc_color2[1]<JAS_MIN(enc_color1[1]+4,32); enc_color2[1]++)
- {
- err_lower_adr = &err_lower[32*32*enc_color2[0]+32*enc_color2[1]];
- err_right_adr = &err_right[32*32*enc_color2[0]+32*enc_color2[1]];
- // since enc_color[2] is between 4 and 29 we do not need to clamp the loop on the next line
- for(enc_color2[2]=enc_color1[2]-4; enc_color2[2]<enc_color1[2]+4; enc_color2[2]++)
- {
- error = error_lying+err_lower_adr[enc_color2[2]];
- if(error<best_err)
- {
- best_flip = 1;
- best_err = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- error = error_standing+err_right_adr[enc_color2[2]];
- if(error<best_err)
- {
- best_flip = 0;
- best_err = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- }
- }
- }
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- }
- for(enc_color1[2]=28; enc_color1[2]<32; enc_color1[2]++)
- {
- error_lying = err_upper[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- error_standing = err_left[32*32*enc_color1[0]+32*enc_color1[1]+enc_color1[2]];
- if(error_lying < total_best_err || error_standing < total_best_err)
- {
- for(enc_color2[0]=JAS_MAX(0,enc_color1[0]-4); enc_color2[0]<JAS_MIN(enc_color1[0]+4,32); enc_color2[0]++)
- {
- for(enc_color2[1]=JAS_MAX(0,enc_color1[1]-4); enc_color2[1]<JAS_MIN(enc_color1[1]+4,32); enc_color2[1]++)
- {
- err_lower_adr = &err_lower[32*32*enc_color2[0]+32*enc_color2[1]];
- err_right_adr = &err_right[32*32*enc_color2[0]+32*enc_color2[1]];
- for(enc_color2[2]=JAS_MAX(0,enc_color1[2]-4); enc_color2[2]<JAS_MIN(enc_color1[2]+4,32); enc_color2[2]++)
- {
- error = error_lying+err_lower_adr[enc_color2[2]];
- if(error<best_err)
- {
- best_flip = 1;
- best_err = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- error = error_standing+err_right_adr[enc_color2[2]];
- if(error<best_err)
- {
- best_flip = 0;
- best_err = error;
- best_enc_color1[0] = enc_color1[0];
- best_enc_color1[1] = enc_color1[1];
- best_enc_color1[2] = enc_color1[2];
- best_enc_color2[0] = enc_color2[0];
- best_enc_color2[1] = enc_color2[1];
- best_enc_color2[2] = enc_color2[2];
- }
- }
- }
- }
- if(best_err < total_best_err)
- total_best_err = best_err;
- }
- }
- }
- }
- free(err_upper);
- free(err_lower);
- free(err_left);
- free(err_right);
- color_quant1[0] = best_enc_color1[0] << 3 | (best_enc_color1[0] >> 2);
- color_quant1[1] = best_enc_color1[1] << 3 | (best_enc_color1[1] >> 2);
- color_quant1[2] = best_enc_color1[2] << 3 | (best_enc_color1[2] >> 2);
- if(best_flip == 0)
- tryalltables_3bittable2x4(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- else
- tryalltables_3bittable4x2(img,width,height,startx,starty,color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB);
- color_quant2[0] = best_enc_color2[0] << 3 | (best_enc_color2[0] >> 2);
- color_quant2[1] = best_enc_color2[1] << 3 | (best_enc_color2[1] >> 2);
- color_quant2[2] = best_enc_color2[2] << 3 | (best_enc_color2[2] >> 2);
- if(best_flip == 0)
- tryalltables_3bittable2x4(img,width,height,startx+2,starty,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- else
- tryalltables_3bittable4x2(img,width,height,startx,starty+2,color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB);
- diff[0] = best_enc_color2[0]-best_enc_color1[0];
- diff[1] = best_enc_color2[1]-best_enc_color1[1];
- diff[2] = best_enc_color2[2]-best_enc_color1[2];
- // ETC1_RGB8_OES:
- //
- // a) bit layout in bits 63 through 32 if diffbit = 0
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip|
- // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // b) bit layout in bits 63 through 32 if diffbit = 1
- //
- // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
- // ---------------------------------------------------------------------------------------------------
- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
- // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
- // ---------------------------------------------------------------------------------------------------
- //
- // c) bit layout in bits 31 through 0 (in both cases)
- //
- // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- // --------------------------------------------------------------------------------------------------
- // | most significant pixel index bits | least significant pixel index bits |
- // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
- // --------------------------------------------------------------------------------------------------
- diffbit = 1;
- compressed1 = 0;
- PUTBITSHIGH( compressed1, diffbit, 1, 33);
- PUTBITSHIGH( compressed1, best_enc_color1[0], 5, 63);
- PUTBITSHIGH( compressed1, best_enc_color1[1], 5, 55);
- PUTBITSHIGH( compressed1, best_enc_color1[2], 5, 47);
- PUTBITSHIGH( compressed1, diff[0], 3, 58);
- PUTBITSHIGH( compressed1, diff[1], 3, 50);
- PUTBITSHIGH( compressed1, diff[2], 3, 42);
- PUTBITSHIGH( compressed1, best_table1, 3, 39);
- PUTBITSHIGH( compressed1, best_table2, 3, 36);
- PUTBITSHIGH( compressed1, best_flip, 1, 32);
- if(best_flip == 0)
- {
- compressed2 = 0;
- PUTBITS( compressed2, (best_pixel_indices1_MSB ), 8, 23);
- PUTBITS( compressed2, (best_pixel_indices2_MSB ), 8, 31);
- PUTBITS( compressed2, (best_pixel_indices1_LSB ), 8, 7);
- PUTBITS( compressed2, (best_pixel_indices2_LSB ), 8, 15);
- }
- else
- {
- best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2);
- best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2);
- compressed2 = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff);
- }
- return best_err;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // This function uses real exhaustive search for the planar mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockPlanar57ExhaustivePerceptual(uint8 *img, int width,int height,int startx,int starty, unsigned int &compressed57_1, unsigned int &compressed57_2, unsigned int best_error_sofar, unsigned int best_error_planar_red, unsigned int best_error_planar_green, unsigned int best_error_planar_blue)
- {
- int colorO_enc[3], colorH_enc[3], colorV_enc[3];
- int best_colorO_enc[3], best_colorH_enc[3], best_colorV_enc[3];
- unsigned int error;
- unsigned int best_error;
- unsigned int lowest_possible_error;
- unsigned int best_error_red_sofar;
- unsigned int best_error_green_sofar;
- unsigned int best_error_blue_sofar;
- unsigned int BBBtable[128*128];
- unsigned int CCCtable[128*128];
- uint8 block[4*4*4];
- // Use 4 bytes per pixel to make it 32-word aligned.
- int count = 0;
- int xx, yy;
- for(yy=0; yy<4; yy++)
- {
- for(xx = 0; xx<4; xx++)
- {
- block[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block[(count)*4+3] = 0;
- count++;
- }
- }
- // The task is to calculate the sum of the error over the entire area of the block.
- //
- // The block can be partitioned into: O A A A
- // B D D C
- // B D C D
- // B C D D
- // where the error in
- // O only depends on colorO
- // A only depends on colorO and colorH
- // B only depends on colorO and colorV
- // C only depends on colorH and colorV
- // D depends on all three (colorO, colorH and colorV)
- //
- // Note that B can be precalculated for all combinations of colorO and colorV
- // and the precalculated values can be used instead of calculating it in the inner loop.
- // The same applies to C.
- //
- // In the code below, the squared error over O A A A is calculated and stored in lowest_possible_error
- // Precalc BBB errors
- for(colorO_enc[0] = 0; colorO_enc[0]<64; colorO_enc[0]++)
- {
- for(colorV_enc[0] = 0; colorV_enc[0]<64; colorV_enc[0]++)
- {
- BBBtable[colorO_enc[0]*64+colorV_enc[0]] = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*calcBBBred(block, colorO_enc[0], colorV_enc[0]);
- }
- }
- // Precalc CCC errors
- for(colorH_enc[0] = 0; colorH_enc[0]<64; colorH_enc[0]++)
- {
- for(colorV_enc[0] = 0; colorV_enc[0]<64; colorV_enc[0]++)
- {
- CCCtable[colorH_enc[0]*64+colorV_enc[0]] = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*calcCCCred(block, colorH_enc[0], colorV_enc[0]);
- }
- }
- best_error = MAXERR1000;
- best_error_red_sofar = JAS_MIN(best_error_planar_red, best_error_sofar);
- for(colorO_enc[0] = 0; colorO_enc[0]<64; colorO_enc[0]++)
- {
- for(colorH_enc[0] = 0; colorH_enc[0]<64; colorH_enc[0]++)
- {
- lowest_possible_error = calcLowestPossibleRedOHperceptual(block, colorO_enc[0], colorH_enc[0], best_error_red_sofar);
- if(lowest_possible_error <= best_error_red_sofar)
- {
- for(colorV_enc[0] = 0; colorV_enc[0]<64; colorV_enc[0]++)
- {
- error = calcErrorPlanarOnlyRedPerceptual(block, colorO_enc[0], colorH_enc[0], colorV_enc[0], lowest_possible_error, BBBtable[colorO_enc[0]*64+colorV_enc[0]], CCCtable[colorH_enc[0]*64+colorV_enc[0]], best_error_red_sofar);
- if(error < best_error)
- {
- best_error = error;
- best_colorO_enc[0] = colorO_enc[0];
- best_colorH_enc[0] = colorH_enc[0];
- best_colorV_enc[0] = colorV_enc[0];
- }
- }
- }
- }
- }
- if(best_error < best_error_planar_red)
- best_error_planar_red = best_error;
- if(best_error_planar_red > best_error_sofar)
- {
- // The red component in itself is already bigger than the previously best value ---- we can give up.
- // use the dummy color black for all colors and report that the errors for the different color components are infinite
- best_error_planar_green = MAXERR1000;
- best_error_planar_blue = MAXERR1000;
- compressed57_1 = 0;
- compressed57_2 = 0;
- return;
- }
- // The task is to calculate the sum of the error over the entire area of the block.
- //
- // The block can be partitioned into: O A A A
- // B D D C
- // B D C D
- // B C D D
- // where the error in
- // O only depends on colorO
- // A only depends on colorO and colorH
- // B only depends on colorO and colorV
- // C only depends on colorH and colorV
- // D depends on all three (colorO, colorH and colorV)
- //
- // Note that B can be precalculated for all combinations of colorO and colorV
- // and the precalculated values can be used instead of calculating it in the inner loop.
- // The same applies to C.
- //
- // In the code below, the squared error over O A A A is calculated and store in lowest_possible_error
- // Precalc BBB errors
- for(colorO_enc[1] = 0; colorO_enc[1]<128; colorO_enc[1]++)
- {
- for(colorV_enc[1] = 0; colorV_enc[1]<128; colorV_enc[1]++)
- {
- BBBtable[colorO_enc[1]*128+colorV_enc[1]] = PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*calcBBBgreen(block, colorO_enc[1], colorV_enc[1]);
- }
- }
- // Precalc CCC errors
- for(colorH_enc[1] = 0; colorH_enc[1]<128; colorH_enc[1]++)
- {
- for(colorV_enc[1] = 0; colorV_enc[1]<128; colorV_enc[1]++)
- {
- CCCtable[colorH_enc[1]*128+colorV_enc[1]] = PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*calcCCCgreen(block, colorH_enc[1], colorV_enc[1]);
- }
- }
- best_error = MAXERR1000;
- best_error_green_sofar = JAS_MIN(best_error_planar_green, best_error_sofar);
- for(colorO_enc[1] = 0; colorO_enc[1]<128; colorO_enc[1]++)
- {
- for(colorH_enc[1] = 0; colorH_enc[1]<128; colorH_enc[1]++)
- {
- lowest_possible_error = calcLowestPossibleGreenOHperceptual(block, colorO_enc[1], colorH_enc[1], best_error_green_sofar);
- if(lowest_possible_error <= best_error_green_sofar)
- {
- for(colorV_enc[1] = 0; colorV_enc[1]<128; colorV_enc[1]++)
- {
- error = calcErrorPlanarOnlyGreenPerceptual(block, colorO_enc[1], colorH_enc[1], colorV_enc[1], lowest_possible_error, BBBtable[colorO_enc[1]*128+colorV_enc[1]], CCCtable[colorH_enc[1]*128+colorV_enc[1]], best_error_green_sofar);
- if(error < best_error)
- {
- best_error = error;
- best_colorO_enc[1] = colorO_enc[1];
- best_colorH_enc[1] = colorH_enc[1];
- best_colorV_enc[1] = colorV_enc[1];
- }
- }
- }
- }
- }
- if(best_error < best_error_planar_green)
- best_error_planar_green = best_error;
- if(best_error_planar_red + best_error_planar_green > best_error_sofar)
- {
- // The red component in itself is already bigger than the previously best value ---- we can give up.
- // use the dummy color black for all colors and report that the errors for the different color components are infinite
- best_error_planar_blue = MAXERR1000;
- compressed57_1 = 0;
- compressed57_2 = 0;
- return;
- }
- // The task is to calculate the sum of the error over the entire area of the block.
- //
- // The block can be partitioned into: O A A A
- // B D D C
- // B D C D
- // B C D D
- // where the error in
- // O only depends on colorO
- // A only depends on colorO and colorH
- // B only depends on colorO and colorV
- // C only depends on colorH and colorV
- // D depends on all three (colorO, colorH and colorV)
- //
- // Note that B can be precalculated for all combinations of colorO and colorV
- // and the precalculated values can be used instead of calculating it in the inner loop.
- // The same applies to C.
- //
- // In the code below, the squared error over O A A A is calculated and store in lowest_possible_error
- // Precalc BBB errors
- for(colorO_enc[2] = 0; colorO_enc[2]<64; colorO_enc[2]++)
- {
- for(colorV_enc[2] = 0; colorV_enc[2]<64; colorV_enc[2]++)
- {
- BBBtable[colorO_enc[2]*64+colorV_enc[2]] = calcBBBbluePerceptual(block, colorO_enc[2], colorV_enc[2]);
- }
- }
- // Precalc CCC errors
- for(colorH_enc[2] = 0; colorH_enc[2]<64; colorH_enc[2]++)
- {
- for(colorV_enc[2] = 0; colorV_enc[2]<64; colorV_enc[2]++)
- {
- CCCtable[colorH_enc[2]*64+colorV_enc[2]] = calcCCCbluePerceptual(block, colorH_enc[2], colorV_enc[2]);
- }
- }
- best_error = MAXERR1000;
- best_error_blue_sofar = JAS_MIN(best_error_planar_blue, best_error_sofar);
- for(colorO_enc[2] = 0; colorO_enc[2]<64; colorO_enc[2]++)
- {
- for(colorH_enc[2] = 0; colorH_enc[2]<64; colorH_enc[2]++)
- {
- lowest_possible_error = calcLowestPossibleBlueOHperceptual(block, colorO_enc[2], colorH_enc[2], best_error_blue_sofar);
- if(lowest_possible_error <= best_error_blue_sofar)
- {
- for(colorV_enc[2] = 0; colorV_enc[2]<64; colorV_enc[2]++)
- {
- error = calcErrorPlanarOnlyBluePerceptual(block, colorO_enc[2], colorH_enc[2], colorV_enc[2], lowest_possible_error, BBBtable[colorO_enc[2]*64+colorV_enc[2]], CCCtable[colorH_enc[2]*64+colorV_enc[2]], best_error_blue_sofar);
- if(error < best_error)
- {
- best_error = error;
- best_colorO_enc[2] = colorO_enc[2];
- best_colorH_enc[2] = colorH_enc[2];
- best_colorV_enc[2] = colorV_enc[2];
- }
- }
- }
- }
- }
- if(best_error < best_error_planar_blue)
- best_error_planar_blue = best_error;
- compressed57_1 = 0;
- compressed57_2 = 0;
- PUTBITSHIGH( compressed57_1, best_colorO_enc[0], 6, 63);
- PUTBITSHIGH( compressed57_1, best_colorO_enc[1], 7, 57);
- PUTBITSHIGH( compressed57_1, best_colorO_enc[2], 6, 50);
- PUTBITSHIGH( compressed57_1, best_colorH_enc[0], 6, 44);
- PUTBITSHIGH( compressed57_1, best_colorH_enc[1], 7, 38);
- PUTBITS( compressed57_2, best_colorH_enc[2], 6, 31);
- PUTBITS( compressed57_2, best_colorV_enc[0], 6, 25);
- PUTBITS( compressed57_2, best_colorV_enc[1], 7, 19);
- PUTBITS( compressed57_2, best_colorV_enc[2], 6, 12);
-
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // This function uses real exhaustive search for the planar mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockPlanar57Exhaustive(uint8 *img, int width,int height,int startx,int starty, unsigned int &compressed57_1, unsigned int &compressed57_2, unsigned int best_error_sofar, unsigned int best_error_red, unsigned int best_error_green, unsigned int best_error_blue)
- {
- int colorO_enc[3], colorH_enc[3], colorV_enc[3];
- int best_colorO_enc[3], best_colorH_enc[3], best_colorV_enc[3];
- unsigned int error;
- unsigned int best_error;
- unsigned int lowest_possible_error;
- unsigned int best_error_red_sofar;
- unsigned int best_error_green_sofar;
- unsigned int best_error_blue_sofar;
- unsigned int BBBtable[128*128];
- unsigned int CCCtable[128*128];
- uint8 block[4*4*4];
- // Use 4 bytes per pixel to make it 32-word aligned.
- int count = 0;
- int xx, yy;
- for(yy=0; yy<4; yy++)
- {
- for(xx = 0; xx<4; xx++)
- {
- block[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block[(count)*4+3] = 0;
- count++;
- }
- }
- // The task is to calculate the sum of the error over the entire area of the block.
- //
- // The block can be partitioned into: O A A A
- // B D D C
- // B D C D
- // B C D D
- // where the error in
- // O only depends on colorO
- // A only depends on colorO and colorH
- // B only depends on colorO and colorV
- // C only depends on colorH and colorV
- // D depends on all three (colorO, colorH and colorV)
- //
- // Note that B can be precalculated for all combinations of colorO and colorV
- // and the precalculated values can be used instead of calculating it in the inner loop.
- // The same applies to C.
- //
- // In the code below, the squared error over O A A A is calculated and store in lowest_possible_error
- // Precalc BBB errors
- for(colorO_enc[0] = 0; colorO_enc[0]<64; colorO_enc[0]++)
- {
- for(colorV_enc[0] = 0; colorV_enc[0]<64; colorV_enc[0]++)
- {
- BBBtable[colorO_enc[0]*64+colorV_enc[0]] = calcBBBred(block, colorO_enc[0], colorV_enc[0]);
- }
- }
- // Precalc CCC errors
- for(colorH_enc[0] = 0; colorH_enc[0]<64; colorH_enc[0]++)
- {
- for(colorV_enc[0] = 0; colorV_enc[0]<64; colorV_enc[0]++)
- {
- CCCtable[colorH_enc[0]*64+colorV_enc[0]] = calcCCCred(block, colorH_enc[0], colorV_enc[0]);
- }
- }
- best_error = MAXERR1000;
- best_error_red_sofar = JAS_MIN(best_error_red, best_error_sofar);
- for(colorO_enc[0] = 0; colorO_enc[0]<64; colorO_enc[0]++)
- {
- for(colorH_enc[0] = 0; colorH_enc[0]<64; colorH_enc[0]++)
- {
- lowest_possible_error = calcLowestPossibleRedOH(block, colorO_enc[0], colorH_enc[0], best_error_red_sofar);
- if(lowest_possible_error <= best_error_red_sofar)
- {
- for(colorV_enc[0] = 0; colorV_enc[0]<64; colorV_enc[0]++)
- {
- error = calcErrorPlanarOnlyRed(block, colorO_enc[0], colorH_enc[0], colorV_enc[0], lowest_possible_error, BBBtable[colorO_enc[0]*64+colorV_enc[0]], CCCtable[colorH_enc[0]*64+colorV_enc[0]], best_error_red_sofar);
- if(error < best_error)
- {
- best_error = error;
- best_colorO_enc[0] = colorO_enc[0];
- best_colorH_enc[0] = colorH_enc[0];
- best_colorV_enc[0] = colorV_enc[0];
- }
- }
- }
- }
- }
- // The task is to calculate the sum of the error over the entire area of the block.
- //
- // The block can be partitioned into: O A A A
- // B D D C
- // B D C D
- // B C D D
- // where the error in
- // O only depends on colorO
- // A only depends on colorO and colorH
- // B only depends on colorO and colorV
- // C only depends on colorH and colorV
- // D depends on all three (colorO, colorH and colorV)
- //
- // Note that B can be precalculated for all combinations of colorO and colorV
- // and the precalculated values can be used instead of calculating it in the inner loop.
- // The same applies to C.
- //
- // In the code below, the squared error over O A A A is calculated and store in lowest_possible_error
- // Precalc BBB errors
- for(colorO_enc[1] = 0; colorO_enc[1]<128; colorO_enc[1]++)
- {
- for(colorV_enc[1] = 0; colorV_enc[1]<128; colorV_enc[1]++)
- {
- BBBtable[colorO_enc[1]*128+colorV_enc[1]] = calcBBBgreen(block, colorO_enc[1], colorV_enc[1]);
- }
- }
- // Precalc CCC errors
- for(colorH_enc[1] = 0; colorH_enc[1]<128; colorH_enc[1]++)
- {
- for(colorV_enc[1] = 0; colorV_enc[1]<128; colorV_enc[1]++)
- {
- CCCtable[colorH_enc[1]*128+colorV_enc[1]] = calcCCCgreen(block, colorH_enc[1], colorV_enc[1]);
- }
- }
- best_error = MAXERR1000;
- best_error_green_sofar = JAS_MIN(best_error_green, best_error_sofar);
- for(colorO_enc[1] = 0; colorO_enc[1]<128; colorO_enc[1]++)
- {
- for(colorH_enc[1] = 0; colorH_enc[1]<128; colorH_enc[1]++)
- {
- lowest_possible_error = calcLowestPossibleGreenOH(block, colorO_enc[1], colorH_enc[1], best_error_green_sofar);
- if(lowest_possible_error <= best_error_green_sofar)
- {
- for(colorV_enc[1] = 0; colorV_enc[1]<128; colorV_enc[1]++)
- {
- error = calcErrorPlanarOnlyGreen(block, colorO_enc[1], colorH_enc[1], colorV_enc[1], lowest_possible_error, BBBtable[colorO_enc[1]*128+colorV_enc[1]], CCCtable[colorH_enc[1]*128+colorV_enc[1]], best_error_green_sofar);
- if(error < best_error)
- {
- best_error = error;
- best_colorO_enc[1] = colorO_enc[1];
- best_colorH_enc[1] = colorH_enc[1];
- best_colorV_enc[1] = colorV_enc[1];
- }
- }
- }
- }
- }
- // The task is to calculate the sum of the error over the entire area of the block.
- //
- // The block can be partitioned into: O A A A
- // B D D C
- // B D C D
- // B C D D
- // where the error in
- // O only depends on colorO
- // A only depends on colorO and colorH
- // B only depends on colorO and colorV
- // C only depends on colorH and colorV
- // D depends on all three (colorO, colorH and colorV)
- //
- // Note that B can be precalculated for all combinations of colorO and colorV
- // and the precalculated values can be used instead of calculating it in the inner loop.
- // The same applies to C.
- //
- // In the code below, the squared error over O A A A is calculated and store in lowest_possible_error
- // Precalc BBB errors
- for(colorO_enc[2] = 0; colorO_enc[2]<64; colorO_enc[2]++)
- {
- for(colorV_enc[2] = 0; colorV_enc[2]<64; colorV_enc[2]++)
- {
- BBBtable[colorO_enc[2]*64+colorV_enc[2]] = calcBBBblue(block, colorO_enc[2], colorV_enc[2]);
- }
- }
- // Precalc CCC errors
- for(colorH_enc[2] = 0; colorH_enc[2]<64; colorH_enc[2]++)
- {
- for(colorV_enc[2] = 0; colorV_enc[2]<64; colorV_enc[2]++)
- {
- CCCtable[colorH_enc[2]*64+colorV_enc[2]] = calcCCCblue(block, colorH_enc[2], colorV_enc[2]);
- }
- }
- best_error = MAXERR1000;
- best_error_blue_sofar = JAS_MIN(best_error_blue, best_error_sofar);
- for(colorO_enc[2] = 0; colorO_enc[2]<64; colorO_enc[2]++)
- {
- for(colorH_enc[2] = 0; colorH_enc[2]<64; colorH_enc[2]++)
- {
- lowest_possible_error = calcLowestPossibleBlueOH(block, colorO_enc[2], colorH_enc[2], best_error_blue_sofar);
- if(lowest_possible_error <= best_error_blue_sofar)
- {
- for(colorV_enc[2] = 0; colorV_enc[2]<64; colorV_enc[2]++)
- {
- error = calcErrorPlanarOnlyBlue(block, colorO_enc[2], colorH_enc[2], colorV_enc[2], lowest_possible_error, BBBtable[colorO_enc[2]*64+colorV_enc[2]], CCCtable[colorH_enc[2]*64+colorV_enc[2]], best_error_blue_sofar);
- if(error < best_error)
- {
- best_error = error;
- best_colorO_enc[2] = colorO_enc[2];
- best_colorH_enc[2] = colorH_enc[2];
- best_colorV_enc[2] = colorV_enc[2];
- }
- }
- }
- }
- }
- compressed57_1 = 0;
- compressed57_2 = 0;
- PUTBITSHIGH( compressed57_1, best_colorO_enc[0], 6, 63);
- PUTBITSHIGH( compressed57_1, best_colorO_enc[1], 7, 57);
- PUTBITSHIGH( compressed57_1, best_colorO_enc[2], 6, 50);
- PUTBITSHIGH( compressed57_1, best_colorH_enc[0], 6, 44);
- PUTBITSHIGH( compressed57_1, best_colorH_enc[1], 7, 38);
- PUTBITS( compressed57_2, best_colorH_enc[2], 6, 31);
- PUTBITS( compressed57_2, best_colorV_enc[0], 6, 25);
- PUTBITS( compressed57_2, best_colorV_enc[1], 7, 19);
- PUTBITS( compressed57_2, best_colorV_enc[2], 6, 12);
-
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col0_Rpercep1000(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col0_R)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff;
- uint8 color;
- uint8 possible_colors[3];
- color = ((colorRGB444_packed >> 8) & 0xf)*17;
- // Test all distances
- for (uint8 d = 0; d < 8; d++)
- {
- possible_colors[0] = CLAMP(0,color - table59T[d],255);
- possible_colors[1] = CLAMP(0,color,255);
- possible_colors[2] = CLAMP(0,color + table59T[d],255);
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- best_pixel_error = MAXERR1000;
- // Loop possible block colors
- for (uint8 c = 0; c < 3; c++)
- {
-
- diff = block[4*x + R] - CLAMP(0,possible_colors[c],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff);
- // Choose best error
- if (pixel_error < best_pixel_error)
- best_pixel_error = pixel_error;
- }
- precalc_err_col0_R[((colorRGB444_packed>>8)*8 + d)*16 + x] = (unsigned int) best_pixel_error;
- }
- }
-
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col0_R(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col0_R)
- {
- unsigned int block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff;
- uint8 color;
- uint8 possible_colors[3];
- color = ((colorRGB444_packed >> 8) & 0xf)*17;
- // Test all distances
- for (uint8 d = 0; d < 8; d++)
- {
- possible_colors[0] = CLAMP(0,color - table59T[d],255);
- possible_colors[1] = CLAMP(0,color,255);
- possible_colors[2] = CLAMP(0,color + table59T[d],255);
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- best_pixel_error = MAXIMUM_ERROR;
- // Loop possible block colors
- for (uint8 c = 0; c < 3; c++)
- {
-
- diff = block[4*x + R] - CLAMP(0,possible_colors[c],255);
- pixel_error = SQUARE(diff);
- // Choose best error
- if (pixel_error < best_pixel_error)
- best_pixel_error = pixel_error;
- }
- precalc_err_col0_R[((colorRGB444_packed>>8)*8 + d)*16 + x] = (unsigned int) best_pixel_error;
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col0_RGpercep1000(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col0_RG)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff[3];
- uint8 color[3];
- uint8 possible_colors[3][2];
- color[R] = ((colorRGB444_packed >> 8) & 0xf)*17;
- color[G] = ((colorRGB444_packed >> 4) & 0xf)*17;
- // Test all distances
- for (uint8 d = 0; d < 8; d++)
- {
- possible_colors[0][R] = CLAMP(0,color[R] - table59T[d],255);
- possible_colors[0][G] = CLAMP(0,color[G] - table59T[d],255);
- possible_colors[1][R] = CLAMP(0,color[R],255);
- possible_colors[1][G] = CLAMP(0,color[G],255);
- possible_colors[2][R] = CLAMP(0,color[R] + table59T[d],255);
- possible_colors[2][G] = CLAMP(0,color[G] + table59T[d],255);
-
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- best_pixel_error = MAXERR1000;
- // Loop possible block colors
- for (uint8 c = 0; c < 3; c++)
- {
-
- diff[R] = block[4*x + R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = block[4*x + G] - CLAMP(0,possible_colors[c][G],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- best_pixel_error = pixel_error;
- }
- precalc_err_col0_RG[((colorRGB444_packed>>4)*8 + d)*16 + x] = (unsigned int) best_pixel_error;
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col0_RG(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col0_RG)
- {
- unsigned int block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- uint8 color[3];
- uint8 possible_colors[3][2];
- color[R] = ((colorRGB444_packed >> 8) & 0xf)*17;
- color[G] = ((colorRGB444_packed >> 4) & 0xf)*17;
- // Test all distances
- for (uint8 d = 0; d < 8; d++)
- {
- possible_colors[0][R] = CLAMP(0,color[R] - table59T[d],255);
- possible_colors[0][G] = CLAMP(0,color[G] - table59T[d],255);
- possible_colors[1][R] = CLAMP(0,color[R],255);
- possible_colors[1][G] = CLAMP(0,color[G],255);
- possible_colors[2][R] = CLAMP(0,color[R] + table59T[d],255);
- possible_colors[2][G] = CLAMP(0,color[G] + table59T[d],255);
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- best_pixel_error = MAXIMUM_ERROR;
- // Loop possible block colors
- for (uint8 c = 0; c < 3; c++)
- {
- diff[R] = block[4*x + R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = block[4*x + G] - CLAMP(0,possible_colors[c][G],255);
- pixel_error = SQUARE(diff[R]) + SQUARE(diff[G]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- best_pixel_error = pixel_error;
- }
- precalc_err_col0_RG[((colorRGB444_packed>>4)*8 + d)*16 + x] = (unsigned int) best_pixel_error;
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col1_Rpercep1000(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col1_R)
- {
- unsigned int pixel_error;
- int diff;
- uint8 color;
- color = ((colorRGB444_packed >> 8) & 0xf)*17;
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- diff = block[4*x + R] - color;
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff);
- precalc_err_col1_R[((colorRGB444_packed>>8))*16 + x] = (unsigned int) pixel_error;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- /**
- * Calculate the error for the block at position (startx,starty)
- * The parameters needed for reconstruction is calculated as well
- *
- * In the 59T bit mode, we only have pattern T.
- */
- void precalcError59T_col1_R(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col1_R)
- {
- unsigned int pixel_error;
- int diff;
- uint8 color;
- color = ((colorRGB444_packed >> 8) & 0xf)*17;
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- diff = block[4*x + R] - color;
- pixel_error = SQUARE(diff);
- precalc_err_col1_R[((colorRGB444_packed>>8))*16 + x] = (unsigned int) pixel_error;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col1_RGpercep1000(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col1_RG)
- {
- unsigned int pixel_error;
- int diff[3];
- uint8 color[2];
- color[R] = ((colorRGB444_packed >> 8) & 0xf)*17;
- color[G] = ((colorRGB444_packed >> 4) & 0xf)*17;
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- diff[R] = block[4*x + R] - color[R];
- diff[G] = block[4*x + G] - color[G];
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]);
- precalc_err_col1_RG[((colorRGB444_packed>>4))*16 + x] = (unsigned int) pixel_error;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col1_RG(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col1_RG)
- {
- unsigned int pixel_error;
- int diff[3];
- uint8 color[2];
- color[R] = ((colorRGB444_packed >> 8) & 0xf)*17;
- color[G] = ((colorRGB444_packed >> 4) & 0xf)*17;
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- diff[R] = block[4*x + R] - color[R];
- diff[G] = block[4*x + G] - color[G];
- pixel_error = SQUARE(diff[R]) + SQUARE(diff[G]);
- precalc_err_col1_RG[((colorRGB444_packed>>4))*16 + x] = (unsigned int) pixel_error;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col0_RGBpercep1000(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col0_RGB)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- uint8 color[3];
- int possible_colors[3][3];
- unsigned int *precalc_err_col0_RGB_adr;
- #define ONEPOINT59RGB_PERCEP(xval) \
- /* Loop possible block colors */\
- /* unroll loop for (uint8 c = 0; c < 3; c++) */\
- {\
- best_pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*square_table[block[4*xval + R] - possible_colors[0][R]]\
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*square_table[block[4*xval + G] - possible_colors[0][G]] \
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[block[4*xval + B] - possible_colors[0][B]];\
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*square_table[block[4*xval + R] - possible_colors[1][R]]\
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*square_table[block[4*xval + G] - possible_colors[1][G]]\
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[block[4*xval + B] - possible_colors[1][B]];\
- if (pixel_error < best_pixel_error)\
- best_pixel_error = pixel_error;\
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*square_table[block[4*xval + R] - possible_colors[2][R]]\
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*square_table[block[4*xval + G] - possible_colors[2][G]]\
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[block[4*xval + B] - possible_colors[2][B]];\
- if (pixel_error < best_pixel_error)\
- best_pixel_error = pixel_error;\
- }\
- precalc_err_col0_RGB_adr[xval] = (unsigned int) best_pixel_error;\
- #define ONETABLE59RGB_PERCEP(dval) \
- possible_colors[0][R] = clamp_table[color[R] - table59T[dval]+255]-255;\
- possible_colors[0][G] = clamp_table[color[G] - table59T[dval]+255]-255;\
- possible_colors[0][B] = clamp_table[color[B] - table59T[dval]+255]-255;\
- possible_colors[1][R] = color[R]-255;\
- possible_colors[1][G] = color[G]-255;\
- possible_colors[1][B] = color[B]-255;\
- possible_colors[2][R] = clamp_table[color[R] + table59T[dval]+255]-255;\
- possible_colors[2][G] = clamp_table[color[G] + table59T[dval]+255]-255;\
- possible_colors[2][B] = clamp_table[color[B] + table59T[dval]+255]-255;\
- precalc_err_col0_RGB_adr = &precalc_err_col0_RGB[(colorRGB444_packed*8 + dval)*16];\
- /* Loop block */\
- /* unroll loop for (int x = 0; x < 16; x++) */\
- {\
- ONEPOINT59RGB_PERCEP(0)\
- ONEPOINT59RGB_PERCEP(1)\
- ONEPOINT59RGB_PERCEP(2)\
- ONEPOINT59RGB_PERCEP(3)\
- ONEPOINT59RGB_PERCEP(4)\
- ONEPOINT59RGB_PERCEP(5)\
- ONEPOINT59RGB_PERCEP(6)\
- ONEPOINT59RGB_PERCEP(7)\
- ONEPOINT59RGB_PERCEP(8)\
- ONEPOINT59RGB_PERCEP(9)\
- ONEPOINT59RGB_PERCEP(10)\
- ONEPOINT59RGB_PERCEP(11)\
- ONEPOINT59RGB_PERCEP(12)\
- ONEPOINT59RGB_PERCEP(13)\
- ONEPOINT59RGB_PERCEP(14)\
- ONEPOINT59RGB_PERCEP(15)\
- }\
- color[R] = (((colorRGB444_packed >> 8) ) << 4) | ((colorRGB444_packed >> 8) ) ;
- color[G] = (((colorRGB444_packed >> 4) & 0xf) << 4) | ((colorRGB444_packed >> 4) & 0xf) ;
- color[B] = (((colorRGB444_packed) & 0xf) << 4) | ((colorRGB444_packed) & 0xf) ;
-
- /* Test all distances */
- /* unroll loop for (uint8 d = 0; d < 8; ++d) */
- {
- ONETABLE59RGB_PERCEP(0)
- ONETABLE59RGB_PERCEP(1)
- ONETABLE59RGB_PERCEP(2)
- ONETABLE59RGB_PERCEP(3)
- ONETABLE59RGB_PERCEP(4)
- ONETABLE59RGB_PERCEP(5)
- ONETABLE59RGB_PERCEP(6)
- ONETABLE59RGB_PERCEP(7)
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col0_RGB(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col0_RGB)
- {
- unsigned int block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- uint8 color[3];
- int possible_colors[3][3];
- unsigned int *precalc_err_col0_RGB_adr;
- #define ONEPOINT59RGB(xval) \
- /* Loop possible block colors */\
- /* unroll loop for (uint8 c = 0; c < 3; c++) */\
- {\
- best_pixel_error = square_table[block[4*xval + R] - possible_colors[0][R]]\
- + square_table[block[4*xval + G] - possible_colors[0][G]] \
- + square_table[block[4*xval + B] - possible_colors[0][B]];\
- pixel_error = square_table[block[4*xval + R] - possible_colors[1][R]]\
- + square_table[block[4*xval + G] - possible_colors[1][G]]\
- + square_table[block[4*xval + B] - possible_colors[1][B]];\
- if (pixel_error < best_pixel_error)\
- best_pixel_error = pixel_error;\
- pixel_error = square_table[block[4*xval + R] - possible_colors[2][R]]\
- + square_table[block[4*xval + G] - possible_colors[2][G]]\
- + square_table[block[4*xval + B] - possible_colors[2][B]];\
- if (pixel_error < best_pixel_error)\
- best_pixel_error = pixel_error;\
- }\
- precalc_err_col0_RGB_adr[xval] = (unsigned int) best_pixel_error;\
- #define ONETABLE59RGB(dval) \
- possible_colors[0][R] = clamp_table[color[R] - table59T[dval]+255]-255;\
- possible_colors[0][G] = clamp_table[color[G] - table59T[dval]+255]-255;\
- possible_colors[0][B] = clamp_table[color[B] - table59T[dval]+255]-255;\
- possible_colors[1][R] = color[R]-255;\
- possible_colors[1][G] = color[G]-255;\
- possible_colors[1][B] = color[B]-255;\
- possible_colors[2][R] = clamp_table[color[R] + table59T[dval]+255]-255;\
- possible_colors[2][G] = clamp_table[color[G] + table59T[dval]+255]-255;\
- possible_colors[2][B] = clamp_table[color[B] + table59T[dval]+255]-255;\
- precalc_err_col0_RGB_adr = &precalc_err_col0_RGB[(colorRGB444_packed*8 + dval)*16];\
- /* Loop block */\
- /* unroll loop for (int x = 0; x < 16; x++) */\
- {\
- ONEPOINT59RGB(0)\
- ONEPOINT59RGB(1)\
- ONEPOINT59RGB(2)\
- ONEPOINT59RGB(3)\
- ONEPOINT59RGB(4)\
- ONEPOINT59RGB(5)\
- ONEPOINT59RGB(6)\
- ONEPOINT59RGB(7)\
- ONEPOINT59RGB(8)\
- ONEPOINT59RGB(9)\
- ONEPOINT59RGB(10)\
- ONEPOINT59RGB(11)\
- ONEPOINT59RGB(12)\
- ONEPOINT59RGB(13)\
- ONEPOINT59RGB(14)\
- ONEPOINT59RGB(15)\
- }\
- color[R] = (((colorRGB444_packed >> 8) ) << 4) | ((colorRGB444_packed >> 8) ) ;
- color[G] = (((colorRGB444_packed >> 4) & 0xf) << 4) | ((colorRGB444_packed >> 4) & 0xf) ;
- color[B] = (((colorRGB444_packed) & 0xf) << 4) | ((colorRGB444_packed) & 0xf) ;
- /* Test all distances */
- /* unroll loop for (uint8 d = 0; d < 8; ++d) */
- {
- ONETABLE59RGB(0)
- ONETABLE59RGB(1)
- ONETABLE59RGB(2)
- ONETABLE59RGB(3)
- ONETABLE59RGB(4)
- ONETABLE59RGB(5)
- ONETABLE59RGB(6)
- ONETABLE59RGB(7)
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col1_RGBpercep1000(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col1_RGB)
- {
- unsigned int pixel_error;
- int diff[3];
- uint8 colorRGB[3];
- colorRGB[0] = ((colorRGB444_packed >> 8) & 0xf)*17;
- colorRGB[1] = ((colorRGB444_packed >> 4) & 0xf)*17;
- colorRGB[2] = ((colorRGB444_packed >> 0) & 0xf)*17;
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- diff[R] = block[4*x + R] - colorRGB[R];
- diff[G] = block[4*x + G] - colorRGB[G];
- diff[B] = block[4*x + B] - colorRGB[B];
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]) + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*SQUARE(diff[B]);
-
- precalc_err_col1_RGB[(colorRGB444_packed)*16 + x] = (unsigned int) pixel_error;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in exhaustive compression of the T-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError59T_col1_RGB(uint8* block, int colorRGB444_packed, unsigned int *precalc_err_col1_RGB)
- {
- unsigned int pixel_error;
- int diff[3];
- uint8 colorRGB[3];
- colorRGB[0] = ((colorRGB444_packed >> 8) & 0xf)*17;
- colorRGB[1] = ((colorRGB444_packed >> 4) & 0xf)*17;
- colorRGB[2] = ((colorRGB444_packed >> 0) & 0xf)*17;
- // Loop block
- for (int x = 0; x < 16; x++)
- {
- diff[R] = block[4*x + R] - colorRGB[R];
- diff[G] = block[4*x + G] - colorRGB[G];
- diff[B] = block[4*x + B] - colorRGB[B];
- pixel_error = SQUARE(diff[R]) + SQUARE(diff[G]) + SQUARE(diff[B]);
- precalc_err_col1_RGB[(colorRGB444_packed)*16 + x] = (unsigned int) pixel_error;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimal error for the T-mode when compressing exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TusingPrecalcRperceptual1000(uint8* block, int *colorsRGB444_packed, unsigned int *precalc_err_col0_R, unsigned int *precalc_err_col1_R, unsigned int best_error_so_far)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000;
- unsigned int *pixel_error_col0_base_adr;
- unsigned int *pixel_error_col0_adr, *pixel_error_col1_adr;
- #define FIRSTCHOICE59R_PERCEP\
- if(*pixel_error_col0_adr < *pixel_error_col1_adr)\
- block_error = *pixel_error_col0_adr;\
- else\
- block_error = *pixel_error_col1_adr;\
- #define CHOICE59R_PERCEP(xval)\
- if(pixel_error_col0_adr[xval] < pixel_error_col1_adr[xval])\
- block_error += pixel_error_col0_adr[xval];\
- else\
- block_error += pixel_error_col1_adr[xval];\
- #define ONETABLE59R_PERCEP(dval) \
- pixel_error_col0_adr = &pixel_error_col0_base_adr[dval*16];\
- /* unroll loop for(int x = 0; block_error < best_error_so_far && x<16; x++) */\
- {\
- FIRSTCHOICE59R_PERCEP\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(1)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(2)\
- CHOICE59R_PERCEP(3)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(4)\
- CHOICE59R_PERCEP(5)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(6)\
- CHOICE59R_PERCEP(7)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(8)\
- CHOICE59R_PERCEP(9)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(10)\
- CHOICE59R_PERCEP(11)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(12)\
- CHOICE59R_PERCEP(13)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R_PERCEP(14)\
- CHOICE59R_PERCEP(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- if (block_error < best_block_error)\
- best_block_error = block_error;\
-
- pixel_error_col0_base_adr = &precalc_err_col0_R[((colorsRGB444_packed[0]>>8)*8)*16];
- pixel_error_col1_adr = &precalc_err_col1_R[((colorsRGB444_packed[1]>>8))*16];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; d++) */
- {
- ONETABLE59R_PERCEP(0)
- ONETABLE59R_PERCEP(1)
- ONETABLE59R_PERCEP(2)
- ONETABLE59R_PERCEP(3)
- ONETABLE59R_PERCEP(4)
- ONETABLE59R_PERCEP(5)
- ONETABLE59R_PERCEP(6)
- ONETABLE59R_PERCEP(7)
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimal error for the T-mode when compressing exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TusingPrecalcR(uint8* block, int *colorsRGB444_packed, unsigned int *precalc_err_col0_R, unsigned int *precalc_err_col1_R, unsigned int best_error_so_far)
- {
- unsigned int block_error = 0,
- best_block_error = MAXIMUM_ERROR;
- unsigned int *pixel_error_col0_base_adr;
- unsigned int *pixel_error_col0_adr, *pixel_error_col1_adr;
- #define FIRSTCHOICE59R\
- if(*pixel_error_col0_adr < *pixel_error_col1_adr)\
- block_error = *pixel_error_col0_adr;\
- else\
- block_error = *pixel_error_col1_adr;\
- #define CHOICE59R(xval)\
- if(pixel_error_col0_adr[xval] < pixel_error_col1_adr[xval])\
- block_error += pixel_error_col0_adr[xval];\
- else\
- block_error += pixel_error_col1_adr[xval];\
- #define ONETABLE59R(dval) \
- pixel_error_col0_adr = &pixel_error_col0_base_adr[dval*16];\
- /* unroll loop for(int x = 0; block_error < best_error_so_far && x<16; x++) */\
- {\
- FIRSTCHOICE59R\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(1)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(2)\
- CHOICE59R(3)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(4)\
- CHOICE59R(5)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(6)\
- CHOICE59R(7)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(8)\
- CHOICE59R(9)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(10)\
- CHOICE59R(11)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(12)\
- CHOICE59R(13)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59R(14)\
- CHOICE59R(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- if (block_error < best_block_error)\
- best_block_error = block_error;\
-
- pixel_error_col0_base_adr = &precalc_err_col0_R[((colorsRGB444_packed[0]>>8)*8)*16];
- pixel_error_col1_adr = &precalc_err_col1_R[((colorsRGB444_packed[1]>>8))*16];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; d++) */
- {
- ONETABLE59R(0)
- ONETABLE59R(1)
- ONETABLE59R(2)
- ONETABLE59R(3)
- ONETABLE59R(4)
- ONETABLE59R(5)
- ONETABLE59R(6)
- ONETABLE59R(7)
- }
-
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimal error for the T-mode when compressing exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TusingPrecalcRGperceptual1000(uint8* block, int *colorsRGB444_packed, unsigned int *precalc_err_col0_RG, unsigned int *precalc_err_col1_RG, unsigned int best_error_so_far)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000;
- unsigned int *pixel_error_col0_adr, *pixel_error_col1_adr;
- unsigned int *pixel_error_col0_base_adr;
- #define FIRSTCHOICE59RG_PERCEP \
- if(*pixel_error_col0_adr < *pixel_error_col1_adr)\
- block_error = *pixel_error_col0_adr;\
- else\
- block_error = *pixel_error_col1_adr;\
- #define CHOICE59RG_PERCEP(xval) \
- if(pixel_error_col0_adr[xval] < pixel_error_col1_adr[xval])\
- block_error += pixel_error_col0_adr[xval];\
- else\
- block_error += pixel_error_col1_adr[xval];\
- #define ONETABLE59RG_PERCEP(dval)\
- pixel_error_col0_adr = &pixel_error_col0_base_adr[dval*16];\
- /* unroll loop for(int x = 0; block_error < best_error_so_far && x<16; x++) */\
- {\
- FIRSTCHOICE59RG_PERCEP\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(1)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(2)\
- CHOICE59RG_PERCEP(3)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(4)\
- CHOICE59RG_PERCEP(5)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(6)\
- CHOICE59RG_PERCEP(7)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(8)\
- CHOICE59RG_PERCEP(9)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(10)\
- CHOICE59RG_PERCEP(11)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(12)\
- CHOICE59RG_PERCEP(13)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG_PERCEP(14)\
- CHOICE59RG_PERCEP(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- if (block_error < best_block_error)\
- best_block_error = block_error;\
- pixel_error_col0_base_adr = &precalc_err_col0_RG[((colorsRGB444_packed[0]>>4)*8)*16];
- pixel_error_col1_adr = &precalc_err_col1_RG[((colorsRGB444_packed[1]>>4))*16];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; d++) */
- {
- ONETABLE59RG_PERCEP(0)
- ONETABLE59RG_PERCEP(1)
- ONETABLE59RG_PERCEP(2)
- ONETABLE59RG_PERCEP(3)
- ONETABLE59RG_PERCEP(4)
- ONETABLE59RG_PERCEP(5)
- ONETABLE59RG_PERCEP(6)
- ONETABLE59RG_PERCEP(7)
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimal error for the T-mode when compressing exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TusingPrecalcRG(uint8* block, int *colorsRGB444_packed, unsigned int *precalc_err_col0_RG, unsigned int *precalc_err_col1_RG, unsigned int best_error_so_far)
- {
- unsigned int block_error = 0,
- best_block_error = MAXIMUM_ERROR;
- unsigned int *pixel_error_col0_adr, *pixel_error_col1_adr;
- unsigned int *pixel_error_col0_base_adr;
- #define FIRSTCHOICE59RG \
- if(*pixel_error_col0_adr < *pixel_error_col1_adr)\
- block_error = *pixel_error_col0_adr;\
- else\
- block_error = *pixel_error_col1_adr;\
- #define CHOICE59RG(xval) \
- if(pixel_error_col0_adr[xval] < pixel_error_col1_adr[xval])\
- block_error += pixel_error_col0_adr[xval];\
- else\
- block_error += pixel_error_col1_adr[xval];\
- #define ONETABLE59RG(dval)\
- pixel_error_col0_adr = &pixel_error_col0_base_adr[dval*16];\
- /* unroll loop for(int x = 0; block_error < best_error_so_far && x<16; x++) */\
- {\
- FIRSTCHOICE59RG\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(1)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(2)\
- CHOICE59RG(3)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(4)\
- CHOICE59RG(5)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(6)\
- CHOICE59RG(7)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(8)\
- CHOICE59RG(9)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(10)\
- CHOICE59RG(11)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(12)\
- CHOICE59RG(13)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59RG(14)\
- CHOICE59RG(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- if (block_error < best_block_error)\
- best_block_error = block_error;\
- pixel_error_col0_base_adr = &precalc_err_col0_RG[((colorsRGB444_packed[0]>>4)*8)*16];
- pixel_error_col1_adr = &precalc_err_col1_RG[((colorsRGB444_packed[1]>>4))*16];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; d++) */
- {
- ONETABLE59RG(0)
- ONETABLE59RG(1)
- ONETABLE59RG(2)
- ONETABLE59RG(3)
- ONETABLE59RG(4)
- ONETABLE59RG(5)
- ONETABLE59RG(6)
- ONETABLE59RG(7)
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimal error for the T-mode when compressing exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TusingPrecalcRGBperceptual1000(uint8* block, int *colorsRGB444_packed, unsigned int *precalc_err_col0_RGB, unsigned int *precalc_err_col1_RGB, unsigned int best_error_so_far)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000;
- unsigned int *pixel_error_col0_adr, *pixel_error_col1_adr;
- unsigned int *pixel_error_col0_base_adr;
- #define FIRSTCHOICE59_PERCEP \
- if(*pixel_error_col0_adr < *pixel_error_col1_adr)\
- block_error = *pixel_error_col0_adr;\
- else\
- block_error = *pixel_error_col1_adr;\
- #define CHOICE59_PERCEP(xval) \
- if(pixel_error_col0_adr[xval] < pixel_error_col1_adr[xval])\
- block_error += pixel_error_col0_adr[xval];\
- else\
- block_error += pixel_error_col1_adr[xval];\
- #define ONETABLE59T_PERCEP(dval)\
- pixel_error_col0_adr = &pixel_error_col0_base_adr[dval*16];\
- /* unroll for(int x = 0; block_error < best_error_so_far && x<16; x++) */\
- {\
- FIRSTCHOICE59_PERCEP\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(1)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(2)\
- CHOICE59_PERCEP(3)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(4)\
- CHOICE59_PERCEP(5)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(6)\
- CHOICE59_PERCEP(7)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(8)\
- CHOICE59_PERCEP(9)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(10)\
- CHOICE59_PERCEP(11)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(12)\
- CHOICE59_PERCEP(13)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59_PERCEP(14)\
- CHOICE59_PERCEP(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- if (block_error < best_block_error)\
- best_block_error = block_error;\
- pixel_error_col1_adr = &precalc_err_col1_RGB[(colorsRGB444_packed[1])*16];
- pixel_error_col0_base_adr = &precalc_err_col0_RGB[(colorsRGB444_packed[0]*8)*16];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; d++)*/
- {
- ONETABLE59T_PERCEP(0)
- ONETABLE59T_PERCEP(1)
- ONETABLE59T_PERCEP(2)
- ONETABLE59T_PERCEP(3)
- ONETABLE59T_PERCEP(4)
- ONETABLE59T_PERCEP(5)
- ONETABLE59T_PERCEP(6)
- ONETABLE59T_PERCEP(7)
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimal error for the T-mode when compressing exhaustively.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateError59TusingPrecalcRGB(uint8* block, int *colorsRGB444_packed, unsigned int *precalc_err_col0_RGB, unsigned int *precalc_err_col1_RGB, unsigned int best_error_so_far)
- {
- unsigned int block_error = 0,
- best_block_error = MAXIMUM_ERROR;
- unsigned int *pixel_error_col0_adr, *pixel_error_col1_adr;
- unsigned int *pixel_error_col0_base_adr;
- #define FIRSTCHOICE59 \
- if(*pixel_error_col0_adr < *pixel_error_col1_adr)\
- block_error = *pixel_error_col0_adr;\
- else\
- block_error = *pixel_error_col1_adr;\
- #define CHOICE59(xval) \
- if(pixel_error_col0_adr[xval] < pixel_error_col1_adr[xval])\
- block_error += pixel_error_col0_adr[xval];\
- else\
- block_error += pixel_error_col1_adr[xval];\
- #define ONETABLE59T(dval)\
- pixel_error_col0_adr = &pixel_error_col0_base_adr[dval*16];\
- /* unroll for(int x = 0; block_error < best_error_so_far && x<16; x++) */\
- {\
- FIRSTCHOICE59\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(1)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(2)\
- CHOICE59(3)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(4)\
- CHOICE59(5)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(6)\
- CHOICE59(7)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(8)\
- CHOICE59(9)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(10)\
- CHOICE59(11)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(12)\
- CHOICE59(13)\
- if( block_error < best_error_so_far)\
- {\
- CHOICE59(14)\
- CHOICE59(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- if (block_error < best_block_error)\
- best_block_error = block_error;\
- pixel_error_col1_adr = &precalc_err_col1_RGB[(colorsRGB444_packed[1])*16];
- pixel_error_col0_base_adr = &precalc_err_col0_RGB[(colorsRGB444_packed[0]*8)*16];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; d++)*/
- {
- ONETABLE59T(0)
- ONETABLE59T(1)
- ONETABLE59T(2)
- ONETABLE59T(3)
- ONETABLE59T(4)
- ONETABLE59T(5)
- ONETABLE59T(6)
- ONETABLE59T(7)
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // The below code should compress the block to 59 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // Note that this method might not return the best possible compression for the T-mode. It will only do so if the best possible T-representation
- // is less than best_error_so_far. To guarantee that the best possible T-representation is found, the function should be called using
- // best_error_so_far = 255*255*3*16, which is the maximum error for a block.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockTHUMB59TExhaustivePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int best_error_so_far)
- {
- uint8 colorsRGB444[2][3];
- unsigned int pixel_indices;
- uint8 distance;
- uint8 block[4*4*4];
- unsigned int *precalc_err_col0_RGB;
- unsigned int *precalc_err_col1_RGB;
- unsigned int *precalc_err_col0_RG;
- unsigned int *precalc_err_col1_RG;
- unsigned int *precalc_err_col0_R;
- unsigned int *precalc_err_col1_R;
- int colorRGB444_packed;
- int colorsRGB444_packed[2];
- int best_colorsRGB444_packed[2];
- unsigned int best_error_using_Tmode;
- // First compress block quickly to a resonable quality so that we can
- // rule out all blocks that are of worse quality than that.
- best_error_using_Tmode = (unsigned int) compressBlockTHUMB59TFastestOnlyColorPerceptual1000(img, width, height, startx, starty, best_colorsRGB444_packed);
- if(best_error_using_Tmode < best_error_so_far)
- best_error_so_far = best_error_using_Tmode;
- // Color numbering is reversed between the above function and the precalc functions below; swap colors.
- int temp = best_colorsRGB444_packed[0];
- best_colorsRGB444_packed[0] = best_colorsRGB444_packed[1];
- best_colorsRGB444_packed[1] = temp;
- int xx,yy,count = 0;
- // Use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<4; xx++)
- {
- for(yy=0; yy<4; yy++)
- {
- block[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block[(count)*4+3] = 0;
- count++;
- }
- }
- // Precalculate error for color 0 (which produces the upper half of the T)
- precalc_err_col0_RGB = (unsigned int*) malloc(4096*8*16*sizeof(unsigned int));
- if(!precalc_err_col0_RGB){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed++)
- {
- precalcError59T_col0_RGBpercep1000(block, colorRGB444_packed, precalc_err_col0_RGB);
- }
- // Precalculate error for color 1 (which produces the lower half of the T -- the lone color)
- precalc_err_col1_RGB = (unsigned int*) malloc(4096*16*sizeof(unsigned int));
- if(!precalc_err_col1_RGB){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed++)
- {
- precalcError59T_col1_RGBpercep1000(block, colorRGB444_packed, precalc_err_col1_RGB);
- }
- precalc_err_col0_RG = (unsigned int*) malloc(16*16*8*16*sizeof(unsigned int));
- if(!precalc_err_col0_RG){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16)
- {
- precalcError59T_col0_RGpercep1000(block, colorRGB444_packed, precalc_err_col0_RG);
- }
- precalc_err_col1_RG = (unsigned int*) malloc(16*16*16*sizeof(unsigned int));
- if(!precalc_err_col1_RG){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16)
- {
- precalcError59T_col1_RGpercep1000(block, colorRGB444_packed, precalc_err_col1_RG);
- }
- precalc_err_col0_R = (unsigned int*) malloc(16*8*16*sizeof(unsigned int));
- if(!precalc_err_col0_R){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16*16)
- {
- precalcError59T_col0_Rpercep1000(block, colorRGB444_packed, precalc_err_col0_R);
- }
- precalc_err_col1_R = (unsigned int*) malloc(16*16*sizeof(unsigned int));
- if(!precalc_err_col1_R){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16*16)
- {
- precalcError59T_col1_Rpercep1000(block, colorRGB444_packed, precalc_err_col1_R);
- }
- unsigned int error;
- unsigned int avoided = 0;
- unsigned int notavoided = 0;
- for(colorsRGB444[0][0] = 0; colorsRGB444[0][0] < 16; colorsRGB444[0][0]++)
- {
- for(colorsRGB444[1][0] = 0; colorsRGB444[1][0] < 16; colorsRGB444[1][0]++)
- {
- colorsRGB444_packed[0] = (colorsRGB444[0][0] << 8);
- colorsRGB444_packed[1] = (colorsRGB444[1][0] << 8);
- error = calculateError59TusingPrecalcRperceptual1000(block, colorsRGB444_packed, precalc_err_col0_R, precalc_err_col1_R, best_error_so_far);
- if(error < best_error_so_far)
- {
- notavoided = notavoided + 1;
- for(colorsRGB444[0][1] = 0; colorsRGB444[0][1] < 16; colorsRGB444[0][1]++)
- {
- colorsRGB444_packed[0] = (colorsRGB444[0][0] << 8) + (colorsRGB444[0][1] <<4);
- for(colorsRGB444[1][1] = 0; colorsRGB444[1][1] < 16; colorsRGB444[1][1]++)
- {
- colorsRGB444_packed[1] = (colorsRGB444[1][0] << 8) + (colorsRGB444[1][1] <<4);
- error = calculateError59TusingPrecalcRGperceptual1000(block, colorsRGB444_packed, precalc_err_col0_RG, precalc_err_col1_RG, best_error_so_far);
- if(error < best_error_so_far)
- {
- for(colorsRGB444[0][2] = 0; colorsRGB444[0][2] < 16; colorsRGB444[0][2]++)
- {
- colorsRGB444_packed[0] = (colorsRGB444[0][0] << 8) + (colorsRGB444[0][1] <<4) + colorsRGB444[0][2];
- for(colorsRGB444[1][2] = 0; colorsRGB444[1][2] < 16; colorsRGB444[1][2]++)
- {
- colorsRGB444_packed[1] = (colorsRGB444[1][0] << 8) + (colorsRGB444[1][1] <<4) + colorsRGB444[1][2];
- error = calculateError59TusingPrecalcRGBperceptual1000(block, colorsRGB444_packed, precalc_err_col0_RGB, precalc_err_col1_RGB, best_error_so_far);
- if(error < best_error_so_far)
- {
- best_error_so_far = error;
- best_error_using_Tmode = error;
- best_colorsRGB444_packed[0] = colorsRGB444_packed[0];
- best_colorsRGB444_packed[1] = colorsRGB444_packed[1];
- }
- }
- }
- }
- }
- }
- }
- }
- }
- free(precalc_err_col0_RGB);
- free(precalc_err_col1_RGB);
- free(precalc_err_col0_RG);
- free(precalc_err_col1_RG);
- free(precalc_err_col0_R);
- free(precalc_err_col1_R);
- // We have got the two best colors. Now find the best distance and pixel indices.
- // Color numbering are reversed between precalc and noSwap
- colorsRGB444[0][0] = (best_colorsRGB444_packed[1] >> 8) & 0xf;
- colorsRGB444[0][1] = (best_colorsRGB444_packed[1] >> 4) & 0xf;
- colorsRGB444[0][2] = (best_colorsRGB444_packed[1] >> 0) & 0xf;
-
- colorsRGB444[1][0] = (best_colorsRGB444_packed[0] >> 8) & 0xf;
- colorsRGB444[1][1] = (best_colorsRGB444_packed[0] >> 4) & 0xf;
- colorsRGB444[1][2] = (best_colorsRGB444_packed[0] >> 0) & 0xf;
- calculateError59TnoSwapPerceptual1000(img, width, startx, starty, colorsRGB444, distance, pixel_indices);
- // Put the compress params into the compression block
- packBlock59T(colorsRGB444, distance, pixel_indices, compressed1, compressed2);
- return best_error_using_Tmode;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // The below code should compress the block to 59 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- //
- //|63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
- //|----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // Note that this method might not return the best possible compression for the T-mode. It will only do so if the best possible T-representation
- // is less than best_error_so_far. To guarantee that the best possible T-representation is found, the function should be called using
- // best_error_so_far = 255*255*3*16, which is the maximum error for a block.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockTHUMB59TExhaustive(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int best_error_so_far)
- {
- uint8 colorsRGB444[2][3];
- unsigned int pixel_indices;
- uint8 distance;
- uint8 block[4*4*4];
- unsigned int *precalc_err_col0_RGB;
- unsigned int *precalc_err_col1_RGB;
- unsigned int *precalc_err_col0_RG;
- unsigned int *precalc_err_col1_RG;
- unsigned int *precalc_err_col0_R;
- unsigned int *precalc_err_col1_R;
- int colorRGB444_packed;
- int colorsRGB444_packed[2];
- int best_colorsRGB444_packed[2];
- unsigned int best_error_using_Tmode;
- // First compress block quickly to a resonable quality so that we can
- // rule out all blocks that are of worse quality than that.
- best_error_using_Tmode = (unsigned int) compressBlockTHUMB59TFastestOnlyColor(img, width, height, startx, starty, best_colorsRGB444_packed);
- if(best_error_using_Tmode < best_error_so_far)
- best_error_so_far = best_error_using_Tmode;
- // Colors numbering is reversed between the above function and the precalc below:
- int temp = best_colorsRGB444_packed[0];
- best_colorsRGB444_packed[0] = best_colorsRGB444_packed[1];
- best_colorsRGB444_packed[1] = temp;
- int xx,yy,count = 0;
- // Use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<4; xx++)
- {
- for(yy=0; yy<4; yy++)
- {
- block[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block[(count)*4+3] = 0;
- count++;
- }
- }
- // Precalculate error for color 0 (which produces the upper half of the T)
- precalc_err_col0_RGB = (unsigned int*) malloc(4096*8*16*sizeof(unsigned int));
- if(!precalc_err_col0_RGB){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed++)
- {
- precalcError59T_col0_RGB(block, colorRGB444_packed, precalc_err_col0_RGB);
- }
- // Precalculate error for color 1 (which produces the lower half of the T -- the lone color)
- precalc_err_col1_RGB = (unsigned int*) malloc(4096*16*sizeof(unsigned int));
- if(!precalc_err_col1_RGB){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed++)
- {
- precalcError59T_col1_RGB(block, colorRGB444_packed, precalc_err_col1_RGB);
- }
- precalc_err_col0_RG = (unsigned int*) malloc(16*16*8*16*sizeof(unsigned int));
- if(!precalc_err_col0_RG){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16)
- {
- precalcError59T_col0_RG(block, colorRGB444_packed, precalc_err_col0_RG);
- }
- precalc_err_col1_RG = (unsigned int*) malloc(16*16*16*sizeof(unsigned int));
- if(!precalc_err_col1_RG){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16)
- {
- precalcError59T_col1_RG(block, colorRGB444_packed, precalc_err_col1_RG);
- }
- precalc_err_col0_R = (unsigned int*) malloc(16*8*16*sizeof(unsigned int));
- if(!precalc_err_col0_R){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16*16)
- {
- precalcError59T_col0_R(block, colorRGB444_packed, precalc_err_col0_R);
- }
- precalc_err_col1_R = (unsigned int*) malloc(16*16*sizeof(unsigned int));
- if(!precalc_err_col1_R){printf("Out of memory allocating \n");exit(1);}
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16*16)
- {
- precalcError59T_col1_R(block, colorRGB444_packed, precalc_err_col1_R);
- }
- unsigned int error;
- unsigned int avoided = 0;
- unsigned int notavoided = 0;
- for(colorsRGB444[0][0] = 0; colorsRGB444[0][0] < 16; colorsRGB444[0][0]++)
- {
- for(colorsRGB444[1][0] = 0; colorsRGB444[1][0] < 16; colorsRGB444[1][0]++)
- {
- colorsRGB444_packed[0] = (colorsRGB444[0][0] << 8);
- colorsRGB444_packed[1] = (colorsRGB444[1][0] << 8);
- error = calculateError59TusingPrecalcR(block, colorsRGB444_packed, precalc_err_col0_R, precalc_err_col1_R, best_error_so_far);
- if(error < best_error_so_far)
- {
- notavoided = notavoided + 1;
- for(colorsRGB444[0][1] = 0; colorsRGB444[0][1] < 16; colorsRGB444[0][1]++)
- {
- colorsRGB444_packed[0] = (colorsRGB444[0][0] << 8) + (colorsRGB444[0][1] <<4);
- for(colorsRGB444[1][1] = 0; colorsRGB444[1][1] < 16; colorsRGB444[1][1]++)
- {
- colorsRGB444_packed[1] = (colorsRGB444[1][0] << 8) + (colorsRGB444[1][1] <<4);
- error = calculateError59TusingPrecalcRG(block, colorsRGB444_packed, precalc_err_col0_RG, precalc_err_col1_RG, best_error_so_far);
- if(error < best_error_so_far)
- {
- for(colorsRGB444[0][2] = 0; colorsRGB444[0][2] < 16; colorsRGB444[0][2]++)
- {
- colorsRGB444_packed[0] = (colorsRGB444[0][0] << 8) + (colorsRGB444[0][1] <<4) + colorsRGB444[0][2];
- for(colorsRGB444[1][2] = 0; colorsRGB444[1][2] < 16; colorsRGB444[1][2]++)
- {
- colorsRGB444_packed[1] = (colorsRGB444[1][0] << 8) + (colorsRGB444[1][1] <<4) + colorsRGB444[1][2];
- error = calculateError59TusingPrecalcRGB(block, colorsRGB444_packed, precalc_err_col0_RGB, precalc_err_col1_RGB, best_error_so_far);
- if(error < best_error_so_far)
- {
- best_error_so_far = error;
- best_error_using_Tmode = error;
- best_colorsRGB444_packed[0] = colorsRGB444_packed[0];
- best_colorsRGB444_packed[1] = colorsRGB444_packed[1];
- }
- }
- }
- }
- }
- }
- }
- }
- }
- free(precalc_err_col0_RGB);
- free(precalc_err_col1_RGB);
- free(precalc_err_col0_RG);
- free(precalc_err_col1_RG);
- free(precalc_err_col0_R);
- free(precalc_err_col1_R);
- // We have got the two best colors. Now find the best distance and pixel indices.
- // Color numbering are reversed between precalc and noSwap
- colorsRGB444[0][0] = (best_colorsRGB444_packed[1] >> 8) & 0xf;
- colorsRGB444[0][1] = (best_colorsRGB444_packed[1] >> 4) & 0xf;
- colorsRGB444[0][2] = (best_colorsRGB444_packed[1] >> 0) & 0xf;
-
- colorsRGB444[1][0] = (best_colorsRGB444_packed[0] >> 8) & 0xf;
- colorsRGB444[1][1] = (best_colorsRGB444_packed[0] >> 4) & 0xf;
- colorsRGB444[1][2] = (best_colorsRGB444_packed[0] >> 0) & 0xf;
- calculateError59TnoSwap(img, width, startx, starty, colorsRGB444, distance, pixel_indices);
- // Put the compress params into the compression block
- packBlock59T(colorsRGB444, distance, pixel_indices, compressed1, compressed2);
- return best_error_using_Tmode;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates tables used in the exhaustive compression of the H-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcErrorR_58Hperceptual1000(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3],int colorRGB444_packed, unsigned int *precalc_errR)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[2][3];
- uint8 colors[2][3];
-
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- possible_colors[0][R] = CLAMP(0,colors[0][R] - table58H[d],255);
- possible_colors[1][R] = CLAMP(0,colors[0][R] + table58H[d],255);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXERR1000;
- // Loop possible block colors
- for (uint8 c = 0; c < 2; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- }
- }
- precalc_errR[((colorRGB444_packed>>8)*8 + d)*16 + (y*4)+x] = (unsigned int) best_pixel_error;
- }
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates tables used in the exhaustive compression of the H-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcErrorR_58H(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3],int colorRGB444_packed, unsigned int *precalc_errR)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[2][3];
- uint8 colors[2][3];
-
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- possible_colors[0][R] = CLAMP(0,colors[0][R] - table58H[d],255);
- possible_colors[1][R] = CLAMP(0,colors[0][R] + table58H[d],255);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXIMUM_ERROR;
- // Loop possible block colors
- for (uint8 c = 0; c < 2; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- pixel_error = weight[R]*SQUARE(diff[R]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- }
- }
- precalc_errR[((colorRGB444_packed>>8)*8 + d)*16 + (y*4)+x] = (unsigned int) best_pixel_error;
- }
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates tables used in the exhaustive compression of the H-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcErrorRG_58Hperceptual1000(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3],int colorRGB444_packed, unsigned int *precalc_errRG)
- {
- unsigned int block_error = 0,
- best_block_error = MAXERR1000,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[2][3];
- uint8 colors[2][3];
-
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- possible_colors[0][R] = CLAMP(0,colors[0][R] - table58H[d],255);
- possible_colors[0][G] = CLAMP(0,colors[0][G] - table58H[d],255);
- possible_colors[1][R] = CLAMP(0,colors[0][R] + table58H[d],255);
- possible_colors[1][G] = CLAMP(0,colors[0][G] + table58H[d],255);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXERR1000;
- // Loop possible block colors
- for (uint8 c = 0; c < 2; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*SQUARE(diff[R]) +
- PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*SQUARE(diff[G]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- }
- }
- precalc_errRG[((colorRGB444_packed>>4)*8 + d)*16 + (y*4)+x] = (unsigned int) best_pixel_error;
- }
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates tables used in the exhaustive compression of the H-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcErrorRG_58H(uint8* srcimg, int width, int startx, int starty, uint8 (colorsRGB444)[2][3],int colorRGB444_packed, unsigned int *precalc_errRG)
- {
- double block_error = 0,
- best_block_error = MAXIMUM_ERROR,
- pixel_error,
- best_pixel_error;
- int diff[3];
- unsigned int pixel_colors;
- uint8 possible_colors[2][3];
- uint8 colors[2][3];
-
- decompressColor(R_BITS58H, G_BITS58H, B_BITS58H, colorsRGB444, colors);
- // Test all distances
- for (uint8 d = 0; d < BINPOW(TABLE_BITS_58H); ++d)
- {
- possible_colors[0][R] = CLAMP(0,colors[0][R] - table58H[d],255);
- possible_colors[0][G] = CLAMP(0,colors[0][G] - table58H[d],255);
- possible_colors[1][R] = CLAMP(0,colors[0][R] + table58H[d],255);
- possible_colors[1][G] = CLAMP(0,colors[0][G] + table58H[d],255);
- block_error = 0;
- pixel_colors = 0;
- // Loop block
- for (size_t y = 0; y < BLOCKHEIGHT; ++y)
- {
- for (size_t x = 0; x < BLOCKWIDTH; ++x)
- {
- best_pixel_error = MAXIMUM_ERROR;
- // Loop possible block colors
- for (uint8 c = 0; c < 2; ++c)
- {
- diff[R] = srcimg[3*((starty+y)*width+startx+x)+R] - CLAMP(0,possible_colors[c][R],255);
- diff[G] = srcimg[3*((starty+y)*width+startx+x)+G] - CLAMP(0,possible_colors[c][G],255);
- pixel_error = weight[R]*SQUARE(diff[R]) +
- weight[G]*SQUARE(diff[G]);
- // Choose best error
- if (pixel_error < best_pixel_error)
- {
- best_pixel_error = pixel_error;
- }
- }
- precalc_errRG[((colorRGB444_packed>>4)*8 + d)*16 + (y*4)+x] = (unsigned int) best_pixel_error;
- }
- }
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in the exhaustive compression of the H-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError58Hperceptual1000(uint8* block, uint8 (colorsRGB444)[2][3],int colorRGB444_packed, unsigned int *precalc_err)
- {
- unsigned int pixel_error,
- best_pixel_error;
- int possible_colors[2][3];
- uint8 colors[2][3];
- unsigned int *precalc_err_tab;
- int red_original;
- int green_original;
- int blue_original;
- #define PRECALC_ONE_58H_PERCEP(qvalue)\
- red_original = block[qvalue*4];\
- green_original = block[qvalue*4+1];\
- blue_original = block[qvalue*4+2];\
- /* unroll loop for (color = 0; color< 2; color++) */\
- best_pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*square_table[(possible_colors[0][R] - red_original)] \
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*square_table[(possible_colors[0][G] - green_original)]\
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[(possible_colors[0][B] - blue_original)];\
- pixel_error = PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000*square_table[(possible_colors[1][R] - red_original)]\
- + PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000*square_table[(possible_colors[1][G] - green_original)]\
- + PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000*square_table[(possible_colors[1][B] - blue_original)];\
- if (pixel_error < best_pixel_error)\
- best_pixel_error = pixel_error;\
- /* end unroll loop */\
- precalc_err_tab[qvalue] = best_pixel_error;\
- #define PRECALC_ONE_TABLE_58H_PERCEP(dvalue)\
- precalc_err_tab = &precalc_err[((colorRGB444_packed*8)+dvalue)*16];\
- possible_colors[0][R] = CLAMP_LEFT_ZERO(colors[0][R] - table58H[dvalue])+255;\
- possible_colors[0][G] = CLAMP_LEFT_ZERO(colors[0][G] - table58H[dvalue])+255;\
- possible_colors[0][B] = CLAMP_LEFT_ZERO(colors[0][B] - table58H[dvalue])+255;\
- possible_colors[1][R] = CLAMP_RIGHT_255(colors[0][R] + table58H[dvalue])+255;\
- possible_colors[1][G] = CLAMP_RIGHT_255(colors[0][G] + table58H[dvalue])+255;\
- possible_colors[1][B] = CLAMP_RIGHT_255(colors[0][B] + table58H[dvalue])+255;\
- /* unrolled loop for(q = 0; q<16; q++)*/\
- PRECALC_ONE_58H_PERCEP(0)\
- PRECALC_ONE_58H_PERCEP(1)\
- PRECALC_ONE_58H_PERCEP(2)\
- PRECALC_ONE_58H_PERCEP(3)\
- PRECALC_ONE_58H_PERCEP(4)\
- PRECALC_ONE_58H_PERCEP(5)\
- PRECALC_ONE_58H_PERCEP(6)\
- PRECALC_ONE_58H_PERCEP(7)\
- PRECALC_ONE_58H_PERCEP(8)\
- PRECALC_ONE_58H_PERCEP(9)\
- PRECALC_ONE_58H_PERCEP(10)\
- PRECALC_ONE_58H_PERCEP(11)\
- PRECALC_ONE_58H_PERCEP(12)\
- PRECALC_ONE_58H_PERCEP(13)\
- PRECALC_ONE_58H_PERCEP(14)\
- PRECALC_ONE_58H_PERCEP(15)\
- /* end unroll loop */\
- colors[0][R] = (colorsRGB444[0][R] << 4) | colorsRGB444[0][R];
- colors[0][G] = (colorsRGB444[0][G] << 4) | colorsRGB444[0][G];
- colors[0][B] = (colorsRGB444[0][B] << 4) | colorsRGB444[0][B];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; ++d) */
- PRECALC_ONE_TABLE_58H_PERCEP(0)
- PRECALC_ONE_TABLE_58H_PERCEP(1)
- PRECALC_ONE_TABLE_58H_PERCEP(2)
- PRECALC_ONE_TABLE_58H_PERCEP(3)
- PRECALC_ONE_TABLE_58H_PERCEP(4)
- PRECALC_ONE_TABLE_58H_PERCEP(5)
- PRECALC_ONE_TABLE_58H_PERCEP(6)
- PRECALC_ONE_TABLE_58H_PERCEP(7)
- /* end unroll loop */
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Precalculates a table used in the exhaustive compression of the H-mode.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void precalcError58H(uint8* block, uint8 (colorsRGB444)[2][3],int colorRGB444_packed, unsigned int *precalc_err)
- {
- unsigned int pixel_error,
- best_pixel_error;
- int possible_colors[2][3];
- uint8 colors[2][3];
- unsigned int *precalc_err_tab;
- int red_original;
- int green_original;
- int blue_original;
- #define PRECALC_ONE_58H(qvalue)\
- red_original = block[qvalue*4];\
- green_original = block[qvalue*4+1];\
- blue_original = block[qvalue*4+2];\
- /* unroll loop for (color = 0; color< 2; color++) */\
- best_pixel_error = square_table[(possible_colors[0][R] - red_original)] + square_table[(possible_colors[0][G] - green_original)] + square_table[(possible_colors[0][B] - blue_original)];\
- pixel_error = square_table[(possible_colors[1][R] - red_original)] + square_table[(possible_colors[1][G] - green_original)] + square_table[(possible_colors[1][B] - blue_original)];\
- if (pixel_error < best_pixel_error)\
- best_pixel_error = pixel_error;\
- /* end unroll loop */\
- precalc_err_tab[qvalue] = best_pixel_error;\
- #define PRECALC_ONE_TABLE_58H(dvalue)\
- precalc_err_tab = &precalc_err[((colorRGB444_packed*8)+dvalue)*16];\
- possible_colors[0][R] = CLAMP_LEFT_ZERO(colors[0][R] - table58H[dvalue])+255;\
- possible_colors[0][G] = CLAMP_LEFT_ZERO(colors[0][G] - table58H[dvalue])+255;\
- possible_colors[0][B] = CLAMP_LEFT_ZERO(colors[0][B] - table58H[dvalue])+255;\
- possible_colors[1][R] = CLAMP_RIGHT_255(colors[0][R] + table58H[dvalue])+255;\
- possible_colors[1][G] = CLAMP_RIGHT_255(colors[0][G] + table58H[dvalue])+255;\
- possible_colors[1][B] = CLAMP_RIGHT_255(colors[0][B] + table58H[dvalue])+255;\
- /* unrolled loop for(q = 0; q<16; q++)*/\
- PRECALC_ONE_58H(0)\
- PRECALC_ONE_58H(1)\
- PRECALC_ONE_58H(2)\
- PRECALC_ONE_58H(3)\
- PRECALC_ONE_58H(4)\
- PRECALC_ONE_58H(5)\
- PRECALC_ONE_58H(6)\
- PRECALC_ONE_58H(7)\
- PRECALC_ONE_58H(8)\
- PRECALC_ONE_58H(9)\
- PRECALC_ONE_58H(10)\
- PRECALC_ONE_58H(11)\
- PRECALC_ONE_58H(12)\
- PRECALC_ONE_58H(13)\
- PRECALC_ONE_58H(14)\
- PRECALC_ONE_58H(15)\
- /* end unroll loop */\
- colors[0][R] = (colorsRGB444[0][R] << 4) | colorsRGB444[0][R];
- colors[0][G] = (colorsRGB444[0][G] << 4) | colorsRGB444[0][G];
- colors[0][B] = (colorsRGB444[0][B] << 4) | colorsRGB444[0][B];
- // Test all distances
- /* unroll loop for (uint8 d = 0; d < 8; ++d) */
- PRECALC_ONE_TABLE_58H(0)
- PRECALC_ONE_TABLE_58H(1)
- PRECALC_ONE_TABLE_58H(2)
- PRECALC_ONE_TABLE_58H(3)
- PRECALC_ONE_TABLE_58H(4)
- PRECALC_ONE_TABLE_58H(5)
- PRECALC_ONE_TABLE_58H(6)
- PRECALC_ONE_TABLE_58H(7)
- /* end unroll loop */
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimum error for the H-mode when doing exhaustive compression.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorFromPrecalcR58Hperceptual1000(int *colorsRGB444_packed, unsigned int *precalc_errR, unsigned int best_err_so_far)
- {
- unsigned int block_error = 0;
- unsigned int best_block_error = MAXERR1000;
- unsigned int *precalc_col1, *precalc_col2;
- unsigned int *precalc_col1tab, *precalc_col2tab;
- precalc_col1 = &precalc_errR[(colorsRGB444_packed[0]>>8)*8*16];
- precalc_col2 = &precalc_errR[(colorsRGB444_packed[1]>>8)*8*16];
- #define CHOICE_R58H_PERCEP(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error += precalc_col1tab[value];\
- else\
- block_error += precalc_col2tab[value];\
- // Test all distances
- for (uint8 d = 0; d < 8; ++d)
- {
- block_error = 0;
- precalc_col1tab = &precalc_col1[d*16];
- precalc_col2tab = &precalc_col2[d*16];
- // Loop block
- /* unroll loop for(q = 0; q<16 && block_error < best_err_so_far; q++) */
- CHOICE_R58H_PERCEP(0)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(1)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(2)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(3)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(4)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(5)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(6)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(7)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(8)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(9)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(10)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(11)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(12)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(13)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(14)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H_PERCEP(15)
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /* end unroll loop */
- if (block_error < best_block_error)
- best_block_error = block_error;
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimum error for the H-mode when doing exhaustive compression.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorFromPrecalcR58H(int *colorsRGB444_packed, unsigned int *precalc_errR, unsigned int best_err_so_far)
- {
- unsigned int block_error = 0;
- unsigned int best_block_error = MAXIMUM_ERROR;
- unsigned int *precalc_col1, *precalc_col2;
- unsigned int *precalc_col1tab, *precalc_col2tab;
- precalc_col1 = &precalc_errR[(colorsRGB444_packed[0]>>8)*8*16];
- precalc_col2 = &precalc_errR[(colorsRGB444_packed[1]>>8)*8*16];
- #define CHOICE_R58H(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error += precalc_col1tab[value];\
- else\
- block_error += precalc_col2tab[value];\
- // Test all distances
- for (uint8 d = 0; d < 8; ++d)
- {
- block_error = 0;
- precalc_col1tab = &precalc_col1[d*16];
- precalc_col2tab = &precalc_col2[d*16];
- // Loop block
- /* unroll loop for(q = 0; q<16 && block_error < best_err_so_far; q++) */
- CHOICE_R58H(0)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(1)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(2)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(3)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(4)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(5)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(6)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(7)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(8)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(9)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(10)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(11)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(12)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(13)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(14)
- if( block_error < best_err_so_far )
- {
- CHOICE_R58H(15)
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /* end unroll loop */
- if (block_error < best_block_error)
- best_block_error = block_error;
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimum error for the H-mode when doing exhaustive compression.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorFromPrecalcRG58Hperceptual1000(int *colorsRGB444_packed, unsigned int *precalc_errRG, unsigned int best_err_so_far)
- {
- unsigned int block_error = 0;
- unsigned int best_block_error = MAXIMUM_ERROR;
- unsigned int *precalc_col1, *precalc_col2;
- unsigned int *precalc_col1tab, *precalc_col2tab;
- precalc_col1 = &precalc_errRG[(colorsRGB444_packed[0]>>4)*8*16];
- precalc_col2 = &precalc_errRG[(colorsRGB444_packed[1]>>4)*8*16];
- #define CHOICE_RG58H_PERCEP(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error += precalc_col1tab[value];\
- else\
- block_error += precalc_col2tab[value];\
- // Test all distances
- for (uint8 d = 0; d < 8; ++d)
- {
- block_error = 0;
- precalc_col1tab = &precalc_col1[d*16];
- precalc_col2tab = &precalc_col2[d*16];
- // Loop block
- /* unroll loop for(q = 0; q<16 && block_error < best_err_so_far; q++) */
- CHOICE_RG58H_PERCEP(0)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(1)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(2)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(3)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(4)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(5)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(6)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(7)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(8)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(9)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(10)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(11)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(12)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(13)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(14)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H_PERCEP(15)
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /* end unroll loop */
- if (block_error < best_block_error)
- best_block_error = block_error;
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimum error for the H-mode when doing exhaustive compression.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorFromPrecalcRG58H(int *colorsRGB444_packed, unsigned int *precalc_errRG, unsigned int best_err_so_far)
- {
- unsigned int block_error = 0;
- unsigned int best_block_error = MAXIMUM_ERROR;
- unsigned int *precalc_col1, *precalc_col2;
- unsigned int *precalc_col1tab, *precalc_col2tab;
- precalc_col1 = &precalc_errRG[(colorsRGB444_packed[0]>>4)*8*16];
- precalc_col2 = &precalc_errRG[(colorsRGB444_packed[1]>>4)*8*16];
- #define CHOICE_RG58H(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error += precalc_col1tab[value];\
- else\
- block_error += precalc_col2tab[value];\
- // Test all distances
- for (uint8 d = 0; d < 8; ++d)
- {
- block_error = 0;
- precalc_col1tab = &precalc_col1[d*16];
- precalc_col2tab = &precalc_col2[d*16];
- // Loop block
- /* unroll loop for(q = 0; q<16 && block_error < best_err_so_far; q++) */
- CHOICE_RG58H(0)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(1)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(2)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(3)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(4)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(5)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(6)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(7)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(8)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(9)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(10)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(11)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(12)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(13)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(14)
- if( block_error < best_err_so_far )
- {
- CHOICE_RG58H(15)
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /* end unroll loop */
- if (block_error < best_block_error)
- best_block_error = block_error;
- }
- return best_block_error;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimum error for the H-mode when doing exhaustive compression.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorFromPrecalc58Hperceptual1000(int *colorsRGB444_packed, unsigned int *precalc_err, unsigned int total_best_err)
- {
- unsigned int block_error;\
- unsigned int *precalc_col1, *precalc_col2;\
- unsigned int *precalc_col1tab, *precalc_col2tab;\
- unsigned int error;
- #define FIRSTCHOICE_RGB58H_PERCEP(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error = precalc_col1tab[value];\
- else\
- block_error = precalc_col2tab[value];\
- #define CHOICE_RGB58H_PERCEP(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error += precalc_col1tab[value];\
- else\
- block_error += precalc_col2tab[value];\
- #define ONETABLE_RGB58H_PERCEP(distance)\
- precalc_col1tab = &precalc_col1[distance*16];\
- precalc_col2tab = &precalc_col2[distance*16];\
- /* unroll loop for(q = 0; q<16 && block_error < total_best_err; q++) */\
- FIRSTCHOICE_RGB58H_PERCEP(0)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(1)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(2)\
- CHOICE_RGB58H_PERCEP(3)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(4)\
- CHOICE_RGB58H_PERCEP(5)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(6)\
- CHOICE_RGB58H_PERCEP(7)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(8)\
- CHOICE_RGB58H_PERCEP(9)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(10)\
- CHOICE_RGB58H_PERCEP(11)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(12)\
- CHOICE_RGB58H_PERCEP(13)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H_PERCEP(14)\
- CHOICE_RGB58H_PERCEP(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- /* end unroll loop */\
- if (block_error < error)\
- error = block_error;\
- #define CALCULATE_ERROR_FROM_PRECALC_RGB58H_PERCEP\
- error = MAXERR1000;\
- precalc_col1 = &precalc_err[colorsRGB444_packed[0]*8*16];\
- precalc_col2 = &precalc_err[colorsRGB444_packed[1]*8*16];\
- /* Test all distances*/\
- /* unroll loop for (uint8 d = 0; d < 8; ++d) */\
- ONETABLE_RGB58H_PERCEP(0)\
- ONETABLE_RGB58H_PERCEP(1)\
- ONETABLE_RGB58H_PERCEP(2)\
- ONETABLE_RGB58H_PERCEP(3)\
- ONETABLE_RGB58H_PERCEP(4)\
- ONETABLE_RGB58H_PERCEP(5)\
- ONETABLE_RGB58H_PERCEP(6)\
- ONETABLE_RGB58H_PERCEP(7)\
- /* end unroll loop */\
- CALCULATE_ERROR_FROM_PRECALC_RGB58H_PERCEP
- return error;\
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Calculate a minimum error for the H-mode when doing exhaustive compression.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int calculateErrorFromPrecalc58H(int *colorsRGB444_packed, unsigned int *precalc_err, unsigned int total_best_err)
- {
- unsigned int block_error;\
- unsigned int *precalc_col1, *precalc_col2;\
- unsigned int *precalc_col1tab, *precalc_col2tab;\
- unsigned int error;
- #define FIRSTCHOICE_RGB58H(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error = precalc_col1tab[value];\
- else\
- block_error = precalc_col2tab[value];\
- #define CHOICE_RGB58H(value)\
- if(precalc_col1tab[value] < precalc_col2tab[value])\
- block_error += precalc_col1tab[value];\
- else\
- block_error += precalc_col2tab[value];\
- #define ONETABLE_RGB58H(distance)\
- precalc_col1tab = &precalc_col1[distance*16];\
- precalc_col2tab = &precalc_col2[distance*16];\
- /* unroll loop for(q = 0; q<16 && block_error < total_best_err; q++) */\
- FIRSTCHOICE_RGB58H(0)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(1)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(2)\
- CHOICE_RGB58H(3)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(4)\
- CHOICE_RGB58H(5)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(6)\
- CHOICE_RGB58H(7)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(8)\
- CHOICE_RGB58H(9)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(10)\
- CHOICE_RGB58H(11)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(12)\
- CHOICE_RGB58H(13)\
- if( block_error < total_best_err)\
- {\
- CHOICE_RGB58H(14)\
- CHOICE_RGB58H(15)\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- }\
- /* end unroll loop */\
- if (block_error < error)\
- error = block_error;\
- #define CALCULATE_ERROR_FROM_PRECALC_RGB58H\
- error = MAXIMUM_ERROR;\
- precalc_col1 = &precalc_err[colorsRGB444_packed[0]*8*16];\
- precalc_col2 = &precalc_err[colorsRGB444_packed[1]*8*16];\
- /* Test all distances*/\
- /* unroll loop for (uint8 d = 0; d < 8; ++d) */\
- ONETABLE_RGB58H(0)\
- ONETABLE_RGB58H(1)\
- ONETABLE_RGB58H(2)\
- ONETABLE_RGB58H(3)\
- ONETABLE_RGB58H(4)\
- ONETABLE_RGB58H(5)\
- ONETABLE_RGB58H(6)\
- ONETABLE_RGB58H(7)\
- /* end unroll loop */\
- CALCULATE_ERROR_FROM_PRECALC_RGB58H
- return error;\
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // The below code should compress the block to 58 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- // The below code should compress the block to 58 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockTHUMB58HExhaustivePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int best_error_so_far)
- {
- unsigned int best_error_using_Hmode;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- unsigned int error;
- uint8 colorsRGB444[2][3];
- int colorsRGB444_packed[2];
- int best_colorsRGB444_packed[2];
- int colorRGB444_packed;
- unsigned int pixel_indices;
- uint8 distance;
- unsigned int *precalc_err; // smallest error per color, table and pixel
- unsigned int *precalc_err_RG; // smallest pixel error for an entire table
- unsigned int *precalc_err_R; // smallest pixel error for an entire table
- uint8 block[4*4*4];
- best_error_using_Hmode = MAXERR1000;
- precalc_err = (unsigned int*) malloc(4096*8*16*sizeof(unsigned int));
- if(!precalc_err){printf("Out of memory allocating \n");exit(1);}
- precalc_err_RG = (unsigned int*) malloc(16*16*8*16*sizeof(unsigned int));
- if(!precalc_err_RG){printf("Out of memory allocating \n");exit(1);}
- precalc_err_R = (unsigned int*) malloc(16*8*16*sizeof(unsigned int));
- if(!precalc_err_R){printf("Out of memory allocating \n");exit(1);}
- unsigned int test1, test2;
- best_error_using_Hmode = (unsigned int)compressBlockTHUMB58HFastestPerceptual1000(img,width, height, startx, starty, test1, test2);
- best_colorsRGB444_packed[0] = 0;
- best_colorsRGB444_packed[0] = GETBITSHIGH(test1, 12, 57);
- best_colorsRGB444_packed[1] = 0;
- best_colorsRGB444_packed[1] = GETBITSHIGH(test1, 12, 45);
- if(best_error_using_Hmode < best_error_so_far)
- best_error_so_far = best_error_using_Hmode;
- int xx,yy,count = 0;
- // Use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<4; xx++)
- {
- for(yy=0; yy<4; yy++)
- {
- block[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block[(count)*4+3] = 0;
- count++;
- }
- }
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed++)
- {
- colorsRGB444[0][0] = (colorRGB444_packed >> 8) & 0xf;
- colorsRGB444[0][1] = (colorRGB444_packed >> 4) & 0xf;
- colorsRGB444[0][2] = (colorRGB444_packed) & 0xf;
- precalcError58Hperceptual1000(block, colorsRGB444, colorRGB444_packed, precalc_err);
- }
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16)
- {
- colorsRGB444[0][0] = (colorRGB444_packed >> 8) & 0xf;
- colorsRGB444[0][1] = (colorRGB444_packed >> 4) & 0xf;
- colorsRGB444[0][2] = (colorRGB444_packed) & 0xf;
- precalcErrorRG_58Hperceptual1000(img, width, startx, starty, colorsRGB444, colorRGB444_packed, precalc_err_RG);
- }
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16*16)
- {
- colorsRGB444[0][0] = (colorRGB444_packed >> 8) & 0xf;
- colorsRGB444[0][1] = (colorRGB444_packed >> 4) & 0xf;
- colorsRGB444[0][2] = (colorRGB444_packed) & 0xf;
- precalcErrorR_58Hperceptual1000(img, width, startx, starty, colorsRGB444, colorRGB444_packed, precalc_err_R);
- }
- int trycols = 0;
- int allcols = 0;
- for( colorsRGB444[0][0] = 0; colorsRGB444[0][0] <16; colorsRGB444[0][0]++)
- {
- colorsRGB444_packed[0] = colorsRGB444[0][0]*256;
- for( colorsRGB444[1][0] = 0; colorsRGB444[1][0] <16; colorsRGB444[1][0]++)
- {
- colorsRGB444_packed[1] = colorsRGB444[1][0]*256;
- if(colorsRGB444_packed[0] <= colorsRGB444_packed[1])
- {
- error = calculateErrorFromPrecalcR58Hperceptual1000(colorsRGB444_packed, precalc_err_R, best_error_so_far);
- if(error < best_error_so_far)
- {
- for( colorsRGB444[0][1] = 0; colorsRGB444[0][1] <16; colorsRGB444[0][1]++)
- {
- colorsRGB444_packed[0] = colorsRGB444[0][0]*256 + colorsRGB444[0][1]*16;
- for( colorsRGB444[1][1] = 0; colorsRGB444[1][1] <16; colorsRGB444[1][1]++)
- {
- colorsRGB444_packed[1] = colorsRGB444[1][0]*256 + colorsRGB444[1][1]*16;
- if(colorsRGB444_packed[0] <= colorsRGB444_packed[1])
- {
- error = calculateErrorFromPrecalcRG58Hperceptual1000(colorsRGB444_packed, precalc_err_RG, best_error_so_far);
- if(error < best_error_so_far)
- {
- for( colorsRGB444[0][2] = 0; colorsRGB444[0][2] <16; colorsRGB444[0][2]++)
- {
- colorsRGB444_packed[0] = colorsRGB444[0][0]*256 + colorsRGB444[0][1]*16 + colorsRGB444[0][2];
- for( colorsRGB444[1][2] = 0; colorsRGB444[1][2] <16; colorsRGB444[1][2]++)
- {
- colorsRGB444_packed[1] = colorsRGB444[1][0]*256 + colorsRGB444[1][1]*16 + colorsRGB444[1][2];
- if(colorsRGB444_packed[0] < colorsRGB444_packed[1])
- {
- error = calculateErrorFromPrecalc58Hperceptual1000(colorsRGB444_packed, precalc_err, best_error_so_far);
- if(error < best_error_so_far)
- {
- best_error_so_far = error;
- best_error_using_Hmode = error;
- best_colorsRGB444_packed[0] = colorsRGB444_packed[0];
- best_colorsRGB444_packed[1] = colorsRGB444_packed[1];
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- best_colorsRGB444[0][0] = (best_colorsRGB444_packed[0] >> 8) & 0xf;
- best_colorsRGB444[0][1] = (best_colorsRGB444_packed[0] >> 4) & 0xf;
- best_colorsRGB444[0][2] = (best_colorsRGB444_packed[0]) & 0xf;
- best_colorsRGB444[1][0] = (best_colorsRGB444_packed[1] >> 8) & 0xf;
- best_colorsRGB444[1][1] = (best_colorsRGB444_packed[1] >> 4) & 0xf;
- best_colorsRGB444[1][2] = (best_colorsRGB444_packed[1]) & 0xf;
- free(precalc_err);
- free(precalc_err_RG);
- free(precalc_err_R);
- error = (unsigned int) calculateErrorAndCompress58Hperceptual1000(img, width, startx, starty, best_colorsRGB444, distance, pixel_indices);
- best_distance = distance;
- best_pixel_indices = pixel_indices;
- // | col0 >= col1 col0 < col1
- //------------------------------------------------------
- // (dist & 1) = 1 | no need to swap | need to swap
- // |-----------------+----------------
- // (dist & 1) = 0 | need to swap | no need to swap
- //
- // This can be done with an xor test.
- best_colorsRGB444_packed[0] = (best_colorsRGB444[0][R] << 8) + (best_colorsRGB444[0][G] << 4) + best_colorsRGB444[0][B];
- best_colorsRGB444_packed[1] = (best_colorsRGB444[1][R] << 8) + (best_colorsRGB444[1][G] << 4) + best_colorsRGB444[1][B];
- if( (best_colorsRGB444_packed[0] >= best_colorsRGB444_packed[1]) ^ ((best_distance & 1)==1) )
- {
- swapColors(best_colorsRGB444);
- // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
- best_pixel_indices = (0x55555555 & best_pixel_indices) | (0xaaaaaaaa & (~best_pixel_indices));
- }
- // Put the compress params into the compression block
- compressed1 = 0;
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][R], 4, 57);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][G], 4, 53);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][B], 4, 49);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][R], 4, 45);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][G], 4, 41);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][B], 4, 37);
- PUTBITSHIGH( compressed1, (best_distance >> 1), 2, 33);
- best_pixel_indices=indexConversion(best_pixel_indices);
- compressed2 = 0;
- PUTBITS( compressed2, best_pixel_indices, 32, 31);
- return best_error_using_Hmode;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // The below code should compress the block to 58 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- // The below code should compress the block to 58 bits.
- // This is supposed to match the first of the three modes in TWOTIMER.
- // The bit layout is thought to be:
- //
- //|63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
- //|-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
- //
- //|31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
- //|----------------------------------------index bits---------------------------------------------|
- //
- // The distance d is three bits, d2 (MSB), d1 and d0 (LSB). d0 is not stored explicitly.
- // Instead if the 12-bit word red0,green0,blue0 < red1,green1,blue1, d0 is assumed to be 0.
- // Else, it is assumed to be 1.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- unsigned int compressBlockTHUMB58HExhaustive(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2, unsigned int best_error_so_far)
- {
- unsigned int best_error_using_Hmode;
- uint8 best_colorsRGB444[2][3];
- unsigned int best_pixel_indices;
- uint8 best_distance;
- unsigned int error;
- uint8 colorsRGB444[2][3];
- int colorsRGB444_packed[2];
- int best_colorsRGB444_packed[2];
- int colorRGB444_packed;
- unsigned int pixel_indices;
- uint8 distance;
- unsigned int *precalc_err; // smallest error per color, table and pixel
- unsigned int *precalc_err_RG; // smallest pixel error for an entire table
- unsigned int *precalc_err_R; // smallest pixel error for an entire table
- uint8 block[4*4*4];
- best_error_using_Hmode = MAXIMUM_ERROR;
- precalc_err = (unsigned int*) malloc(4096*8*16*sizeof(unsigned int));
- if(!precalc_err){printf("Out of memory allocating \n");exit(1);}
- precalc_err_RG = (unsigned int*) malloc(16*16*8*16*sizeof(unsigned int));
- if(!precalc_err_RG){printf("Out of memory allocating \n");exit(1);}
- precalc_err_R = (unsigned int*) malloc(16*8*16*sizeof(unsigned int));
- if(!precalc_err_R){printf("Out of memory allocating \n");exit(1);}
- unsigned int test1, test2;
- best_error_using_Hmode = (unsigned int)compressBlockTHUMB58HFastest(img,width, height, startx, starty, test1, test2);
- best_colorsRGB444_packed[0] = 0;
- best_colorsRGB444_packed[0] = GETBITSHIGH(test1, 12, 57);
- best_colorsRGB444_packed[1] = 0;
- best_colorsRGB444_packed[1] = GETBITSHIGH(test1, 12, 45);
- if(best_error_using_Hmode < best_error_so_far)
- best_error_so_far = best_error_using_Hmode;
- int xx,yy,count = 0;
- // Reshuffle pixels so that the top left 2x2 pixels arrive first, then the top right 2x2 pixels etc. Also put use 4 bytes per pixel to make it 32-word aligned.
- for(xx = 0; xx<4; xx++)
- {
- for(yy=0; yy<4; yy++)
- {
- block[(count)*4] = img[((starty+yy)*width+(startx+xx))*3];
- block[(count)*4+1] = img[((starty+yy)*width+(startx+xx))*3+1];
- block[(count)*4+2] = img[((starty+yy)*width+(startx+xx))*3+2];
- block[(count)*4+3] = 0;
- count++;
- }
- }
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed++)
- {
- colorsRGB444[0][0] = (colorRGB444_packed >> 8) & 0xf;
- colorsRGB444[0][1] = (colorRGB444_packed >> 4) & 0xf;
- colorsRGB444[0][2] = (colorRGB444_packed) & 0xf;
- precalcError58H(block, colorsRGB444, colorRGB444_packed, precalc_err);
- }
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16)
- {
- colorsRGB444[0][0] = (colorRGB444_packed >> 8) & 0xf;
- colorsRGB444[0][1] = (colorRGB444_packed >> 4) & 0xf;
- colorsRGB444[0][2] = (colorRGB444_packed) & 0xf;
- precalcErrorRG_58H(img, width, startx, starty, colorsRGB444, colorRGB444_packed, precalc_err_RG);
- }
- for( colorRGB444_packed = 0; colorRGB444_packed<16*16*16; colorRGB444_packed+=16*16)
- {
- colorsRGB444[0][0] = (colorRGB444_packed >> 8) & 0xf;
- colorsRGB444[0][1] = (colorRGB444_packed >> 4) & 0xf;
- colorsRGB444[0][2] = (colorRGB444_packed) & 0xf;
- precalcErrorR_58H(img, width, startx, starty, colorsRGB444, colorRGB444_packed, precalc_err_R);
- }
- int trycols = 0;
- int allcols = 0;
- for( colorsRGB444[0][0] = 0; colorsRGB444[0][0] <16; colorsRGB444[0][0]++)
- {
- colorsRGB444_packed[0] = colorsRGB444[0][0]*256;
- for( colorsRGB444[1][0] = 0; colorsRGB444[1][0] <16; colorsRGB444[1][0]++)
- {
- colorsRGB444_packed[1] = colorsRGB444[1][0]*256;
- if(colorsRGB444_packed[0] <= colorsRGB444_packed[1])
- {
- error = calculateErrorFromPrecalcR58H(colorsRGB444_packed, precalc_err_R, best_error_so_far);
- if(error < best_error_so_far)
- {
- for( colorsRGB444[0][1] = 0; colorsRGB444[0][1] <16; colorsRGB444[0][1]++)
- {
- colorsRGB444_packed[0] = colorsRGB444[0][0]*256 + colorsRGB444[0][1]*16;
- for( colorsRGB444[1][1] = 0; colorsRGB444[1][1] <16; colorsRGB444[1][1]++)
- {
- colorsRGB444_packed[1] = colorsRGB444[1][0]*256 + colorsRGB444[1][1]*16;
- if(colorsRGB444_packed[0] <= colorsRGB444_packed[1])
- {
- error = calculateErrorFromPrecalcRG58H(colorsRGB444_packed, precalc_err_RG, best_error_so_far);
- if(error < best_error_so_far)
- {
- for( colorsRGB444[0][2] = 0; colorsRGB444[0][2] <16; colorsRGB444[0][2]++)
- {
- colorsRGB444_packed[0] = colorsRGB444[0][0]*256 + colorsRGB444[0][1]*16 + colorsRGB444[0][2];
- for( colorsRGB444[1][2] = 0; colorsRGB444[1][2] <16; colorsRGB444[1][2]++)
- {
- colorsRGB444_packed[1] = colorsRGB444[1][0]*256 + colorsRGB444[1][1]*16 + colorsRGB444[1][2];
- if(colorsRGB444_packed[0] < colorsRGB444_packed[1])
- {
- error = calculateErrorFromPrecalc58H(colorsRGB444_packed, precalc_err, best_error_so_far);
- if(error < best_error_so_far)
- {
- best_error_so_far = error;
- best_error_using_Hmode = error;
- best_colorsRGB444_packed[0] = colorsRGB444_packed[0];
- best_colorsRGB444_packed[1] = colorsRGB444_packed[1];
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- best_colorsRGB444[0][0] = (best_colorsRGB444_packed[0] >> 8) & 0xf;
- best_colorsRGB444[0][1] = (best_colorsRGB444_packed[0] >> 4) & 0xf;
- best_colorsRGB444[0][2] = (best_colorsRGB444_packed[0]) & 0xf;
- best_colorsRGB444[1][0] = (best_colorsRGB444_packed[1] >> 8) & 0xf;
- best_colorsRGB444[1][1] = (best_colorsRGB444_packed[1] >> 4) & 0xf;
- best_colorsRGB444[1][2] = (best_colorsRGB444_packed[1]) & 0xf;
- free(precalc_err);
- free(precalc_err_RG);
- free(precalc_err_R);
- error = (unsigned int) calculateErrorAndCompress58H(img, width, startx, starty, best_colorsRGB444, distance, pixel_indices);
- best_distance = distance;
- best_pixel_indices = pixel_indices;
- // | col0 >= col1 col0 < col1
- //------------------------------------------------------
- // (dist & 1) = 1 | no need to swap | need to swap
- // |-----------------+----------------
- // (dist & 1) = 0 | need to swap | no need to swap
- //
- // This can be done with an xor test.
- best_colorsRGB444_packed[0] = (best_colorsRGB444[0][R] << 8) + (best_colorsRGB444[0][G] << 4) + best_colorsRGB444[0][B];
- best_colorsRGB444_packed[1] = (best_colorsRGB444[1][R] << 8) + (best_colorsRGB444[1][G] << 4) + best_colorsRGB444[1][B];
- if( (best_colorsRGB444_packed[0] >= best_colorsRGB444_packed[1]) ^ ((best_distance & 1)==1) )
- {
- swapColors(best_colorsRGB444);
- // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
- best_pixel_indices = (0x55555555 & best_pixel_indices) | (0xaaaaaaaa & (~best_pixel_indices));
- }
- // Put the compress params into the compression block
- compressed1 = 0;
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][R], 4, 57);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][G], 4, 53);
- PUTBITSHIGH( compressed1, best_colorsRGB444[0][B], 4, 49);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][R], 4, 45);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][G], 4, 41);
- PUTBITSHIGH( compressed1, best_colorsRGB444[1][B], 4, 37);
- PUTBITSHIGH( compressed1, (best_distance >> 1), 2, 33);
- best_pixel_indices=indexConversion(best_pixel_indices);
- compressed2 = 0;
- PUTBITS( compressed2, best_pixel_indices, 32, 31);
- return best_error_using_Hmode;
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compress a block exhaustively for the ETC1 codec.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockETC1Exhaustive(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int error_currently_best;
- unsigned int etc1_differential_word1;
- unsigned int etc1_differential_word2;
- unsigned int error_etc1_differential;
- unsigned int etc1_individual_word1;
- unsigned int etc1_individual_word2;
- unsigned int error_etc1_individual;
-
- unsigned int error_best;
- signed char best_char;
- int best_mode;
- error_currently_best = 255*255*16*3;
- // First pass -- quickly find a low error so that we can later cull away a lot of
- // calculations later that are guaranteed to be higher than that error.
- unsigned int error_etc1;
- unsigned int etc1_word1;
- unsigned int etc1_word2;
- error_etc1 = (unsigned int) compressBlockDiffFlipFast(img, imgdec, width, height, startx, starty, etc1_word1, etc1_word2);
- if(error_etc1 < error_currently_best)
- error_currently_best = error_etc1;
- error_etc1_individual = compressBlockIndividualExhaustive(img, width, height, startx, starty, etc1_individual_word1, etc1_individual_word2, error_currently_best);
- if(error_etc1_individual < error_currently_best)
- error_currently_best = error_etc1_individual;
- error_etc1_differential = compressBlockDifferentialExhaustive(img, width, height, startx, starty, etc1_differential_word1, etc1_differential_word2, error_currently_best);
- if(error_etc1_differential < error_currently_best)
- error_currently_best = error_etc1_differential;
- error_best = error_etc1_differential;
- compressed1 = etc1_differential_word1;
- compressed2 = etc1_differential_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- if(error_etc1_individual < error_best)
- {
- compressed1 = etc1_individual_word1;
- compressed2 = etc1_individual_word2;
- best_char = ',';
- error_best = error_etc1_individual;
- best_mode = MODE_ETC1;
- }
- if(error_etc1 < error_best)
- {
- compressed1 = etc1_word1;
- compressed2 = etc1_word2;
- best_char = '.';
- error_best = error_etc1;
- best_mode = MODE_ETC1;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compress a block exhaustively for the ETC1 codec using perceptual error measure.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockETC1ExhaustivePerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int error_currently_best;
-
- unsigned int etc1_differential_word1;
- unsigned int etc1_differential_word2;
- unsigned int error_etc1_differential;
- unsigned int etc1_individual_word1;
- unsigned int etc1_individual_word2;
- unsigned int error_etc1_individual;
- unsigned int error_best;
- signed char best_char;
- int best_mode;
- error_currently_best = 255*255*16*1000;
- // First pass -- quickly find a low error so that we can later cull away a lot of
- // calculations later that are guaranteed to be higher than that error.
- unsigned int error_etc1;
- unsigned int etc1_word1;
- unsigned int etc1_word2;
- compressBlockDiffFlipFastPerceptual(img, imgdec, width, height, startx, starty, etc1_word1, etc1_word2);
- decompressBlockDiffFlip(etc1_word1, etc1_word2, imgdec, width, height, startx, starty);
- error_etc1 = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- if(error_etc1 < error_currently_best)
- error_currently_best = error_etc1;
- // Second pass --- now find the lowest error, but only if it is lower than error_currently_best
- error_etc1_differential = compressBlockDifferentialExhaustivePerceptual(img, width, height, startx, starty, etc1_differential_word1, etc1_differential_word2, error_currently_best);
- if(error_etc1_differential < error_currently_best)
- error_currently_best = error_etc1_differential;
- error_etc1_individual = compressBlockIndividualExhaustivePerceptual(img, width, height, startx, starty, etc1_individual_word1, etc1_individual_word2, error_currently_best);
- if(error_etc1_individual < error_currently_best)
- error_currently_best = error_etc1_individual;
- // Now find the best error.
- error_best = error_etc1;
- compressed1 = etc1_word1;
- compressed2 = etc1_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- if(error_etc1_differential < error_best)
- {
- error_best = error_etc1_differential;
- compressed1 = etc1_differential_word1;
- compressed2 = etc1_differential_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- }
- if(error_etc1_individual < error_best)
- {
- compressed1 = etc1_individual_word1;
- compressed2 = etc1_individual_word2;
- best_char = ',';
- error_best = error_etc1_individual;
- best_mode = MODE_ETC1;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compress a block exhaustively for the ETC2 RGB codec using perceptual error measure.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockETC2ExhaustivePerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int error_currently_best;
-
- unsigned int etc1_differential_word1;
- unsigned int etc1_differential_word2;
- unsigned int error_etc1_differential;
- unsigned int etc1_individual_word1;
- unsigned int etc1_individual_word2;
- unsigned int error_etc1_individual;
- unsigned int planar57_word1;
- unsigned int planar57_word2;
- unsigned int planar_word1;
- unsigned int planar_word2;
- double error_planar;
- unsigned int error_planar_red, error_planar_green, error_planar_blue;
- unsigned int thumbH58_word1;
- unsigned int thumbH58_word2;
- unsigned int thumbH_word1;
- unsigned int thumbH_word2;
- unsigned int error_thumbH;
-
- unsigned int thumbT59_word1;
- unsigned int thumbT59_word2;
- unsigned int thumbT_word1;
- unsigned int thumbT_word2;
- unsigned int error_thumbT;
-
- unsigned int error_best;
- signed char best_char;
- int best_mode;
- error_currently_best = 255*255*16*1000;
- // First pass -- quickly find a low error so that we can later cull away a lot of
- // calculations later that are guaranteed to be higher than that error.
- unsigned int error_etc1;
- unsigned int etc1_word1;
- unsigned int etc1_word2;
- compressBlockDiffFlipFastPerceptual(img, imgdec, width, height, startx, starty, etc1_word1, etc1_word2);
- decompressBlockDiffFlip(etc1_word1, etc1_word2, imgdec, width, height, startx, starty);
- error_etc1 = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- if(error_etc1 < error_currently_best)
- error_currently_best = error_etc1;
- // The planar mode treats every channel independently and should not be affected by the weights in the error measure.
- // We can hence use the nonperceptual version of the encoder also to find the best perceptual description of the block.
- compressBlockPlanar57(img, width, height, startx, starty, planar57_word1, planar57_word2);
- decompressBlockPlanar57errorPerComponent(planar57_word1, planar57_word2, imgdec, width, height, startx, starty, img, error_planar_red, error_planar_green, error_planar_blue);
- error_planar = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- stuff57bits(planar57_word1, planar57_word2, planar_word1, planar_word2);
- if(error_planar < error_currently_best)
- error_currently_best = (unsigned int) error_planar;
- error_thumbT = (unsigned int) compressBlockTHUMB59TFastestPerceptual1000(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- if(error_thumbT < error_currently_best)
- error_currently_best = error_thumbT;
- error_thumbH = (unsigned int) compressBlockTHUMB58HFastestPerceptual1000(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- if(error_thumbH < error_currently_best)
- error_currently_best = error_thumbH;
-
- // Second pass --- now find the lowest error, but only if it is lower than error_currently_best
- // Correct the individual errors for the different planes so that they sum to 1000 instead of 1.
- error_planar_red *=PERCEPTUAL_WEIGHT_R_SQUARED_TIMES1000;
- error_planar_green *=PERCEPTUAL_WEIGHT_G_SQUARED_TIMES1000;
- error_planar_blue *=PERCEPTUAL_WEIGHT_B_SQUARED_TIMES1000;
- compressBlockPlanar57ExhaustivePerceptual(img, width, height, startx, starty, planar57_word1, planar57_word2, error_currently_best, error_planar_red, error_planar_green, error_planar_blue);
- decompressBlockPlanar57(planar57_word1, planar57_word2, imgdec, width, height, startx, starty);
- error_planar = 1000*calcBlockPerceptualErrorRGB(img, imgdec, width, height, startx, starty);
- stuff57bits(planar57_word1, planar57_word2, planar_word1, planar_word2);
- if(error_planar < error_currently_best)
- error_currently_best = (unsigned int) error_planar;
-
- error_etc1_differential = compressBlockDifferentialExhaustivePerceptual(img, width, height, startx, starty, etc1_differential_word1, etc1_differential_word2, error_currently_best);
- if(error_etc1_differential < error_currently_best)
- error_currently_best = error_etc1_differential;
- error_etc1_individual = compressBlockIndividualExhaustivePerceptual(img, width, height, startx, starty, etc1_individual_word1, etc1_individual_word2, error_currently_best);
- if(error_etc1_individual < error_currently_best)
- error_currently_best = error_etc1_individual;
- error_thumbH = compressBlockTHUMB58HExhaustivePerceptual(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2, error_currently_best);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- if( error_thumbH < error_currently_best)
- error_currently_best = error_thumbH;
- error_thumbT = compressBlockTHUMB59TExhaustivePerceptual(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2, error_currently_best);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- if(error_thumbT < error_currently_best)
- error_currently_best = error_thumbT;
- // Now find the best error.
- error_best = error_etc1;
- compressed1 = etc1_word1;
- compressed2 = etc1_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- if(error_etc1_differential < error_best)
- {
- error_best = error_etc1_differential;
- compressed1 = etc1_differential_word1;
- compressed2 = etc1_differential_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- }
- if(error_etc1_individual < error_best)
- {
- compressed1 = etc1_individual_word1;
- compressed2 = etc1_individual_word2;
- best_char = ',';
- error_best = error_etc1_individual;
- best_mode = MODE_ETC1;
- }
- if(error_planar < error_best)
- {
- compressed1 = planar_word1;
- compressed2 = planar_word2;
- best_char = 'p';
- error_best = (unsigned int) error_planar;
- best_mode = MODE_PLANAR;
- }
- if(error_thumbH < error_best)
- {
- compressed1 = thumbH_word1;
- compressed2 = thumbH_word2;
- best_char = 'H';
- error_best = error_thumbH;
- best_mode = MODE_THUMB_H;
- }
- if(error_thumbT < error_best)
- {
- compressed1 = thumbT_word1;
- compressed2 = thumbT_word2;
- best_char = 'T';
- error_best = error_thumbT;
- best_mode = MODE_THUMB_T;
- }
- }
- #endif
- #if EXHAUSTIVE_CODE_ACTIVE
- // Compress a block exhaustively for the ETC2 RGB codec.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressBlockETC2Exhaustive(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2)
- {
- unsigned int error_currently_best;
- unsigned int etc1_differential_word1;
- unsigned int etc1_differential_word2;
- unsigned int error_etc1_differential;
- unsigned int etc1_individual_word1;
- unsigned int etc1_individual_word2;
- unsigned int error_etc1_individual;
- unsigned int planar57_word1;
- unsigned int planar57_word2;
- unsigned int planar_word1;
- unsigned int planar_word2;
- double error_planar;
- unsigned int error_planar_red;
- unsigned int error_planar_green;
- unsigned int error_planar_blue;
- unsigned int thumbH58_word1;
- unsigned int thumbH58_word2;
- unsigned int thumbH_word1;
- unsigned int thumbH_word2;
- unsigned int error_thumbH;
-
- unsigned int thumbT59_word1;
- unsigned int thumbT59_word2;
- unsigned int thumbT_word1;
- unsigned int thumbT_word2;
- unsigned int error_thumbT;
-
- unsigned int error_best;
- signed char best_char;
- int best_mode;
- error_currently_best = 255*255*16*3;
- // First pass -- quickly find a low error so that we can later cull away a lot of
- // calculations later that are guaranteed to be higher than that error.
- unsigned int error_etc1;
- unsigned int etc1_word1;
- unsigned int etc1_word2;
- error_etc1 = (unsigned int) compressBlockDiffFlipFast(img, imgdec, width, height, startx, starty, etc1_word1, etc1_word2);
- if(error_etc1 < error_currently_best)
- error_currently_best = error_etc1;
- compressBlockPlanar57(img, width, height, startx, starty, planar57_word1, planar57_word2);
- decompressBlockPlanar57errorPerComponent(planar57_word1, planar57_word2, imgdec, width, height, startx, starty, img, error_planar_red, error_planar_green, error_planar_blue);
- error_planar = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff57bits(planar57_word1, planar57_word2, planar_word1, planar_word2);
- if(error_planar < error_currently_best)
- error_currently_best = (unsigned int) error_planar;
- error_thumbT = (unsigned int) compressBlockTHUMB59TFastest(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2);
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- if(error_thumbT < error_currently_best)
- error_currently_best = error_thumbT;
- error_thumbH = (unsigned int) compressBlockTHUMB58HFastest(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2);
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- if(error_thumbH < error_currently_best)
- error_currently_best = error_thumbH;
- // Second pass --- now find the lowest error, but only if it is lower than error_currently_best
- error_etc1_differential = compressBlockDifferentialExhaustive(img, width, height, startx, starty, etc1_differential_word1, etc1_differential_word2, error_currently_best);
- if(error_etc1_differential < error_currently_best)
- error_currently_best = error_etc1_differential;
- compressBlockPlanar57Exhaustive(img, width, height, startx, starty, planar57_word1, planar57_word2, error_currently_best, error_planar_red, error_planar_green, error_planar_blue);
- decompressBlockPlanar57(planar57_word1, planar57_word2, imgdec, width, height, startx, starty);
- error_planar = calcBlockErrorRGB(img, imgdec, width, height, startx, starty);
- stuff57bits(planar57_word1, planar57_word2, planar_word1, planar_word2);
- if(error_planar < error_currently_best)
- error_currently_best = (unsigned int) error_planar;
-
- error_etc1_individual = compressBlockIndividualExhaustive(img, width, height, startx, starty, etc1_individual_word1, etc1_individual_word2, error_currently_best);
- if(error_etc1_individual < error_currently_best)
- error_currently_best = error_etc1_individual;
- error_thumbH = compressBlockTHUMB58HExhaustive(img,width,height,startx, starty, thumbH58_word1, thumbH58_word2, error_currently_best);
- if( error_thumbH < error_currently_best)
- error_currently_best = error_thumbH;
- stuff58bits(thumbH58_word1, thumbH58_word2, thumbH_word1, thumbH_word2);
- error_thumbT = compressBlockTHUMB59TExhaustive(img,width, height, startx, starty, thumbT59_word1, thumbT59_word2, error_currently_best);
- if(error_thumbT < error_currently_best)
- error_currently_best = error_thumbT;
- stuff59bits(thumbT59_word1, thumbT59_word2, thumbT_word1, thumbT_word2);
- error_best = 255*255*3*16;
- // Now find the best error.
- error_best = error_etc1;
- compressed1 = etc1_word1;
- compressed2 = etc1_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- if(error_etc1_differential < error_best)
- {
- error_best = error_etc1_differential;
- compressed1 = etc1_differential_word1;
- compressed2 = etc1_differential_word2;
- best_char = '.';
- best_mode = MODE_ETC1;
- }
- if(error_etc1_individual < error_best)
- {
- compressed1 = etc1_individual_word1;
- compressed2 = etc1_individual_word2;
- best_char = ',';
- error_best = error_etc1_individual;
- best_mode = MODE_ETC1;
- }
- if(error_planar < error_best)
- {
- compressed1 = planar_word1;
- compressed2 = planar_word2;
- best_char = 'p';
- error_best = (unsigned int) error_planar;
- best_mode = MODE_PLANAR;
- }
- if(error_thumbH < error_best)
- {
- compressed1 = thumbH_word1;
- compressed2 = thumbH_word2;
- best_char = 'H';
- error_best = error_thumbH;
- best_mode = MODE_THUMB_H;
- }
- if(error_thumbT < error_best)
- {
- compressed1 = thumbT_word1;
- compressed2 = thumbT_word2;
- best_char = 'T';
- error_best = error_thumbT;
- best_mode = MODE_THUMB_T;
- }
- }
- #endif
- //// Exhaustive code ends here.
- // Compress an image file.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- /*void compressImageFile(uint8 *img, uint8 *alphaimg,int width,int height,char *dstfile, int expandedwidth, int expandedheight)
- {
- FILE *f;
- int x,y,w,h;
- unsigned int block1, block2;
- unsigned short wi, hi;
- unsigned char magic[4];
- unsigned char version[2];
- unsigned short texture_type=format;
- uint8 *imgdec;
- uint8* alphaimg2;
- imgdec = (unsigned char*) malloc(expandedwidth*expandedheight*3);
- if(!imgdec)
- {
- printf("Could not allocate decompression buffer --- exiting\n");
- }
- magic[0] = 'P'; magic[1] = 'K'; magic[2] = 'M'; magic[3] = ' ';
- if(codec==CODEC_ETC2)
- {
- version[0] = '2'; version[1] = '0';
- }
- else
- {
- version[0] = '1'; version[1] = '0';
- }
- if(f=fopen(dstfile,"wb"))
- {
- w=expandedwidth/4; w*=4;
- h=expandedheight/4; h*=4;
- wi = w;
- hi = h;
- if(ktxFile)
- {
- //.ktx file: KTX header followed by compressed binary data.
- KTX_header header;
- //identifier
- for(int i=0; i<12; i++)
- {
- header.identifier[i]=ktx_identifier[i];
- }
- //endianess int.. if this comes out reversed, all of the other ints will too.
- header.endianness=KTX_ENDIAN_REF;
-
- //these values are always 0/1 for compressed textures.
- header.glType=0;
- header.glTypeSize=1;
- header.glFormat=0;
- header.pixelWidth=width;
- header.pixelHeight=height;
- header.pixelDepth=0;
- //we only support single non-mipmapped non-cubemap textures..
- header.numberOfArrayElements=0;
- header.numberOfFaces=1;
- header.numberOfMipmapLevels=1;
- //and no metadata..
- header.bytesOfKeyValueData=0;
-
- int halfbytes=1;
- //header.glInternalFormat=?
- //header.glBaseInternalFormat=?
- if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- header.glBaseInternalFormat=GL_R;
- if(formatSigned)
- header.glInternalFormat=GL_COMPRESSED_SIGNED_R11_EAC;
- else
- header.glInternalFormat=GL_COMPRESSED_R11_EAC;
- }
- else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- halfbytes=2;
- header.glBaseInternalFormat=GL_RG;
- if(formatSigned)
- header.glInternalFormat=GL_COMPRESSED_SIGNED_RG11_EAC;
- else
- header.glInternalFormat=GL_COMPRESSED_RG11_EAC;
- }
- else if(format==ETC2PACKAGE_RGB_NO_MIPMAPS)
- {
- header.glBaseInternalFormat=GL_RGB;
- header.glInternalFormat=GL_COMPRESSED_RGB8_ETC2;
- }
- else if(format==ETC2PACKAGE_sRGB_NO_MIPMAPS)
- {
- header.glBaseInternalFormat=GL_SRGB;
- header.glInternalFormat=GL_COMPRESSED_SRGB8_ETC2;
- }
- else if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS)
- {
- halfbytes=2;
- header.glBaseInternalFormat=GL_RGBA;
- header.glInternalFormat=GL_COMPRESSED_RGBA8_ETC2_EAC;
- }
- else if(format==ETC2PACKAGE_sRGBA_NO_MIPMAPS)
- {
- halfbytes=2;
- header.glBaseInternalFormat=GL_SRGB8_ALPHA8;
- header.glInternalFormat=GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
- }
- else if(format==ETC2PACKAGE_RGBA1_NO_MIPMAPS)
- {
- header.glBaseInternalFormat=GL_RGBA;
- header.glInternalFormat=GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
- }
- else if(format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- header.glBaseInternalFormat=GL_SRGB8_ALPHA8;
- header.glInternalFormat=GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
- }
- else if(format==ETC1_RGB_NO_MIPMAPS)
- {
- header.glBaseInternalFormat=GL_RGB;
- header.glInternalFormat=GL_ETC1_RGB8_OES;
- }
- else
- {
- printf("internal error: bad format!\n");
- exit(1);
- }
- //write header
- fwrite(&header,sizeof(KTX_header),1,f);
-
- //write size of compressed data.. which depend on the expanded size..
- unsigned int imagesize=(w*h*halfbytes)/2;
- fwrite(&imagesize,sizeof(int),1,f);
- }
- else
- {
- //.pkm file, contains small header..
- // Write magic number
- fwrite(&magic[0], sizeof(unsigned char), 1, f);
- fwrite(&magic[1], sizeof(unsigned char), 1, f);
- fwrite(&magic[2], sizeof(unsigned char), 1, f);
- fwrite(&magic[3], sizeof(unsigned char), 1, f);
-
- // Write version
- fwrite(&version[0], sizeof(unsigned char), 1, f);
- fwrite(&version[1], sizeof(unsigned char), 1, f);
- // Write texture type
- if(texture_type==ETC2PACKAGE_RG_NO_MIPMAPS&&formatSigned)
- {
- unsigned short temp = ETC2PACKAGE_RG_SIGNED_NO_MIPMAPS;
- write_big_endian_2byte_word(&temp,f);
- }
- else if(texture_type==ETC2PACKAGE_R_NO_MIPMAPS&&formatSigned)
- {
- unsigned short temp = ETC2PACKAGE_R_SIGNED_NO_MIPMAPS;
- write_big_endian_2byte_word(&temp,f);
- }
- else
- write_big_endian_2byte_word(&texture_type, f);
- // Write binary header: the width and height as unsigned 16-bit words
- write_big_endian_2byte_word(&wi, f);
- write_big_endian_2byte_word(&hi, f);
- // Also write the active pixels. For instance, if we want to compress
- // a 128 x 129 image, we have to extend it to 128 x 132 pixels.
- // Then the wi and hi written above will be 128 and 132, but the
- // additional information that we write below will be 128 and 129,
- // to indicate that it is only the top 129 lines of data in the
- // decompressed image that will be valid data, and the rest will
- // be just garbage.
- unsigned short activew, activeh;
- activew = width;
- activeh = height;
- write_big_endian_2byte_word(&activew, f);
- write_big_endian_2byte_word(&activeh, f);
- }
- int totblocks = expandedheight/4 * expandedwidth/4;
- int countblocks = 0;
- double percentageblocks=-1.0;
- double oldpercentageblocks;
-
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- //extract data from red and green channel into two alpha channels.
- //note that the image will be 16-bit per channel in this case.
- alphaimg= (unsigned char*)malloc(expandedwidth*expandedheight*2);
- alphaimg2=(unsigned char*)malloc(expandedwidth*expandedheight*2);
- setupAlphaTableAndValtab();
- if(!alphaimg||!alphaimg2)
- {
- printf("failed allocating space for alpha buffers!\n");
- exit(1);
- }
- for(y=0;y<expandedheight;y++)
- {
- for(x=0;x<expandedwidth;x++)
- {
- alphaimg[2*(y*expandedwidth+x)]=img[6*(y*expandedwidth+x)];
- alphaimg[2*(y*expandedwidth+x)+1]=img[6*(y*expandedwidth+x)+1];
- alphaimg2[2*(y*expandedwidth+x)]=img[6*(y*expandedwidth+x)+2];
- alphaimg2[2*(y*expandedwidth+x)+1]=img[6*(y*expandedwidth+x)+3];
- }
- }
- }
- for(y=0;y<expandedheight/4;y++)
- {
- for(x=0;x<expandedwidth/4;x++)
- {
- countblocks++;
- oldpercentageblocks = percentageblocks;
- percentageblocks = 100.0*countblocks/(1.0*totblocks);
- //compress color channels
- if(codec==CODEC_ETC)
- {
- if(metric==METRIC_NONPERCEPTUAL)
- {
- if(speed==SPEED_FAST)
- compressBlockDiffFlipFast(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- else
- #if EXHAUSTIVE_CODE_ACTIVE
- compressBlockETC1Exhaustive(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- #else
- printf("Not implemented in this version\n");
- #endif
- }
- else
- {
- if(speed==SPEED_FAST)
- compressBlockDiffFlipFastPerceptual(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- else
- #if EXHAUSTIVE_CODE_ACTIVE
- compressBlockETC1ExhaustivePerceptual(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- #else
- printf("Not implemented in this version\n");
- #endif
- }
- }
- else
- {
- if(format==ETC2PACKAGE_R_NO_MIPMAPS||format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- //don't compress color
- }
- else if(format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- //this is only available for fast/nonperceptual
- if(speed == SPEED_SLOW && first_time_message)
- {
- printf("Slow codec not implemented for RGBA1 --- using fast codec instead.\n");
- first_time_message = false;
- }
- compressBlockETC2Fast(img, alphaimg,imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- }
- else if(metric==METRIC_NONPERCEPTUAL)
- {
- if(speed==SPEED_FAST)
- compressBlockETC2Fast(img, alphaimg,imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- else
- #if EXHAUSTIVE_CODE_ACTIVE
- compressBlockETC2Exhaustive(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- #else
- printf("Not implemented in this version\n");
- #endif
- }
- else
- {
- if(speed==SPEED_FAST)
- compressBlockETC2FastPerceptual(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- else
- #if EXHAUSTIVE_CODE_ACTIVE
- compressBlockETC2ExhaustivePerceptual(img, imgdec, expandedwidth, expandedheight, 4*x, 4*y, block1, block2);
- #else
- printf("Not implemented in this version\n");
- #endif
- }
- }
-
- //compression of alpha channel in case of 4-bit alpha. Uses 8-bit alpha channel as input, and has 8-bit precision.
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS)
- {
- uint8 alphadata[8];
- if(speed==SPEED_SLOW)
- compressBlockAlphaSlow(alphaimg,4*x,4*y,expandedwidth,expandedheight,alphadata);
- else
- compressBlockAlphaFast(alphaimg,4*x,4*y,expandedwidth,expandedheight,alphadata);
- //write the 8 bytes of alphadata into f.
- fwrite(alphadata,1,8,f);
- }
- //store compressed color channels
- if(format!=ETC2PACKAGE_R_NO_MIPMAPS&&format!=ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- write_big_endian_4byte_word(&block1, f);
- write_big_endian_4byte_word(&block2, f);
- }
- //1-channel or 2-channel alpha compression: uses 16-bit data as input, and has 11-bit precision
- if(format==ETC2PACKAGE_R_NO_MIPMAPS||format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- uint8 alphadata[8];
- compressBlockAlpha16(alphaimg,4*x,4*y,expandedwidth,expandedheight,alphadata);
- fwrite(alphadata,1,8,f);
- }
- //compression of second alpha channel in RG-compression
- if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- {
- uint8 alphadata[8];
- compressBlockAlpha16(alphaimg2,4*x,4*y,expandedwidth,expandedheight,alphadata);
- fwrite(alphadata,1,8,f);
- }
- #if 1
- if(verbose)
- {
- if(speed==SPEED_FAST)
- {
- if( ((int)(percentageblocks) != (int)(oldpercentageblocks) ) || percentageblocks == 100.0)
- printf("Compressed %d of %d blocks, %.0f%% finished.\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", countblocks, totblocks, 100.0*countblocks/(1.0*totblocks));
- }
- else
- printf("Compressed %d of %d blocks, %.0f%% finished.\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", countblocks, totblocks, 100.0*countblocks/(1.0*totblocks));
- }
- #endif
- }
- }
- printf("\n");
- fclose(f);
- printf("Saved file <%s>.\n",dstfile);
- }
- }
- // Compress an file.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- void compressFile(char *srcfile,char *dstfile)
- {
- uint8 *srcimg;
- int width,height;
- int extendedwidth, extendedheight;
- struct _timeb tstruct;
- int tstart;
- int tstop;
- // 0: compress from .any to .pkm with SPEED_FAST, METRIC_NONPERCEPTUAL, ETC
- // 1: compress from .any to .pkm with SPEED_MEDIUM, METRIC_NONPERCEPTUAL, ETC
- // 2: compress from .any to .pkm with SPEED_SLOW, METRIC_NONPERCEPTUAL, ETC
- // 3: compress from .any to .pkm with SPEED_FAST, METRIC_PERCEPTUAL, ETC
- // 4: compress from .any to .pkm with SPEED_MEDIUM, METRIC_PERCEPTUAL, ETC
- // 5: compress from .any to .pkm with SPEED_SLOW, METRIC_PERCEPTUAL, ETC
- // 6: decompress from .pkm to .any
- // 7: calculate PSNR between .any and .any
- // 8: compress from .any to .pkm with SPEED_FAST, METRIC_NONPERCEPTUAL, ETC2
- // 9: compress from .any to .pkm with SPEED_MEDIUM, METRIC_NONPERCEPTUAL, ETC2
- //10: compress from .any to .pkm with SPEED_SLOW, METRIC_NONPERCEPTUAL, ETC2
- //11: compress from .any to .pkm with SPEED_FAST, METRIC_PERCEPTUAL, ETC2
- //12: compress from .any to .pkm with SPEED_MEDIUM, METRIC_PERCEPTUAL, ETC2
- //13: compress from .any to .pkm with SPEED_SLOW, METRIC_PERCEPTUAL, ETC2
- printf("\n");
- if(codec==CODEC_ETC)
- printf("ETC codec, ");
- else
- printf("ETC2 codec, ");
- if(speed==SPEED_FAST)
- printf("using FAST compression mode and ");
- else if(speed==SPEED_MEDIUM)
- printf("using MEDIUM compression mode and ");
- else
- printf("using SLOW compression mode and ");
- if(metric==METRIC_PERCEPTUAL)
- printf("PERCEPTUAL error metric, ");
- else
- printf("NONPERCEPTUAL error metric, ");
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS)
- printf("in RGBA format");
- else if(format==ETC2PACKAGE_sRGBA_NO_MIPMAPS)
- printf("in sRGBA format");
- else if(format==ETC2PACKAGE_RGBA1_NO_MIPMAPS)
- printf("in RGB + punch-through alpha format");
- else if(format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- printf("in sRGB + punch-through alpha format");
- else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- printf("in R format");
- else if(format==ETC2PACKAGE_RGB_NO_MIPMAPS||format==ETC1_RGB_NO_MIPMAPS)
- printf("in RGB format");
- else if(format==ETC2PACKAGE_RG_NO_MIPMAPS)
- printf("in RG format");
- else
- printf("in OTHER format");
- printf("\n");
- if(readCompressParams())
- {
- if(format==ETC2PACKAGE_R_NO_MIPMAPS||readSrcFile(srcfile,srcimg,width,height,extendedwidth, extendedheight))
- {
- //make sure that alphasrcimg contains the alpha channel or is null here, and pass it to compressimagefile
- uint8* alphaimg=NULL;
- if(format==ETC2PACKAGE_RGBA_NO_MIPMAPS||format==ETC2PACKAGE_RGBA1_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA_NO_MIPMAPS||format==ETC2PACKAGE_sRGBA1_NO_MIPMAPS)
- {
- char str[300];
- //printf("reading alpha channel....");
- sprintf(str,"imconv %s -alpha extract alpha.pgm\n",srcfile);
- system(str);
- readAlpha(alphaimg,width,height,extendedwidth,extendedheight);
- printf("ok!\n");
- setupAlphaTableAndValtab();
- }
- else if(format==ETC2PACKAGE_R_NO_MIPMAPS)
- {
- char str[300];
- sprintf(str,"imconv %s alpha.pgm\n",srcfile);
- system(str);
- readAlpha(alphaimg,width,height,extendedwidth,extendedheight);
- printf("read alpha ok, size is %d,%d (%d,%d)",width,height,extendedwidth,extendedheight);
- setupAlphaTableAndValtab();
- }
- printf("Compressing...\n");
- tstart=time(NULL);
- _ftime( &tstruct );
- tstart=tstart*1000+tstruct.millitm;
- compressImageFile(srcimg,alphaimg,width,height,dstfile,extendedwidth, extendedheight);
- tstop = time(NULL);
- _ftime( &tstruct );
- tstop = tstop*1000+tstruct.millitm;
- printf( "It took %u milliseconds to compress:\n", tstop - tstart);
- calculatePSNRfile(dstfile,srcimg,alphaimg);
- }
- }
- }
- // Calculates the PSNR between two files.
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- double calculatePSNRTwoFiles(char *srcfile1,char *srcfile2)
- {
- uint8 *srcimg1;
- uint8 *srcimg2;
- int width1, height1;
- int width2, height2;
- double PSNR;
- double perceptually_weighted_PSNR;
- if(readSrcFileNoExpand(srcfile1,srcimg1,width1,height1))
- {
- if(readSrcFileNoExpand(srcfile2,srcimg2,width2,height2))
- {
- if((width1 == width2) && (height1 == height2))
- {
- PSNR = calculatePSNR(srcimg1, srcimg2, width1, height1);
- printf("%f\n",PSNR);
- perceptually_weighted_PSNR = calculateWeightedPSNR(srcimg1, srcimg2, width1, height1, 0.299, 0.587, 0.114);
- }
- else
- {
- printf("\n Width and height do no not match for image: width, height = (%d, %d) and (%d, %d)\n",width1,height1, width2, height2);
- }
- }
- else
- {
- printf("Couldn't open file %s.\n",srcfile2);
- }
- }
- else
- {
- printf("Couldn't open file %s.\n",srcfile1);
- }
- return PSNR;
- }
- // Main function
- // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
- int main(int argc,char *argv[])
- {
- if(argc==3 || argc==4 || argc == 5 || argc == 7 || argc == 9 || argc == 11 || argc == 13)
- {
- // The source file is always the second last one.
- char srcfile[200];
- char dstfile[200];
- readArguments(argc,argv,srcfile,dstfile);
-
- int q = find_pos_of_extension(srcfile);
- int q2 = find_pos_of_extension(dstfile);
-
- if(!fileExist(srcfile))
- {
- printf("Error: file <%s> does not exist.\n",srcfile);
- exit(0);
- }
-
- if(mode==MODE_UNCOMPRESS)
- {
- printf("Decompressing .pkm/.ktx file ...\n");
- uint8* alphaimg=NULL, *img;
- int w, h;
- uncompressFile(srcfile,img,alphaimg,w,h);
- writeOutputFile(dstfile,img,alphaimg,w,h);
- }
- else if(mode==MODE_PSNR)
- {
- calculatePSNRTwoFiles(srcfile,dstfile);
- }
- else
- {
- compressFile(srcfile, dstfile);
- }
- }
- else
- {
- printf("ETCPACK v2.74 For ETC and ETC2\n");
- printf("Compresses and decompresses images using the Ericsson Texture Compression (ETC) version 1.0 and 2.0.\n\nUsage: etcpack srcfile dstfile\n\n");
- printf(" -s {fast|slow} Compression speed. Slow = exhaustive \n");
- printf(" search for optimal quality\n");
- printf(" (default: fast)\n");
- printf(" -e {perceptual|nonperceptual} Error metric: Perceptual (nicest) or \n");
- printf(" nonperceptual (highest PSNR)\n");
- printf(" (default: perceptual)\n");
- printf(" -c {etc1|etc2} Codec: etc1 (most compatible) or \n");
- printf(" etc2 (highest quality)\n");
- printf(" (default: etc2)\n");
- printf(" -f {R|R_signed|RG|RG_signed| Format: one, two, three or four \n");
- printf(" RGB|RGBA1|RGBA8| channels, and 1 or 8 bits for alpha\n");
- printf(" sRGB|sRGBA1|sRGBA8|} RGB or sRGB.\n");
- printf(" (1 equals punchthrough)\n");
- printf(" (default: RGB)\n");
- printf(" -v {on|off} Detailed progress info. (default on)\n");
- printf(" \n");
- printf("Examples: \n");
- printf(" etcpack img.ppm img.pkm Compresses img.ppm to img.pkm in\n");
- printf(" ETC2 RGB format\n");
- printf(" etcpack img.ppm img.ktx Compresses img.ppm to img.ktx in\n");
- printf(" ETC2 RGB format\n");
- printf(" etcpack img.pkm img_copy.ppm Decompresses img.pkm to img_copy.ppm\n");
- printf(" etcpack -s slow img.ppm img.pkm Compress using the slow mode.\n");
- printf(" etcpack -p orig.ppm copy.ppm Calculate PSNR between orig and copy\n");
- printf(" etcpack -f RGBA8 img.tga img.pkm Compresses img.tga to img.pkm, using \n");
- printf(" etc2 + alpha.\n");
- printf(" etcpack -f RG img.ppm img.pkm Compresses red and green channels of\n");
- printf(" img.ppm\n");
- }
- return 0;
- }
- */
|