tinyexr.h 289 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307
  1. #ifndef TINYEXR_H_
  2. #define TINYEXR_H_
  3. /*
  4. Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without
  7. modification, are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright
  9. notice, this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright
  11. notice, this list of conditions and the following disclaimer in the
  12. documentation and/or other materials provided with the distribution.
  13. * Neither the name of the Syoyo Fujita nor the
  14. names of its contributors may be used to endorse or promote products
  15. derived from this software without specific prior written permission.
  16. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  20. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. // TinyEXR contains some OpenEXR code, which is licensed under ------------
  28. ///////////////////////////////////////////////////////////////////////////
  29. //
  30. // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
  31. // Digital Ltd. LLC
  32. //
  33. // All rights reserved.
  34. //
  35. // Redistribution and use in source and binary forms, with or without
  36. // modification, are permitted provided that the following conditions are
  37. // met:
  38. // * Redistributions of source code must retain the above copyright
  39. // notice, this list of conditions and the following disclaimer.
  40. // * Redistributions in binary form must reproduce the above
  41. // copyright notice, this list of conditions and the following disclaimer
  42. // in the documentation and/or other materials provided with the
  43. // distribution.
  44. // * Neither the name of Industrial Light & Magic nor the names of
  45. // its contributors may be used to endorse or promote products derived
  46. // from this software without specific prior written permission.
  47. //
  48. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  49. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  51. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  52. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  54. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  55. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  56. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  57. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  58. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  59. //
  60. ///////////////////////////////////////////////////////////////////////////
  61. // End of OpenEXR license -------------------------------------------------
  62. //
  63. //
  64. // Do this:
  65. // #define TINYEXR_IMPLEMENTATION
  66. // before you include this file in *one* C or C++ file to create the
  67. // implementation.
  68. //
  69. // // i.e. it should look like this:
  70. // #include ...
  71. // #include ...
  72. // #include ...
  73. // #define TINYEXR_IMPLEMENTATION
  74. // #include "tinyexr.h"
  75. //
  76. //
  77. #include <stddef.h> // for size_t
  78. #include <stdint.h> // guess stdint.h is available(C99)
  79. #ifdef __cplusplus
  80. extern "C" {
  81. #endif
  82. #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
  83. defined(__i386) || defined(__i486__) || defined(__i486) || \
  84. defined(i386) || defined(__ia64__) || defined(__x86_64__)
  85. #define TINYEXR_X86_OR_X64_CPU 1
  86. #else
  87. #define TINYEXR_X86_OR_X64_CPU 0
  88. #endif
  89. #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || TINYEXR_X86_OR_X64_CPU
  90. #define TINYEXR_LITTLE_ENDIAN 1
  91. #else
  92. #define TINYEXR_LITTLE_ENDIAN 0
  93. #endif
  94. // Use miniz or not to decode ZIP format pixel. Linking with zlib
  95. // required if this flag is 0 and TINYEXR_USE_STB_ZLIB is 0.
  96. #ifndef TINYEXR_USE_MINIZ
  97. #define TINYEXR_USE_MINIZ (1)
  98. #endif
  99. // Use the ZIP implementation of stb_image.h and stb_image_write.h.
  100. #ifndef TINYEXR_USE_STB_ZLIB
  101. #define TINYEXR_USE_STB_ZLIB (0)
  102. #endif
  103. // Use nanozlib.
  104. #ifndef TINYEXR_USE_NANOZLIB
  105. #define TINYEXR_USE_NANOZLIB (0)
  106. #endif
  107. // Disable PIZ compression when applying cpplint.
  108. #ifndef TINYEXR_USE_PIZ
  109. #define TINYEXR_USE_PIZ (1)
  110. #endif
  111. #ifndef TINYEXR_USE_ZFP
  112. #define TINYEXR_USE_ZFP (0) // TinyEXR extension.
  113. // http://computation.llnl.gov/projects/floating-point-compression
  114. #endif
  115. #ifndef TINYEXR_USE_THREAD
  116. #define TINYEXR_USE_THREAD (0) // No threaded loading.
  117. // http://computation.llnl.gov/projects/floating-point-compression
  118. #endif
  119. #ifndef TINYEXR_USE_OPENMP
  120. #ifdef _OPENMP
  121. #define TINYEXR_USE_OPENMP (1)
  122. #else
  123. #define TINYEXR_USE_OPENMP (0)
  124. #endif
  125. #endif
  126. #define TINYEXR_SUCCESS (0)
  127. #define TINYEXR_ERROR_INVALID_MAGIC_NUMBER (-1)
  128. #define TINYEXR_ERROR_INVALID_EXR_VERSION (-2)
  129. #define TINYEXR_ERROR_INVALID_ARGUMENT (-3)
  130. #define TINYEXR_ERROR_INVALID_DATA (-4)
  131. #define TINYEXR_ERROR_INVALID_FILE (-5)
  132. #define TINYEXR_ERROR_INVALID_PARAMETER (-6)
  133. #define TINYEXR_ERROR_CANT_OPEN_FILE (-7)
  134. #define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-8)
  135. #define TINYEXR_ERROR_INVALID_HEADER (-9)
  136. #define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-10)
  137. #define TINYEXR_ERROR_CANT_WRITE_FILE (-11)
  138. #define TINYEXR_ERROR_SERIALIZATION_FAILED (-12)
  139. #define TINYEXR_ERROR_LAYER_NOT_FOUND (-13)
  140. #define TINYEXR_ERROR_DATA_TOO_LARGE (-14)
  141. // @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf }
  142. // pixel type: possible values are: UINT = 0 HALF = 1 FLOAT = 2
  143. #define TINYEXR_PIXELTYPE_UINT (0)
  144. #define TINYEXR_PIXELTYPE_HALF (1)
  145. #define TINYEXR_PIXELTYPE_FLOAT (2)
  146. #define TINYEXR_MAX_HEADER_ATTRIBUTES (1024)
  147. #define TINYEXR_MAX_CUSTOM_ATTRIBUTES (128)
  148. #define TINYEXR_COMPRESSIONTYPE_NONE (0)
  149. #define TINYEXR_COMPRESSIONTYPE_RLE (1)
  150. #define TINYEXR_COMPRESSIONTYPE_ZIPS (2)
  151. #define TINYEXR_COMPRESSIONTYPE_ZIP (3)
  152. #define TINYEXR_COMPRESSIONTYPE_PIZ (4)
  153. #define TINYEXR_COMPRESSIONTYPE_ZFP (128) // TinyEXR extension
  154. #define TINYEXR_ZFP_COMPRESSIONTYPE_RATE (0)
  155. #define TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION (1)
  156. #define TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY (2)
  157. #define TINYEXR_TILE_ONE_LEVEL (0)
  158. #define TINYEXR_TILE_MIPMAP_LEVELS (1)
  159. #define TINYEXR_TILE_RIPMAP_LEVELS (2)
  160. #define TINYEXR_TILE_ROUND_DOWN (0)
  161. #define TINYEXR_TILE_ROUND_UP (1)
  162. typedef struct TEXRVersion {
  163. int version; // this must be 2
  164. // tile format image;
  165. // not zero for only a single-part "normal" tiled file (according to spec.)
  166. int tiled;
  167. int long_name; // long name attribute
  168. // deep image(EXR 2.0);
  169. // for a multi-part file, indicates that at least one part is of type deep* (according to spec.)
  170. int non_image;
  171. int multipart; // multi-part(EXR 2.0)
  172. } EXRVersion;
  173. typedef struct TEXRAttribute {
  174. char name[256]; // name and type are up to 255 chars long.
  175. char type[256];
  176. unsigned char *value; // uint8_t*
  177. int size;
  178. int pad0;
  179. } EXRAttribute;
  180. typedef struct TEXRChannelInfo {
  181. char name[256]; // less than 255 bytes long
  182. int pixel_type;
  183. int x_sampling;
  184. int y_sampling;
  185. unsigned char p_linear;
  186. unsigned char pad[3];
  187. } EXRChannelInfo;
  188. typedef struct TEXRTile {
  189. int offset_x;
  190. int offset_y;
  191. int level_x;
  192. int level_y;
  193. int width; // actual width in a tile.
  194. int height; // actual height int a tile.
  195. unsigned char **images; // image[channels][pixels]
  196. } EXRTile;
  197. typedef struct TEXRBox2i {
  198. int min_x;
  199. int min_y;
  200. int max_x;
  201. int max_y;
  202. } EXRBox2i;
  203. typedef struct TEXRHeader {
  204. float pixel_aspect_ratio;
  205. int line_order;
  206. EXRBox2i data_window;
  207. EXRBox2i display_window;
  208. float screen_window_center[2];
  209. float screen_window_width;
  210. int chunk_count;
  211. // Properties for tiled format(`tiledesc`).
  212. int tiled;
  213. int tile_size_x;
  214. int tile_size_y;
  215. int tile_level_mode;
  216. int tile_rounding_mode;
  217. int long_name;
  218. // for a single-part file, agree with the version field bit 11
  219. // for a multi-part file, it is consistent with the type of part
  220. int non_image;
  221. int multipart;
  222. unsigned int header_len;
  223. // Custom attributes(exludes required attributes(e.g. `channels`,
  224. // `compression`, etc)
  225. int num_custom_attributes;
  226. EXRAttribute *custom_attributes; // array of EXRAttribute. size =
  227. // `num_custom_attributes`.
  228. EXRChannelInfo *channels; // [num_channels]
  229. int *pixel_types; // Loaded pixel type(TINYEXR_PIXELTYPE_*) of `images` for
  230. // each channel. This is overwritten with `requested_pixel_types` when
  231. // loading.
  232. int num_channels;
  233. int compression_type; // compression type(TINYEXR_COMPRESSIONTYPE_*)
  234. int *requested_pixel_types; // Filled initially by
  235. // ParseEXRHeaderFrom(Meomory|File), then users
  236. // can edit it(only valid for HALF pixel type
  237. // channel)
  238. // name attribute required for multipart files;
  239. // must be unique and non empty (according to spec.);
  240. // use EXRSetNameAttr for setting value;
  241. // max 255 character allowed - excluding terminating zero
  242. char name[256];
  243. } EXRHeader;
  244. typedef struct TEXRMultiPartHeader {
  245. int num_headers;
  246. EXRHeader *headers;
  247. } EXRMultiPartHeader;
  248. typedef struct TEXRImage {
  249. EXRTile *tiles; // Tiled pixel data. The application must reconstruct image
  250. // from tiles manually. NULL if scanline format.
  251. struct TEXRImage* next_level; // NULL if scanline format or image is the last level.
  252. int level_x; // x level index
  253. int level_y; // y level index
  254. unsigned char **images; // image[channels][pixels]. NULL if tiled format.
  255. int width;
  256. int height;
  257. int num_channels;
  258. // Properties for tile format.
  259. int num_tiles;
  260. } EXRImage;
  261. typedef struct TEXRMultiPartImage {
  262. int num_images;
  263. EXRImage *images;
  264. } EXRMultiPartImage;
  265. typedef struct TDeepImage {
  266. const char **channel_names;
  267. float ***image; // image[channels][scanlines][samples]
  268. int **offset_table; // offset_table[scanline][offsets]
  269. int num_channels;
  270. int width;
  271. int height;
  272. int pad0;
  273. } DeepImage;
  274. // @deprecated { For backward compatibility. Not recommended to use. }
  275. // Loads single-frame OpenEXR image. Assume EXR image contains A(single channel
  276. // alpha) or RGB(A) channels.
  277. // Application must free image data as returned by `out_rgba`
  278. // Result image format is: float x RGBA x width x hight
  279. // Returns negative value and may set error string in `err` when there's an
  280. // error
  281. extern int LoadEXR(float **out_rgba, int *width, int *height,
  282. const char *filename, const char **err);
  283. // Loads single-frame OpenEXR image by specifying layer name. Assume EXR image
  284. // contains A(single channel alpha) or RGB(A) channels. Application must free
  285. // image data as returned by `out_rgba` Result image format is: float x RGBA x
  286. // width x hight Returns negative value and may set error string in `err` when
  287. // there's an error When the specified layer name is not found in the EXR file,
  288. // the function will return `TINYEXR_ERROR_LAYER_NOT_FOUND`.
  289. extern int LoadEXRWithLayer(float **out_rgba, int *width, int *height,
  290. const char *filename, const char *layer_name,
  291. const char **err);
  292. //
  293. // Get layer infos from EXR file.
  294. //
  295. // @param[out] layer_names List of layer names. Application must free memory
  296. // after using this.
  297. // @param[out] num_layers The number of layers
  298. // @param[out] err Error string(will be filled when the function returns error
  299. // code). Free it using FreeEXRErrorMessage after using this value.
  300. //
  301. // @return TINYEXR_SUCCEES upon success.
  302. //
  303. extern int EXRLayers(const char *filename, const char **layer_names[],
  304. int *num_layers, const char **err);
  305. // @deprecated
  306. // Simple wrapper API for ParseEXRHeaderFromFile.
  307. // checking given file is a EXR file(by just look up header)
  308. // @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for
  309. // others
  310. extern int IsEXR(const char *filename);
  311. // Simple wrapper API for ParseEXRHeaderFromMemory.
  312. // Check if given data is a EXR image(by just looking up a header section)
  313. // @return TINYEXR_SUCCEES for EXR image, TINYEXR_ERROR_INVALID_HEADER for
  314. // others
  315. extern int IsEXRFromMemory(const unsigned char *memory, size_t size);
  316. // @deprecated
  317. // Saves single-frame OpenEXR image to a buffer. Assume EXR image contains RGB(A) channels.
  318. // components must be 1(Grayscale), 3(RGB) or 4(RGBA).
  319. // Input image format is: `float x width x height`, or `float x RGB(A) x width x
  320. // hight`
  321. // Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
  322. // value.
  323. // Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
  324. // Use ZIP compression by default.
  325. // `buffer` is the pointer to write EXR data.
  326. // Memory for `buffer` is allocated internally in SaveEXRToMemory.
  327. // Returns the data size of EXR file when the value is positive(up to 2GB EXR data).
  328. // Returns negative value and may set error string in `err` when there's an
  329. // error
  330. extern int SaveEXRToMemory(const float *data, const int width, const int height,
  331. const int components, const int save_as_fp16,
  332. unsigned char **buffer, const char **err);
  333. // @deprecated { Not recommended, but handy to use. }
  334. // Saves single-frame OpenEXR image to a buffer. Assume EXR image contains RGB(A) channels.
  335. // components must be 1(Grayscale), 3(RGB) or 4(RGBA).
  336. // Input image format is: `float x width x height`, or `float x RGB(A) x width x
  337. // hight`
  338. // Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
  339. // value.
  340. // Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
  341. // Use ZIP compression by default.
  342. // Returns TINYEXR_SUCCEES(0) when success.
  343. // Returns negative value and may set error string in `err` when there's an
  344. // error
  345. extern int SaveEXR(const float *data, const int width, const int height,
  346. const int components, const int save_as_fp16,
  347. const char *filename, const char **err);
  348. // Returns the number of resolution levels of the image (including the base)
  349. extern int EXRNumLevels(const EXRImage* exr_image);
  350. // Initialize EXRHeader struct
  351. extern void InitEXRHeader(EXRHeader *exr_header);
  352. // Set name attribute of EXRHeader struct (it makes a copy)
  353. extern void EXRSetNameAttr(EXRHeader *exr_header, const char* name);
  354. // Initialize EXRImage struct
  355. extern void InitEXRImage(EXRImage *exr_image);
  356. // Frees internal data of EXRHeader struct
  357. extern int FreeEXRHeader(EXRHeader *exr_header);
  358. // Frees internal data of EXRImage struct
  359. extern int FreeEXRImage(EXRImage *exr_image);
  360. // Frees error message
  361. extern void FreeEXRErrorMessage(const char *msg);
  362. // Parse EXR version header of a file.
  363. extern int ParseEXRVersionFromFile(EXRVersion *version, const char *filename);
  364. // Parse EXR version header from memory-mapped EXR data.
  365. extern int ParseEXRVersionFromMemory(EXRVersion *version,
  366. const unsigned char *memory, size_t size);
  367. // Parse single-part OpenEXR header from a file and initialize `EXRHeader`.
  368. // When there was an error message, Application must free `err` with
  369. // FreeEXRErrorMessage()
  370. extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version,
  371. const char *filename, const char **err);
  372. // Parse single-part OpenEXR header from a memory and initialize `EXRHeader`.
  373. // When there was an error message, Application must free `err` with
  374. // FreeEXRErrorMessage()
  375. extern int ParseEXRHeaderFromMemory(EXRHeader *header,
  376. const EXRVersion *version,
  377. const unsigned char *memory, size_t size,
  378. const char **err);
  379. // Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*`
  380. // array.
  381. // When there was an error message, Application must free `err` with
  382. // FreeEXRErrorMessage()
  383. extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers,
  384. int *num_headers,
  385. const EXRVersion *version,
  386. const char *filename,
  387. const char **err);
  388. // Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*`
  389. // array
  390. // When there was an error message, Application must free `err` with
  391. // FreeEXRErrorMessage()
  392. extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers,
  393. int *num_headers,
  394. const EXRVersion *version,
  395. const unsigned char *memory,
  396. size_t size, const char **err);
  397. // Loads single-part OpenEXR image from a file.
  398. // Application must setup `ParseEXRHeaderFromFile` before calling this function.
  399. // Application can free EXRImage using `FreeEXRImage`
  400. // Returns negative value and may set error string in `err` when there's an
  401. // error
  402. // When there was an error message, Application must free `err` with
  403. // FreeEXRErrorMessage()
  404. extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header,
  405. const char *filename, const char **err);
  406. // Loads single-part OpenEXR image from a memory.
  407. // Application must setup `EXRHeader` with
  408. // `ParseEXRHeaderFromMemory` before calling this function.
  409. // Application can free EXRImage using `FreeEXRImage`
  410. // Returns negative value and may set error string in `err` when there's an
  411. // error
  412. // When there was an error message, Application must free `err` with
  413. // FreeEXRErrorMessage()
  414. extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header,
  415. const unsigned char *memory,
  416. const size_t size, const char **err);
  417. // Loads multi-part OpenEXR image from a file.
  418. // Application must setup `ParseEXRMultipartHeaderFromFile` before calling this
  419. // function.
  420. // Application can free EXRImage using `FreeEXRImage`
  421. // Returns negative value and may set error string in `err` when there's an
  422. // error
  423. // When there was an error message, Application must free `err` with
  424. // FreeEXRErrorMessage()
  425. extern int LoadEXRMultipartImageFromFile(EXRImage *images,
  426. const EXRHeader **headers,
  427. unsigned int num_parts,
  428. const char *filename,
  429. const char **err);
  430. // Loads multi-part OpenEXR image from a memory.
  431. // Application must setup `EXRHeader*` array with
  432. // `ParseEXRMultipartHeaderFromMemory` before calling this function.
  433. // Application can free EXRImage using `FreeEXRImage`
  434. // Returns negative value and may set error string in `err` when there's an
  435. // error
  436. // When there was an error message, Application must free `err` with
  437. // FreeEXRErrorMessage()
  438. extern int LoadEXRMultipartImageFromMemory(EXRImage *images,
  439. const EXRHeader **headers,
  440. unsigned int num_parts,
  441. const unsigned char *memory,
  442. const size_t size, const char **err);
  443. // Saves multi-channel, single-frame OpenEXR image to a file.
  444. // Returns negative value and may set error string in `err` when there's an
  445. // error
  446. // When there was an error message, Application must free `err` with
  447. // FreeEXRErrorMessage()
  448. extern int SaveEXRImageToFile(const EXRImage *image,
  449. const EXRHeader *exr_header, const char *filename,
  450. const char **err);
  451. // Saves multi-channel, single-frame OpenEXR image to a memory.
  452. // Image is compressed using EXRImage.compression value.
  453. // Return the number of bytes if success.
  454. // Return zero and will set error string in `err` when there's an
  455. // error.
  456. // When there was an error message, Application must free `err` with
  457. // FreeEXRErrorMessage()
  458. extern size_t SaveEXRImageToMemory(const EXRImage *image,
  459. const EXRHeader *exr_header,
  460. unsigned char **memory, const char **err);
  461. // Saves multi-channel, multi-frame OpenEXR image to a memory.
  462. // Image is compressed using EXRImage.compression value.
  463. // File global attributes (eg. display_window) must be set in the first header.
  464. // Returns negative value and may set error string in `err` when there's an
  465. // error
  466. // When there was an error message, Application must free `err` with
  467. // FreeEXRErrorMessage()
  468. extern int SaveEXRMultipartImageToFile(const EXRImage *images,
  469. const EXRHeader **exr_headers,
  470. unsigned int num_parts,
  471. const char *filename, const char **err);
  472. // Saves multi-channel, multi-frame OpenEXR image to a memory.
  473. // Image is compressed using EXRImage.compression value.
  474. // File global attributes (eg. display_window) must be set in the first header.
  475. // Return the number of bytes if success.
  476. // Return zero and will set error string in `err` when there's an
  477. // error.
  478. // When there was an error message, Application must free `err` with
  479. // FreeEXRErrorMessage()
  480. extern size_t SaveEXRMultipartImageToMemory(const EXRImage *images,
  481. const EXRHeader **exr_headers,
  482. unsigned int num_parts,
  483. unsigned char **memory, const char **err);
  484. // Loads single-frame OpenEXR deep image.
  485. // Application must free memory of variables in DeepImage(image, offset_table)
  486. // Returns negative value and may set error string in `err` when there's an
  487. // error
  488. // When there was an error message, Application must free `err` with
  489. // FreeEXRErrorMessage()
  490. extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
  491. const char **err);
  492. // NOT YET IMPLEMENTED:
  493. // Saves single-frame OpenEXR deep image.
  494. // Returns negative value and may set error string in `err` when there's an
  495. // error
  496. // extern int SaveDeepEXR(const DeepImage *in_image, const char *filename,
  497. // const char **err);
  498. // NOT YET IMPLEMENTED:
  499. // Loads multi-part OpenEXR deep image.
  500. // Application must free memory of variables in DeepImage(image, offset_table)
  501. // extern int LoadMultiPartDeepEXR(DeepImage **out_image, int num_parts, const
  502. // char *filename,
  503. // const char **err);
  504. // For emscripten.
  505. // Loads single-frame OpenEXR image from memory. Assume EXR image contains
  506. // RGB(A) channels.
  507. // Returns negative value and may set error string in `err` when there's an
  508. // error
  509. // When there was an error message, Application must free `err` with
  510. // FreeEXRErrorMessage()
  511. extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
  512. const unsigned char *memory, size_t size,
  513. const char **err);
  514. #ifdef __cplusplus
  515. }
  516. #endif
  517. #endif // TINYEXR_H_
  518. #ifdef TINYEXR_IMPLEMENTATION
  519. #ifndef TINYEXR_IMPLEMENTATION_DEFINED
  520. #define TINYEXR_IMPLEMENTATION_DEFINED
  521. #ifdef _WIN32
  522. #ifndef WIN32_LEAN_AND_MEAN
  523. #define WIN32_LEAN_AND_MEAN
  524. #endif
  525. #ifndef NOMINMAX
  526. #define NOMINMAX
  527. #endif
  528. #include <windows.h> // for UTF-8 and memory-mapping
  529. #if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
  530. #define TINYEXR_USE_WIN32_MMAP (1)
  531. #endif
  532. #elif defined(__linux__) || defined(__unix__)
  533. #include <fcntl.h> // for open()
  534. #include <sys/mman.h> // for memory-mapping
  535. #include <sys/stat.h> // for stat
  536. #include <unistd.h> // for close()
  537. #define TINYEXR_USE_POSIX_MMAP (1)
  538. #endif
  539. #include <algorithm>
  540. #include <cstdio>
  541. #include <cstdlib>
  542. #include <cstring>
  543. #include <sstream>
  544. //#include <iostream> // debug
  545. #include <limits>
  546. #include <string>
  547. #include <vector>
  548. #include <set>
  549. // https://stackoverflow.com/questions/5047971/how-do-i-check-for-c11-support
  550. #if __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER >= 1900)
  551. #define TINYEXR_HAS_CXX11 (1)
  552. // C++11
  553. #include <cstdint>
  554. #if TINYEXR_USE_THREAD
  555. #include <atomic>
  556. #include <thread>
  557. #endif
  558. #else // __cplusplus > 199711L
  559. #define TINYEXR_HAS_CXX11 (0)
  560. #endif // __cplusplus > 199711L
  561. #if TINYEXR_USE_OPENMP
  562. #include <omp.h>
  563. #endif
  564. #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
  565. #include <miniz.h>
  566. #else
  567. // Issue #46. Please include your own zlib-compatible API header before
  568. // including `tinyexr.h`
  569. //#include "zlib.h"
  570. #endif
  571. #if defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1)
  572. #define NANOZLIB_IMPLEMENTATION
  573. #include "nanozlib.h"
  574. #endif
  575. #if TINYEXR_USE_STB_ZLIB
  576. // Since we don't know where a project has stb_image.h and stb_image_write.h
  577. // and whether they are in the include path, we don't include them here, and
  578. // instead declare the two relevant functions manually.
  579. // from stb_image.h:
  580. extern "C" int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
  581. // from stb_image_write.h:
  582. extern "C" unsigned char *stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality);
  583. #endif
  584. #if TINYEXR_USE_ZFP
  585. #ifdef __clang__
  586. #pragma clang diagnostic push
  587. #pragma clang diagnostic ignored "-Weverything"
  588. #endif
  589. #include "zfp.h"
  590. #ifdef __clang__
  591. #pragma clang diagnostic pop
  592. #endif
  593. #endif
  594. // cond: conditional expression
  595. // msg: std::string
  596. // err: std::string*
  597. #define TINYEXR_CHECK_AND_RETURN_MSG(cond, msg, err) do { \
  598. if (!(cond)) { \
  599. if (!err) { \
  600. std::ostringstream ss_e; \
  601. ss_e << __func__ << "():" << __LINE__ << msg << "\n"; \
  602. (*err) += ss_e.str(); \
  603. } \
  604. return false;\
  605. } \
  606. } while(0)
  607. // no error message.
  608. #define TINYEXR_CHECK_AND_RETURN_C(cond, retcode) do { \
  609. if (!(cond)) { \
  610. return retcode; \
  611. } \
  612. } while(0)
  613. namespace tinyexr {
  614. #if __cplusplus > 199711L
  615. // C++11
  616. typedef uint64_t tinyexr_uint64;
  617. typedef int64_t tinyexr_int64;
  618. #else
  619. // Although `long long` is not a standard type pre C++11, assume it is defined
  620. // as a compiler's extension.
  621. #ifdef __clang__
  622. #pragma clang diagnostic push
  623. #pragma clang diagnostic ignored "-Wc++11-long-long"
  624. #endif
  625. typedef unsigned long long tinyexr_uint64;
  626. typedef long long tinyexr_int64;
  627. #ifdef __clang__
  628. #pragma clang diagnostic pop
  629. #endif
  630. #endif
  631. // static bool IsBigEndian(void) {
  632. // union {
  633. // unsigned int i;
  634. // char c[4];
  635. // } bint = {0x01020304};
  636. //
  637. // return bint.c[0] == 1;
  638. //}
  639. static void SetErrorMessage(const std::string &msg, const char **err) {
  640. if (err) {
  641. #ifdef _WIN32
  642. (*err) = _strdup(msg.c_str());
  643. #else
  644. (*err) = strdup(msg.c_str());
  645. #endif
  646. }
  647. }
  648. #if 0
  649. static void SetWarningMessage(const std::string &msg, const char **warn) {
  650. if (warn) {
  651. #ifdef _WIN32
  652. (*warn) = _strdup(msg.c_str());
  653. #else
  654. (*warn) = strdup(msg.c_str());
  655. #endif
  656. }
  657. }
  658. #endif
  659. static const int kEXRVersionSize = 8;
  660. static void cpy2(unsigned short *dst_val, const unsigned short *src_val) {
  661. unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
  662. const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
  663. dst[0] = src[0];
  664. dst[1] = src[1];
  665. }
  666. static void swap2(unsigned short *val) {
  667. #if TINYEXR_LITTLE_ENDIAN
  668. (void)val;
  669. #else
  670. unsigned short tmp = *val;
  671. unsigned char *dst = reinterpret_cast<unsigned char *>(val);
  672. unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
  673. dst[0] = src[1];
  674. dst[1] = src[0];
  675. #endif
  676. }
  677. #ifdef __clang__
  678. #pragma clang diagnostic push
  679. #pragma clang diagnostic ignored "-Wunused-function"
  680. #endif
  681. #ifdef __GNUC__
  682. #pragma GCC diagnostic push
  683. #pragma GCC diagnostic ignored "-Wunused-function"
  684. #endif
  685. static void cpy4(int *dst_val, const int *src_val) {
  686. unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
  687. const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
  688. dst[0] = src[0];
  689. dst[1] = src[1];
  690. dst[2] = src[2];
  691. dst[3] = src[3];
  692. }
  693. static void cpy4(unsigned int *dst_val, const unsigned int *src_val) {
  694. unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
  695. const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
  696. dst[0] = src[0];
  697. dst[1] = src[1];
  698. dst[2] = src[2];
  699. dst[3] = src[3];
  700. }
  701. static void cpy4(float *dst_val, const float *src_val) {
  702. unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
  703. const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
  704. dst[0] = src[0];
  705. dst[1] = src[1];
  706. dst[2] = src[2];
  707. dst[3] = src[3];
  708. }
  709. #ifdef __clang__
  710. #pragma clang diagnostic pop
  711. #endif
  712. #ifdef __GNUC__
  713. #pragma GCC diagnostic pop
  714. #endif
  715. static void swap4(unsigned int *val) {
  716. #if TINYEXR_LITTLE_ENDIAN
  717. (void)val;
  718. #else
  719. unsigned int tmp = *val;
  720. unsigned char *dst = reinterpret_cast<unsigned char *>(val);
  721. unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
  722. dst[0] = src[3];
  723. dst[1] = src[2];
  724. dst[2] = src[1];
  725. dst[3] = src[0];
  726. #endif
  727. }
  728. static void swap4(int *val) {
  729. #if TINYEXR_LITTLE_ENDIAN
  730. (void)val;
  731. #else
  732. int tmp = *val;
  733. unsigned char *dst = reinterpret_cast<unsigned char *>(val);
  734. unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
  735. dst[0] = src[3];
  736. dst[1] = src[2];
  737. dst[2] = src[1];
  738. dst[3] = src[0];
  739. #endif
  740. }
  741. static void swap4(float *val) {
  742. #if TINYEXR_LITTLE_ENDIAN
  743. (void)val;
  744. #else
  745. float tmp = *val;
  746. unsigned char *dst = reinterpret_cast<unsigned char *>(val);
  747. unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
  748. dst[0] = src[3];
  749. dst[1] = src[2];
  750. dst[2] = src[1];
  751. dst[3] = src[0];
  752. #endif
  753. }
  754. #if 0
  755. static void cpy8(tinyexr::tinyexr_uint64 *dst_val, const tinyexr::tinyexr_uint64 *src_val) {
  756. unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val);
  757. const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val);
  758. dst[0] = src[0];
  759. dst[1] = src[1];
  760. dst[2] = src[2];
  761. dst[3] = src[3];
  762. dst[4] = src[4];
  763. dst[5] = src[5];
  764. dst[6] = src[6];
  765. dst[7] = src[7];
  766. }
  767. #endif
  768. static void swap8(tinyexr::tinyexr_uint64 *val) {
  769. #if TINYEXR_LITTLE_ENDIAN
  770. (void)val;
  771. #else
  772. tinyexr::tinyexr_uint64 tmp = (*val);
  773. unsigned char *dst = reinterpret_cast<unsigned char *>(val);
  774. unsigned char *src = reinterpret_cast<unsigned char *>(&tmp);
  775. dst[0] = src[7];
  776. dst[1] = src[6];
  777. dst[2] = src[5];
  778. dst[3] = src[4];
  779. dst[4] = src[3];
  780. dst[5] = src[2];
  781. dst[6] = src[1];
  782. dst[7] = src[0];
  783. #endif
  784. }
  785. // https://gist.github.com/rygorous/2156668
  786. union FP32 {
  787. unsigned int u;
  788. float f;
  789. struct {
  790. #if TINYEXR_LITTLE_ENDIAN
  791. unsigned int Mantissa : 23;
  792. unsigned int Exponent : 8;
  793. unsigned int Sign : 1;
  794. #else
  795. unsigned int Sign : 1;
  796. unsigned int Exponent : 8;
  797. unsigned int Mantissa : 23;
  798. #endif
  799. } s;
  800. };
  801. #ifdef __clang__
  802. #pragma clang diagnostic push
  803. #pragma clang diagnostic ignored "-Wpadded"
  804. #endif
  805. union FP16 {
  806. unsigned short u;
  807. struct {
  808. #if TINYEXR_LITTLE_ENDIAN
  809. unsigned int Mantissa : 10;
  810. unsigned int Exponent : 5;
  811. unsigned int Sign : 1;
  812. #else
  813. unsigned int Sign : 1;
  814. unsigned int Exponent : 5;
  815. unsigned int Mantissa : 10;
  816. #endif
  817. } s;
  818. };
  819. #ifdef __clang__
  820. #pragma clang diagnostic pop
  821. #endif
  822. static FP32 half_to_float(FP16 h) {
  823. static const FP32 magic = {113 << 23};
  824. static const unsigned int shifted_exp = 0x7c00
  825. << 13; // exponent mask after shift
  826. FP32 o;
  827. o.u = (h.u & 0x7fffU) << 13U; // exponent/mantissa bits
  828. unsigned int exp_ = shifted_exp & o.u; // just the exponent
  829. o.u += (127 - 15) << 23; // exponent adjust
  830. // handle exponent special cases
  831. if (exp_ == shifted_exp) // Inf/NaN?
  832. o.u += (128 - 16) << 23; // extra exp adjust
  833. else if (exp_ == 0) // Zero/Denormal?
  834. {
  835. o.u += 1 << 23; // extra exp adjust
  836. o.f -= magic.f; // renormalize
  837. }
  838. o.u |= (h.u & 0x8000U) << 16U; // sign bit
  839. return o;
  840. }
  841. static FP16 float_to_half_full(FP32 f) {
  842. FP16 o = {0};
  843. // Based on ISPC reference code (with minor modifications)
  844. if (f.s.Exponent == 0) // Signed zero/denormal (which will underflow)
  845. o.s.Exponent = 0;
  846. else if (f.s.Exponent == 255) // Inf or NaN (all exponent bits set)
  847. {
  848. o.s.Exponent = 31;
  849. o.s.Mantissa = f.s.Mantissa ? 0x200 : 0; // NaN->qNaN and Inf->Inf
  850. } else // Normalized number
  851. {
  852. // Exponent unbias the single, then bias the halfp
  853. int newexp = f.s.Exponent - 127 + 15;
  854. if (newexp >= 31) // Overflow, return signed infinity
  855. o.s.Exponent = 31;
  856. else if (newexp <= 0) // Underflow
  857. {
  858. if ((14 - newexp) <= 24) // Mantissa might be non-zero
  859. {
  860. unsigned int mant = f.s.Mantissa | 0x800000; // Hidden 1 bit
  861. o.s.Mantissa = mant >> (14 - newexp);
  862. if ((mant >> (13 - newexp)) & 1) // Check for rounding
  863. o.u++; // Round, might overflow into exp bit, but this is OK
  864. }
  865. } else {
  866. o.s.Exponent = static_cast<unsigned int>(newexp);
  867. o.s.Mantissa = f.s.Mantissa >> 13;
  868. if (f.s.Mantissa & 0x1000) // Check for rounding
  869. o.u++; // Round, might overflow to inf, this is OK
  870. }
  871. }
  872. o.s.Sign = f.s.Sign;
  873. return o;
  874. }
  875. // NOTE: From OpenEXR code
  876. // #define IMF_INCREASING_Y 0
  877. // #define IMF_DECREASING_Y 1
  878. // #define IMF_RAMDOM_Y 2
  879. //
  880. // #define IMF_NO_COMPRESSION 0
  881. // #define IMF_RLE_COMPRESSION 1
  882. // #define IMF_ZIPS_COMPRESSION 2
  883. // #define IMF_ZIP_COMPRESSION 3
  884. // #define IMF_PIZ_COMPRESSION 4
  885. // #define IMF_PXR24_COMPRESSION 5
  886. // #define IMF_B44_COMPRESSION 6
  887. // #define IMF_B44A_COMPRESSION 7
  888. #ifdef __clang__
  889. #pragma clang diagnostic push
  890. #if __has_warning("-Wzero-as-null-pointer-constant")
  891. #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
  892. #endif
  893. #endif
  894. static const char *ReadString(std::string *s, const char *ptr, size_t len) {
  895. // Read untile NULL(\0).
  896. const char *p = ptr;
  897. const char *q = ptr;
  898. while ((size_t(q - ptr) < len) && (*q) != 0) {
  899. q++;
  900. }
  901. if (size_t(q - ptr) >= len) {
  902. (*s).clear();
  903. return NULL;
  904. }
  905. (*s) = std::string(p, q);
  906. return q + 1; // skip '\0'
  907. }
  908. static bool ReadAttribute(std::string *name, std::string *type,
  909. std::vector<unsigned char> *data, size_t *marker_size,
  910. const char *marker, size_t size) {
  911. size_t name_len = strnlen(marker, size);
  912. if (name_len == size) {
  913. // String does not have a terminating character.
  914. return false;
  915. }
  916. *name = std::string(marker, name_len);
  917. marker += name_len + 1;
  918. size -= name_len + 1;
  919. size_t type_len = strnlen(marker, size);
  920. if (type_len == size) {
  921. return false;
  922. }
  923. *type = std::string(marker, type_len);
  924. marker += type_len + 1;
  925. size -= type_len + 1;
  926. if (size < sizeof(uint32_t)) {
  927. return false;
  928. }
  929. uint32_t data_len;
  930. memcpy(&data_len, marker, sizeof(uint32_t));
  931. tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
  932. if (data_len == 0) {
  933. if ((*type).compare("string") == 0) {
  934. // Accept empty string attribute.
  935. marker += sizeof(uint32_t);
  936. size -= sizeof(uint32_t);
  937. *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t);
  938. data->resize(1);
  939. (*data)[0] = '\0';
  940. return true;
  941. } else {
  942. return false;
  943. }
  944. }
  945. marker += sizeof(uint32_t);
  946. size -= sizeof(uint32_t);
  947. if (size < data_len) {
  948. return false;
  949. }
  950. data->resize(static_cast<size_t>(data_len));
  951. memcpy(&data->at(0), marker, static_cast<size_t>(data_len));
  952. *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t) + data_len;
  953. return true;
  954. }
  955. static void WriteAttributeToMemory(std::vector<unsigned char> *out,
  956. const char *name, const char *type,
  957. const unsigned char *data, int len) {
  958. out->insert(out->end(), name, name + strlen(name) + 1);
  959. out->insert(out->end(), type, type + strlen(type) + 1);
  960. int outLen = len;
  961. tinyexr::swap4(&outLen);
  962. out->insert(out->end(), reinterpret_cast<unsigned char *>(&outLen),
  963. reinterpret_cast<unsigned char *>(&outLen) + sizeof(int));
  964. out->insert(out->end(), data, data + len);
  965. }
  966. typedef struct TChannelInfo {
  967. std::string name; // less than 255 bytes long
  968. int pixel_type;
  969. int requested_pixel_type;
  970. int x_sampling;
  971. int y_sampling;
  972. unsigned char p_linear;
  973. unsigned char pad[3];
  974. } ChannelInfo;
  975. typedef struct {
  976. int min_x;
  977. int min_y;
  978. int max_x;
  979. int max_y;
  980. } Box2iInfo;
  981. struct HeaderInfo {
  982. std::vector<tinyexr::ChannelInfo> channels;
  983. std::vector<EXRAttribute> attributes;
  984. Box2iInfo data_window;
  985. int line_order;
  986. Box2iInfo display_window;
  987. float screen_window_center[2];
  988. float screen_window_width;
  989. float pixel_aspect_ratio;
  990. int chunk_count;
  991. // Tiled format
  992. int tiled; // Non-zero if the part is tiled.
  993. int tile_size_x;
  994. int tile_size_y;
  995. int tile_level_mode;
  996. int tile_rounding_mode;
  997. unsigned int header_len;
  998. int compression_type;
  999. // required for multi-part or non-image files
  1000. std::string name;
  1001. // required for multi-part or non-image files
  1002. std::string type;
  1003. void clear() {
  1004. channels.clear();
  1005. attributes.clear();
  1006. data_window.min_x = 0;
  1007. data_window.min_y = 0;
  1008. data_window.max_x = 0;
  1009. data_window.max_y = 0;
  1010. line_order = 0;
  1011. display_window.min_x = 0;
  1012. display_window.min_y = 0;
  1013. display_window.max_x = 0;
  1014. display_window.max_y = 0;
  1015. screen_window_center[0] = 0.0f;
  1016. screen_window_center[1] = 0.0f;
  1017. screen_window_width = 0.0f;
  1018. pixel_aspect_ratio = 0.0f;
  1019. chunk_count = 0;
  1020. // Tiled format
  1021. tiled = 0;
  1022. tile_size_x = 0;
  1023. tile_size_y = 0;
  1024. tile_level_mode = 0;
  1025. tile_rounding_mode = 0;
  1026. header_len = 0;
  1027. compression_type = 0;
  1028. name.clear();
  1029. type.clear();
  1030. }
  1031. };
  1032. static bool ReadChannelInfo(std::vector<ChannelInfo> &channels,
  1033. const std::vector<unsigned char> &data) {
  1034. const char *p = reinterpret_cast<const char *>(&data.at(0));
  1035. for (;;) {
  1036. if ((*p) == 0) {
  1037. break;
  1038. }
  1039. ChannelInfo info;
  1040. info.requested_pixel_type = 0;
  1041. tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) -
  1042. (p - reinterpret_cast<const char *>(data.data()));
  1043. if (data_len < 0) {
  1044. return false;
  1045. }
  1046. p = ReadString(&info.name, p, size_t(data_len));
  1047. if ((p == NULL) && (info.name.empty())) {
  1048. // Buffer overrun. Issue #51.
  1049. return false;
  1050. }
  1051. const unsigned char *data_end =
  1052. reinterpret_cast<const unsigned char *>(p) + 16;
  1053. if (data_end >= (data.data() + data.size())) {
  1054. return false;
  1055. }
  1056. memcpy(&info.pixel_type, p, sizeof(int));
  1057. p += 4;
  1058. info.p_linear = static_cast<unsigned char>(p[0]); // uchar
  1059. p += 1 + 3; // reserved: uchar[3]
  1060. memcpy(&info.x_sampling, p, sizeof(int)); // int
  1061. p += 4;
  1062. memcpy(&info.y_sampling, p, sizeof(int)); // int
  1063. p += 4;
  1064. tinyexr::swap4(&info.pixel_type);
  1065. tinyexr::swap4(&info.x_sampling);
  1066. tinyexr::swap4(&info.y_sampling);
  1067. channels.push_back(info);
  1068. }
  1069. return true;
  1070. }
  1071. static void WriteChannelInfo(std::vector<unsigned char> &data,
  1072. const std::vector<ChannelInfo> &channels) {
  1073. size_t sz = 0;
  1074. // Calculate total size.
  1075. for (size_t c = 0; c < channels.size(); c++) {
  1076. sz += channels[c].name.length() + 1; // +1 for \0
  1077. sz += 16; // 4 * int
  1078. }
  1079. data.resize(sz + 1);
  1080. unsigned char *p = &data.at(0);
  1081. for (size_t c = 0; c < channels.size(); c++) {
  1082. memcpy(p, channels[c].name.c_str(), channels[c].name.length());
  1083. p += channels[c].name.length();
  1084. (*p) = '\0';
  1085. p++;
  1086. int pixel_type = channels[c].requested_pixel_type;
  1087. int x_sampling = channels[c].x_sampling;
  1088. int y_sampling = channels[c].y_sampling;
  1089. tinyexr::swap4(&pixel_type);
  1090. tinyexr::swap4(&x_sampling);
  1091. tinyexr::swap4(&y_sampling);
  1092. memcpy(p, &pixel_type, sizeof(int));
  1093. p += sizeof(int);
  1094. (*p) = channels[c].p_linear;
  1095. p += 4;
  1096. memcpy(p, &x_sampling, sizeof(int));
  1097. p += sizeof(int);
  1098. memcpy(p, &y_sampling, sizeof(int));
  1099. p += sizeof(int);
  1100. }
  1101. (*p) = '\0';
  1102. }
  1103. static bool CompressZip(unsigned char *dst,
  1104. tinyexr::tinyexr_uint64 &compressedSize,
  1105. const unsigned char *src, unsigned long src_size) {
  1106. std::vector<unsigned char> tmpBuf(src_size);
  1107. //
  1108. // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
  1109. // ImfZipCompressor.cpp
  1110. //
  1111. //
  1112. // Reorder the pixel data.
  1113. //
  1114. const char *srcPtr = reinterpret_cast<const char *>(src);
  1115. {
  1116. char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0));
  1117. char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2;
  1118. const char *stop = srcPtr + src_size;
  1119. for (;;) {
  1120. if (srcPtr < stop)
  1121. *(t1++) = *(srcPtr++);
  1122. else
  1123. break;
  1124. if (srcPtr < stop)
  1125. *(t2++) = *(srcPtr++);
  1126. else
  1127. break;
  1128. }
  1129. }
  1130. //
  1131. // Predictor.
  1132. //
  1133. {
  1134. unsigned char *t = &tmpBuf.at(0) + 1;
  1135. unsigned char *stop = &tmpBuf.at(0) + src_size;
  1136. int p = t[-1];
  1137. while (t < stop) {
  1138. int d = int(t[0]) - p + (128 + 256);
  1139. p = t[0];
  1140. t[0] = static_cast<unsigned char>(d);
  1141. ++t;
  1142. }
  1143. }
  1144. #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
  1145. //
  1146. // Compress the data using miniz
  1147. //
  1148. mz_ulong outSize = mz_compressBound(src_size);
  1149. int ret = mz_compress(
  1150. dst, &outSize, static_cast<const unsigned char *>(&tmpBuf.at(0)),
  1151. src_size);
  1152. if (ret != MZ_OK) {
  1153. return false;
  1154. }
  1155. compressedSize = outSize;
  1156. #elif defined(TINYEXR_USE_STB_ZLIB) && (TINYEXR_USE_STB_ZLIB==1)
  1157. int outSize;
  1158. unsigned char* ret = stbi_zlib_compress(const_cast<unsigned char*>(&tmpBuf.at(0)), src_size, &outSize, 8);
  1159. if (!ret) {
  1160. return false;
  1161. }
  1162. memcpy(dst, ret, outSize);
  1163. free(ret);
  1164. compressedSize = outSize;
  1165. #elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1)
  1166. uint64_t dstSize = nanoz_compressBound(static_cast<uint64_t>(src_size));
  1167. int outSize{0};
  1168. unsigned char *ret = nanoz_compress(&tmpBuf.at(0), src_size, &outSize, /* quality */8);
  1169. if (!ret) {
  1170. return false;
  1171. }
  1172. memcpy(dst, ret, outSize);
  1173. free(ret);
  1174. compressedSize = outSize;
  1175. #else
  1176. uLong outSize = compressBound(static_cast<uLong>(src_size));
  1177. int ret = compress(dst, &outSize, static_cast<const Bytef *>(&tmpBuf.at(0)),
  1178. src_size);
  1179. if (ret != Z_OK) {
  1180. return false;
  1181. }
  1182. compressedSize = outSize;
  1183. #endif
  1184. // Use uncompressed data when compressed data is larger than uncompressed.
  1185. // (Issue 40)
  1186. if (compressedSize >= src_size) {
  1187. compressedSize = src_size;
  1188. memcpy(dst, src, src_size);
  1189. }
  1190. return true;
  1191. }
  1192. static bool DecompressZip(unsigned char *dst,
  1193. unsigned long *uncompressed_size /* inout */,
  1194. const unsigned char *src, unsigned long src_size) {
  1195. if ((*uncompressed_size) == src_size) {
  1196. // Data is not compressed(Issue 40).
  1197. memcpy(dst, src, src_size);
  1198. return true;
  1199. }
  1200. std::vector<unsigned char> tmpBuf(*uncompressed_size);
  1201. #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
  1202. int ret =
  1203. mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
  1204. if (MZ_OK != ret) {
  1205. return false;
  1206. }
  1207. #elif TINYEXR_USE_STB_ZLIB
  1208. int ret = stbi_zlib_decode_buffer(reinterpret_cast<char*>(&tmpBuf.at(0)),
  1209. *uncompressed_size, reinterpret_cast<const char*>(src), src_size);
  1210. if (ret < 0) {
  1211. return false;
  1212. }
  1213. #elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1)
  1214. uint64_t dest_size = (*uncompressed_size);
  1215. uint64_t uncomp_size{0};
  1216. nanoz_status_t ret =
  1217. nanoz_uncompress(src, src_size, dest_size, &tmpBuf.at(0), &uncomp_size);
  1218. if (NANOZ_SUCCESS != ret) {
  1219. return false;
  1220. }
  1221. if ((*uncompressed_size) != uncomp_size) {
  1222. return false;
  1223. }
  1224. #else
  1225. int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
  1226. if (Z_OK != ret) {
  1227. return false;
  1228. }
  1229. #endif
  1230. //
  1231. // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
  1232. // ImfZipCompressor.cpp
  1233. //
  1234. // Predictor.
  1235. {
  1236. unsigned char *t = &tmpBuf.at(0) + 1;
  1237. unsigned char *stop = &tmpBuf.at(0) + (*uncompressed_size);
  1238. while (t < stop) {
  1239. int d = int(t[-1]) + int(t[0]) - 128;
  1240. t[0] = static_cast<unsigned char>(d);
  1241. ++t;
  1242. }
  1243. }
  1244. // Reorder the pixel data.
  1245. {
  1246. const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0));
  1247. const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) +
  1248. (*uncompressed_size + 1) / 2;
  1249. char *s = reinterpret_cast<char *>(dst);
  1250. char *stop = s + (*uncompressed_size);
  1251. for (;;) {
  1252. if (s < stop)
  1253. *(s++) = *(t1++);
  1254. else
  1255. break;
  1256. if (s < stop)
  1257. *(s++) = *(t2++);
  1258. else
  1259. break;
  1260. }
  1261. }
  1262. return true;
  1263. }
  1264. // RLE code from OpenEXR --------------------------------------
  1265. #ifdef __clang__
  1266. #pragma clang diagnostic push
  1267. #pragma clang diagnostic ignored "-Wsign-conversion"
  1268. #if __has_warning("-Wextra-semi-stmt")
  1269. #pragma clang diagnostic ignored "-Wextra-semi-stmt"
  1270. #endif
  1271. #endif
  1272. #ifdef _MSC_VER
  1273. #pragma warning(push)
  1274. #pragma warning(disable : 4204) // nonstandard extension used : non-constant
  1275. // aggregate initializer (also supported by GNU
  1276. // C and C99, so no big deal)
  1277. #pragma warning(disable : 4244) // 'initializing': conversion from '__int64' to
  1278. // 'int', possible loss of data
  1279. #pragma warning(disable : 4267) // 'argument': conversion from '__int64' to
  1280. // 'int', possible loss of data
  1281. #pragma warning(disable : 4996) // 'strdup': The POSIX name for this item is
  1282. // deprecated. Instead, use the ISO C and C++
  1283. // conformant name: _strdup.
  1284. #endif
  1285. const int MIN_RUN_LENGTH = 3;
  1286. const int MAX_RUN_LENGTH = 127;
  1287. //
  1288. // Compress an array of bytes, using run-length encoding,
  1289. // and return the length of the compressed data.
  1290. //
  1291. static int rleCompress(int inLength, const char in[], signed char out[]) {
  1292. const char *inEnd = in + inLength;
  1293. const char *runStart = in;
  1294. const char *runEnd = in + 1;
  1295. signed char *outWrite = out;
  1296. while (runStart < inEnd) {
  1297. while (runEnd < inEnd && *runStart == *runEnd &&
  1298. runEnd - runStart - 1 < MAX_RUN_LENGTH) {
  1299. ++runEnd;
  1300. }
  1301. if (runEnd - runStart >= MIN_RUN_LENGTH) {
  1302. //
  1303. // Compressible run
  1304. //
  1305. *outWrite++ = static_cast<char>(runEnd - runStart) - 1;
  1306. *outWrite++ = *(reinterpret_cast<const signed char *>(runStart));
  1307. runStart = runEnd;
  1308. } else {
  1309. //
  1310. // Uncompressable run
  1311. //
  1312. while (runEnd < inEnd &&
  1313. ((runEnd + 1 >= inEnd || *runEnd != *(runEnd + 1)) ||
  1314. (runEnd + 2 >= inEnd || *(runEnd + 1) != *(runEnd + 2))) &&
  1315. runEnd - runStart < MAX_RUN_LENGTH) {
  1316. ++runEnd;
  1317. }
  1318. *outWrite++ = static_cast<char>(runStart - runEnd);
  1319. while (runStart < runEnd) {
  1320. *outWrite++ = *(reinterpret_cast<const signed char *>(runStart++));
  1321. }
  1322. }
  1323. ++runEnd;
  1324. }
  1325. return static_cast<int>(outWrite - out);
  1326. }
  1327. //
  1328. // Uncompress an array of bytes compressed with rleCompress().
  1329. // Returns the length of the uncompressed data, or 0 if the
  1330. // length of the uncompressed data would be more than maxLength.
  1331. //
  1332. static int rleUncompress(int inLength, int maxLength, const signed char in[],
  1333. char out[]) {
  1334. char *outStart = out;
  1335. while (inLength > 0) {
  1336. if (*in < 0) {
  1337. int count = -(static_cast<int>(*in++));
  1338. inLength -= count + 1;
  1339. // Fixes #116: Add bounds check to in buffer.
  1340. if ((0 > (maxLength -= count)) || (inLength < 0)) return 0;
  1341. memcpy(out, in, count);
  1342. out += count;
  1343. in += count;
  1344. } else {
  1345. int count = *in++;
  1346. inLength -= 2;
  1347. if ((0 > (maxLength -= count + 1)) || (inLength < 0)) return 0;
  1348. memset(out, *reinterpret_cast<const char *>(in), count + 1);
  1349. out += count + 1;
  1350. in++;
  1351. }
  1352. }
  1353. return static_cast<int>(out - outStart);
  1354. }
  1355. #ifdef __clang__
  1356. #pragma clang diagnostic pop
  1357. #endif
  1358. // End of RLE code from OpenEXR -----------------------------------
  1359. static bool CompressRle(unsigned char *dst,
  1360. tinyexr::tinyexr_uint64 &compressedSize,
  1361. const unsigned char *src, unsigned long src_size) {
  1362. std::vector<unsigned char> tmpBuf(src_size);
  1363. //
  1364. // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
  1365. // ImfRleCompressor.cpp
  1366. //
  1367. //
  1368. // Reorder the pixel data.
  1369. //
  1370. const char *srcPtr = reinterpret_cast<const char *>(src);
  1371. {
  1372. char *t1 = reinterpret_cast<char *>(&tmpBuf.at(0));
  1373. char *t2 = reinterpret_cast<char *>(&tmpBuf.at(0)) + (src_size + 1) / 2;
  1374. const char *stop = srcPtr + src_size;
  1375. for (;;) {
  1376. if (srcPtr < stop)
  1377. *(t1++) = *(srcPtr++);
  1378. else
  1379. break;
  1380. if (srcPtr < stop)
  1381. *(t2++) = *(srcPtr++);
  1382. else
  1383. break;
  1384. }
  1385. }
  1386. //
  1387. // Predictor.
  1388. //
  1389. {
  1390. unsigned char *t = &tmpBuf.at(0) + 1;
  1391. unsigned char *stop = &tmpBuf.at(0) + src_size;
  1392. int p = t[-1];
  1393. while (t < stop) {
  1394. int d = int(t[0]) - p + (128 + 256);
  1395. p = t[0];
  1396. t[0] = static_cast<unsigned char>(d);
  1397. ++t;
  1398. }
  1399. }
  1400. // outSize will be (srcSiz * 3) / 2 at max.
  1401. int outSize = rleCompress(static_cast<int>(src_size),
  1402. reinterpret_cast<const char *>(&tmpBuf.at(0)),
  1403. reinterpret_cast<signed char *>(dst));
  1404. TINYEXR_CHECK_AND_RETURN_C(outSize > 0, false);
  1405. compressedSize = static_cast<tinyexr::tinyexr_uint64>(outSize);
  1406. // Use uncompressed data when compressed data is larger than uncompressed.
  1407. // (Issue 40)
  1408. if (compressedSize >= src_size) {
  1409. compressedSize = src_size;
  1410. memcpy(dst, src, src_size);
  1411. }
  1412. return true;
  1413. }
  1414. static bool DecompressRle(unsigned char *dst,
  1415. const unsigned long uncompressed_size,
  1416. const unsigned char *src, unsigned long src_size) {
  1417. if (uncompressed_size == src_size) {
  1418. // Data is not compressed(Issue 40).
  1419. memcpy(dst, src, src_size);
  1420. return true;
  1421. }
  1422. // Workaround for issue #112.
  1423. // TODO(syoyo): Add more robust out-of-bounds check in `rleUncompress`.
  1424. if (src_size <= 2) {
  1425. return false;
  1426. }
  1427. std::vector<unsigned char> tmpBuf(uncompressed_size);
  1428. int ret = rleUncompress(static_cast<int>(src_size),
  1429. static_cast<int>(uncompressed_size),
  1430. reinterpret_cast<const signed char *>(src),
  1431. reinterpret_cast<char *>(&tmpBuf.at(0)));
  1432. if (ret != static_cast<int>(uncompressed_size)) {
  1433. return false;
  1434. }
  1435. //
  1436. // Apply EXR-specific? postprocess. Grabbed from OpenEXR's
  1437. // ImfRleCompressor.cpp
  1438. //
  1439. // Predictor.
  1440. {
  1441. unsigned char *t = &tmpBuf.at(0) + 1;
  1442. unsigned char *stop = &tmpBuf.at(0) + uncompressed_size;
  1443. while (t < stop) {
  1444. int d = int(t[-1]) + int(t[0]) - 128;
  1445. t[0] = static_cast<unsigned char>(d);
  1446. ++t;
  1447. }
  1448. }
  1449. // Reorder the pixel data.
  1450. {
  1451. const char *t1 = reinterpret_cast<const char *>(&tmpBuf.at(0));
  1452. const char *t2 = reinterpret_cast<const char *>(&tmpBuf.at(0)) +
  1453. (uncompressed_size + 1) / 2;
  1454. char *s = reinterpret_cast<char *>(dst);
  1455. char *stop = s + uncompressed_size;
  1456. for (;;) {
  1457. if (s < stop)
  1458. *(s++) = *(t1++);
  1459. else
  1460. break;
  1461. if (s < stop)
  1462. *(s++) = *(t2++);
  1463. else
  1464. break;
  1465. }
  1466. }
  1467. return true;
  1468. }
  1469. #if TINYEXR_USE_PIZ
  1470. #ifdef __clang__
  1471. #pragma clang diagnostic push
  1472. #pragma clang diagnostic ignored "-Wc++11-long-long"
  1473. #pragma clang diagnostic ignored "-Wold-style-cast"
  1474. #pragma clang diagnostic ignored "-Wpadded"
  1475. #pragma clang diagnostic ignored "-Wsign-conversion"
  1476. #pragma clang diagnostic ignored "-Wc++11-extensions"
  1477. #pragma clang diagnostic ignored "-Wconversion"
  1478. #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
  1479. #if __has_warning("-Wcast-qual")
  1480. #pragma clang diagnostic ignored "-Wcast-qual"
  1481. #endif
  1482. #if __has_warning("-Wextra-semi-stmt")
  1483. #pragma clang diagnostic ignored "-Wextra-semi-stmt"
  1484. #endif
  1485. #endif
  1486. //
  1487. // PIZ compress/uncompress, based on OpenEXR's ImfPizCompressor.cpp
  1488. //
  1489. // -----------------------------------------------------------------
  1490. // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
  1491. // Digital Ltd. LLC)
  1492. // (3 clause BSD license)
  1493. //
  1494. struct PIZChannelData {
  1495. unsigned short *start;
  1496. unsigned short *end;
  1497. int nx;
  1498. int ny;
  1499. int ys;
  1500. int size;
  1501. };
  1502. //-----------------------------------------------------------------------------
  1503. //
  1504. // 16-bit Haar Wavelet encoding and decoding
  1505. //
  1506. // The source code in this file is derived from the encoding
  1507. // and decoding routines written by Christian Rouet for his
  1508. // PIZ image file format.
  1509. //
  1510. //-----------------------------------------------------------------------------
  1511. //
  1512. // Wavelet basis functions without modulo arithmetic; they produce
  1513. // the best compression ratios when the wavelet-transformed data are
  1514. // Huffman-encoded, but the wavelet transform works only for 14-bit
  1515. // data (untransformed data values must be less than (1 << 14)).
  1516. //
  1517. inline void wenc14(unsigned short a, unsigned short b, unsigned short &l,
  1518. unsigned short &h) {
  1519. short as = static_cast<short>(a);
  1520. short bs = static_cast<short>(b);
  1521. short ms = (as + bs) >> 1;
  1522. short ds = as - bs;
  1523. l = static_cast<unsigned short>(ms);
  1524. h = static_cast<unsigned short>(ds);
  1525. }
  1526. inline void wdec14(unsigned short l, unsigned short h, unsigned short &a,
  1527. unsigned short &b) {
  1528. short ls = static_cast<short>(l);
  1529. short hs = static_cast<short>(h);
  1530. int hi = hs;
  1531. int ai = ls + (hi & 1) + (hi >> 1);
  1532. short as = static_cast<short>(ai);
  1533. short bs = static_cast<short>(ai - hi);
  1534. a = static_cast<unsigned short>(as);
  1535. b = static_cast<unsigned short>(bs);
  1536. }
  1537. //
  1538. // Wavelet basis functions with modulo arithmetic; they work with full
  1539. // 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't
  1540. // compress the data quite as well.
  1541. //
  1542. const int NBITS = 16;
  1543. const int A_OFFSET = 1 << (NBITS - 1);
  1544. const int M_OFFSET = 1 << (NBITS - 1);
  1545. const int MOD_MASK = (1 << NBITS) - 1;
  1546. inline void wenc16(unsigned short a, unsigned short b, unsigned short &l,
  1547. unsigned short &h) {
  1548. int ao = (a + A_OFFSET) & MOD_MASK;
  1549. int m = ((ao + b) >> 1);
  1550. int d = ao - b;
  1551. if (d < 0) m = (m + M_OFFSET) & MOD_MASK;
  1552. d &= MOD_MASK;
  1553. l = static_cast<unsigned short>(m);
  1554. h = static_cast<unsigned short>(d);
  1555. }
  1556. inline void wdec16(unsigned short l, unsigned short h, unsigned short &a,
  1557. unsigned short &b) {
  1558. int m = l;
  1559. int d = h;
  1560. int bb = (m - (d >> 1)) & MOD_MASK;
  1561. int aa = (d + bb - A_OFFSET) & MOD_MASK;
  1562. b = static_cast<unsigned short>(bb);
  1563. a = static_cast<unsigned short>(aa);
  1564. }
  1565. //
  1566. // 2D Wavelet encoding:
  1567. //
  1568. static void wav2Encode(
  1569. unsigned short *in, // io: values are transformed in place
  1570. int nx, // i : x size
  1571. int ox, // i : x offset
  1572. int ny, // i : y size
  1573. int oy, // i : y offset
  1574. unsigned short mx) // i : maximum in[x][y] value
  1575. {
  1576. bool w14 = (mx < (1 << 14));
  1577. int n = (nx > ny) ? ny : nx;
  1578. int p = 1; // == 1 << level
  1579. int p2 = 2; // == 1 << (level+1)
  1580. //
  1581. // Hierarchical loop on smaller dimension n
  1582. //
  1583. while (p2 <= n) {
  1584. unsigned short *py = in;
  1585. unsigned short *ey = in + oy * (ny - p2);
  1586. int oy1 = oy * p;
  1587. int oy2 = oy * p2;
  1588. int ox1 = ox * p;
  1589. int ox2 = ox * p2;
  1590. unsigned short i00, i01, i10, i11;
  1591. //
  1592. // Y loop
  1593. //
  1594. for (; py <= ey; py += oy2) {
  1595. unsigned short *px = py;
  1596. unsigned short *ex = py + ox * (nx - p2);
  1597. //
  1598. // X loop
  1599. //
  1600. for (; px <= ex; px += ox2) {
  1601. unsigned short *p01 = px + ox1;
  1602. unsigned short *p10 = px + oy1;
  1603. unsigned short *p11 = p10 + ox1;
  1604. //
  1605. // 2D wavelet encoding
  1606. //
  1607. if (w14) {
  1608. wenc14(*px, *p01, i00, i01);
  1609. wenc14(*p10, *p11, i10, i11);
  1610. wenc14(i00, i10, *px, *p10);
  1611. wenc14(i01, i11, *p01, *p11);
  1612. } else {
  1613. wenc16(*px, *p01, i00, i01);
  1614. wenc16(*p10, *p11, i10, i11);
  1615. wenc16(i00, i10, *px, *p10);
  1616. wenc16(i01, i11, *p01, *p11);
  1617. }
  1618. }
  1619. //
  1620. // Encode (1D) odd column (still in Y loop)
  1621. //
  1622. if (nx & p) {
  1623. unsigned short *p10 = px + oy1;
  1624. if (w14)
  1625. wenc14(*px, *p10, i00, *p10);
  1626. else
  1627. wenc16(*px, *p10, i00, *p10);
  1628. *px = i00;
  1629. }
  1630. }
  1631. //
  1632. // Encode (1D) odd line (must loop in X)
  1633. //
  1634. if (ny & p) {
  1635. unsigned short *px = py;
  1636. unsigned short *ex = py + ox * (nx - p2);
  1637. for (; px <= ex; px += ox2) {
  1638. unsigned short *p01 = px + ox1;
  1639. if (w14)
  1640. wenc14(*px, *p01, i00, *p01);
  1641. else
  1642. wenc16(*px, *p01, i00, *p01);
  1643. *px = i00;
  1644. }
  1645. }
  1646. //
  1647. // Next level
  1648. //
  1649. p = p2;
  1650. p2 <<= 1;
  1651. }
  1652. }
  1653. //
  1654. // 2D Wavelet decoding:
  1655. //
  1656. static void wav2Decode(
  1657. unsigned short *in, // io: values are transformed in place
  1658. int nx, // i : x size
  1659. int ox, // i : x offset
  1660. int ny, // i : y size
  1661. int oy, // i : y offset
  1662. unsigned short mx) // i : maximum in[x][y] value
  1663. {
  1664. bool w14 = (mx < (1 << 14));
  1665. int n = (nx > ny) ? ny : nx;
  1666. int p = 1;
  1667. int p2;
  1668. //
  1669. // Search max level
  1670. //
  1671. while (p <= n) p <<= 1;
  1672. p >>= 1;
  1673. p2 = p;
  1674. p >>= 1;
  1675. //
  1676. // Hierarchical loop on smaller dimension n
  1677. //
  1678. while (p >= 1) {
  1679. unsigned short *py = in;
  1680. unsigned short *ey = in + oy * (ny - p2);
  1681. int oy1 = oy * p;
  1682. int oy2 = oy * p2;
  1683. int ox1 = ox * p;
  1684. int ox2 = ox * p2;
  1685. unsigned short i00, i01, i10, i11;
  1686. //
  1687. // Y loop
  1688. //
  1689. for (; py <= ey; py += oy2) {
  1690. unsigned short *px = py;
  1691. unsigned short *ex = py + ox * (nx - p2);
  1692. //
  1693. // X loop
  1694. //
  1695. for (; px <= ex; px += ox2) {
  1696. unsigned short *p01 = px + ox1;
  1697. unsigned short *p10 = px + oy1;
  1698. unsigned short *p11 = p10 + ox1;
  1699. //
  1700. // 2D wavelet decoding
  1701. //
  1702. if (w14) {
  1703. wdec14(*px, *p10, i00, i10);
  1704. wdec14(*p01, *p11, i01, i11);
  1705. wdec14(i00, i01, *px, *p01);
  1706. wdec14(i10, i11, *p10, *p11);
  1707. } else {
  1708. wdec16(*px, *p10, i00, i10);
  1709. wdec16(*p01, *p11, i01, i11);
  1710. wdec16(i00, i01, *px, *p01);
  1711. wdec16(i10, i11, *p10, *p11);
  1712. }
  1713. }
  1714. //
  1715. // Decode (1D) odd column (still in Y loop)
  1716. //
  1717. if (nx & p) {
  1718. unsigned short *p10 = px + oy1;
  1719. if (w14)
  1720. wdec14(*px, *p10, i00, *p10);
  1721. else
  1722. wdec16(*px, *p10, i00, *p10);
  1723. *px = i00;
  1724. }
  1725. }
  1726. //
  1727. // Decode (1D) odd line (must loop in X)
  1728. //
  1729. if (ny & p) {
  1730. unsigned short *px = py;
  1731. unsigned short *ex = py + ox * (nx - p2);
  1732. for (; px <= ex; px += ox2) {
  1733. unsigned short *p01 = px + ox1;
  1734. if (w14)
  1735. wdec14(*px, *p01, i00, *p01);
  1736. else
  1737. wdec16(*px, *p01, i00, *p01);
  1738. *px = i00;
  1739. }
  1740. }
  1741. //
  1742. // Next level
  1743. //
  1744. p2 = p;
  1745. p >>= 1;
  1746. }
  1747. }
  1748. //-----------------------------------------------------------------------------
  1749. //
  1750. // 16-bit Huffman compression and decompression.
  1751. //
  1752. // The source code in this file is derived from the 8-bit
  1753. // Huffman compression and decompression routines written
  1754. // by Christian Rouet for his PIZ image file format.
  1755. //
  1756. //-----------------------------------------------------------------------------
  1757. // Adds some modification for tinyexr.
  1758. const int HUF_ENCBITS = 16; // literal (value) bit length
  1759. const int HUF_DECBITS = 14; // decoding bit size (>= 8)
  1760. const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1; // encoding table size
  1761. const int HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size
  1762. const int HUF_DECMASK = HUF_DECSIZE - 1;
  1763. struct HufDec { // short code long code
  1764. //-------------------------------
  1765. unsigned int len : 8; // code length 0
  1766. unsigned int lit : 24; // lit p size
  1767. unsigned int *p; // 0 lits
  1768. };
  1769. inline long long hufLength(long long code) { return code & 63; }
  1770. inline long long hufCode(long long code) { return code >> 6; }
  1771. inline void outputBits(int nBits, long long bits, long long &c, int &lc,
  1772. char *&out) {
  1773. c <<= nBits;
  1774. lc += nBits;
  1775. c |= bits;
  1776. while (lc >= 8) *out++ = static_cast<char>((c >> (lc -= 8)));
  1777. }
  1778. inline long long getBits(int nBits, long long &c, int &lc, const char *&in) {
  1779. while (lc < nBits) {
  1780. c = (c << 8) | *(reinterpret_cast<const unsigned char *>(in++));
  1781. lc += 8;
  1782. }
  1783. lc -= nBits;
  1784. return (c >> lc) & ((1 << nBits) - 1);
  1785. }
  1786. //
  1787. // ENCODING TABLE BUILDING & (UN)PACKING
  1788. //
  1789. //
  1790. // Build a "canonical" Huffman code table:
  1791. // - for each (uncompressed) symbol, hcode contains the length
  1792. // of the corresponding code (in the compressed data)
  1793. // - canonical codes are computed and stored in hcode
  1794. // - the rules for constructing canonical codes are as follows:
  1795. // * shorter codes (if filled with zeroes to the right)
  1796. // have a numerically higher value than longer codes
  1797. // * for codes with the same length, numerical values
  1798. // increase with numerical symbol values
  1799. // - because the canonical code table can be constructed from
  1800. // symbol lengths alone, the code table can be transmitted
  1801. // without sending the actual code values
  1802. // - see http://www.compressconsult.com/huffman/
  1803. //
  1804. static void hufCanonicalCodeTable(long long hcode[HUF_ENCSIZE]) {
  1805. long long n[59];
  1806. //
  1807. // For each i from 0 through 58, count the
  1808. // number of different codes of length i, and
  1809. // store the count in n[i].
  1810. //
  1811. for (int i = 0; i <= 58; ++i) n[i] = 0;
  1812. for (int i = 0; i < HUF_ENCSIZE; ++i) n[hcode[i]] += 1;
  1813. //
  1814. // For each i from 58 through 1, compute the
  1815. // numerically lowest code with length i, and
  1816. // store that code in n[i].
  1817. //
  1818. long long c = 0;
  1819. for (int i = 58; i > 0; --i) {
  1820. long long nc = ((c + n[i]) >> 1);
  1821. n[i] = c;
  1822. c = nc;
  1823. }
  1824. //
  1825. // hcode[i] contains the length, l, of the
  1826. // code for symbol i. Assign the next available
  1827. // code of length l to the symbol and store both
  1828. // l and the code in hcode[i].
  1829. //
  1830. for (int i = 0; i < HUF_ENCSIZE; ++i) {
  1831. int l = static_cast<int>(hcode[i]);
  1832. if (l > 0) hcode[i] = l | (n[l]++ << 6);
  1833. }
  1834. }
  1835. //
  1836. // Compute Huffman codes (based on frq input) and store them in frq:
  1837. // - code structure is : [63:lsb - 6:msb] | [5-0: bit length];
  1838. // - max code length is 58 bits;
  1839. // - codes outside the range [im-iM] have a null length (unused values);
  1840. // - original frequencies are destroyed;
  1841. // - encoding tables are used by hufEncode() and hufBuildDecTable();
  1842. //
  1843. struct FHeapCompare {
  1844. bool operator()(long long *a, long long *b) { return *a > *b; }
  1845. };
  1846. static bool hufBuildEncTable(
  1847. long long *frq, // io: input frequencies [HUF_ENCSIZE], output table
  1848. int *im, // o: min frq index
  1849. int *iM) // o: max frq index
  1850. {
  1851. //
  1852. // This function assumes that when it is called, array frq
  1853. // indicates the frequency of all possible symbols in the data
  1854. // that are to be Huffman-encoded. (frq[i] contains the number
  1855. // of occurrences of symbol i in the data.)
  1856. //
  1857. // The loop below does three things:
  1858. //
  1859. // 1) Finds the minimum and maximum indices that point
  1860. // to non-zero entries in frq:
  1861. //
  1862. // frq[im] != 0, and frq[i] == 0 for all i < im
  1863. // frq[iM] != 0, and frq[i] == 0 for all i > iM
  1864. //
  1865. // 2) Fills array fHeap with pointers to all non-zero
  1866. // entries in frq.
  1867. //
  1868. // 3) Initializes array hlink such that hlink[i] == i
  1869. // for all array entries.
  1870. //
  1871. std::vector<int> hlink(HUF_ENCSIZE);
  1872. std::vector<long long *> fHeap(HUF_ENCSIZE);
  1873. *im = 0;
  1874. while (!frq[*im]) (*im)++;
  1875. int nf = 0;
  1876. for (int i = *im; i < HUF_ENCSIZE; i++) {
  1877. hlink[i] = i;
  1878. if (frq[i]) {
  1879. fHeap[nf] = &frq[i];
  1880. nf++;
  1881. *iM = i;
  1882. }
  1883. }
  1884. //
  1885. // Add a pseudo-symbol, with a frequency count of 1, to frq;
  1886. // adjust the fHeap and hlink array accordingly. Function
  1887. // hufEncode() uses the pseudo-symbol for run-length encoding.
  1888. //
  1889. (*iM)++;
  1890. frq[*iM] = 1;
  1891. fHeap[nf] = &frq[*iM];
  1892. nf++;
  1893. //
  1894. // Build an array, scode, such that scode[i] contains the number
  1895. // of bits assigned to symbol i. Conceptually this is done by
  1896. // constructing a tree whose leaves are the symbols with non-zero
  1897. // frequency:
  1898. //
  1899. // Make a heap that contains all symbols with a non-zero frequency,
  1900. // with the least frequent symbol on top.
  1901. //
  1902. // Repeat until only one symbol is left on the heap:
  1903. //
  1904. // Take the two least frequent symbols off the top of the heap.
  1905. // Create a new node that has first two nodes as children, and
  1906. // whose frequency is the sum of the frequencies of the first
  1907. // two nodes. Put the new node back into the heap.
  1908. //
  1909. // The last node left on the heap is the root of the tree. For each
  1910. // leaf node, the distance between the root and the leaf is the length
  1911. // of the code for the corresponding symbol.
  1912. //
  1913. // The loop below doesn't actually build the tree; instead we compute
  1914. // the distances of the leaves from the root on the fly. When a new
  1915. // node is added to the heap, then that node's descendants are linked
  1916. // into a single linear list that starts at the new node, and the code
  1917. // lengths of the descendants (that is, their distance from the root
  1918. // of the tree) are incremented by one.
  1919. //
  1920. std::make_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
  1921. std::vector<long long> scode(HUF_ENCSIZE);
  1922. memset(scode.data(), 0, sizeof(long long) * HUF_ENCSIZE);
  1923. while (nf > 1) {
  1924. //
  1925. // Find the indices, mm and m, of the two smallest non-zero frq
  1926. // values in fHeap, add the smallest frq to the second-smallest
  1927. // frq, and remove the smallest frq value from fHeap.
  1928. //
  1929. int mm = fHeap[0] - frq;
  1930. std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
  1931. --nf;
  1932. int m = fHeap[0] - frq;
  1933. std::pop_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
  1934. frq[m] += frq[mm];
  1935. std::push_heap(&fHeap[0], &fHeap[nf], FHeapCompare());
  1936. //
  1937. // The entries in scode are linked into lists with the
  1938. // entries in hlink serving as "next" pointers and with
  1939. // the end of a list marked by hlink[j] == j.
  1940. //
  1941. // Traverse the lists that start at scode[m] and scode[mm].
  1942. // For each element visited, increment the length of the
  1943. // corresponding code by one bit. (If we visit scode[j]
  1944. // during the traversal, then the code for symbol j becomes
  1945. // one bit longer.)
  1946. //
  1947. // Merge the lists that start at scode[m] and scode[mm]
  1948. // into a single list that starts at scode[m].
  1949. //
  1950. //
  1951. // Add a bit to all codes in the first list.
  1952. //
  1953. for (int j = m;; j = hlink[j]) {
  1954. scode[j]++;
  1955. TINYEXR_CHECK_AND_RETURN_C(scode[j] <= 58, false);
  1956. if (hlink[j] == j) {
  1957. //
  1958. // Merge the two lists.
  1959. //
  1960. hlink[j] = mm;
  1961. break;
  1962. }
  1963. }
  1964. //
  1965. // Add a bit to all codes in the second list
  1966. //
  1967. for (int j = mm;; j = hlink[j]) {
  1968. scode[j]++;
  1969. TINYEXR_CHECK_AND_RETURN_C(scode[j] <= 58, false);
  1970. if (hlink[j] == j) break;
  1971. }
  1972. }
  1973. //
  1974. // Build a canonical Huffman code table, replacing the code
  1975. // lengths in scode with (code, code length) pairs. Copy the
  1976. // code table from scode into frq.
  1977. //
  1978. hufCanonicalCodeTable(scode.data());
  1979. memcpy(frq, scode.data(), sizeof(long long) * HUF_ENCSIZE);
  1980. return true;
  1981. }
  1982. //
  1983. // Pack an encoding table:
  1984. // - only code lengths, not actual codes, are stored
  1985. // - runs of zeroes are compressed as follows:
  1986. //
  1987. // unpacked packed
  1988. // --------------------------------
  1989. // 1 zero 0 (6 bits)
  1990. // 2 zeroes 59
  1991. // 3 zeroes 60
  1992. // 4 zeroes 61
  1993. // 5 zeroes 62
  1994. // n zeroes (6 or more) 63 n-6 (6 + 8 bits)
  1995. //
  1996. const int SHORT_ZEROCODE_RUN = 59;
  1997. const int LONG_ZEROCODE_RUN = 63;
  1998. const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
  1999. const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;
  2000. static void hufPackEncTable(
  2001. const long long *hcode, // i : encoding table [HUF_ENCSIZE]
  2002. int im, // i : min hcode index
  2003. int iM, // i : max hcode index
  2004. char **pcode) // o: ptr to packed table (updated)
  2005. {
  2006. char *p = *pcode;
  2007. long long c = 0;
  2008. int lc = 0;
  2009. for (; im <= iM; im++) {
  2010. int l = hufLength(hcode[im]);
  2011. if (l == 0) {
  2012. int zerun = 1;
  2013. while ((im < iM) && (zerun < LONGEST_LONG_RUN)) {
  2014. if (hufLength(hcode[im + 1]) > 0) break;
  2015. im++;
  2016. zerun++;
  2017. }
  2018. if (zerun >= 2) {
  2019. if (zerun >= SHORTEST_LONG_RUN) {
  2020. outputBits(6, LONG_ZEROCODE_RUN, c, lc, p);
  2021. outputBits(8, zerun - SHORTEST_LONG_RUN, c, lc, p);
  2022. } else {
  2023. outputBits(6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p);
  2024. }
  2025. continue;
  2026. }
  2027. }
  2028. outputBits(6, l, c, lc, p);
  2029. }
  2030. if (lc > 0) *p++ = (unsigned char)(c << (8 - lc));
  2031. *pcode = p;
  2032. }
  2033. //
  2034. // Unpack an encoding table packed by hufPackEncTable():
  2035. //
  2036. static bool hufUnpackEncTable(
  2037. const char **pcode, // io: ptr to packed table (updated)
  2038. int ni, // i : input size (in bytes)
  2039. int im, // i : min hcode index
  2040. int iM, // i : max hcode index
  2041. long long *hcode) // o: encoding table [HUF_ENCSIZE]
  2042. {
  2043. memset(hcode, 0, sizeof(long long) * HUF_ENCSIZE);
  2044. const char *p = *pcode;
  2045. long long c = 0;
  2046. int lc = 0;
  2047. for (; im <= iM; im++) {
  2048. if (p - *pcode >= ni) {
  2049. return false;
  2050. }
  2051. long long l = hcode[im] = getBits(6, c, lc, p); // code length
  2052. if (l == (long long)LONG_ZEROCODE_RUN) {
  2053. if (p - *pcode > ni) {
  2054. return false;
  2055. }
  2056. int zerun = getBits(8, c, lc, p) + SHORTEST_LONG_RUN;
  2057. if (im + zerun > iM + 1) {
  2058. return false;
  2059. }
  2060. while (zerun--) hcode[im++] = 0;
  2061. im--;
  2062. } else if (l >= (long long)SHORT_ZEROCODE_RUN) {
  2063. int zerun = l - SHORT_ZEROCODE_RUN + 2;
  2064. if (im + zerun > iM + 1) {
  2065. return false;
  2066. }
  2067. while (zerun--) hcode[im++] = 0;
  2068. im--;
  2069. }
  2070. }
  2071. *pcode = const_cast<char *>(p);
  2072. hufCanonicalCodeTable(hcode);
  2073. return true;
  2074. }
  2075. //
  2076. // DECODING TABLE BUILDING
  2077. //
  2078. //
  2079. // Clear a newly allocated decoding table so that it contains only zeroes.
  2080. //
  2081. static void hufClearDecTable(HufDec *hdecod) // io: (allocated by caller)
  2082. // decoding table [HUF_DECSIZE]
  2083. {
  2084. for (int i = 0; i < HUF_DECSIZE; i++) {
  2085. hdecod[i].len = 0;
  2086. hdecod[i].lit = 0;
  2087. hdecod[i].p = NULL;
  2088. }
  2089. // memset(hdecod, 0, sizeof(HufDec) * HUF_DECSIZE);
  2090. }
  2091. //
  2092. // Build a decoding hash table based on the encoding table hcode:
  2093. // - short codes (<= HUF_DECBITS) are resolved with a single table access;
  2094. // - long code entry allocations are not optimized, because long codes are
  2095. // unfrequent;
  2096. // - decoding tables are used by hufDecode();
  2097. //
  2098. static bool hufBuildDecTable(const long long *hcode, // i : encoding table
  2099. int im, // i : min index in hcode
  2100. int iM, // i : max index in hcode
  2101. HufDec *hdecod) // o: (allocated by caller)
  2102. // decoding table [HUF_DECSIZE]
  2103. {
  2104. //
  2105. // Init hashtable & loop on all codes.
  2106. // Assumes that hufClearDecTable(hdecod) has already been called.
  2107. //
  2108. for (; im <= iM; im++) {
  2109. long long c = hufCode(hcode[im]);
  2110. int l = hufLength(hcode[im]);
  2111. if (c >> l) {
  2112. //
  2113. // Error: c is supposed to be an l-bit code,
  2114. // but c contains a value that is greater
  2115. // than the largest l-bit number.
  2116. //
  2117. // invalidTableEntry();
  2118. return false;
  2119. }
  2120. if (l > HUF_DECBITS) {
  2121. //
  2122. // Long code: add a secondary entry
  2123. //
  2124. HufDec *pl = hdecod + (c >> (l - HUF_DECBITS));
  2125. if (pl->len) {
  2126. //
  2127. // Error: a short code has already
  2128. // been stored in table entry *pl.
  2129. //
  2130. // invalidTableEntry();
  2131. return false;
  2132. }
  2133. pl->lit++;
  2134. if (pl->p) {
  2135. unsigned int *p = pl->p;
  2136. pl->p = new unsigned int[pl->lit];
  2137. for (unsigned int i = 0; i < pl->lit - 1u; ++i) pl->p[i] = p[i];
  2138. delete[] p;
  2139. } else {
  2140. pl->p = new unsigned int[1];
  2141. }
  2142. pl->p[pl->lit - 1] = im;
  2143. } else if (l) {
  2144. //
  2145. // Short code: init all primary entries
  2146. //
  2147. HufDec *pl = hdecod + (c << (HUF_DECBITS - l));
  2148. for (long long i = 1ULL << (HUF_DECBITS - l); i > 0; i--, pl++) {
  2149. if (pl->len || pl->p) {
  2150. //
  2151. // Error: a short code or a long code has
  2152. // already been stored in table entry *pl.
  2153. //
  2154. // invalidTableEntry();
  2155. return false;
  2156. }
  2157. pl->len = l;
  2158. pl->lit = im;
  2159. }
  2160. }
  2161. }
  2162. return true;
  2163. }
  2164. //
  2165. // Free the long code entries of a decoding table built by hufBuildDecTable()
  2166. //
  2167. static void hufFreeDecTable(HufDec *hdecod) // io: Decoding table
  2168. {
  2169. for (int i = 0; i < HUF_DECSIZE; i++) {
  2170. if (hdecod[i].p) {
  2171. delete[] hdecod[i].p;
  2172. hdecod[i].p = 0;
  2173. }
  2174. }
  2175. }
  2176. //
  2177. // ENCODING
  2178. //
  2179. inline void outputCode(long long code, long long &c, int &lc, char *&out) {
  2180. outputBits(hufLength(code), hufCode(code), c, lc, out);
  2181. }
  2182. inline void sendCode(long long sCode, int runCount, long long runCode,
  2183. long long &c, int &lc, char *&out) {
  2184. //
  2185. // Output a run of runCount instances of the symbol sCount.
  2186. // Output the symbols explicitly, or if that is shorter, output
  2187. // the sCode symbol once followed by a runCode symbol and runCount
  2188. // expressed as an 8-bit number.
  2189. //
  2190. if (hufLength(sCode) + hufLength(runCode) + 8 < hufLength(sCode) * runCount) {
  2191. outputCode(sCode, c, lc, out);
  2192. outputCode(runCode, c, lc, out);
  2193. outputBits(8, runCount, c, lc, out);
  2194. } else {
  2195. while (runCount-- >= 0) outputCode(sCode, c, lc, out);
  2196. }
  2197. }
  2198. //
  2199. // Encode (compress) ni values based on the Huffman encoding table hcode:
  2200. //
  2201. static int hufEncode // return: output size (in bits)
  2202. (const long long *hcode, // i : encoding table
  2203. const unsigned short *in, // i : uncompressed input buffer
  2204. const int ni, // i : input buffer size (in bytes)
  2205. int rlc, // i : rl code
  2206. char *out) // o: compressed output buffer
  2207. {
  2208. char *outStart = out;
  2209. long long c = 0; // bits not yet written to out
  2210. int lc = 0; // number of valid bits in c (LSB)
  2211. int s = in[0];
  2212. int cs = 0;
  2213. //
  2214. // Loop on input values
  2215. //
  2216. for (int i = 1; i < ni; i++) {
  2217. //
  2218. // Count same values or send code
  2219. //
  2220. if (s == in[i] && cs < 255) {
  2221. cs++;
  2222. } else {
  2223. sendCode(hcode[s], cs, hcode[rlc], c, lc, out);
  2224. cs = 0;
  2225. }
  2226. s = in[i];
  2227. }
  2228. //
  2229. // Send remaining code
  2230. //
  2231. sendCode(hcode[s], cs, hcode[rlc], c, lc, out);
  2232. if (lc) *out = (c << (8 - lc)) & 0xff;
  2233. return (out - outStart) * 8 + lc;
  2234. }
  2235. //
  2236. // DECODING
  2237. //
  2238. //
  2239. // In order to force the compiler to inline them,
  2240. // getChar() and getCode() are implemented as macros
  2241. // instead of "inline" functions.
  2242. //
  2243. #define getChar(c, lc, in) \
  2244. { \
  2245. c = (c << 8) | *(unsigned char *)(in++); \
  2246. lc += 8; \
  2247. }
  2248. #if 0
  2249. #define getCode(po, rlc, c, lc, in, out, ob, oe) \
  2250. { \
  2251. if (po == rlc) { \
  2252. if (lc < 8) getChar(c, lc, in); \
  2253. \
  2254. lc -= 8; \
  2255. \
  2256. unsigned char cs = (c >> lc); \
  2257. \
  2258. if (out + cs > oe) return false; \
  2259. \
  2260. /* TinyEXR issue 78 */ \
  2261. unsigned short s = out[-1]; \
  2262. \
  2263. while (cs-- > 0) *out++ = s; \
  2264. } else if (out < oe) { \
  2265. *out++ = po; \
  2266. } else { \
  2267. return false; \
  2268. } \
  2269. }
  2270. #else
  2271. static bool getCode(int po, int rlc, long long &c, int &lc, const char *&in,
  2272. const char *in_end, unsigned short *&out,
  2273. const unsigned short *ob, const unsigned short *oe) {
  2274. (void)ob;
  2275. if (po == rlc) {
  2276. if (lc < 8) {
  2277. /* TinyEXR issue 78 */
  2278. /* TinyEXR issue 160. in + 1 -> in */
  2279. if (in >= in_end) {
  2280. return false;
  2281. }
  2282. getChar(c, lc, in);
  2283. }
  2284. lc -= 8;
  2285. unsigned char cs = (c >> lc);
  2286. if (out + cs > oe) return false;
  2287. // Bounds check for safety
  2288. // Issue 100.
  2289. if ((out - 1) < ob) return false;
  2290. unsigned short s = out[-1];
  2291. while (cs-- > 0) *out++ = s;
  2292. } else if (out < oe) {
  2293. *out++ = po;
  2294. } else {
  2295. return false;
  2296. }
  2297. return true;
  2298. }
  2299. #endif
  2300. //
  2301. // Decode (uncompress) ni bits based on encoding & decoding tables:
  2302. //
  2303. static bool hufDecode(const long long *hcode, // i : encoding table
  2304. const HufDec *hdecod, // i : decoding table
  2305. const char *in, // i : compressed input buffer
  2306. int ni, // i : input size (in bits)
  2307. int rlc, // i : run-length code
  2308. int no, // i : expected output size (in bytes)
  2309. unsigned short *out) // o: uncompressed output buffer
  2310. {
  2311. long long c = 0;
  2312. int lc = 0;
  2313. unsigned short *outb = out; // begin
  2314. unsigned short *oe = out + no; // end
  2315. const char *ie = in + (ni + 7) / 8; // input byte size
  2316. //
  2317. // Loop on input bytes
  2318. //
  2319. while (in < ie) {
  2320. getChar(c, lc, in);
  2321. //
  2322. // Access decoding table
  2323. //
  2324. while (lc >= HUF_DECBITS) {
  2325. const HufDec pl = hdecod[(c >> (lc - HUF_DECBITS)) & HUF_DECMASK];
  2326. if (pl.len) {
  2327. //
  2328. // Get short code
  2329. //
  2330. lc -= pl.len;
  2331. // std::cout << "lit = " << pl.lit << std::endl;
  2332. // std::cout << "rlc = " << rlc << std::endl;
  2333. // std::cout << "c = " << c << std::endl;
  2334. // std::cout << "lc = " << lc << std::endl;
  2335. // std::cout << "in = " << in << std::endl;
  2336. // std::cout << "out = " << out << std::endl;
  2337. // std::cout << "oe = " << oe << std::endl;
  2338. if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) {
  2339. return false;
  2340. }
  2341. } else {
  2342. if (!pl.p) {
  2343. return false;
  2344. }
  2345. // invalidCode(); // wrong code
  2346. //
  2347. // Search long code
  2348. //
  2349. unsigned int j;
  2350. for (j = 0; j < pl.lit; j++) {
  2351. int l = hufLength(hcode[pl.p[j]]);
  2352. while (lc < l && in < ie) // get more bits
  2353. getChar(c, lc, in);
  2354. if (lc >= l) {
  2355. if (hufCode(hcode[pl.p[j]]) ==
  2356. ((c >> (lc - l)) & (((long long)(1) << l) - 1))) {
  2357. //
  2358. // Found : get long code
  2359. //
  2360. lc -= l;
  2361. if (!getCode(pl.p[j], rlc, c, lc, in, ie, out, outb, oe)) {
  2362. return false;
  2363. }
  2364. break;
  2365. }
  2366. }
  2367. }
  2368. if (j == pl.lit) {
  2369. return false;
  2370. // invalidCode(); // Not found
  2371. }
  2372. }
  2373. }
  2374. }
  2375. //
  2376. // Get remaining (short) codes
  2377. //
  2378. int i = (8 - ni) & 7;
  2379. c >>= i;
  2380. lc -= i;
  2381. while (lc > 0) {
  2382. const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK];
  2383. if (pl.len) {
  2384. lc -= pl.len;
  2385. if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) {
  2386. return false;
  2387. }
  2388. } else {
  2389. return false;
  2390. // invalidCode(); // wrong (long) code
  2391. }
  2392. }
  2393. if (out - outb != no) {
  2394. return false;
  2395. }
  2396. // notEnoughData ();
  2397. return true;
  2398. }
  2399. static void countFrequencies(std::vector<long long> &freq,
  2400. const unsigned short data[/*n*/], int n) {
  2401. for (int i = 0; i < HUF_ENCSIZE; ++i) freq[i] = 0;
  2402. for (int i = 0; i < n; ++i) ++freq[data[i]];
  2403. }
  2404. static void writeUInt(char buf[4], unsigned int i) {
  2405. unsigned char *b = (unsigned char *)buf;
  2406. b[0] = i;
  2407. b[1] = i >> 8;
  2408. b[2] = i >> 16;
  2409. b[3] = i >> 24;
  2410. }
  2411. static unsigned int readUInt(const char buf[4]) {
  2412. const unsigned char *b = (const unsigned char *)buf;
  2413. return (b[0] & 0x000000ff) | ((b[1] << 8) & 0x0000ff00) |
  2414. ((b[2] << 16) & 0x00ff0000) | ((b[3] << 24) & 0xff000000);
  2415. }
  2416. //
  2417. // EXTERNAL INTERFACE
  2418. //
  2419. static int hufCompress(const unsigned short raw[], int nRaw,
  2420. char compressed[]) {
  2421. if (nRaw == 0) return 0;
  2422. std::vector<long long> freq(HUF_ENCSIZE);
  2423. countFrequencies(freq, raw, nRaw);
  2424. int im = 0;
  2425. int iM = 0;
  2426. hufBuildEncTable(freq.data(), &im, &iM);
  2427. char *tableStart = compressed + 20;
  2428. char *tableEnd = tableStart;
  2429. hufPackEncTable(freq.data(), im, iM, &tableEnd);
  2430. int tableLength = tableEnd - tableStart;
  2431. char *dataStart = tableEnd;
  2432. int nBits = hufEncode(freq.data(), raw, nRaw, iM, dataStart);
  2433. int data_length = (nBits + 7) / 8;
  2434. writeUInt(compressed, im);
  2435. writeUInt(compressed + 4, iM);
  2436. writeUInt(compressed + 8, tableLength);
  2437. writeUInt(compressed + 12, nBits);
  2438. writeUInt(compressed + 16, 0); // room for future extensions
  2439. return dataStart + data_length - compressed;
  2440. }
  2441. static bool hufUncompress(const char compressed[], int nCompressed,
  2442. std::vector<unsigned short> *raw) {
  2443. if (nCompressed == 0) {
  2444. if (raw->size() != 0) return false;
  2445. return false;
  2446. }
  2447. int im = readUInt(compressed);
  2448. int iM = readUInt(compressed + 4);
  2449. // int tableLength = readUInt (compressed + 8);
  2450. int nBits = readUInt(compressed + 12);
  2451. if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) return false;
  2452. const char *ptr = compressed + 20;
  2453. //
  2454. // Fast decoder needs at least 2x64-bits of compressed data, and
  2455. // needs to be run-able on this platform. Otherwise, fall back
  2456. // to the original decoder
  2457. //
  2458. // if (FastHufDecoder::enabled() && nBits > 128)
  2459. //{
  2460. // FastHufDecoder fhd (ptr, nCompressed - (ptr - compressed), im, iM, iM);
  2461. // fhd.decode ((unsigned char*)ptr, nBits, raw, nRaw);
  2462. //}
  2463. // else
  2464. {
  2465. std::vector<long long> freq(HUF_ENCSIZE);
  2466. std::vector<HufDec> hdec(HUF_DECSIZE);
  2467. hufClearDecTable(&hdec.at(0));
  2468. hufUnpackEncTable(&ptr, nCompressed - (ptr - compressed), im, iM,
  2469. &freq.at(0));
  2470. {
  2471. if (nBits > 8 * (nCompressed - (ptr - compressed))) {
  2472. return false;
  2473. }
  2474. hufBuildDecTable(&freq.at(0), im, iM, &hdec.at(0));
  2475. hufDecode(&freq.at(0), &hdec.at(0), ptr, nBits, iM, raw->size(),
  2476. raw->data());
  2477. }
  2478. // catch (...)
  2479. //{
  2480. // hufFreeDecTable (hdec);
  2481. // throw;
  2482. //}
  2483. hufFreeDecTable(&hdec.at(0));
  2484. }
  2485. return true;
  2486. }
  2487. //
  2488. // Functions to compress the range of values in the pixel data
  2489. //
  2490. const int USHORT_RANGE = (1 << 16);
  2491. const int BITMAP_SIZE = (USHORT_RANGE >> 3);
  2492. static void bitmapFromData(const unsigned short data[/*nData*/], int nData,
  2493. unsigned char bitmap[BITMAP_SIZE],
  2494. unsigned short &minNonZero,
  2495. unsigned short &maxNonZero) {
  2496. for (int i = 0; i < BITMAP_SIZE; ++i) bitmap[i] = 0;
  2497. for (int i = 0; i < nData; ++i) bitmap[data[i] >> 3] |= (1 << (data[i] & 7));
  2498. bitmap[0] &= ~1; // zero is not explicitly stored in
  2499. // the bitmap; we assume that the
  2500. // data always contain zeroes
  2501. minNonZero = BITMAP_SIZE - 1;
  2502. maxNonZero = 0;
  2503. for (int i = 0; i < BITMAP_SIZE; ++i) {
  2504. if (bitmap[i]) {
  2505. if (minNonZero > i) minNonZero = i;
  2506. if (maxNonZero < i) maxNonZero = i;
  2507. }
  2508. }
  2509. }
  2510. static unsigned short forwardLutFromBitmap(
  2511. const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) {
  2512. int k = 0;
  2513. for (int i = 0; i < USHORT_RANGE; ++i) {
  2514. if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))))
  2515. lut[i] = k++;
  2516. else
  2517. lut[i] = 0;
  2518. }
  2519. return k - 1; // maximum value stored in lut[],
  2520. } // i.e. number of ones in bitmap minus 1
  2521. static unsigned short reverseLutFromBitmap(
  2522. const unsigned char bitmap[BITMAP_SIZE], unsigned short lut[USHORT_RANGE]) {
  2523. int k = 0;
  2524. for (int i = 0; i < USHORT_RANGE; ++i) {
  2525. if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) lut[k++] = i;
  2526. }
  2527. int n = k - 1;
  2528. while (k < USHORT_RANGE) lut[k++] = 0;
  2529. return n; // maximum k where lut[k] is non-zero,
  2530. } // i.e. number of ones in bitmap minus 1
  2531. static void applyLut(const unsigned short lut[USHORT_RANGE],
  2532. unsigned short data[/*nData*/], int nData) {
  2533. for (int i = 0; i < nData; ++i) data[i] = lut[data[i]];
  2534. }
  2535. #ifdef __clang__
  2536. #pragma clang diagnostic pop
  2537. #endif // __clang__
  2538. #ifdef _MSC_VER
  2539. #pragma warning(pop)
  2540. #endif
  2541. static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
  2542. const unsigned char *inPtr, size_t inSize,
  2543. const std::vector<ChannelInfo> &channelInfo,
  2544. int data_width, int num_lines) {
  2545. std::vector<unsigned char> bitmap(BITMAP_SIZE);
  2546. unsigned short minNonZero;
  2547. unsigned short maxNonZero;
  2548. #if !TINYEXR_LITTLE_ENDIAN
  2549. // @todo { PIZ compression on BigEndian architecture. }
  2550. return false;
  2551. #endif
  2552. // Assume `inSize` is multiple of 2 or 4.
  2553. std::vector<unsigned short> tmpBuffer(inSize / sizeof(unsigned short));
  2554. std::vector<PIZChannelData> channelData(channelInfo.size());
  2555. unsigned short *tmpBufferEnd = &tmpBuffer.at(0);
  2556. for (size_t c = 0; c < channelData.size(); c++) {
  2557. PIZChannelData &cd = channelData[c];
  2558. cd.start = tmpBufferEnd;
  2559. cd.end = cd.start;
  2560. cd.nx = data_width;
  2561. cd.ny = num_lines;
  2562. // cd.ys = c.channel().ySampling;
  2563. size_t pixelSize = sizeof(int); // UINT and FLOAT
  2564. if (channelInfo[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) {
  2565. pixelSize = sizeof(short);
  2566. }
  2567. cd.size = static_cast<int>(pixelSize / sizeof(short));
  2568. tmpBufferEnd += cd.nx * cd.ny * cd.size;
  2569. }
  2570. const unsigned char *ptr = inPtr;
  2571. for (int y = 0; y < num_lines; ++y) {
  2572. for (size_t i = 0; i < channelData.size(); ++i) {
  2573. PIZChannelData &cd = channelData[i];
  2574. // if (modp (y, cd.ys) != 0)
  2575. // continue;
  2576. size_t n = static_cast<size_t>(cd.nx * cd.size);
  2577. memcpy(cd.end, ptr, n * sizeof(unsigned short));
  2578. ptr += n * sizeof(unsigned short);
  2579. cd.end += n;
  2580. }
  2581. }
  2582. bitmapFromData(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()),
  2583. bitmap.data(), minNonZero, maxNonZero);
  2584. std::vector<unsigned short> lut(USHORT_RANGE);
  2585. unsigned short maxValue = forwardLutFromBitmap(bitmap.data(), lut.data());
  2586. applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()));
  2587. //
  2588. // Store range compression info in _outBuffer
  2589. //
  2590. char *buf = reinterpret_cast<char *>(outPtr);
  2591. memcpy(buf, &minNonZero, sizeof(unsigned short));
  2592. buf += sizeof(unsigned short);
  2593. memcpy(buf, &maxNonZero, sizeof(unsigned short));
  2594. buf += sizeof(unsigned short);
  2595. if (minNonZero <= maxNonZero) {
  2596. memcpy(buf, reinterpret_cast<char *>(&bitmap[0] + minNonZero),
  2597. maxNonZero - minNonZero + 1);
  2598. buf += maxNonZero - minNonZero + 1;
  2599. }
  2600. //
  2601. // Apply wavelet encoding
  2602. //
  2603. for (size_t i = 0; i < channelData.size(); ++i) {
  2604. PIZChannelData &cd = channelData[i];
  2605. for (int j = 0; j < cd.size; ++j) {
  2606. wav2Encode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size,
  2607. maxValue);
  2608. }
  2609. }
  2610. //
  2611. // Apply Huffman encoding; append the result to _outBuffer
  2612. //
  2613. // length header(4byte), then huff data. Initialize length header with zero,
  2614. // then later fill it by `length`.
  2615. char *lengthPtr = buf;
  2616. int zero = 0;
  2617. memcpy(buf, &zero, sizeof(int));
  2618. buf += sizeof(int);
  2619. int length =
  2620. hufCompress(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), buf);
  2621. memcpy(lengthPtr, &length, sizeof(int));
  2622. (*outSize) = static_cast<unsigned int>(
  2623. (reinterpret_cast<unsigned char *>(buf) - outPtr) +
  2624. static_cast<unsigned int>(length));
  2625. // Use uncompressed data when compressed data is larger than uncompressed.
  2626. // (Issue 40)
  2627. if ((*outSize) >= inSize) {
  2628. (*outSize) = static_cast<unsigned int>(inSize);
  2629. memcpy(outPtr, inPtr, inSize);
  2630. }
  2631. return true;
  2632. }
  2633. static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr,
  2634. size_t tmpBufSizeInBytes, size_t inLen, int num_channels,
  2635. const EXRChannelInfo *channels, int data_width,
  2636. int num_lines) {
  2637. if (inLen == tmpBufSizeInBytes) {
  2638. // Data is not compressed(Issue 40).
  2639. memcpy(outPtr, inPtr, inLen);
  2640. return true;
  2641. }
  2642. std::vector<unsigned char> bitmap(BITMAP_SIZE);
  2643. unsigned short minNonZero;
  2644. unsigned short maxNonZero;
  2645. #if !TINYEXR_LITTLE_ENDIAN
  2646. // @todo { PIZ compression on BigEndian architecture. }
  2647. return false;
  2648. #endif
  2649. memset(bitmap.data(), 0, BITMAP_SIZE);
  2650. if (inLen < 4) {
  2651. return false;
  2652. }
  2653. size_t readLen = 0;
  2654. const unsigned char *ptr = inPtr;
  2655. // minNonZero = *(reinterpret_cast<const unsigned short *>(ptr));
  2656. tinyexr::cpy2(&minNonZero, reinterpret_cast<const unsigned short *>(ptr));
  2657. // maxNonZero = *(reinterpret_cast<const unsigned short *>(ptr + 2));
  2658. tinyexr::cpy2(&maxNonZero, reinterpret_cast<const unsigned short *>(ptr + 2));
  2659. ptr += 4;
  2660. readLen += 4;
  2661. if (maxNonZero >= BITMAP_SIZE) {
  2662. return false;
  2663. }
  2664. //printf("maxNonZero = %d\n", maxNonZero);
  2665. //printf("minNonZero = %d\n", minNonZero);
  2666. //printf("len = %d\n", (maxNonZero - minNonZero + 1));
  2667. //printf("BITMAPSIZE - min = %d\n", (BITMAP_SIZE - minNonZero));
  2668. if (minNonZero <= maxNonZero) {
  2669. if (((maxNonZero - minNonZero + 1) + readLen) > inLen) {
  2670. // Input too short
  2671. return false;
  2672. }
  2673. memcpy(reinterpret_cast<char *>(&bitmap[0] + minNonZero), ptr,
  2674. maxNonZero - minNonZero + 1);
  2675. ptr += maxNonZero - minNonZero + 1;
  2676. readLen += maxNonZero - minNonZero + 1;
  2677. } else {
  2678. // Issue 194
  2679. if ((minNonZero == (BITMAP_SIZE - 1)) && (maxNonZero == 0)) {
  2680. // OK. all pixels are zero. And no need to read `bitmap` data.
  2681. } else {
  2682. // invalid minNonZero/maxNonZero combination.
  2683. return false;
  2684. }
  2685. }
  2686. std::vector<unsigned short> lut(USHORT_RANGE);
  2687. memset(lut.data(), 0, sizeof(unsigned short) * USHORT_RANGE);
  2688. unsigned short maxValue = reverseLutFromBitmap(bitmap.data(), lut.data());
  2689. //
  2690. // Huffman decoding
  2691. //
  2692. if ((readLen + 4) > inLen) {
  2693. return false;
  2694. }
  2695. int length=0;
  2696. // length = *(reinterpret_cast<const int *>(ptr));
  2697. tinyexr::cpy4(&length, reinterpret_cast<const int *>(ptr));
  2698. ptr += sizeof(int);
  2699. if (size_t((ptr - inPtr) + length) > inLen) {
  2700. return false;
  2701. }
  2702. std::vector<unsigned short> tmpBuffer(tmpBufSizeInBytes / sizeof(unsigned short));
  2703. hufUncompress(reinterpret_cast<const char *>(ptr), length, &tmpBuffer);
  2704. //
  2705. // Wavelet decoding
  2706. //
  2707. std::vector<PIZChannelData> channelData(static_cast<size_t>(num_channels));
  2708. unsigned short *tmpBufferEnd = &tmpBuffer.at(0);
  2709. for (size_t i = 0; i < static_cast<size_t>(num_channels); ++i) {
  2710. const EXRChannelInfo &chan = channels[i];
  2711. size_t pixelSize = sizeof(int); // UINT and FLOAT
  2712. if (chan.pixel_type == TINYEXR_PIXELTYPE_HALF) {
  2713. pixelSize = sizeof(short);
  2714. }
  2715. channelData[i].start = tmpBufferEnd;
  2716. channelData[i].end = channelData[i].start;
  2717. channelData[i].nx = data_width;
  2718. channelData[i].ny = num_lines;
  2719. // channelData[i].ys = 1;
  2720. channelData[i].size = static_cast<int>(pixelSize / sizeof(short));
  2721. tmpBufferEnd += channelData[i].nx * channelData[i].ny * channelData[i].size;
  2722. }
  2723. for (size_t i = 0; i < channelData.size(); ++i) {
  2724. PIZChannelData &cd = channelData[i];
  2725. for (int j = 0; j < cd.size; ++j) {
  2726. wav2Decode(cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size,
  2727. maxValue);
  2728. }
  2729. }
  2730. //
  2731. // Expand the pixel data to their original range
  2732. //
  2733. applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBufSizeInBytes / sizeof(unsigned short)));
  2734. for (int y = 0; y < num_lines; y++) {
  2735. for (size_t i = 0; i < channelData.size(); ++i) {
  2736. PIZChannelData &cd = channelData[i];
  2737. // if (modp (y, cd.ys) != 0)
  2738. // continue;
  2739. size_t n = static_cast<size_t>(cd.nx * cd.size);
  2740. memcpy(outPtr, cd.end, static_cast<size_t>(n * sizeof(unsigned short)));
  2741. outPtr += n * sizeof(unsigned short);
  2742. cd.end += n;
  2743. }
  2744. }
  2745. return true;
  2746. }
  2747. #endif // TINYEXR_USE_PIZ
  2748. #if TINYEXR_USE_ZFP
  2749. struct ZFPCompressionParam {
  2750. double rate;
  2751. unsigned int precision;
  2752. unsigned int __pad0;
  2753. double tolerance;
  2754. int type; // TINYEXR_ZFP_COMPRESSIONTYPE_*
  2755. unsigned int __pad1;
  2756. ZFPCompressionParam() {
  2757. type = TINYEXR_ZFP_COMPRESSIONTYPE_RATE;
  2758. rate = 2.0;
  2759. precision = 0;
  2760. tolerance = 0.0;
  2761. }
  2762. };
  2763. static bool FindZFPCompressionParam(ZFPCompressionParam *param,
  2764. const EXRAttribute *attributes,
  2765. int num_attributes, std::string *err) {
  2766. bool foundType = false;
  2767. for (int i = 0; i < num_attributes; i++) {
  2768. if ((strcmp(attributes[i].name, "zfpCompressionType") == 0)) {
  2769. if (attributes[i].size == 1) {
  2770. param->type = static_cast<int>(attributes[i].value[0]);
  2771. foundType = true;
  2772. break;
  2773. } else {
  2774. if (err) {
  2775. (*err) +=
  2776. "zfpCompressionType attribute must be uchar(1 byte) type.\n";
  2777. }
  2778. return false;
  2779. }
  2780. }
  2781. }
  2782. if (!foundType) {
  2783. if (err) {
  2784. (*err) += "`zfpCompressionType` attribute not found.\n";
  2785. }
  2786. return false;
  2787. }
  2788. if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
  2789. for (int i = 0; i < num_attributes; i++) {
  2790. if ((strcmp(attributes[i].name, "zfpCompressionRate") == 0) &&
  2791. (attributes[i].size == 8)) {
  2792. param->rate = *(reinterpret_cast<double *>(attributes[i].value));
  2793. return true;
  2794. }
  2795. }
  2796. if (err) {
  2797. (*err) += "`zfpCompressionRate` attribute not found.\n";
  2798. }
  2799. } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
  2800. for (int i = 0; i < num_attributes; i++) {
  2801. if ((strcmp(attributes[i].name, "zfpCompressionPrecision") == 0) &&
  2802. (attributes[i].size == 4)) {
  2803. param->rate = *(reinterpret_cast<int *>(attributes[i].value));
  2804. return true;
  2805. }
  2806. }
  2807. if (err) {
  2808. (*err) += "`zfpCompressionPrecision` attribute not found.\n";
  2809. }
  2810. } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
  2811. for (int i = 0; i < num_attributes; i++) {
  2812. if ((strcmp(attributes[i].name, "zfpCompressionTolerance") == 0) &&
  2813. (attributes[i].size == 8)) {
  2814. param->tolerance = *(reinterpret_cast<double *>(attributes[i].value));
  2815. return true;
  2816. }
  2817. }
  2818. if (err) {
  2819. (*err) += "`zfpCompressionTolerance` attribute not found.\n";
  2820. }
  2821. } else {
  2822. if (err) {
  2823. (*err) += "Unknown value specified for `zfpCompressionType`.\n";
  2824. }
  2825. }
  2826. return false;
  2827. }
  2828. // Assume pixel format is FLOAT for all channels.
  2829. static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines,
  2830. size_t num_channels, const unsigned char *src,
  2831. unsigned long src_size,
  2832. const ZFPCompressionParam &param) {
  2833. size_t uncompressed_size =
  2834. size_t(dst_width) * size_t(dst_num_lines) * num_channels;
  2835. if (uncompressed_size == src_size) {
  2836. // Data is not compressed(Issue 40).
  2837. memcpy(dst, src, src_size);
  2838. }
  2839. zfp_stream *zfp = NULL;
  2840. zfp_field *field = NULL;
  2841. TINYEXR_CHECK_AND_RETURN_C((dst_width % 4) == 0, false);
  2842. TINYEXR_CHECK_AND_RETURN_C((dst_num_lines % 4) == 0, false);
  2843. if ((size_t(dst_width) & 3U) || (size_t(dst_num_lines) & 3U)) {
  2844. return false;
  2845. }
  2846. field =
  2847. zfp_field_2d(reinterpret_cast<void *>(const_cast<unsigned char *>(src)),
  2848. zfp_type_float, static_cast<unsigned int>(dst_width),
  2849. static_cast<unsigned int>(dst_num_lines) *
  2850. static_cast<unsigned int>(num_channels));
  2851. zfp = zfp_stream_open(NULL);
  2852. if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
  2853. zfp_stream_set_rate(zfp, param.rate, zfp_type_float, /* dimension */ 2,
  2854. /* write random access */ 0);
  2855. } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
  2856. zfp_stream_set_precision(zfp, param.precision);
  2857. } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
  2858. zfp_stream_set_accuracy(zfp, param.tolerance);
  2859. } else {
  2860. return false;
  2861. }
  2862. size_t buf_size = zfp_stream_maximum_size(zfp, field);
  2863. std::vector<unsigned char> buf(buf_size);
  2864. memcpy(&buf.at(0), src, src_size);
  2865. bitstream *stream = stream_open(&buf.at(0), buf_size);
  2866. zfp_stream_set_bit_stream(zfp, stream);
  2867. zfp_stream_rewind(zfp);
  2868. size_t image_size = size_t(dst_width) * size_t(dst_num_lines);
  2869. for (size_t c = 0; c < size_t(num_channels); c++) {
  2870. // decompress 4x4 pixel block.
  2871. for (size_t y = 0; y < size_t(dst_num_lines); y += 4) {
  2872. for (size_t x = 0; x < size_t(dst_width); x += 4) {
  2873. float fblock[16];
  2874. zfp_decode_block_float_2(zfp, fblock);
  2875. for (size_t j = 0; j < 4; j++) {
  2876. for (size_t i = 0; i < 4; i++) {
  2877. dst[c * image_size + ((y + j) * size_t(dst_width) + (x + i))] =
  2878. fblock[j * 4 + i];
  2879. }
  2880. }
  2881. }
  2882. }
  2883. }
  2884. zfp_field_free(field);
  2885. zfp_stream_close(zfp);
  2886. stream_close(stream);
  2887. return true;
  2888. }
  2889. // Assume pixel format is FLOAT for all channels.
  2890. static bool CompressZfp(std::vector<unsigned char> *outBuf,
  2891. unsigned int *outSize, const float *inPtr, int width,
  2892. int num_lines, int num_channels,
  2893. const ZFPCompressionParam &param) {
  2894. zfp_stream *zfp = NULL;
  2895. zfp_field *field = NULL;
  2896. TINYEXR_CHECK_AND_RETURN_C((width % 4) == 0, false);
  2897. TINYEXR_CHECK_AND_RETURN_C((num_lines % 4) == 0, false);
  2898. if ((size_t(width) & 3U) || (size_t(num_lines) & 3U)) {
  2899. return false;
  2900. }
  2901. // create input array.
  2902. field = zfp_field_2d(reinterpret_cast<void *>(const_cast<float *>(inPtr)),
  2903. zfp_type_float, static_cast<unsigned int>(width),
  2904. static_cast<unsigned int>(num_lines * num_channels));
  2905. zfp = zfp_stream_open(NULL);
  2906. if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) {
  2907. zfp_stream_set_rate(zfp, param.rate, zfp_type_float, 2, 0);
  2908. } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) {
  2909. zfp_stream_set_precision(zfp, param.precision);
  2910. } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) {
  2911. zfp_stream_set_accuracy(zfp, param.tolerance);
  2912. } else {
  2913. return false;
  2914. }
  2915. size_t buf_size = zfp_stream_maximum_size(zfp, field);
  2916. outBuf->resize(buf_size);
  2917. bitstream *stream = stream_open(&outBuf->at(0), buf_size);
  2918. zfp_stream_set_bit_stream(zfp, stream);
  2919. zfp_field_free(field);
  2920. size_t image_size = size_t(width) * size_t(num_lines);
  2921. for (size_t c = 0; c < size_t(num_channels); c++) {
  2922. // compress 4x4 pixel block.
  2923. for (size_t y = 0; y < size_t(num_lines); y += 4) {
  2924. for (size_t x = 0; x < size_t(width); x += 4) {
  2925. float fblock[16];
  2926. for (size_t j = 0; j < 4; j++) {
  2927. for (size_t i = 0; i < 4; i++) {
  2928. fblock[j * 4 + i] =
  2929. inPtr[c * image_size + ((y + j) * size_t(width) + (x + i))];
  2930. }
  2931. }
  2932. zfp_encode_block_float_2(zfp, fblock);
  2933. }
  2934. }
  2935. }
  2936. zfp_stream_flush(zfp);
  2937. (*outSize) = static_cast<unsigned int>(zfp_stream_compressed_size(zfp));
  2938. zfp_stream_close(zfp);
  2939. return true;
  2940. }
  2941. #endif
  2942. //
  2943. // -----------------------------------------------------------------
  2944. //
  2945. // heuristics
  2946. #define TINYEXR_DIMENSION_THRESHOLD (1024 * 8192)
  2947. // TODO(syoyo): Refactor function arguments.
  2948. static bool DecodePixelData(/* out */ unsigned char **out_images,
  2949. const int *requested_pixel_types,
  2950. const unsigned char *data_ptr, size_t data_len,
  2951. int compression_type, int line_order, int width,
  2952. int height, int x_stride, int y, int line_no,
  2953. int num_lines, size_t pixel_data_size,
  2954. size_t num_attributes,
  2955. const EXRAttribute *attributes, size_t num_channels,
  2956. const EXRChannelInfo *channels,
  2957. const std::vector<size_t> &channel_offset_list) {
  2958. if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { // PIZ
  2959. #if TINYEXR_USE_PIZ
  2960. if ((width == 0) || (num_lines == 0) || (pixel_data_size == 0)) {
  2961. // Invalid input #90
  2962. return false;
  2963. }
  2964. // Allocate original data size.
  2965. std::vector<unsigned char> outBuf(static_cast<size_t>(
  2966. static_cast<size_t>(width * num_lines) * pixel_data_size));
  2967. size_t tmpBufLen = outBuf.size();
  2968. bool ret = tinyexr::DecompressPiz(
  2969. reinterpret_cast<unsigned char *>(&outBuf.at(0)), data_ptr, tmpBufLen,
  2970. data_len, static_cast<int>(num_channels), channels, width, num_lines);
  2971. if (!ret) {
  2972. return false;
  2973. }
  2974. // For PIZ_COMPRESSION:
  2975. // pixel sample data for channel 0 for scanline 0
  2976. // pixel sample data for channel 1 for scanline 0
  2977. // pixel sample data for channel ... for scanline 0
  2978. // pixel sample data for channel n for scanline 0
  2979. // pixel sample data for channel 0 for scanline 1
  2980. // pixel sample data for channel 1 for scanline 1
  2981. // pixel sample data for channel ... for scanline 1
  2982. // pixel sample data for channel n for scanline 1
  2983. // ...
  2984. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  2985. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  2986. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  2987. const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
  2988. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  2989. channel_offset_list[c] * static_cast<size_t>(width)));
  2990. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  2991. FP16 hf;
  2992. // hf.u = line_ptr[u];
  2993. // use `cpy` to avoid unaligned memory access when compiler's
  2994. // optimization is on.
  2995. tinyexr::cpy2(&(hf.u), line_ptr + u);
  2996. tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
  2997. if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
  2998. unsigned short *image =
  2999. reinterpret_cast<unsigned short **>(out_images)[c];
  3000. if (line_order == 0) {
  3001. image += (static_cast<size_t>(line_no) + v) *
  3002. static_cast<size_t>(x_stride) +
  3003. u;
  3004. } else {
  3005. image += static_cast<size_t>(
  3006. (height - 1 - (line_no + static_cast<int>(v)))) *
  3007. static_cast<size_t>(x_stride) +
  3008. u;
  3009. }
  3010. *image = hf.u;
  3011. } else { // HALF -> FLOAT
  3012. FP32 f32 = half_to_float(hf);
  3013. float *image = reinterpret_cast<float **>(out_images)[c];
  3014. size_t offset = 0;
  3015. if (line_order == 0) {
  3016. offset = (static_cast<size_t>(line_no) + v) *
  3017. static_cast<size_t>(x_stride) +
  3018. u;
  3019. } else {
  3020. offset = static_cast<size_t>(
  3021. (height - 1 - (line_no + static_cast<int>(v)))) *
  3022. static_cast<size_t>(x_stride) +
  3023. u;
  3024. }
  3025. image += offset;
  3026. *image = f32.f;
  3027. }
  3028. }
  3029. }
  3030. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  3031. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT, false);
  3032. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3033. const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
  3034. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  3035. channel_offset_list[c] * static_cast<size_t>(width)));
  3036. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3037. unsigned int val;
  3038. // val = line_ptr[u];
  3039. tinyexr::cpy4(&val, line_ptr + u);
  3040. tinyexr::swap4(&val);
  3041. unsigned int *image =
  3042. reinterpret_cast<unsigned int **>(out_images)[c];
  3043. if (line_order == 0) {
  3044. image += (static_cast<size_t>(line_no) + v) *
  3045. static_cast<size_t>(x_stride) +
  3046. u;
  3047. } else {
  3048. image += static_cast<size_t>(
  3049. (height - 1 - (line_no + static_cast<int>(v)))) *
  3050. static_cast<size_t>(x_stride) +
  3051. u;
  3052. }
  3053. *image = val;
  3054. }
  3055. }
  3056. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3057. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false);
  3058. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3059. const float *line_ptr = reinterpret_cast<float *>(&outBuf.at(
  3060. v * pixel_data_size * static_cast<size_t>(width) +
  3061. channel_offset_list[c] * static_cast<size_t>(width)));
  3062. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3063. float val;
  3064. // val = line_ptr[u];
  3065. tinyexr::cpy4(&val, line_ptr + u);
  3066. tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
  3067. float *image = reinterpret_cast<float **>(out_images)[c];
  3068. if (line_order == 0) {
  3069. image += (static_cast<size_t>(line_no) + v) *
  3070. static_cast<size_t>(x_stride) +
  3071. u;
  3072. } else {
  3073. image += static_cast<size_t>(
  3074. (height - 1 - (line_no + static_cast<int>(v)))) *
  3075. static_cast<size_t>(x_stride) +
  3076. u;
  3077. }
  3078. *image = val;
  3079. }
  3080. }
  3081. } else {
  3082. return false;
  3083. }
  3084. }
  3085. #else
  3086. return false;
  3087. #endif
  3088. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS ||
  3089. compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
  3090. // Allocate original data size.
  3091. std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
  3092. static_cast<size_t>(num_lines) *
  3093. pixel_data_size);
  3094. unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
  3095. TINYEXR_CHECK_AND_RETURN_C(dstLen > 0, false);
  3096. if (!tinyexr::DecompressZip(
  3097. reinterpret_cast<unsigned char *>(&outBuf.at(0)), &dstLen, data_ptr,
  3098. static_cast<unsigned long>(data_len))) {
  3099. return false;
  3100. }
  3101. // For ZIP_COMPRESSION:
  3102. // pixel sample data for channel 0 for scanline 0
  3103. // pixel sample data for channel 1 for scanline 0
  3104. // pixel sample data for channel ... for scanline 0
  3105. // pixel sample data for channel n for scanline 0
  3106. // pixel sample data for channel 0 for scanline 1
  3107. // pixel sample data for channel 1 for scanline 1
  3108. // pixel sample data for channel ... for scanline 1
  3109. // pixel sample data for channel n for scanline 1
  3110. // ...
  3111. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3112. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  3113. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3114. const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
  3115. &outBuf.at(v * static_cast<size_t>(pixel_data_size) *
  3116. static_cast<size_t>(width) +
  3117. channel_offset_list[c] * static_cast<size_t>(width)));
  3118. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3119. tinyexr::FP16 hf;
  3120. // hf.u = line_ptr[u];
  3121. tinyexr::cpy2(&(hf.u), line_ptr + u);
  3122. tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
  3123. if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
  3124. unsigned short *image =
  3125. reinterpret_cast<unsigned short **>(out_images)[c];
  3126. if (line_order == 0) {
  3127. image += (static_cast<size_t>(line_no) + v) *
  3128. static_cast<size_t>(x_stride) +
  3129. u;
  3130. } else {
  3131. image += (static_cast<size_t>(height) - 1U -
  3132. (static_cast<size_t>(line_no) + v)) *
  3133. static_cast<size_t>(x_stride) +
  3134. u;
  3135. }
  3136. *image = hf.u;
  3137. } else { // HALF -> FLOAT
  3138. tinyexr::FP32 f32 = half_to_float(hf);
  3139. float *image = reinterpret_cast<float **>(out_images)[c];
  3140. size_t offset = 0;
  3141. if (line_order == 0) {
  3142. offset = (static_cast<size_t>(line_no) + v) *
  3143. static_cast<size_t>(x_stride) +
  3144. u;
  3145. } else {
  3146. offset = (static_cast<size_t>(height) - 1U -
  3147. (static_cast<size_t>(line_no) + v)) *
  3148. static_cast<size_t>(x_stride) +
  3149. u;
  3150. }
  3151. image += offset;
  3152. *image = f32.f;
  3153. }
  3154. }
  3155. }
  3156. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  3157. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT, false);
  3158. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3159. const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
  3160. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  3161. channel_offset_list[c] * static_cast<size_t>(width)));
  3162. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3163. unsigned int val;
  3164. // val = line_ptr[u];
  3165. tinyexr::cpy4(&val, line_ptr + u);
  3166. tinyexr::swap4(&val);
  3167. unsigned int *image =
  3168. reinterpret_cast<unsigned int **>(out_images)[c];
  3169. if (line_order == 0) {
  3170. image += (static_cast<size_t>(line_no) + v) *
  3171. static_cast<size_t>(x_stride) +
  3172. u;
  3173. } else {
  3174. image += (static_cast<size_t>(height) - 1U -
  3175. (static_cast<size_t>(line_no) + v)) *
  3176. static_cast<size_t>(x_stride) +
  3177. u;
  3178. }
  3179. *image = val;
  3180. }
  3181. }
  3182. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3183. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false);
  3184. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3185. const float *line_ptr = reinterpret_cast<float *>(
  3186. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  3187. channel_offset_list[c] * static_cast<size_t>(width)));
  3188. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3189. float val;
  3190. // val = line_ptr[u];
  3191. tinyexr::cpy4(&val, line_ptr + u);
  3192. tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
  3193. float *image = reinterpret_cast<float **>(out_images)[c];
  3194. if (line_order == 0) {
  3195. image += (static_cast<size_t>(line_no) + v) *
  3196. static_cast<size_t>(x_stride) +
  3197. u;
  3198. } else {
  3199. image += (static_cast<size_t>(height) - 1U -
  3200. (static_cast<size_t>(line_no) + v)) *
  3201. static_cast<size_t>(x_stride) +
  3202. u;
  3203. }
  3204. *image = val;
  3205. }
  3206. }
  3207. } else {
  3208. return false;
  3209. }
  3210. }
  3211. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
  3212. // Allocate original data size.
  3213. std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
  3214. static_cast<size_t>(num_lines) *
  3215. pixel_data_size);
  3216. unsigned long dstLen = static_cast<unsigned long>(outBuf.size());
  3217. if (dstLen == 0) {
  3218. return false;
  3219. }
  3220. if (!tinyexr::DecompressRle(
  3221. reinterpret_cast<unsigned char *>(&outBuf.at(0)), dstLen, data_ptr,
  3222. static_cast<unsigned long>(data_len))) {
  3223. return false;
  3224. }
  3225. // For RLE_COMPRESSION:
  3226. // pixel sample data for channel 0 for scanline 0
  3227. // pixel sample data for channel 1 for scanline 0
  3228. // pixel sample data for channel ... for scanline 0
  3229. // pixel sample data for channel n for scanline 0
  3230. // pixel sample data for channel 0 for scanline 1
  3231. // pixel sample data for channel 1 for scanline 1
  3232. // pixel sample data for channel ... for scanline 1
  3233. // pixel sample data for channel n for scanline 1
  3234. // ...
  3235. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3236. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  3237. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3238. const unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
  3239. &outBuf.at(v * static_cast<size_t>(pixel_data_size) *
  3240. static_cast<size_t>(width) +
  3241. channel_offset_list[c] * static_cast<size_t>(width)));
  3242. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3243. tinyexr::FP16 hf;
  3244. // hf.u = line_ptr[u];
  3245. tinyexr::cpy2(&(hf.u), line_ptr + u);
  3246. tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
  3247. if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
  3248. unsigned short *image =
  3249. reinterpret_cast<unsigned short **>(out_images)[c];
  3250. if (line_order == 0) {
  3251. image += (static_cast<size_t>(line_no) + v) *
  3252. static_cast<size_t>(x_stride) +
  3253. u;
  3254. } else {
  3255. image += (static_cast<size_t>(height) - 1U -
  3256. (static_cast<size_t>(line_no) + v)) *
  3257. static_cast<size_t>(x_stride) +
  3258. u;
  3259. }
  3260. *image = hf.u;
  3261. } else { // HALF -> FLOAT
  3262. tinyexr::FP32 f32 = half_to_float(hf);
  3263. float *image = reinterpret_cast<float **>(out_images)[c];
  3264. if (line_order == 0) {
  3265. image += (static_cast<size_t>(line_no) + v) *
  3266. static_cast<size_t>(x_stride) +
  3267. u;
  3268. } else {
  3269. image += (static_cast<size_t>(height) - 1U -
  3270. (static_cast<size_t>(line_no) + v)) *
  3271. static_cast<size_t>(x_stride) +
  3272. u;
  3273. }
  3274. *image = f32.f;
  3275. }
  3276. }
  3277. }
  3278. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  3279. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_UINT, false);
  3280. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3281. const unsigned int *line_ptr = reinterpret_cast<unsigned int *>(
  3282. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  3283. channel_offset_list[c] * static_cast<size_t>(width)));
  3284. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3285. unsigned int val;
  3286. // val = line_ptr[u];
  3287. tinyexr::cpy4(&val, line_ptr + u);
  3288. tinyexr::swap4(&val);
  3289. unsigned int *image =
  3290. reinterpret_cast<unsigned int **>(out_images)[c];
  3291. if (line_order == 0) {
  3292. image += (static_cast<size_t>(line_no) + v) *
  3293. static_cast<size_t>(x_stride) +
  3294. u;
  3295. } else {
  3296. image += (static_cast<size_t>(height) - 1U -
  3297. (static_cast<size_t>(line_no) + v)) *
  3298. static_cast<size_t>(x_stride) +
  3299. u;
  3300. }
  3301. *image = val;
  3302. }
  3303. }
  3304. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3305. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false);
  3306. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3307. const float *line_ptr = reinterpret_cast<float *>(
  3308. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  3309. channel_offset_list[c] * static_cast<size_t>(width)));
  3310. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3311. float val;
  3312. // val = line_ptr[u];
  3313. tinyexr::cpy4(&val, line_ptr + u);
  3314. tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
  3315. float *image = reinterpret_cast<float **>(out_images)[c];
  3316. if (line_order == 0) {
  3317. image += (static_cast<size_t>(line_no) + v) *
  3318. static_cast<size_t>(x_stride) +
  3319. u;
  3320. } else {
  3321. image += (static_cast<size_t>(height) - 1U -
  3322. (static_cast<size_t>(line_no) + v)) *
  3323. static_cast<size_t>(x_stride) +
  3324. u;
  3325. }
  3326. *image = val;
  3327. }
  3328. }
  3329. } else {
  3330. return false;
  3331. }
  3332. }
  3333. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  3334. #if TINYEXR_USE_ZFP
  3335. tinyexr::ZFPCompressionParam zfp_compression_param;
  3336. std::string e;
  3337. if (!tinyexr::FindZFPCompressionParam(&zfp_compression_param, attributes,
  3338. int(num_attributes), &e)) {
  3339. // This code path should not be reachable.
  3340. return false;
  3341. }
  3342. // Allocate original data size.
  3343. std::vector<unsigned char> outBuf(static_cast<size_t>(width) *
  3344. static_cast<size_t>(num_lines) *
  3345. pixel_data_size);
  3346. unsigned long dstLen = outBuf.size();
  3347. TINYEXR_CHECK_AND_RETURN_C(dstLen > 0, false);
  3348. tinyexr::DecompressZfp(reinterpret_cast<float *>(&outBuf.at(0)), width,
  3349. num_lines, num_channels, data_ptr,
  3350. static_cast<unsigned long>(data_len),
  3351. zfp_compression_param);
  3352. // For ZFP_COMPRESSION:
  3353. // pixel sample data for channel 0 for scanline 0
  3354. // pixel sample data for channel 1 for scanline 0
  3355. // pixel sample data for channel ... for scanline 0
  3356. // pixel sample data for channel n for scanline 0
  3357. // pixel sample data for channel 0 for scanline 1
  3358. // pixel sample data for channel 1 for scanline 1
  3359. // pixel sample data for channel ... for scanline 1
  3360. // pixel sample data for channel n for scanline 1
  3361. // ...
  3362. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3363. TINYEXR_CHECK_AND_RETURN_C(channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT, false);
  3364. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3365. TINYEXR_CHECK_AND_RETURN_C(requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT, false);
  3366. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3367. const float *line_ptr = reinterpret_cast<float *>(
  3368. &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) +
  3369. channel_offset_list[c] * static_cast<size_t>(width)));
  3370. for (size_t u = 0; u < static_cast<size_t>(width); u++) {
  3371. float val;
  3372. tinyexr::cpy4(&val, line_ptr + u);
  3373. tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
  3374. float *image = reinterpret_cast<float **>(out_images)[c];
  3375. if (line_order == 0) {
  3376. image += (static_cast<size_t>(line_no) + v) *
  3377. static_cast<size_t>(x_stride) +
  3378. u;
  3379. } else {
  3380. image += (static_cast<size_t>(height) - 1U -
  3381. (static_cast<size_t>(line_no) + v)) *
  3382. static_cast<size_t>(x_stride) +
  3383. u;
  3384. }
  3385. *image = val;
  3386. }
  3387. }
  3388. } else {
  3389. return false;
  3390. }
  3391. }
  3392. #else
  3393. (void)attributes;
  3394. (void)num_attributes;
  3395. (void)num_channels;
  3396. return false;
  3397. #endif
  3398. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
  3399. for (size_t c = 0; c < num_channels; c++) {
  3400. for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) {
  3401. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  3402. const unsigned short *line_ptr =
  3403. reinterpret_cast<const unsigned short *>(
  3404. data_ptr + v * pixel_data_size * size_t(width) +
  3405. channel_offset_list[c] * static_cast<size_t>(width));
  3406. if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
  3407. unsigned short *outLine =
  3408. reinterpret_cast<unsigned short *>(out_images[c]);
  3409. if (line_order == 0) {
  3410. outLine += (size_t(y) + v) * size_t(x_stride);
  3411. } else {
  3412. outLine +=
  3413. (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
  3414. }
  3415. for (int u = 0; u < width; u++) {
  3416. tinyexr::FP16 hf;
  3417. // hf.u = line_ptr[u];
  3418. tinyexr::cpy2(&(hf.u), line_ptr + u);
  3419. tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
  3420. outLine[u] = hf.u;
  3421. }
  3422. } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
  3423. float *outLine = reinterpret_cast<float *>(out_images[c]);
  3424. if (line_order == 0) {
  3425. outLine += (size_t(y) + v) * size_t(x_stride);
  3426. } else {
  3427. outLine +=
  3428. (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
  3429. }
  3430. if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
  3431. (data_ptr + data_len)) {
  3432. // Insufficient data size
  3433. return false;
  3434. }
  3435. for (int u = 0; u < width; u++) {
  3436. tinyexr::FP16 hf;
  3437. // address may not be aligned. use byte-wise copy for safety.#76
  3438. // hf.u = line_ptr[u];
  3439. tinyexr::cpy2(&(hf.u), line_ptr + u);
  3440. tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u));
  3441. tinyexr::FP32 f32 = half_to_float(hf);
  3442. outLine[u] = f32.f;
  3443. }
  3444. } else {
  3445. return false;
  3446. }
  3447. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3448. const float *line_ptr = reinterpret_cast<const float *>(
  3449. data_ptr + v * pixel_data_size * size_t(width) +
  3450. channel_offset_list[c] * static_cast<size_t>(width));
  3451. float *outLine = reinterpret_cast<float *>(out_images[c]);
  3452. if (line_order == 0) {
  3453. outLine += (size_t(y) + v) * size_t(x_stride);
  3454. } else {
  3455. outLine +=
  3456. (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
  3457. }
  3458. if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
  3459. (data_ptr + data_len)) {
  3460. // Insufficient data size
  3461. return false;
  3462. }
  3463. for (int u = 0; u < width; u++) {
  3464. float val;
  3465. tinyexr::cpy4(&val, line_ptr + u);
  3466. tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
  3467. outLine[u] = val;
  3468. }
  3469. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  3470. const unsigned int *line_ptr = reinterpret_cast<const unsigned int *>(
  3471. data_ptr + v * pixel_data_size * size_t(width) +
  3472. channel_offset_list[c] * static_cast<size_t>(width));
  3473. unsigned int *outLine =
  3474. reinterpret_cast<unsigned int *>(out_images[c]);
  3475. if (line_order == 0) {
  3476. outLine += (size_t(y) + v) * size_t(x_stride);
  3477. } else {
  3478. outLine +=
  3479. (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
  3480. }
  3481. if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
  3482. (data_ptr + data_len)) {
  3483. // Corrupted data
  3484. return false;
  3485. }
  3486. for (int u = 0; u < width; u++) {
  3487. unsigned int val;
  3488. tinyexr::cpy4(&val, line_ptr + u);
  3489. tinyexr::swap4(reinterpret_cast<unsigned int *>(&val));
  3490. outLine[u] = val;
  3491. }
  3492. }
  3493. }
  3494. }
  3495. }
  3496. return true;
  3497. }
  3498. static bool DecodeTiledPixelData(
  3499. unsigned char **out_images, int *width, int *height,
  3500. const int *requested_pixel_types, const unsigned char *data_ptr,
  3501. size_t data_len, int compression_type, int line_order, int data_width,
  3502. int data_height, int tile_offset_x, int tile_offset_y, int tile_size_x,
  3503. int tile_size_y, size_t pixel_data_size, size_t num_attributes,
  3504. const EXRAttribute *attributes, size_t num_channels,
  3505. const EXRChannelInfo *channels,
  3506. const std::vector<size_t> &channel_offset_list) {
  3507. // Here, data_width and data_height are the dimensions of the current (sub)level.
  3508. if (tile_size_x * tile_offset_x > data_width ||
  3509. tile_size_y * tile_offset_y > data_height) {
  3510. return false;
  3511. }
  3512. // Compute actual image size in a tile.
  3513. if ((tile_offset_x + 1) * tile_size_x >= data_width) {
  3514. (*width) = data_width - (tile_offset_x * tile_size_x);
  3515. } else {
  3516. (*width) = tile_size_x;
  3517. }
  3518. if ((tile_offset_y + 1) * tile_size_y >= data_height) {
  3519. (*height) = data_height - (tile_offset_y * tile_size_y);
  3520. } else {
  3521. (*height) = tile_size_y;
  3522. }
  3523. // Image size = tile size.
  3524. return DecodePixelData(out_images, requested_pixel_types, data_ptr, data_len,
  3525. compression_type, line_order, (*width), tile_size_y,
  3526. /* stride */ tile_size_x, /* y */ 0, /* line_no */ 0,
  3527. (*height), pixel_data_size, num_attributes, attributes,
  3528. num_channels, channels, channel_offset_list);
  3529. }
  3530. static bool ComputeChannelLayout(std::vector<size_t> *channel_offset_list,
  3531. int *pixel_data_size, size_t *channel_offset,
  3532. int num_channels,
  3533. const EXRChannelInfo *channels) {
  3534. channel_offset_list->resize(static_cast<size_t>(num_channels));
  3535. (*pixel_data_size) = 0;
  3536. (*channel_offset) = 0;
  3537. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3538. (*channel_offset_list)[c] = (*channel_offset);
  3539. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  3540. (*pixel_data_size) += sizeof(unsigned short);
  3541. (*channel_offset) += sizeof(unsigned short);
  3542. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3543. (*pixel_data_size) += sizeof(float);
  3544. (*channel_offset) += sizeof(float);
  3545. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  3546. (*pixel_data_size) += sizeof(unsigned int);
  3547. (*channel_offset) += sizeof(unsigned int);
  3548. } else {
  3549. // ???
  3550. return false;
  3551. }
  3552. }
  3553. return true;
  3554. }
  3555. // TODO: Simply return nullptr when failed to allocate?
  3556. static unsigned char **AllocateImage(int num_channels,
  3557. const EXRChannelInfo *channels,
  3558. const int *requested_pixel_types,
  3559. int data_width, int data_height, bool *success) {
  3560. unsigned char **images =
  3561. reinterpret_cast<unsigned char **>(static_cast<float **>(
  3562. malloc(sizeof(float *) * static_cast<size_t>(num_channels))));
  3563. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3564. images[c] = NULL;
  3565. }
  3566. bool valid = true;
  3567. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3568. size_t data_len =
  3569. static_cast<size_t>(data_width) * static_cast<size_t>(data_height);
  3570. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  3571. // pixel_data_size += sizeof(unsigned short);
  3572. // channel_offset += sizeof(unsigned short);
  3573. // Alloc internal image for half type.
  3574. if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
  3575. images[c] =
  3576. reinterpret_cast<unsigned char *>(static_cast<unsigned short *>(
  3577. malloc(sizeof(unsigned short) * data_len)));
  3578. } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
  3579. images[c] = reinterpret_cast<unsigned char *>(
  3580. static_cast<float *>(malloc(sizeof(float) * data_len)));
  3581. } else {
  3582. images[c] = NULL; // just in case.
  3583. valid = false;
  3584. break;
  3585. }
  3586. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  3587. // pixel_data_size += sizeof(float);
  3588. // channel_offset += sizeof(float);
  3589. images[c] = reinterpret_cast<unsigned char *>(
  3590. static_cast<float *>(malloc(sizeof(float) * data_len)));
  3591. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  3592. // pixel_data_size += sizeof(unsigned int);
  3593. // channel_offset += sizeof(unsigned int);
  3594. images[c] = reinterpret_cast<unsigned char *>(
  3595. static_cast<unsigned int *>(malloc(sizeof(unsigned int) * data_len)));
  3596. } else {
  3597. images[c] = NULL; // just in case.
  3598. valid = false;
  3599. break;
  3600. }
  3601. }
  3602. if (!valid) {
  3603. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  3604. if (images[c]) {
  3605. free(images[c]);
  3606. images[c] = NULL;
  3607. }
  3608. }
  3609. if (success) {
  3610. (*success) = false;
  3611. }
  3612. } else {
  3613. if (success) {
  3614. (*success) = true;
  3615. }
  3616. }
  3617. return images;
  3618. }
  3619. #ifdef _WIN32
  3620. static inline std::wstring UTF8ToWchar(const std::string &str) {
  3621. int wstr_size =
  3622. MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), NULL, 0);
  3623. std::wstring wstr(wstr_size, 0);
  3624. MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &wstr[0],
  3625. (int)wstr.size());
  3626. return wstr;
  3627. }
  3628. #endif
  3629. static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
  3630. const EXRVersion *version, std::string *err,
  3631. const unsigned char *buf, size_t size) {
  3632. const char *marker = reinterpret_cast<const char *>(&buf[0]);
  3633. if (empty_header) {
  3634. (*empty_header) = false;
  3635. }
  3636. if (version->multipart) {
  3637. if (size > 0 && marker[0] == '\0') {
  3638. // End of header list.
  3639. if (empty_header) {
  3640. (*empty_header) = true;
  3641. }
  3642. return TINYEXR_SUCCESS;
  3643. }
  3644. }
  3645. // According to the spec, the header of every OpenEXR file must contain at
  3646. // least the following attributes:
  3647. //
  3648. // channels chlist
  3649. // compression compression
  3650. // dataWindow box2i
  3651. // displayWindow box2i
  3652. // lineOrder lineOrder
  3653. // pixelAspectRatio float
  3654. // screenWindowCenter v2f
  3655. // screenWindowWidth float
  3656. bool has_channels = false;
  3657. bool has_compression = false;
  3658. bool has_data_window = false;
  3659. bool has_display_window = false;
  3660. bool has_line_order = false;
  3661. bool has_pixel_aspect_ratio = false;
  3662. bool has_screen_window_center = false;
  3663. bool has_screen_window_width = false;
  3664. bool has_name = false;
  3665. bool has_type = false;
  3666. info->name.clear();
  3667. info->type.clear();
  3668. info->data_window.min_x = 0;
  3669. info->data_window.min_y = 0;
  3670. info->data_window.max_x = 0;
  3671. info->data_window.max_y = 0;
  3672. info->line_order = 0; // @fixme
  3673. info->display_window.min_x = 0;
  3674. info->display_window.min_y = 0;
  3675. info->display_window.max_x = 0;
  3676. info->display_window.max_y = 0;
  3677. info->screen_window_center[0] = 0.0f;
  3678. info->screen_window_center[1] = 0.0f;
  3679. info->screen_window_width = -1.0f;
  3680. info->pixel_aspect_ratio = -1.0f;
  3681. info->tiled = 0;
  3682. info->tile_size_x = -1;
  3683. info->tile_size_y = -1;
  3684. info->tile_level_mode = -1;
  3685. info->tile_rounding_mode = -1;
  3686. info->attributes.clear();
  3687. // Read attributes
  3688. size_t orig_size = size;
  3689. for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) {
  3690. if (0 == size) {
  3691. if (err) {
  3692. (*err) += "Insufficient data size for attributes.\n";
  3693. }
  3694. return TINYEXR_ERROR_INVALID_DATA;
  3695. } else if (marker[0] == '\0') {
  3696. size--;
  3697. break;
  3698. }
  3699. std::string attr_name;
  3700. std::string attr_type;
  3701. std::vector<unsigned char> data;
  3702. size_t marker_size;
  3703. if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
  3704. marker, size)) {
  3705. if (err) {
  3706. (*err) += "Failed to read attribute.\n";
  3707. }
  3708. return TINYEXR_ERROR_INVALID_DATA;
  3709. }
  3710. marker += marker_size;
  3711. size -= marker_size;
  3712. // For a multipart file, the version field 9th bit is 0.
  3713. if ((version->tiled || version->multipart || version->non_image) && attr_name.compare("tiles") == 0) {
  3714. unsigned int x_size, y_size;
  3715. unsigned char tile_mode;
  3716. if (data.size() != 9) {
  3717. if (err) {
  3718. (*err) += "(ParseEXRHeader) Invalid attribute data size. Attribute data size must be 9.\n";
  3719. }
  3720. return TINYEXR_ERROR_INVALID_DATA;
  3721. }
  3722. memcpy(&x_size, &data.at(0), sizeof(int));
  3723. memcpy(&y_size, &data.at(4), sizeof(int));
  3724. tile_mode = data[8];
  3725. tinyexr::swap4(&x_size);
  3726. tinyexr::swap4(&y_size);
  3727. if (x_size > static_cast<unsigned int>(std::numeric_limits<int>::max()) ||
  3728. y_size > static_cast<unsigned int>(std::numeric_limits<int>::max())) {
  3729. if (err) {
  3730. (*err) = "Tile sizes were invalid.";
  3731. }
  3732. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  3733. }
  3734. info->tile_size_x = static_cast<int>(x_size);
  3735. info->tile_size_y = static_cast<int>(y_size);
  3736. // mode = levelMode + roundingMode * 16
  3737. info->tile_level_mode = tile_mode & 0x3;
  3738. info->tile_rounding_mode = (tile_mode >> 4) & 0x1;
  3739. info->tiled = 1;
  3740. } else if (attr_name.compare("compression") == 0) {
  3741. bool ok = false;
  3742. if (data[0] < TINYEXR_COMPRESSIONTYPE_PIZ) {
  3743. ok = true;
  3744. }
  3745. if (data[0] == TINYEXR_COMPRESSIONTYPE_PIZ) {
  3746. #if TINYEXR_USE_PIZ
  3747. ok = true;
  3748. #else
  3749. if (err) {
  3750. (*err) = "PIZ compression is not supported.";
  3751. }
  3752. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  3753. #endif
  3754. }
  3755. if (data[0] == TINYEXR_COMPRESSIONTYPE_ZFP) {
  3756. #if TINYEXR_USE_ZFP
  3757. ok = true;
  3758. #else
  3759. if (err) {
  3760. (*err) = "ZFP compression is not supported.";
  3761. }
  3762. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  3763. #endif
  3764. }
  3765. if (!ok) {
  3766. if (err) {
  3767. (*err) = "Unknown compression type.";
  3768. }
  3769. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  3770. }
  3771. info->compression_type = static_cast<int>(data[0]);
  3772. has_compression = true;
  3773. } else if (attr_name.compare("channels") == 0) {
  3774. // name: zero-terminated string, from 1 to 255 bytes long
  3775. // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2
  3776. // pLinear: unsigned char, possible values are 0 and 1
  3777. // reserved: three chars, should be zero
  3778. // xSampling: int
  3779. // ySampling: int
  3780. if (!ReadChannelInfo(info->channels, data)) {
  3781. if (err) {
  3782. (*err) += "Failed to parse channel info.\n";
  3783. }
  3784. return TINYEXR_ERROR_INVALID_DATA;
  3785. }
  3786. if (info->channels.size() < 1) {
  3787. if (err) {
  3788. (*err) += "# of channels is zero.\n";
  3789. }
  3790. return TINYEXR_ERROR_INVALID_DATA;
  3791. }
  3792. has_channels = true;
  3793. } else if (attr_name.compare("dataWindow") == 0) {
  3794. if (data.size() >= 16) {
  3795. memcpy(&info->data_window.min_x, &data.at(0), sizeof(int));
  3796. memcpy(&info->data_window.min_y, &data.at(4), sizeof(int));
  3797. memcpy(&info->data_window.max_x, &data.at(8), sizeof(int));
  3798. memcpy(&info->data_window.max_y, &data.at(12), sizeof(int));
  3799. tinyexr::swap4(&info->data_window.min_x);
  3800. tinyexr::swap4(&info->data_window.min_y);
  3801. tinyexr::swap4(&info->data_window.max_x);
  3802. tinyexr::swap4(&info->data_window.max_y);
  3803. has_data_window = true;
  3804. }
  3805. } else if (attr_name.compare("displayWindow") == 0) {
  3806. if (data.size() >= 16) {
  3807. memcpy(&info->display_window.min_x, &data.at(0), sizeof(int));
  3808. memcpy(&info->display_window.min_y, &data.at(4), sizeof(int));
  3809. memcpy(&info->display_window.max_x, &data.at(8), sizeof(int));
  3810. memcpy(&info->display_window.max_y, &data.at(12), sizeof(int));
  3811. tinyexr::swap4(&info->display_window.min_x);
  3812. tinyexr::swap4(&info->display_window.min_y);
  3813. tinyexr::swap4(&info->display_window.max_x);
  3814. tinyexr::swap4(&info->display_window.max_y);
  3815. has_display_window = true;
  3816. }
  3817. } else if (attr_name.compare("lineOrder") == 0) {
  3818. if (data.size() >= 1) {
  3819. info->line_order = static_cast<int>(data[0]);
  3820. has_line_order = true;
  3821. }
  3822. } else if (attr_name.compare("pixelAspectRatio") == 0) {
  3823. if (data.size() >= sizeof(float)) {
  3824. memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float));
  3825. tinyexr::swap4(&info->pixel_aspect_ratio);
  3826. has_pixel_aspect_ratio = true;
  3827. }
  3828. } else if (attr_name.compare("screenWindowCenter") == 0) {
  3829. if (data.size() >= 8) {
  3830. memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float));
  3831. memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float));
  3832. tinyexr::swap4(&info->screen_window_center[0]);
  3833. tinyexr::swap4(&info->screen_window_center[1]);
  3834. has_screen_window_center = true;
  3835. }
  3836. } else if (attr_name.compare("screenWindowWidth") == 0) {
  3837. if (data.size() >= sizeof(float)) {
  3838. memcpy(&info->screen_window_width, &data.at(0), sizeof(float));
  3839. tinyexr::swap4(&info->screen_window_width);
  3840. has_screen_window_width = true;
  3841. }
  3842. } else if (attr_name.compare("chunkCount") == 0) {
  3843. if (data.size() >= sizeof(int)) {
  3844. memcpy(&info->chunk_count, &data.at(0), sizeof(int));
  3845. tinyexr::swap4(&info->chunk_count);
  3846. }
  3847. } else if (attr_name.compare("name") == 0) {
  3848. if (!data.empty() && data[0]) {
  3849. data.push_back(0);
  3850. size_t len = strlen(reinterpret_cast<const char*>(&data[0]));
  3851. info->name.resize(len);
  3852. info->name.assign(reinterpret_cast<const char*>(&data[0]), len);
  3853. has_name = true;
  3854. }
  3855. } else if (attr_name.compare("type") == 0) {
  3856. if (!data.empty() && data[0]) {
  3857. data.push_back(0);
  3858. size_t len = strlen(reinterpret_cast<const char*>(&data[0]));
  3859. info->type.resize(len);
  3860. info->type.assign(reinterpret_cast<const char*>(&data[0]), len);
  3861. has_type = true;
  3862. }
  3863. } else {
  3864. // Custom attribute(up to TINYEXR_MAX_CUSTOM_ATTRIBUTES)
  3865. if (info->attributes.size() < TINYEXR_MAX_CUSTOM_ATTRIBUTES) {
  3866. EXRAttribute attrib;
  3867. #ifdef _MSC_VER
  3868. strncpy_s(attrib.name, attr_name.c_str(), 255);
  3869. strncpy_s(attrib.type, attr_type.c_str(), 255);
  3870. #else
  3871. strncpy(attrib.name, attr_name.c_str(), 255);
  3872. strncpy(attrib.type, attr_type.c_str(), 255);
  3873. #endif
  3874. attrib.name[255] = '\0';
  3875. attrib.type[255] = '\0';
  3876. //std::cout << "i = " << info->attributes.size() << ", dsize = " << data.size() << "\n";
  3877. attrib.size = static_cast<int>(data.size());
  3878. attrib.value = static_cast<unsigned char *>(malloc(data.size()));
  3879. memcpy(reinterpret_cast<char *>(attrib.value), &data.at(0),
  3880. data.size());
  3881. info->attributes.push_back(attrib);
  3882. }
  3883. }
  3884. }
  3885. // Check if required attributes exist
  3886. {
  3887. std::stringstream ss_err;
  3888. if (!has_compression) {
  3889. ss_err << "\"compression\" attribute not found in the header."
  3890. << std::endl;
  3891. }
  3892. if (!has_channels) {
  3893. ss_err << "\"channels\" attribute not found in the header." << std::endl;
  3894. }
  3895. if (!has_line_order) {
  3896. ss_err << "\"lineOrder\" attribute not found in the header." << std::endl;
  3897. }
  3898. if (!has_display_window) {
  3899. ss_err << "\"displayWindow\" attribute not found in the header."
  3900. << std::endl;
  3901. }
  3902. if (!has_data_window) {
  3903. ss_err << "\"dataWindow\" attribute not found in the header or invalid."
  3904. << std::endl;
  3905. }
  3906. if (!has_pixel_aspect_ratio) {
  3907. ss_err << "\"pixelAspectRatio\" attribute not found in the header."
  3908. << std::endl;
  3909. }
  3910. if (!has_screen_window_width) {
  3911. ss_err << "\"screenWindowWidth\" attribute not found in the header."
  3912. << std::endl;
  3913. }
  3914. if (!has_screen_window_center) {
  3915. ss_err << "\"screenWindowCenter\" attribute not found in the header."
  3916. << std::endl;
  3917. }
  3918. if (version->multipart || version->non_image) {
  3919. if (!has_name) {
  3920. ss_err << "\"name\" attribute not found in the header."
  3921. << std::endl;
  3922. }
  3923. if (!has_type) {
  3924. ss_err << "\"type\" attribute not found in the header."
  3925. << std::endl;
  3926. }
  3927. }
  3928. if (!(ss_err.str().empty())) {
  3929. if (err) {
  3930. (*err) += ss_err.str();
  3931. }
  3932. return TINYEXR_ERROR_INVALID_HEADER;
  3933. }
  3934. }
  3935. info->header_len = static_cast<unsigned int>(orig_size - size);
  3936. return TINYEXR_SUCCESS;
  3937. }
  3938. // C++ HeaderInfo to C EXRHeader conversion.
  3939. static bool ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info, std::string *warn, std::string *err) {
  3940. exr_header->pixel_aspect_ratio = info.pixel_aspect_ratio;
  3941. exr_header->screen_window_center[0] = info.screen_window_center[0];
  3942. exr_header->screen_window_center[1] = info.screen_window_center[1];
  3943. exr_header->screen_window_width = info.screen_window_width;
  3944. exr_header->chunk_count = info.chunk_count;
  3945. exr_header->display_window.min_x = info.display_window.min_x;
  3946. exr_header->display_window.min_y = info.display_window.min_y;
  3947. exr_header->display_window.max_x = info.display_window.max_x;
  3948. exr_header->display_window.max_y = info.display_window.max_y;
  3949. exr_header->data_window.min_x = info.data_window.min_x;
  3950. exr_header->data_window.min_y = info.data_window.min_y;
  3951. exr_header->data_window.max_x = info.data_window.max_x;
  3952. exr_header->data_window.max_y = info.data_window.max_y;
  3953. exr_header->line_order = info.line_order;
  3954. exr_header->compression_type = info.compression_type;
  3955. exr_header->tiled = info.tiled;
  3956. exr_header->tile_size_x = info.tile_size_x;
  3957. exr_header->tile_size_y = info.tile_size_y;
  3958. exr_header->tile_level_mode = info.tile_level_mode;
  3959. exr_header->tile_rounding_mode = info.tile_rounding_mode;
  3960. EXRSetNameAttr(exr_header, info.name.c_str());
  3961. if (!info.type.empty()) {
  3962. bool valid = true;
  3963. if (info.type == "scanlineimage") {
  3964. if (exr_header->tiled) {
  3965. if (err) {
  3966. (*err) += "(ConvertHeader) tiled bit must be off for `scanlineimage` type.\n";
  3967. }
  3968. valid = false;
  3969. }
  3970. } else if (info.type == "tiledimage") {
  3971. if (!exr_header->tiled) {
  3972. if (err) {
  3973. (*err) += "(ConvertHeader) tiled bit must be on for `tiledimage` type.\n";
  3974. }
  3975. valid = false;
  3976. }
  3977. } else if (info.type == "deeptile") {
  3978. exr_header->non_image = 1;
  3979. if (!exr_header->tiled) {
  3980. if (err) {
  3981. (*err) += "(ConvertHeader) tiled bit must be on for `deeptile` type.\n";
  3982. }
  3983. valid = false;
  3984. }
  3985. } else if (info.type == "deepscanline") {
  3986. exr_header->non_image = 1;
  3987. if (exr_header->tiled) {
  3988. if (err) {
  3989. (*err) += "(ConvertHeader) tiled bit must be off for `deepscanline` type.\n";
  3990. }
  3991. //valid = false;
  3992. }
  3993. } else {
  3994. if (warn) {
  3995. std::stringstream ss;
  3996. ss << "(ConvertHeader) Unsupported or unknown info.type: " << info.type << "\n";
  3997. (*warn) += ss.str();
  3998. }
  3999. }
  4000. if (!valid) {
  4001. return false;
  4002. }
  4003. }
  4004. exr_header->num_channels = static_cast<int>(info.channels.size());
  4005. exr_header->channels = static_cast<EXRChannelInfo *>(malloc(
  4006. sizeof(EXRChannelInfo) * static_cast<size_t>(exr_header->num_channels)));
  4007. for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
  4008. #ifdef _MSC_VER
  4009. strncpy_s(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
  4010. #else
  4011. strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
  4012. #endif
  4013. // manually add '\0' for safety.
  4014. exr_header->channels[c].name[255] = '\0';
  4015. exr_header->channels[c].pixel_type = info.channels[c].pixel_type;
  4016. exr_header->channels[c].p_linear = info.channels[c].p_linear;
  4017. exr_header->channels[c].x_sampling = info.channels[c].x_sampling;
  4018. exr_header->channels[c].y_sampling = info.channels[c].y_sampling;
  4019. }
  4020. exr_header->pixel_types = static_cast<int *>(
  4021. malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels)));
  4022. for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
  4023. exr_header->pixel_types[c] = info.channels[c].pixel_type;
  4024. }
  4025. // Initially fill with values of `pixel_types`
  4026. exr_header->requested_pixel_types = static_cast<int *>(
  4027. malloc(sizeof(int) * static_cast<size_t>(exr_header->num_channels)));
  4028. for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
  4029. exr_header->requested_pixel_types[c] = info.channels[c].pixel_type;
  4030. }
  4031. exr_header->num_custom_attributes = static_cast<int>(info.attributes.size());
  4032. if (exr_header->num_custom_attributes > 0) {
  4033. // TODO(syoyo): Report warning when # of attributes exceeds
  4034. // `TINYEXR_MAX_CUSTOM_ATTRIBUTES`
  4035. if (exr_header->num_custom_attributes > TINYEXR_MAX_CUSTOM_ATTRIBUTES) {
  4036. exr_header->num_custom_attributes = TINYEXR_MAX_CUSTOM_ATTRIBUTES;
  4037. }
  4038. exr_header->custom_attributes = static_cast<EXRAttribute *>(malloc(
  4039. sizeof(EXRAttribute) * size_t(exr_header->num_custom_attributes)));
  4040. for (size_t i = 0; i < size_t(exr_header->num_custom_attributes); i++) {
  4041. memcpy(exr_header->custom_attributes[i].name, info.attributes[i].name,
  4042. 256);
  4043. memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type,
  4044. 256);
  4045. exr_header->custom_attributes[i].size = info.attributes[i].size;
  4046. // Just copy pointer
  4047. exr_header->custom_attributes[i].value = info.attributes[i].value;
  4048. }
  4049. } else {
  4050. exr_header->custom_attributes = NULL;
  4051. }
  4052. exr_header->header_len = info.header_len;
  4053. return true;
  4054. }
  4055. struct OffsetData {
  4056. OffsetData() : num_x_levels(0), num_y_levels(0) {}
  4057. std::vector<std::vector<std::vector <tinyexr::tinyexr_uint64> > > offsets;
  4058. int num_x_levels;
  4059. int num_y_levels;
  4060. };
  4061. // -1 = error
  4062. static int LevelIndex(int lx, int ly, int tile_level_mode, int num_x_levels) {
  4063. switch (tile_level_mode) {
  4064. case TINYEXR_TILE_ONE_LEVEL:
  4065. return 0;
  4066. case TINYEXR_TILE_MIPMAP_LEVELS:
  4067. return lx;
  4068. case TINYEXR_TILE_RIPMAP_LEVELS:
  4069. return lx + ly * num_x_levels;
  4070. default:
  4071. return -1;
  4072. }
  4073. return 0;
  4074. }
  4075. static int LevelSize(int toplevel_size, int level, int tile_rounding_mode) {
  4076. if (level < 0) {
  4077. return -1;
  4078. }
  4079. int b = static_cast<int>(1u << static_cast<unsigned int>(level));
  4080. int level_size = toplevel_size / b;
  4081. if (tile_rounding_mode == TINYEXR_TILE_ROUND_UP && level_size * b < toplevel_size)
  4082. level_size += 1;
  4083. return std::max(level_size, 1);
  4084. }
  4085. static int DecodeTiledLevel(EXRImage* exr_image, const EXRHeader* exr_header,
  4086. const OffsetData& offset_data,
  4087. const std::vector<size_t>& channel_offset_list,
  4088. int pixel_data_size,
  4089. const unsigned char* head, const size_t size,
  4090. std::string* err) {
  4091. int num_channels = exr_header->num_channels;
  4092. int level_index = LevelIndex(exr_image->level_x, exr_image->level_y, exr_header->tile_level_mode, offset_data.num_x_levels);
  4093. int num_y_tiles = int(offset_data.offsets[size_t(level_index)].size());
  4094. if (num_y_tiles < 1) {
  4095. return TINYEXR_ERROR_INVALID_DATA;
  4096. }
  4097. int num_x_tiles = int(offset_data.offsets[size_t(level_index)][0].size());
  4098. if (num_x_tiles < 1) {
  4099. return TINYEXR_ERROR_INVALID_DATA;
  4100. }
  4101. int num_tiles = num_x_tiles * num_y_tiles;
  4102. int err_code = TINYEXR_SUCCESS;
  4103. enum {
  4104. EF_SUCCESS = 0,
  4105. EF_INVALID_DATA = 1,
  4106. EF_INSUFFICIENT_DATA = 2,
  4107. EF_FAILED_TO_DECODE = 4
  4108. };
  4109. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  4110. std::atomic<unsigned> error_flag(EF_SUCCESS);
  4111. #else
  4112. unsigned error_flag(EF_SUCCESS);
  4113. #endif
  4114. // Although the spec says : "...the data window is subdivided into an array of smaller rectangles...",
  4115. // the IlmImf library allows the dimensions of the tile to be larger (or equal) than the dimensions of the data window.
  4116. #if 0
  4117. if ((exr_header->tile_size_x > exr_image->width || exr_header->tile_size_y > exr_image->height) &&
  4118. exr_image->level_x == 0 && exr_image->level_y == 0) {
  4119. if (err) {
  4120. (*err) += "Failed to decode tile data.\n";
  4121. }
  4122. err_code = TINYEXR_ERROR_INVALID_DATA;
  4123. }
  4124. #endif
  4125. exr_image->tiles = static_cast<EXRTile*>(
  4126. calloc(sizeof(EXRTile), static_cast<size_t>(num_tiles)));
  4127. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  4128. std::vector<std::thread> workers;
  4129. std::atomic<int> tile_count(0);
  4130. int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
  4131. if (num_threads > int(num_tiles)) {
  4132. num_threads = int(num_tiles);
  4133. }
  4134. for (int t = 0; t < num_threads; t++) {
  4135. workers.emplace_back(std::thread([&]()
  4136. {
  4137. int tile_idx = 0;
  4138. while ((tile_idx = tile_count++) < num_tiles) {
  4139. #else
  4140. #if TINYEXR_USE_OPENMP
  4141. #pragma omp parallel for
  4142. #endif
  4143. for (int tile_idx = 0; tile_idx < num_tiles; tile_idx++) {
  4144. #endif
  4145. // Allocate memory for each tile.
  4146. bool alloc_success = false;
  4147. exr_image->tiles[tile_idx].images = tinyexr::AllocateImage(
  4148. num_channels, exr_header->channels,
  4149. exr_header->requested_pixel_types, exr_header->tile_size_x,
  4150. exr_header->tile_size_y, &alloc_success);
  4151. if (!alloc_success) {
  4152. error_flag |= EF_INVALID_DATA;
  4153. continue;
  4154. }
  4155. int x_tile = tile_idx % num_x_tiles;
  4156. int y_tile = tile_idx / num_x_tiles;
  4157. // 16 byte: tile coordinates
  4158. // 4 byte : data size
  4159. // ~ : data(uncompressed or compressed)
  4160. tinyexr::tinyexr_uint64 offset = offset_data.offsets[size_t(level_index)][size_t(y_tile)][size_t(x_tile)];
  4161. if (offset + sizeof(int) * 5 > size) {
  4162. // Insufficient data size.
  4163. error_flag |= EF_INSUFFICIENT_DATA;
  4164. continue;
  4165. }
  4166. size_t data_size =
  4167. size_t(size - (offset + sizeof(int) * 5));
  4168. const unsigned char* data_ptr =
  4169. reinterpret_cast<const unsigned char*>(head + offset);
  4170. int tile_coordinates[4];
  4171. memcpy(tile_coordinates, data_ptr, sizeof(int) * 4);
  4172. tinyexr::swap4(&tile_coordinates[0]);
  4173. tinyexr::swap4(&tile_coordinates[1]);
  4174. tinyexr::swap4(&tile_coordinates[2]);
  4175. tinyexr::swap4(&tile_coordinates[3]);
  4176. if (tile_coordinates[2] != exr_image->level_x) {
  4177. // Invalid data.
  4178. error_flag |= EF_INVALID_DATA;
  4179. continue;
  4180. }
  4181. if (tile_coordinates[3] != exr_image->level_y) {
  4182. // Invalid data.
  4183. error_flag |= EF_INVALID_DATA;
  4184. continue;
  4185. }
  4186. int data_len;
  4187. memcpy(&data_len, data_ptr + 16,
  4188. sizeof(int)); // 16 = sizeof(tile_coordinates)
  4189. tinyexr::swap4(&data_len);
  4190. if (data_len < 2 || size_t(data_len) > data_size) {
  4191. // Insufficient data size.
  4192. error_flag |= EF_INSUFFICIENT_DATA;
  4193. continue;
  4194. }
  4195. // Move to data addr: 20 = 16 + 4;
  4196. data_ptr += 20;
  4197. bool ret = tinyexr::DecodeTiledPixelData(
  4198. exr_image->tiles[tile_idx].images,
  4199. &(exr_image->tiles[tile_idx].width),
  4200. &(exr_image->tiles[tile_idx].height),
  4201. exr_header->requested_pixel_types, data_ptr,
  4202. static_cast<size_t>(data_len), exr_header->compression_type,
  4203. exr_header->line_order,
  4204. exr_image->width, exr_image->height,
  4205. tile_coordinates[0], tile_coordinates[1], exr_header->tile_size_x,
  4206. exr_header->tile_size_y, static_cast<size_t>(pixel_data_size),
  4207. static_cast<size_t>(exr_header->num_custom_attributes),
  4208. exr_header->custom_attributes,
  4209. static_cast<size_t>(exr_header->num_channels),
  4210. exr_header->channels, channel_offset_list);
  4211. if (!ret) {
  4212. // Failed to decode tile data.
  4213. error_flag |= EF_FAILED_TO_DECODE;
  4214. }
  4215. exr_image->tiles[tile_idx].offset_x = tile_coordinates[0];
  4216. exr_image->tiles[tile_idx].offset_y = tile_coordinates[1];
  4217. exr_image->tiles[tile_idx].level_x = tile_coordinates[2];
  4218. exr_image->tiles[tile_idx].level_y = tile_coordinates[3];
  4219. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  4220. }
  4221. }));
  4222. } // num_thread loop
  4223. for (auto& t : workers) {
  4224. t.join();
  4225. }
  4226. #else
  4227. } // parallel for
  4228. #endif
  4229. // Even in the event of an error, the reserved memory may be freed.
  4230. exr_image->num_channels = num_channels;
  4231. exr_image->num_tiles = static_cast<int>(num_tiles);
  4232. if (error_flag) err_code = TINYEXR_ERROR_INVALID_DATA;
  4233. if (err) {
  4234. if (error_flag & EF_INSUFFICIENT_DATA) {
  4235. (*err) += "Insufficient data length.\n";
  4236. }
  4237. if (error_flag & EF_FAILED_TO_DECODE) {
  4238. (*err) += "Failed to decode tile data.\n";
  4239. }
  4240. }
  4241. return err_code;
  4242. }
  4243. static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
  4244. const OffsetData& offset_data,
  4245. const unsigned char *head, const size_t size,
  4246. std::string *err) {
  4247. int num_channels = exr_header->num_channels;
  4248. int num_scanline_blocks = 1;
  4249. if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
  4250. num_scanline_blocks = 16;
  4251. } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
  4252. num_scanline_blocks = 32;
  4253. } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  4254. num_scanline_blocks = 16;
  4255. #if TINYEXR_USE_ZFP
  4256. tinyexr::ZFPCompressionParam zfp_compression_param;
  4257. if (!FindZFPCompressionParam(&zfp_compression_param,
  4258. exr_header->custom_attributes,
  4259. int(exr_header->num_custom_attributes), err)) {
  4260. return TINYEXR_ERROR_INVALID_HEADER;
  4261. }
  4262. #endif
  4263. }
  4264. if (exr_header->data_window.max_x < exr_header->data_window.min_x ||
  4265. exr_header->data_window.max_y < exr_header->data_window.min_y) {
  4266. if (err) {
  4267. (*err) += "Invalid data window.\n";
  4268. }
  4269. return TINYEXR_ERROR_INVALID_DATA;
  4270. }
  4271. tinyexr_int64 data_width =
  4272. static_cast<tinyexr_int64>(exr_header->data_window.max_x) - static_cast<tinyexr_int64>(exr_header->data_window.min_x) + static_cast<tinyexr_int64>(1);
  4273. tinyexr_int64 data_height =
  4274. static_cast<tinyexr_int64>(exr_header->data_window.max_y) - static_cast<tinyexr_int64>(exr_header->data_window.min_y) + static_cast<tinyexr_int64>(1);
  4275. if (data_width <= 0) {
  4276. if (err) {
  4277. (*err) += "Invalid data window width.\n";
  4278. }
  4279. return TINYEXR_ERROR_INVALID_DATA;
  4280. }
  4281. if (data_height <= 0) {
  4282. if (err) {
  4283. (*err) += "Invalid data window height.\n";
  4284. }
  4285. return TINYEXR_ERROR_INVALID_DATA;
  4286. }
  4287. // Do not allow too large data_width and data_height. header invalid?
  4288. {
  4289. if ((data_width > TINYEXR_DIMENSION_THRESHOLD) || (data_height > TINYEXR_DIMENSION_THRESHOLD)) {
  4290. if (err) {
  4291. std::stringstream ss;
  4292. ss << "data_with or data_height too large. data_width: " << data_width
  4293. << ", "
  4294. << "data_height = " << data_height << std::endl;
  4295. (*err) += ss.str();
  4296. }
  4297. return TINYEXR_ERROR_INVALID_DATA;
  4298. }
  4299. if (exr_header->tiled) {
  4300. if ((exr_header->tile_size_x > TINYEXR_DIMENSION_THRESHOLD) || (exr_header->tile_size_y > TINYEXR_DIMENSION_THRESHOLD)) {
  4301. if (err) {
  4302. std::stringstream ss;
  4303. ss << "tile with or tile height too large. tile width: " << exr_header->tile_size_x
  4304. << ", "
  4305. << "tile height = " << exr_header->tile_size_y << std::endl;
  4306. (*err) += ss.str();
  4307. }
  4308. return TINYEXR_ERROR_INVALID_DATA;
  4309. }
  4310. }
  4311. }
  4312. const std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data.offsets[0][0];
  4313. size_t num_blocks = offsets.size();
  4314. std::vector<size_t> channel_offset_list;
  4315. int pixel_data_size = 0;
  4316. size_t channel_offset = 0;
  4317. if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size,
  4318. &channel_offset, num_channels,
  4319. exr_header->channels)) {
  4320. if (err) {
  4321. (*err) += "Failed to compute channel layout.\n";
  4322. }
  4323. return TINYEXR_ERROR_INVALID_DATA;
  4324. }
  4325. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  4326. std::atomic<bool> invalid_data(false);
  4327. #else
  4328. bool invalid_data(false);
  4329. #endif
  4330. if (exr_header->tiled) {
  4331. // value check
  4332. if (exr_header->tile_size_x < 0) {
  4333. if (err) {
  4334. std::stringstream ss;
  4335. ss << "Invalid tile size x : " << exr_header->tile_size_x << "\n";
  4336. (*err) += ss.str();
  4337. }
  4338. return TINYEXR_ERROR_INVALID_HEADER;
  4339. }
  4340. if (exr_header->tile_size_y < 0) {
  4341. if (err) {
  4342. std::stringstream ss;
  4343. ss << "Invalid tile size y : " << exr_header->tile_size_y << "\n";
  4344. (*err) += ss.str();
  4345. }
  4346. return TINYEXR_ERROR_INVALID_HEADER;
  4347. }
  4348. if (exr_header->tile_level_mode != TINYEXR_TILE_RIPMAP_LEVELS) {
  4349. EXRImage* level_image = NULL;
  4350. for (int level = 0; level < offset_data.num_x_levels; ++level) {
  4351. if (!level_image) {
  4352. level_image = exr_image;
  4353. } else {
  4354. level_image->next_level = new EXRImage;
  4355. InitEXRImage(level_image->next_level);
  4356. level_image = level_image->next_level;
  4357. }
  4358. level_image->width =
  4359. LevelSize(exr_header->data_window.max_x - exr_header->data_window.min_x + 1, level, exr_header->tile_rounding_mode);
  4360. if (level_image->width < 1) {
  4361. return TINYEXR_ERROR_INVALID_DATA;
  4362. }
  4363. level_image->height =
  4364. LevelSize(exr_header->data_window.max_y - exr_header->data_window.min_y + 1, level, exr_header->tile_rounding_mode);
  4365. if (level_image->height < 1) {
  4366. return TINYEXR_ERROR_INVALID_DATA;
  4367. }
  4368. level_image->level_x = level;
  4369. level_image->level_y = level;
  4370. int ret = DecodeTiledLevel(level_image, exr_header,
  4371. offset_data,
  4372. channel_offset_list,
  4373. pixel_data_size,
  4374. head, size,
  4375. err);
  4376. if (ret != TINYEXR_SUCCESS) return ret;
  4377. }
  4378. } else {
  4379. EXRImage* level_image = NULL;
  4380. for (int level_y = 0; level_y < offset_data.num_y_levels; ++level_y)
  4381. for (int level_x = 0; level_x < offset_data.num_x_levels; ++level_x) {
  4382. if (!level_image) {
  4383. level_image = exr_image;
  4384. } else {
  4385. level_image->next_level = new EXRImage;
  4386. InitEXRImage(level_image->next_level);
  4387. level_image = level_image->next_level;
  4388. }
  4389. level_image->width =
  4390. LevelSize(exr_header->data_window.max_x - exr_header->data_window.min_x + 1, level_x, exr_header->tile_rounding_mode);
  4391. if (level_image->width < 1) {
  4392. return TINYEXR_ERROR_INVALID_DATA;
  4393. }
  4394. level_image->height =
  4395. LevelSize(exr_header->data_window.max_y - exr_header->data_window.min_y + 1, level_y, exr_header->tile_rounding_mode);
  4396. if (level_image->height < 1) {
  4397. return TINYEXR_ERROR_INVALID_DATA;
  4398. }
  4399. level_image->level_x = level_x;
  4400. level_image->level_y = level_y;
  4401. int ret = DecodeTiledLevel(level_image, exr_header,
  4402. offset_data,
  4403. channel_offset_list,
  4404. pixel_data_size,
  4405. head, size,
  4406. err);
  4407. if (ret != TINYEXR_SUCCESS) return ret;
  4408. }
  4409. }
  4410. } else { // scanline format
  4411. // Don't allow too large image(256GB * pixel_data_size or more). Workaround
  4412. // for #104.
  4413. size_t total_data_len =
  4414. size_t(data_width) * size_t(data_height) * size_t(num_channels);
  4415. const bool total_data_len_overflown =
  4416. sizeof(void *) == 8 ? (total_data_len >= 0x4000000000) : false;
  4417. if ((total_data_len == 0) || total_data_len_overflown) {
  4418. if (err) {
  4419. std::stringstream ss;
  4420. ss << "Image data size is zero or too large: width = " << data_width
  4421. << ", height = " << data_height << ", channels = " << num_channels
  4422. << std::endl;
  4423. (*err) += ss.str();
  4424. }
  4425. return TINYEXR_ERROR_INVALID_DATA;
  4426. }
  4427. bool alloc_success = false;
  4428. exr_image->images = tinyexr::AllocateImage(
  4429. num_channels, exr_header->channels, exr_header->requested_pixel_types,
  4430. int(data_width), int(data_height), &alloc_success);
  4431. if (!alloc_success) {
  4432. if (err) {
  4433. std::stringstream ss;
  4434. ss << "Failed to allocate memory for Images. Maybe EXR header is corrupted or Image data size is too large: width = " << data_width
  4435. << ", height = " << data_height << ", channels = " << num_channels
  4436. << std::endl;
  4437. (*err) += ss.str();
  4438. }
  4439. return TINYEXR_ERROR_INVALID_DATA;
  4440. }
  4441. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  4442. std::vector<std::thread> workers;
  4443. std::atomic<int> y_count(0);
  4444. int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
  4445. if (num_threads > int(num_blocks)) {
  4446. num_threads = int(num_blocks);
  4447. }
  4448. for (int t = 0; t < num_threads; t++) {
  4449. workers.emplace_back(std::thread([&]() {
  4450. int y = 0;
  4451. while ((y = y_count++) < int(num_blocks)) {
  4452. #else
  4453. #if TINYEXR_USE_OPENMP
  4454. #pragma omp parallel for
  4455. #endif
  4456. for (int y = 0; y < static_cast<int>(num_blocks); y++) {
  4457. #endif
  4458. size_t y_idx = static_cast<size_t>(y);
  4459. if (offsets[y_idx] + sizeof(int) * 2 > size) {
  4460. invalid_data = true;
  4461. } else {
  4462. // 4 byte: scan line
  4463. // 4 byte: data size
  4464. // ~ : pixel data(uncompressed or compressed)
  4465. size_t data_size =
  4466. size_t(size - (offsets[y_idx] + sizeof(int) * 2));
  4467. const unsigned char *data_ptr =
  4468. reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
  4469. int line_no;
  4470. memcpy(&line_no, data_ptr, sizeof(int));
  4471. int data_len;
  4472. memcpy(&data_len, data_ptr + 4, sizeof(int));
  4473. tinyexr::swap4(&line_no);
  4474. tinyexr::swap4(&data_len);
  4475. if (size_t(data_len) > data_size) {
  4476. invalid_data = true;
  4477. } else if ((line_no > (2 << 20)) || (line_no < -(2 << 20))) {
  4478. // Too large value. Assume this is invalid
  4479. // 2**20 = 1048576 = heuristic value.
  4480. invalid_data = true;
  4481. } else if (data_len == 0) {
  4482. // TODO(syoyo): May be ok to raise the threshold for example
  4483. // `data_len < 4`
  4484. invalid_data = true;
  4485. } else {
  4486. // line_no may be negative.
  4487. int end_line_no = (std::min)(line_no + num_scanline_blocks,
  4488. (exr_header->data_window.max_y + 1));
  4489. int num_lines = end_line_no - line_no;
  4490. if (num_lines <= 0) {
  4491. invalid_data = true;
  4492. } else {
  4493. // Move to data addr: 8 = 4 + 4;
  4494. data_ptr += 8;
  4495. // Adjust line_no with data_window.bmin.y
  4496. // overflow check
  4497. tinyexr_int64 lno =
  4498. static_cast<tinyexr_int64>(line_no) -
  4499. static_cast<tinyexr_int64>(exr_header->data_window.min_y);
  4500. if (lno > std::numeric_limits<int>::max()) {
  4501. line_no = -1; // invalid
  4502. } else if (lno < -std::numeric_limits<int>::max()) {
  4503. line_no = -1; // invalid
  4504. } else {
  4505. line_no -= exr_header->data_window.min_y;
  4506. }
  4507. if (line_no < 0) {
  4508. invalid_data = true;
  4509. } else {
  4510. if (!tinyexr::DecodePixelData(
  4511. exr_image->images, exr_header->requested_pixel_types,
  4512. data_ptr, static_cast<size_t>(data_len),
  4513. exr_header->compression_type, exr_header->line_order,
  4514. int(data_width), int(data_height), int(data_width), y, line_no,
  4515. num_lines, static_cast<size_t>(pixel_data_size),
  4516. static_cast<size_t>(
  4517. exr_header->num_custom_attributes),
  4518. exr_header->custom_attributes,
  4519. static_cast<size_t>(exr_header->num_channels),
  4520. exr_header->channels, channel_offset_list)) {
  4521. invalid_data = true;
  4522. }
  4523. }
  4524. }
  4525. }
  4526. }
  4527. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  4528. }
  4529. }));
  4530. }
  4531. for (auto &t : workers) {
  4532. t.join();
  4533. }
  4534. #else
  4535. } // omp parallel
  4536. #endif
  4537. }
  4538. if (invalid_data) {
  4539. if (err) {
  4540. (*err) += "Invalid/Corrupted data found when decoding pixels.\n";
  4541. }
  4542. // free alloced image.
  4543. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  4544. if (exr_image->images[c]) {
  4545. free(exr_image->images[c]);
  4546. exr_image->images[c] = NULL;
  4547. }
  4548. }
  4549. return TINYEXR_ERROR_INVALID_DATA;
  4550. }
  4551. // Overwrite `pixel_type` with `requested_pixel_type`.
  4552. {
  4553. for (int c = 0; c < exr_header->num_channels; c++) {
  4554. exr_header->pixel_types[c] = exr_header->requested_pixel_types[c];
  4555. }
  4556. }
  4557. {
  4558. exr_image->num_channels = num_channels;
  4559. exr_image->width = int(data_width);
  4560. exr_image->height = int(data_height);
  4561. }
  4562. return TINYEXR_SUCCESS;
  4563. }
  4564. static bool ReconstructLineOffsets(
  4565. std::vector<tinyexr::tinyexr_uint64> *offsets, size_t n,
  4566. const unsigned char *head, const unsigned char *marker, const size_t size) {
  4567. if (head >= marker) {
  4568. return false;
  4569. }
  4570. if (offsets->size() != n) {
  4571. return false;
  4572. }
  4573. for (size_t i = 0; i < n; i++) {
  4574. size_t offset = static_cast<size_t>(marker - head);
  4575. // Offset should not exceed whole EXR file/data size.
  4576. if ((offset + sizeof(tinyexr::tinyexr_uint64)) >= size) {
  4577. return false;
  4578. }
  4579. int y;
  4580. unsigned int data_len;
  4581. memcpy(&y, marker, sizeof(int));
  4582. memcpy(&data_len, marker + 4, sizeof(unsigned int));
  4583. if (data_len >= size) {
  4584. return false;
  4585. }
  4586. tinyexr::swap4(&y);
  4587. tinyexr::swap4(&data_len);
  4588. (*offsets)[i] = offset;
  4589. marker += data_len + 8; // 8 = 4 bytes(y) + 4 bytes(data_len)
  4590. }
  4591. return true;
  4592. }
  4593. static int FloorLog2(unsigned x) {
  4594. //
  4595. // For x > 0, floorLog2(y) returns floor(log(x)/log(2)).
  4596. //
  4597. int y = 0;
  4598. while (x > 1) {
  4599. y += 1;
  4600. x >>= 1u;
  4601. }
  4602. return y;
  4603. }
  4604. static int CeilLog2(unsigned x) {
  4605. //
  4606. // For x > 0, ceilLog2(y) returns ceil(log(x)/log(2)).
  4607. //
  4608. int y = 0;
  4609. int r = 0;
  4610. while (x > 1) {
  4611. if (x & 1)
  4612. r = 1;
  4613. y += 1;
  4614. x >>= 1u;
  4615. }
  4616. return y + r;
  4617. }
  4618. static int RoundLog2(int x, int tile_rounding_mode) {
  4619. return (tile_rounding_mode == TINYEXR_TILE_ROUND_DOWN) ? FloorLog2(static_cast<unsigned>(x)) : CeilLog2(static_cast<unsigned>(x));
  4620. }
  4621. static int CalculateNumXLevels(const EXRHeader* exr_header) {
  4622. int min_x = exr_header->data_window.min_x;
  4623. int max_x = exr_header->data_window.max_x;
  4624. int min_y = exr_header->data_window.min_y;
  4625. int max_y = exr_header->data_window.max_y;
  4626. int num = 0;
  4627. switch (exr_header->tile_level_mode) {
  4628. case TINYEXR_TILE_ONE_LEVEL:
  4629. num = 1;
  4630. break;
  4631. case TINYEXR_TILE_MIPMAP_LEVELS:
  4632. {
  4633. int w = max_x - min_x + 1;
  4634. int h = max_y - min_y + 1;
  4635. num = RoundLog2(std::max(w, h), exr_header->tile_rounding_mode) + 1;
  4636. }
  4637. break;
  4638. case TINYEXR_TILE_RIPMAP_LEVELS:
  4639. {
  4640. int w = max_x - min_x + 1;
  4641. num = RoundLog2(w, exr_header->tile_rounding_mode) + 1;
  4642. }
  4643. break;
  4644. default:
  4645. return -1;
  4646. }
  4647. return num;
  4648. }
  4649. static int CalculateNumYLevels(const EXRHeader* exr_header) {
  4650. int min_x = exr_header->data_window.min_x;
  4651. int max_x = exr_header->data_window.max_x;
  4652. int min_y = exr_header->data_window.min_y;
  4653. int max_y = exr_header->data_window.max_y;
  4654. int num = 0;
  4655. switch (exr_header->tile_level_mode) {
  4656. case TINYEXR_TILE_ONE_LEVEL:
  4657. num = 1;
  4658. break;
  4659. case TINYEXR_TILE_MIPMAP_LEVELS:
  4660. {
  4661. int w = max_x - min_x + 1;
  4662. int h = max_y - min_y + 1;
  4663. num = RoundLog2(std::max(w, h), exr_header->tile_rounding_mode) + 1;
  4664. }
  4665. break;
  4666. case TINYEXR_TILE_RIPMAP_LEVELS:
  4667. {
  4668. int h = max_y - min_y + 1;
  4669. num = RoundLog2(h, exr_header->tile_rounding_mode) + 1;
  4670. }
  4671. break;
  4672. default:
  4673. return -1;
  4674. }
  4675. return num;
  4676. }
  4677. static bool CalculateNumTiles(std::vector<int>& numTiles,
  4678. int toplevel_size,
  4679. int size,
  4680. int tile_rounding_mode) {
  4681. for (unsigned i = 0; i < numTiles.size(); i++) {
  4682. int l = LevelSize(toplevel_size, int(i), tile_rounding_mode);
  4683. if (l < 0) {
  4684. return false;
  4685. }
  4686. TINYEXR_CHECK_AND_RETURN_C(l <= std::numeric_limits<int>::max() - size + 1, false);
  4687. numTiles[i] = (l + size - 1) / size;
  4688. }
  4689. return true;
  4690. }
  4691. static bool PrecalculateTileInfo(std::vector<int>& num_x_tiles,
  4692. std::vector<int>& num_y_tiles,
  4693. const EXRHeader* exr_header) {
  4694. int min_x = exr_header->data_window.min_x;
  4695. int max_x = exr_header->data_window.max_x;
  4696. int min_y = exr_header->data_window.min_y;
  4697. int max_y = exr_header->data_window.max_y;
  4698. int num_x_levels = CalculateNumXLevels(exr_header);
  4699. if (num_x_levels < 0) {
  4700. return false;
  4701. }
  4702. int num_y_levels = CalculateNumYLevels(exr_header);
  4703. if (num_y_levels < 0) {
  4704. return false;
  4705. }
  4706. num_x_tiles.resize(size_t(num_x_levels));
  4707. num_y_tiles.resize(size_t(num_y_levels));
  4708. if (!CalculateNumTiles(num_x_tiles,
  4709. max_x - min_x + 1,
  4710. exr_header->tile_size_x,
  4711. exr_header->tile_rounding_mode)) {
  4712. return false;
  4713. }
  4714. if (!CalculateNumTiles(num_y_tiles,
  4715. max_y - min_y + 1,
  4716. exr_header->tile_size_y,
  4717. exr_header->tile_rounding_mode)) {
  4718. return false;
  4719. }
  4720. return true;
  4721. }
  4722. static void InitSingleResolutionOffsets(OffsetData& offset_data, size_t num_blocks) {
  4723. offset_data.offsets.resize(1);
  4724. offset_data.offsets[0].resize(1);
  4725. offset_data.offsets[0][0].resize(num_blocks);
  4726. offset_data.num_x_levels = 1;
  4727. offset_data.num_y_levels = 1;
  4728. }
  4729. // Return sum of tile blocks.
  4730. // 0 = error
  4731. static int InitTileOffsets(OffsetData& offset_data,
  4732. const EXRHeader* exr_header,
  4733. const std::vector<int>& num_x_tiles,
  4734. const std::vector<int>& num_y_tiles) {
  4735. int num_tile_blocks = 0;
  4736. offset_data.num_x_levels = static_cast<int>(num_x_tiles.size());
  4737. offset_data.num_y_levels = static_cast<int>(num_y_tiles.size());
  4738. switch (exr_header->tile_level_mode) {
  4739. case TINYEXR_TILE_ONE_LEVEL:
  4740. case TINYEXR_TILE_MIPMAP_LEVELS:
  4741. TINYEXR_CHECK_AND_RETURN_C(offset_data.num_x_levels == offset_data.num_y_levels, 0);
  4742. offset_data.offsets.resize(size_t(offset_data.num_x_levels));
  4743. for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) {
  4744. offset_data.offsets[l].resize(size_t(num_y_tiles[l]));
  4745. for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) {
  4746. offset_data.offsets[l][dy].resize(size_t(num_x_tiles[l]));
  4747. num_tile_blocks += num_x_tiles[l];
  4748. }
  4749. }
  4750. break;
  4751. case TINYEXR_TILE_RIPMAP_LEVELS:
  4752. offset_data.offsets.resize(static_cast<size_t>(offset_data.num_x_levels) * static_cast<size_t>(offset_data.num_y_levels));
  4753. for (int ly = 0; ly < offset_data.num_y_levels; ++ly) {
  4754. for (int lx = 0; lx < offset_data.num_x_levels; ++lx) {
  4755. int l = ly * offset_data.num_x_levels + lx;
  4756. offset_data.offsets[size_t(l)].resize(size_t(num_y_tiles[size_t(ly)]));
  4757. for (size_t dy = 0; dy < offset_data.offsets[size_t(l)].size(); ++dy) {
  4758. offset_data.offsets[size_t(l)][dy].resize(size_t(num_x_tiles[size_t(lx)]));
  4759. num_tile_blocks += num_x_tiles[size_t(lx)];
  4760. }
  4761. }
  4762. }
  4763. break;
  4764. default:
  4765. return 0;
  4766. }
  4767. return num_tile_blocks;
  4768. }
  4769. static bool IsAnyOffsetsAreInvalid(const OffsetData& offset_data) {
  4770. for (unsigned int l = 0; l < offset_data.offsets.size(); ++l)
  4771. for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy)
  4772. for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx)
  4773. if (reinterpret_cast<const tinyexr::tinyexr_int64&>(offset_data.offsets[l][dy][dx]) <= 0)
  4774. return true;
  4775. return false;
  4776. }
  4777. static bool isValidTile(const EXRHeader* exr_header,
  4778. const OffsetData& offset_data,
  4779. int dx, int dy, int lx, int ly) {
  4780. if (lx < 0 || ly < 0 || dx < 0 || dy < 0) return false;
  4781. int num_x_levels = offset_data.num_x_levels;
  4782. int num_y_levels = offset_data.num_y_levels;
  4783. switch (exr_header->tile_level_mode) {
  4784. case TINYEXR_TILE_ONE_LEVEL:
  4785. if (lx == 0 &&
  4786. ly == 0 &&
  4787. offset_data.offsets.size() > 0 &&
  4788. offset_data.offsets[0].size() > static_cast<size_t>(dy) &&
  4789. offset_data.offsets[0][size_t(dy)].size() > static_cast<size_t>(dx)) {
  4790. return true;
  4791. }
  4792. break;
  4793. case TINYEXR_TILE_MIPMAP_LEVELS:
  4794. if (lx < num_x_levels &&
  4795. ly < num_y_levels &&
  4796. offset_data.offsets.size() > static_cast<size_t>(lx) &&
  4797. offset_data.offsets[size_t(lx)].size() > static_cast<size_t>(dy) &&
  4798. offset_data.offsets[size_t(lx)][size_t(dy)].size() > static_cast<size_t>(dx)) {
  4799. return true;
  4800. }
  4801. break;
  4802. case TINYEXR_TILE_RIPMAP_LEVELS:
  4803. {
  4804. size_t idx = static_cast<size_t>(lx) + static_cast<size_t>(ly)* static_cast<size_t>(num_x_levels);
  4805. if (lx < num_x_levels &&
  4806. ly < num_y_levels &&
  4807. (offset_data.offsets.size() > idx) &&
  4808. offset_data.offsets[idx].size() > static_cast<size_t>(dy) &&
  4809. offset_data.offsets[idx][size_t(dy)].size() > static_cast<size_t>(dx)) {
  4810. return true;
  4811. }
  4812. }
  4813. break;
  4814. default:
  4815. return false;
  4816. }
  4817. return false;
  4818. }
  4819. static bool ReconstructTileOffsets(OffsetData& offset_data,
  4820. const EXRHeader* exr_header,
  4821. const unsigned char* head, const unsigned char* marker, const size_t size,
  4822. bool isMultiPartFile,
  4823. bool isDeep) {
  4824. int numXLevels = offset_data.num_x_levels;
  4825. for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) {
  4826. for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) {
  4827. for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) {
  4828. tinyexr::tinyexr_uint64 tileOffset = tinyexr::tinyexr_uint64(marker - head);
  4829. if (isMultiPartFile) {
  4830. if ((marker + sizeof(int)) >= (head + size)) {
  4831. return false;
  4832. }
  4833. //int partNumber;
  4834. marker += sizeof(int);
  4835. }
  4836. if ((marker + 4 * sizeof(int)) >= (head + size)) {
  4837. return false;
  4838. }
  4839. int tileX;
  4840. memcpy(&tileX, marker, sizeof(int));
  4841. tinyexr::swap4(&tileX);
  4842. marker += sizeof(int);
  4843. int tileY;
  4844. memcpy(&tileY, marker, sizeof(int));
  4845. tinyexr::swap4(&tileY);
  4846. marker += sizeof(int);
  4847. int levelX;
  4848. memcpy(&levelX, marker, sizeof(int));
  4849. tinyexr::swap4(&levelX);
  4850. marker += sizeof(int);
  4851. int levelY;
  4852. memcpy(&levelY, marker, sizeof(int));
  4853. tinyexr::swap4(&levelY);
  4854. marker += sizeof(int);
  4855. if (isDeep) {
  4856. if ((marker + 2 * sizeof(tinyexr::tinyexr_int64)) >= (head + size)) {
  4857. return false;
  4858. }
  4859. tinyexr::tinyexr_int64 packed_offset_table_size;
  4860. memcpy(&packed_offset_table_size, marker, sizeof(tinyexr::tinyexr_int64));
  4861. tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64*>(&packed_offset_table_size));
  4862. marker += sizeof(tinyexr::tinyexr_int64);
  4863. tinyexr::tinyexr_int64 packed_sample_size;
  4864. memcpy(&packed_sample_size, marker, sizeof(tinyexr::tinyexr_int64));
  4865. tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64*>(&packed_sample_size));
  4866. marker += sizeof(tinyexr::tinyexr_int64);
  4867. // next Int64 is unpacked sample size - skip that too
  4868. marker += packed_offset_table_size + packed_sample_size + 8;
  4869. if (marker >= (head + size)) {
  4870. return false;
  4871. }
  4872. } else {
  4873. if ((marker + sizeof(uint32_t)) >= (head + size)) {
  4874. return false;
  4875. }
  4876. uint32_t dataSize;
  4877. memcpy(&dataSize, marker, sizeof(uint32_t));
  4878. tinyexr::swap4(&dataSize);
  4879. marker += sizeof(uint32_t);
  4880. marker += dataSize;
  4881. if (marker >= (head + size)) {
  4882. return false;
  4883. }
  4884. }
  4885. if (!isValidTile(exr_header, offset_data,
  4886. tileX, tileY, levelX, levelY)) {
  4887. return false;
  4888. }
  4889. int level_idx = LevelIndex(levelX, levelY, exr_header->tile_level_mode, numXLevels);
  4890. if (level_idx < 0) {
  4891. return false;
  4892. }
  4893. if (size_t(level_idx) >= offset_data.offsets.size()) {
  4894. return false;
  4895. }
  4896. if (size_t(tileY) >= offset_data.offsets[size_t(level_idx)].size()) {
  4897. return false;
  4898. }
  4899. if (size_t(tileX) >= offset_data.offsets[size_t(level_idx)][size_t(tileY)].size()) {
  4900. return false;
  4901. }
  4902. offset_data.offsets[size_t(level_idx)][size_t(tileY)][size_t(tileX)] = tileOffset;
  4903. }
  4904. }
  4905. }
  4906. return true;
  4907. }
  4908. // marker output is also
  4909. static int ReadOffsets(OffsetData& offset_data,
  4910. const unsigned char* head,
  4911. const unsigned char*& marker,
  4912. const size_t size,
  4913. const char** err) {
  4914. for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) {
  4915. for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) {
  4916. for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) {
  4917. tinyexr::tinyexr_uint64 offset;
  4918. if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) {
  4919. tinyexr::SetErrorMessage("Insufficient data size in offset table.", err);
  4920. return TINYEXR_ERROR_INVALID_DATA;
  4921. }
  4922. memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64));
  4923. tinyexr::swap8(&offset);
  4924. if (offset >= size) {
  4925. tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err);
  4926. return TINYEXR_ERROR_INVALID_DATA;
  4927. }
  4928. marker += sizeof(tinyexr::tinyexr_uint64); // = 8
  4929. offset_data.offsets[l][dy][dx] = offset;
  4930. }
  4931. }
  4932. }
  4933. return TINYEXR_SUCCESS;
  4934. }
  4935. static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
  4936. const unsigned char *head,
  4937. const unsigned char *marker, const size_t size,
  4938. const char **err) {
  4939. if (exr_image == NULL || exr_header == NULL || head == NULL ||
  4940. marker == NULL || (size <= tinyexr::kEXRVersionSize)) {
  4941. tinyexr::SetErrorMessage("Invalid argument for DecodeEXRImage().", err);
  4942. return TINYEXR_ERROR_INVALID_ARGUMENT;
  4943. }
  4944. int num_scanline_blocks = 1;
  4945. if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
  4946. num_scanline_blocks = 16;
  4947. } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
  4948. num_scanline_blocks = 32;
  4949. } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  4950. num_scanline_blocks = 16;
  4951. }
  4952. if (exr_header->data_window.max_x < exr_header->data_window.min_x ||
  4953. exr_header->data_window.max_x - exr_header->data_window.min_x ==
  4954. std::numeric_limits<int>::max()) {
  4955. // Issue 63
  4956. tinyexr::SetErrorMessage("Invalid data width value", err);
  4957. return TINYEXR_ERROR_INVALID_DATA;
  4958. }
  4959. tinyexr_int64 data_width =
  4960. static_cast<tinyexr_int64>(exr_header->data_window.max_x) - static_cast<tinyexr_int64>(exr_header->data_window.min_x) + static_cast<tinyexr_int64>(1);
  4961. if (data_width <= 0) {
  4962. tinyexr::SetErrorMessage("Invalid data window width value", err);
  4963. return TINYEXR_ERROR_INVALID_DATA;
  4964. }
  4965. if (exr_header->data_window.max_y < exr_header->data_window.min_y ||
  4966. exr_header->data_window.max_y - exr_header->data_window.min_y ==
  4967. std::numeric_limits<int>::max()) {
  4968. tinyexr::SetErrorMessage("Invalid data height value", err);
  4969. return TINYEXR_ERROR_INVALID_DATA;
  4970. }
  4971. tinyexr_int64 data_height =
  4972. static_cast<tinyexr_int64>(exr_header->data_window.max_y) - static_cast<tinyexr_int64>(exr_header->data_window.min_y) + static_cast<tinyexr_int64>(1);
  4973. if (data_height <= 0) {
  4974. tinyexr::SetErrorMessage("Invalid data window height value", err);
  4975. return TINYEXR_ERROR_INVALID_DATA;
  4976. }
  4977. // Do not allow too large data_width and data_height. header invalid?
  4978. {
  4979. if (data_width > TINYEXR_DIMENSION_THRESHOLD) {
  4980. tinyexr::SetErrorMessage("data width too large.", err);
  4981. return TINYEXR_ERROR_INVALID_DATA;
  4982. }
  4983. if (data_height > TINYEXR_DIMENSION_THRESHOLD) {
  4984. tinyexr::SetErrorMessage("data height too large.", err);
  4985. return TINYEXR_ERROR_INVALID_DATA;
  4986. }
  4987. }
  4988. if (exr_header->tiled) {
  4989. if (exr_header->tile_size_x > TINYEXR_DIMENSION_THRESHOLD) {
  4990. tinyexr::SetErrorMessage("tile width too large.", err);
  4991. return TINYEXR_ERROR_INVALID_DATA;
  4992. }
  4993. if (exr_header->tile_size_y > TINYEXR_DIMENSION_THRESHOLD) {
  4994. tinyexr::SetErrorMessage("tile height too large.", err);
  4995. return TINYEXR_ERROR_INVALID_DATA;
  4996. }
  4997. }
  4998. // Read offset tables.
  4999. OffsetData offset_data;
  5000. size_t num_blocks = 0;
  5001. // For a multi-resolution image, the size of the offset table will be calculated from the other attributes of the header.
  5002. // If chunk_count > 0 then chunk_count must be equal to the calculated tile count.
  5003. if (exr_header->tiled) {
  5004. {
  5005. std::vector<int> num_x_tiles, num_y_tiles;
  5006. if (!PrecalculateTileInfo(num_x_tiles, num_y_tiles, exr_header)) {
  5007. tinyexr::SetErrorMessage("Failed to precalculate tile info.", err);
  5008. return TINYEXR_ERROR_INVALID_DATA;
  5009. }
  5010. num_blocks = size_t(InitTileOffsets(offset_data, exr_header, num_x_tiles, num_y_tiles));
  5011. if (exr_header->chunk_count > 0) {
  5012. if (exr_header->chunk_count != static_cast<int>(num_blocks)) {
  5013. tinyexr::SetErrorMessage("Invalid offset table size.", err);
  5014. return TINYEXR_ERROR_INVALID_DATA;
  5015. }
  5016. }
  5017. }
  5018. int ret = ReadOffsets(offset_data, head, marker, size, err);
  5019. if (ret != TINYEXR_SUCCESS) return ret;
  5020. if (IsAnyOffsetsAreInvalid(offset_data)) {
  5021. if (!ReconstructTileOffsets(offset_data, exr_header,
  5022. head, marker, size,
  5023. exr_header->multipart, exr_header->non_image)) {
  5024. tinyexr::SetErrorMessage("Invalid Tile Offsets data.", err);
  5025. return TINYEXR_ERROR_INVALID_DATA;
  5026. }
  5027. }
  5028. } else if (exr_header->chunk_count > 0) {
  5029. // Use `chunkCount` attribute.
  5030. num_blocks = static_cast<size_t>(exr_header->chunk_count);
  5031. InitSingleResolutionOffsets(offset_data, num_blocks);
  5032. } else {
  5033. num_blocks = static_cast<size_t>(data_height) /
  5034. static_cast<size_t>(num_scanline_blocks);
  5035. if (num_blocks * static_cast<size_t>(num_scanline_blocks) <
  5036. static_cast<size_t>(data_height)) {
  5037. num_blocks++;
  5038. }
  5039. InitSingleResolutionOffsets(offset_data, num_blocks);
  5040. }
  5041. if (!exr_header->tiled) {
  5042. std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data.offsets[0][0];
  5043. for (size_t y = 0; y < num_blocks; y++) {
  5044. tinyexr::tinyexr_uint64 offset;
  5045. // Issue #81
  5046. if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) {
  5047. tinyexr::SetErrorMessage("Insufficient data size in offset table.", err);
  5048. return TINYEXR_ERROR_INVALID_DATA;
  5049. }
  5050. memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64));
  5051. tinyexr::swap8(&offset);
  5052. if (offset >= size) {
  5053. tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err);
  5054. return TINYEXR_ERROR_INVALID_DATA;
  5055. }
  5056. marker += sizeof(tinyexr::tinyexr_uint64); // = 8
  5057. offsets[y] = offset;
  5058. }
  5059. // If line offsets are invalid, we try to reconstruct it.
  5060. // See OpenEXR/IlmImf/ImfScanLineInputFile.cpp::readLineOffsets() for details.
  5061. for (size_t y = 0; y < num_blocks; y++) {
  5062. if (offsets[y] <= 0) {
  5063. // TODO(syoyo) Report as warning?
  5064. // if (err) {
  5065. // stringstream ss;
  5066. // ss << "Incomplete lineOffsets." << std::endl;
  5067. // (*err) += ss.str();
  5068. //}
  5069. bool ret =
  5070. ReconstructLineOffsets(&offsets, num_blocks, head, marker, size);
  5071. if (ret) {
  5072. // OK
  5073. break;
  5074. } else {
  5075. tinyexr::SetErrorMessage(
  5076. "Cannot reconstruct lineOffset table in DecodeEXRImage.", err);
  5077. return TINYEXR_ERROR_INVALID_DATA;
  5078. }
  5079. }
  5080. }
  5081. }
  5082. {
  5083. std::string e;
  5084. int ret = DecodeChunk(exr_image, exr_header, offset_data, head, size, &e);
  5085. if (ret != TINYEXR_SUCCESS) {
  5086. if (!e.empty()) {
  5087. tinyexr::SetErrorMessage(e, err);
  5088. }
  5089. #if 1
  5090. FreeEXRImage(exr_image);
  5091. #else
  5092. // release memory(if exists)
  5093. if ((exr_header->num_channels > 0) && exr_image && exr_image->images) {
  5094. for (size_t c = 0; c < size_t(exr_header->num_channels); c++) {
  5095. if (exr_image->images[c]) {
  5096. free(exr_image->images[c]);
  5097. exr_image->images[c] = NULL;
  5098. }
  5099. }
  5100. free(exr_image->images);
  5101. exr_image->images = NULL;
  5102. }
  5103. #endif
  5104. }
  5105. return ret;
  5106. }
  5107. }
  5108. static void GetLayers(const EXRHeader &exr_header,
  5109. std::vector<std::string> &layer_names) {
  5110. // Naive implementation
  5111. // Group channels by layers
  5112. // go over all channel names, split by periods
  5113. // collect unique names
  5114. layer_names.clear();
  5115. for (int c = 0; c < exr_header.num_channels; c++) {
  5116. std::string full_name(exr_header.channels[c].name);
  5117. const size_t pos = full_name.find_last_of('.');
  5118. if (pos != std::string::npos && pos != 0 && pos + 1 < full_name.size()) {
  5119. full_name.erase(pos);
  5120. if (std::find(layer_names.begin(), layer_names.end(), full_name) ==
  5121. layer_names.end())
  5122. layer_names.push_back(full_name);
  5123. }
  5124. }
  5125. }
  5126. struct LayerChannel {
  5127. explicit LayerChannel(size_t i, std::string n) : index(i), name(n) {}
  5128. size_t index;
  5129. std::string name;
  5130. };
  5131. static void ChannelsInLayer(const EXRHeader &exr_header,
  5132. const std::string &layer_name,
  5133. std::vector<LayerChannel> &channels) {
  5134. channels.clear();
  5135. //std::cout << "layer_name = " << layer_name << "\n";
  5136. for (int c = 0; c < exr_header.num_channels; c++) {
  5137. //std::cout << "chan[" << c << "] = " << exr_header.channels[c].name << "\n";
  5138. std::string ch_name(exr_header.channels[c].name);
  5139. if (layer_name.empty()) {
  5140. const size_t pos = ch_name.find_last_of('.');
  5141. if (pos != std::string::npos && pos < ch_name.size()) {
  5142. if (pos != 0) continue;
  5143. ch_name = ch_name.substr(pos + 1);
  5144. }
  5145. } else {
  5146. const size_t pos = ch_name.find(layer_name + '.');
  5147. if (pos == std::string::npos) continue;
  5148. if (pos == 0) {
  5149. ch_name = ch_name.substr(layer_name.size() + 1);
  5150. }
  5151. }
  5152. LayerChannel ch(size_t(c), ch_name);
  5153. channels.push_back(ch);
  5154. }
  5155. }
  5156. } // namespace tinyexr
  5157. int EXRLayers(const char *filename, const char **layer_names[], int *num_layers,
  5158. const char **err) {
  5159. EXRVersion exr_version;
  5160. EXRHeader exr_header;
  5161. InitEXRHeader(&exr_header);
  5162. {
  5163. int ret = ParseEXRVersionFromFile(&exr_version, filename);
  5164. if (ret != TINYEXR_SUCCESS) {
  5165. tinyexr::SetErrorMessage("Invalid EXR header.", err);
  5166. return ret;
  5167. }
  5168. if (exr_version.multipart || exr_version.non_image) {
  5169. tinyexr::SetErrorMessage(
  5170. "Loading multipart or DeepImage is not supported in LoadEXR() API",
  5171. err);
  5172. return TINYEXR_ERROR_INVALID_DATA; // @fixme.
  5173. }
  5174. }
  5175. int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err);
  5176. if (ret != TINYEXR_SUCCESS) {
  5177. FreeEXRHeader(&exr_header);
  5178. return ret;
  5179. }
  5180. std::vector<std::string> layer_vec;
  5181. tinyexr::GetLayers(exr_header, layer_vec);
  5182. (*num_layers) = int(layer_vec.size());
  5183. (*layer_names) = static_cast<const char **>(
  5184. malloc(sizeof(const char *) * static_cast<size_t>(layer_vec.size())));
  5185. for (size_t c = 0; c < static_cast<size_t>(layer_vec.size()); c++) {
  5186. #ifdef _MSC_VER
  5187. (*layer_names)[c] = _strdup(layer_vec[c].c_str());
  5188. #else
  5189. (*layer_names)[c] = strdup(layer_vec[c].c_str());
  5190. #endif
  5191. }
  5192. FreeEXRHeader(&exr_header);
  5193. return TINYEXR_SUCCESS;
  5194. }
  5195. int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
  5196. const char **err) {
  5197. return LoadEXRWithLayer(out_rgba, width, height, filename,
  5198. /* layername */ NULL, err);
  5199. }
  5200. int LoadEXRWithLayer(float **out_rgba, int *width, int *height,
  5201. const char *filename, const char *layername,
  5202. const char **err) {
  5203. if (out_rgba == NULL) {
  5204. tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err);
  5205. return TINYEXR_ERROR_INVALID_ARGUMENT;
  5206. }
  5207. EXRVersion exr_version;
  5208. EXRImage exr_image;
  5209. EXRHeader exr_header;
  5210. InitEXRHeader(&exr_header);
  5211. InitEXRImage(&exr_image);
  5212. {
  5213. int ret = ParseEXRVersionFromFile(&exr_version, filename);
  5214. if (ret != TINYEXR_SUCCESS) {
  5215. std::stringstream ss;
  5216. ss << "Failed to open EXR file or read version info from EXR file. code("
  5217. << ret << ")";
  5218. tinyexr::SetErrorMessage(ss.str(), err);
  5219. return ret;
  5220. }
  5221. if (exr_version.multipart || exr_version.non_image) {
  5222. tinyexr::SetErrorMessage(
  5223. "Loading multipart or DeepImage is not supported in LoadEXR() API",
  5224. err);
  5225. return TINYEXR_ERROR_INVALID_DATA; // @fixme.
  5226. }
  5227. }
  5228. {
  5229. int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err);
  5230. if (ret != TINYEXR_SUCCESS) {
  5231. FreeEXRHeader(&exr_header);
  5232. return ret;
  5233. }
  5234. }
  5235. // Read HALF channel as FLOAT.
  5236. for (int i = 0; i < exr_header.num_channels; i++) {
  5237. if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
  5238. exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
  5239. }
  5240. }
  5241. // TODO: Probably limit loading to layers (channels) selected by layer index
  5242. {
  5243. int ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename, err);
  5244. if (ret != TINYEXR_SUCCESS) {
  5245. FreeEXRHeader(&exr_header);
  5246. return ret;
  5247. }
  5248. }
  5249. // RGBA
  5250. int idxR = -1;
  5251. int idxG = -1;
  5252. int idxB = -1;
  5253. int idxA = -1;
  5254. std::vector<std::string> layer_names;
  5255. tinyexr::GetLayers(exr_header, layer_names);
  5256. std::vector<tinyexr::LayerChannel> channels;
  5257. tinyexr::ChannelsInLayer(
  5258. exr_header, layername == NULL ? "" : std::string(layername), channels);
  5259. if (channels.size() < 1) {
  5260. if (layername == NULL) {
  5261. tinyexr::SetErrorMessage("Layer Not Found. Seems EXR contains channels with layer(e.g. `diffuse.R`). if you are using LoadEXR(), please try LoadEXRWithLayer(). LoadEXR() cannot load EXR having channels with layer.", err);
  5262. } else {
  5263. tinyexr::SetErrorMessage("Layer Not Found", err);
  5264. }
  5265. FreeEXRHeader(&exr_header);
  5266. FreeEXRImage(&exr_image);
  5267. return TINYEXR_ERROR_LAYER_NOT_FOUND;
  5268. }
  5269. size_t ch_count = channels.size() < 4 ? channels.size() : 4;
  5270. for (size_t c = 0; c < ch_count; c++) {
  5271. const tinyexr::LayerChannel &ch = channels[c];
  5272. if (ch.name == "R") {
  5273. idxR = int(ch.index);
  5274. } else if (ch.name == "G") {
  5275. idxG = int(ch.index);
  5276. } else if (ch.name == "B") {
  5277. idxB = int(ch.index);
  5278. } else if (ch.name == "A") {
  5279. idxA = int(ch.index);
  5280. }
  5281. }
  5282. if (channels.size() == 1) {
  5283. int chIdx = int(channels.front().index);
  5284. // Grayscale channel only.
  5285. (*out_rgba) = reinterpret_cast<float *>(
  5286. malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
  5287. static_cast<size_t>(exr_image.height)));
  5288. if (exr_header.tiled) {
  5289. const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x);
  5290. const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y);
  5291. for (int it = 0; it < exr_image.num_tiles; it++) {
  5292. for (size_t j = 0; j < tile_size_y; j++) {
  5293. for (size_t i = 0; i < tile_size_x; i++) {
  5294. const size_t ii =
  5295. static_cast<size_t>(exr_image.tiles[it].offset_x) * tile_size_x +
  5296. i;
  5297. const size_t jj =
  5298. static_cast<size_t>(exr_image.tiles[it].offset_y) * tile_size_y +
  5299. j;
  5300. const size_t idx = ii + jj * static_cast<size_t>(exr_image.width);
  5301. // out of region check.
  5302. if (ii >= static_cast<size_t>(exr_image.width)) {
  5303. continue;
  5304. }
  5305. if (jj >= static_cast<size_t>(exr_image.height)) {
  5306. continue;
  5307. }
  5308. const size_t srcIdx = i + j * tile_size_x;
  5309. unsigned char **src = exr_image.tiles[it].images;
  5310. (*out_rgba)[4 * idx + 0] =
  5311. reinterpret_cast<float **>(src)[chIdx][srcIdx];
  5312. (*out_rgba)[4 * idx + 1] =
  5313. reinterpret_cast<float **>(src)[chIdx][srcIdx];
  5314. (*out_rgba)[4 * idx + 2] =
  5315. reinterpret_cast<float **>(src)[chIdx][srcIdx];
  5316. (*out_rgba)[4 * idx + 3] =
  5317. reinterpret_cast<float **>(src)[chIdx][srcIdx];
  5318. }
  5319. }
  5320. }
  5321. } else {
  5322. const size_t pixel_size = static_cast<size_t>(exr_image.width) *
  5323. static_cast<size_t>(exr_image.height);
  5324. for (size_t i = 0; i < pixel_size; i++) {
  5325. const float val =
  5326. reinterpret_cast<float **>(exr_image.images)[chIdx][i];
  5327. (*out_rgba)[4 * i + 0] = val;
  5328. (*out_rgba)[4 * i + 1] = val;
  5329. (*out_rgba)[4 * i + 2] = val;
  5330. (*out_rgba)[4 * i + 3] = val;
  5331. }
  5332. }
  5333. } else {
  5334. // Assume RGB(A)
  5335. if (idxR == -1) {
  5336. tinyexr::SetErrorMessage("R channel not found", err);
  5337. FreeEXRHeader(&exr_header);
  5338. FreeEXRImage(&exr_image);
  5339. return TINYEXR_ERROR_INVALID_DATA;
  5340. }
  5341. if (idxG == -1) {
  5342. tinyexr::SetErrorMessage("G channel not found", err);
  5343. FreeEXRHeader(&exr_header);
  5344. FreeEXRImage(&exr_image);
  5345. return TINYEXR_ERROR_INVALID_DATA;
  5346. }
  5347. if (idxB == -1) {
  5348. tinyexr::SetErrorMessage("B channel not found", err);
  5349. FreeEXRHeader(&exr_header);
  5350. FreeEXRImage(&exr_image);
  5351. return TINYEXR_ERROR_INVALID_DATA;
  5352. }
  5353. (*out_rgba) = reinterpret_cast<float *>(
  5354. malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
  5355. static_cast<size_t>(exr_image.height)));
  5356. if (exr_header.tiled) {
  5357. const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x);
  5358. const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y);
  5359. for (int it = 0; it < exr_image.num_tiles; it++) {
  5360. for (size_t j = 0; j < tile_size_y; j++) {
  5361. for (size_t i = 0; i < tile_size_x; i++) {
  5362. const size_t ii =
  5363. static_cast<size_t>(exr_image.tiles[it].offset_x) *
  5364. tile_size_x +
  5365. i;
  5366. const size_t jj =
  5367. static_cast<size_t>(exr_image.tiles[it].offset_y) *
  5368. tile_size_y +
  5369. j;
  5370. const size_t idx = ii + jj * static_cast<size_t>(exr_image.width);
  5371. // out of region check.
  5372. if (ii >= static_cast<size_t>(exr_image.width)) {
  5373. continue;
  5374. }
  5375. if (jj >= static_cast<size_t>(exr_image.height)) {
  5376. continue;
  5377. }
  5378. const size_t srcIdx = i + j * tile_size_x;
  5379. unsigned char **src = exr_image.tiles[it].images;
  5380. (*out_rgba)[4 * idx + 0] =
  5381. reinterpret_cast<float **>(src)[idxR][srcIdx];
  5382. (*out_rgba)[4 * idx + 1] =
  5383. reinterpret_cast<float **>(src)[idxG][srcIdx];
  5384. (*out_rgba)[4 * idx + 2] =
  5385. reinterpret_cast<float **>(src)[idxB][srcIdx];
  5386. if (idxA != -1) {
  5387. (*out_rgba)[4 * idx + 3] =
  5388. reinterpret_cast<float **>(src)[idxA][srcIdx];
  5389. } else {
  5390. (*out_rgba)[4 * idx + 3] = 1.0;
  5391. }
  5392. }
  5393. }
  5394. }
  5395. } else {
  5396. const size_t pixel_size = static_cast<size_t>(exr_image.width) *
  5397. static_cast<size_t>(exr_image.height);
  5398. for (size_t i = 0; i < pixel_size; i++) {
  5399. (*out_rgba)[4 * i + 0] =
  5400. reinterpret_cast<float **>(exr_image.images)[idxR][i];
  5401. (*out_rgba)[4 * i + 1] =
  5402. reinterpret_cast<float **>(exr_image.images)[idxG][i];
  5403. (*out_rgba)[4 * i + 2] =
  5404. reinterpret_cast<float **>(exr_image.images)[idxB][i];
  5405. if (idxA != -1) {
  5406. (*out_rgba)[4 * i + 3] =
  5407. reinterpret_cast<float **>(exr_image.images)[idxA][i];
  5408. } else {
  5409. (*out_rgba)[4 * i + 3] = 1.0;
  5410. }
  5411. }
  5412. }
  5413. }
  5414. (*width) = exr_image.width;
  5415. (*height) = exr_image.height;
  5416. FreeEXRHeader(&exr_header);
  5417. FreeEXRImage(&exr_image);
  5418. return TINYEXR_SUCCESS;
  5419. }
  5420. int IsEXR(const char *filename) {
  5421. EXRVersion exr_version;
  5422. int ret = ParseEXRVersionFromFile(&exr_version, filename);
  5423. if (ret != TINYEXR_SUCCESS) {
  5424. return ret;
  5425. }
  5426. return TINYEXR_SUCCESS;
  5427. }
  5428. int IsEXRFromMemory(const unsigned char *memory, size_t size) {
  5429. EXRVersion exr_version;
  5430. int ret = ParseEXRVersionFromMemory(&exr_version, memory, size);
  5431. if (ret != TINYEXR_SUCCESS) {
  5432. return ret;
  5433. }
  5434. return TINYEXR_SUCCESS;
  5435. }
  5436. int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
  5437. const unsigned char *memory, size_t size,
  5438. const char **err) {
  5439. if (memory == NULL || exr_header == NULL) {
  5440. tinyexr::SetErrorMessage(
  5441. "Invalid argument. `memory` or `exr_header` argument is null in "
  5442. "ParseEXRHeaderFromMemory()",
  5443. err);
  5444. // Invalid argument
  5445. return TINYEXR_ERROR_INVALID_ARGUMENT;
  5446. }
  5447. if (size < tinyexr::kEXRVersionSize) {
  5448. tinyexr::SetErrorMessage("Insufficient header/data size.\n", err);
  5449. return TINYEXR_ERROR_INVALID_DATA;
  5450. }
  5451. const unsigned char *marker = memory + tinyexr::kEXRVersionSize;
  5452. size_t marker_size = size - tinyexr::kEXRVersionSize;
  5453. tinyexr::HeaderInfo info;
  5454. info.clear();
  5455. int ret;
  5456. {
  5457. std::string err_str;
  5458. ret = ParseEXRHeader(&info, NULL, version, &err_str, marker, marker_size);
  5459. if (ret != TINYEXR_SUCCESS) {
  5460. if (err && !err_str.empty()) {
  5461. tinyexr::SetErrorMessage(err_str, err);
  5462. }
  5463. }
  5464. }
  5465. {
  5466. std::string warn;
  5467. std::string err_str;
  5468. if (!ConvertHeader(exr_header, info, &warn, &err_str)) {
  5469. // release mem
  5470. for (size_t i = 0; i < info.attributes.size(); i++) {
  5471. if (info.attributes[i].value) {
  5472. free(info.attributes[i].value);
  5473. }
  5474. }
  5475. if (err && !err_str.empty()) {
  5476. tinyexr::SetErrorMessage(err_str, err);
  5477. }
  5478. ret = TINYEXR_ERROR_INVALID_HEADER;
  5479. }
  5480. }
  5481. exr_header->multipart = version->multipart ? 1 : 0;
  5482. exr_header->non_image = version->non_image ? 1 : 0;
  5483. return ret;
  5484. }
  5485. int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
  5486. const unsigned char *memory, size_t size,
  5487. const char **err) {
  5488. if (out_rgba == NULL || memory == NULL) {
  5489. tinyexr::SetErrorMessage("Invalid argument for LoadEXRFromMemory", err);
  5490. return TINYEXR_ERROR_INVALID_ARGUMENT;
  5491. }
  5492. EXRVersion exr_version;
  5493. EXRImage exr_image;
  5494. EXRHeader exr_header;
  5495. InitEXRHeader(&exr_header);
  5496. int ret = ParseEXRVersionFromMemory(&exr_version, memory, size);
  5497. if (ret != TINYEXR_SUCCESS) {
  5498. std::stringstream ss;
  5499. ss << "Failed to parse EXR version. code(" << ret << ")";
  5500. tinyexr::SetErrorMessage(ss.str(), err);
  5501. return ret;
  5502. }
  5503. ret = ParseEXRHeaderFromMemory(&exr_header, &exr_version, memory, size, err);
  5504. if (ret != TINYEXR_SUCCESS) {
  5505. return ret;
  5506. }
  5507. // Read HALF channel as FLOAT.
  5508. for (int i = 0; i < exr_header.num_channels; i++) {
  5509. if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
  5510. exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
  5511. }
  5512. }
  5513. InitEXRImage(&exr_image);
  5514. ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err);
  5515. if (ret != TINYEXR_SUCCESS) {
  5516. return ret;
  5517. }
  5518. // RGBA
  5519. int idxR = -1;
  5520. int idxG = -1;
  5521. int idxB = -1;
  5522. int idxA = -1;
  5523. for (int c = 0; c < exr_header.num_channels; c++) {
  5524. if (strcmp(exr_header.channels[c].name, "R") == 0) {
  5525. idxR = c;
  5526. } else if (strcmp(exr_header.channels[c].name, "G") == 0) {
  5527. idxG = c;
  5528. } else if (strcmp(exr_header.channels[c].name, "B") == 0) {
  5529. idxB = c;
  5530. } else if (strcmp(exr_header.channels[c].name, "A") == 0) {
  5531. idxA = c;
  5532. }
  5533. }
  5534. // TODO(syoyo): Refactor removing same code as used in LoadEXR().
  5535. if (exr_header.num_channels == 1) {
  5536. // Grayscale channel only.
  5537. (*out_rgba) = reinterpret_cast<float *>(
  5538. malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
  5539. static_cast<size_t>(exr_image.height)));
  5540. if (exr_header.tiled) {
  5541. const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x);
  5542. const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y);
  5543. for (int it = 0; it < exr_image.num_tiles; it++) {
  5544. for (size_t j = 0; j < tile_size_y; j++) {
  5545. for (size_t i = 0; i < tile_size_x; i++) {
  5546. const size_t ii =
  5547. static_cast<size_t>(exr_image.tiles[it].offset_x) *
  5548. tile_size_x +
  5549. i;
  5550. const size_t jj =
  5551. static_cast<size_t>(exr_image.tiles[it].offset_y) *
  5552. tile_size_y +
  5553. j;
  5554. const size_t idx = ii + jj * static_cast<size_t>(exr_image.width);
  5555. // out of region check.
  5556. if (ii >= static_cast<size_t>(exr_image.width)) {
  5557. continue;
  5558. }
  5559. if (jj >= static_cast<size_t>(exr_image.height)) {
  5560. continue;
  5561. }
  5562. const size_t srcIdx = i + j * tile_size_x;
  5563. unsigned char **src = exr_image.tiles[it].images;
  5564. (*out_rgba)[4 * idx + 0] =
  5565. reinterpret_cast<float **>(src)[0][srcIdx];
  5566. (*out_rgba)[4 * idx + 1] =
  5567. reinterpret_cast<float **>(src)[0][srcIdx];
  5568. (*out_rgba)[4 * idx + 2] =
  5569. reinterpret_cast<float **>(src)[0][srcIdx];
  5570. (*out_rgba)[4 * idx + 3] =
  5571. reinterpret_cast<float **>(src)[0][srcIdx];
  5572. }
  5573. }
  5574. }
  5575. } else {
  5576. const size_t pixel_size = static_cast<size_t>(exr_image.width) *
  5577. static_cast<size_t>(exr_image.height);
  5578. for (size_t i = 0; i < pixel_size; i++) {
  5579. const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
  5580. (*out_rgba)[4 * i + 0] = val;
  5581. (*out_rgba)[4 * i + 1] = val;
  5582. (*out_rgba)[4 * i + 2] = val;
  5583. (*out_rgba)[4 * i + 3] = val;
  5584. }
  5585. }
  5586. } else {
  5587. // TODO(syoyo): Support non RGBA image.
  5588. if (idxR == -1) {
  5589. tinyexr::SetErrorMessage("R channel not found", err);
  5590. // @todo { free exr_image }
  5591. return TINYEXR_ERROR_INVALID_DATA;
  5592. }
  5593. if (idxG == -1) {
  5594. tinyexr::SetErrorMessage("G channel not found", err);
  5595. // @todo { free exr_image }
  5596. return TINYEXR_ERROR_INVALID_DATA;
  5597. }
  5598. if (idxB == -1) {
  5599. tinyexr::SetErrorMessage("B channel not found", err);
  5600. // @todo { free exr_image }
  5601. return TINYEXR_ERROR_INVALID_DATA;
  5602. }
  5603. (*out_rgba) = reinterpret_cast<float *>(
  5604. malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
  5605. static_cast<size_t>(exr_image.height)));
  5606. if (exr_header.tiled) {
  5607. const size_t tile_size_x = static_cast<size_t>(exr_header.tile_size_x);
  5608. const size_t tile_size_y = static_cast<size_t>(exr_header.tile_size_y);
  5609. for (int it = 0; it < exr_image.num_tiles; it++) {
  5610. for (size_t j = 0; j < tile_size_y; j++)
  5611. for (size_t i = 0; i < tile_size_x; i++) {
  5612. const size_t ii =
  5613. static_cast<size_t>(exr_image.tiles[it].offset_x) *
  5614. tile_size_x +
  5615. i;
  5616. const size_t jj =
  5617. static_cast<size_t>(exr_image.tiles[it].offset_y) *
  5618. tile_size_y +
  5619. j;
  5620. const size_t idx = ii + jj * static_cast<size_t>(exr_image.width);
  5621. // out of region check.
  5622. if (ii >= static_cast<size_t>(exr_image.width)) {
  5623. continue;
  5624. }
  5625. if (jj >= static_cast<size_t>(exr_image.height)) {
  5626. continue;
  5627. }
  5628. const size_t srcIdx = i + j * tile_size_x;
  5629. unsigned char **src = exr_image.tiles[it].images;
  5630. (*out_rgba)[4 * idx + 0] =
  5631. reinterpret_cast<float **>(src)[idxR][srcIdx];
  5632. (*out_rgba)[4 * idx + 1] =
  5633. reinterpret_cast<float **>(src)[idxG][srcIdx];
  5634. (*out_rgba)[4 * idx + 2] =
  5635. reinterpret_cast<float **>(src)[idxB][srcIdx];
  5636. if (idxA != -1) {
  5637. (*out_rgba)[4 * idx + 3] =
  5638. reinterpret_cast<float **>(src)[idxA][srcIdx];
  5639. } else {
  5640. (*out_rgba)[4 * idx + 3] = 1.0;
  5641. }
  5642. }
  5643. }
  5644. } else {
  5645. const size_t pixel_size = static_cast<size_t>(exr_image.width) *
  5646. static_cast<size_t>(exr_image.height);
  5647. for (size_t i = 0; i < pixel_size; i++) {
  5648. (*out_rgba)[4 * i + 0] =
  5649. reinterpret_cast<float **>(exr_image.images)[idxR][i];
  5650. (*out_rgba)[4 * i + 1] =
  5651. reinterpret_cast<float **>(exr_image.images)[idxG][i];
  5652. (*out_rgba)[4 * i + 2] =
  5653. reinterpret_cast<float **>(exr_image.images)[idxB][i];
  5654. if (idxA != -1) {
  5655. (*out_rgba)[4 * i + 3] =
  5656. reinterpret_cast<float **>(exr_image.images)[idxA][i];
  5657. } else {
  5658. (*out_rgba)[4 * i + 3] = 1.0;
  5659. }
  5660. }
  5661. }
  5662. }
  5663. (*width) = exr_image.width;
  5664. (*height) = exr_image.height;
  5665. FreeEXRHeader(&exr_header);
  5666. FreeEXRImage(&exr_image);
  5667. return TINYEXR_SUCCESS;
  5668. }
  5669. // Represents a read-only file mapped to an address space in memory.
  5670. // If no memory-mapping API is available, falls back to allocating a buffer
  5671. // with a copy of the file's data.
  5672. struct MemoryMappedFile {
  5673. unsigned char *data; // To the start of the file's data.
  5674. size_t size; // The size of the file in bytes.
  5675. #ifdef TINYEXR_USE_WIN32_MMAP
  5676. HANDLE windows_file;
  5677. HANDLE windows_file_mapping;
  5678. #elif defined(TINYEXR_USE_POSIX_MMAP)
  5679. int posix_descriptor;
  5680. #endif
  5681. // MemoryMappedFile's constructor tries to map memory to a file.
  5682. // If this succeeds, valid() will return true and all fields
  5683. // are usable; otherwise, valid() will return false.
  5684. MemoryMappedFile(const char *filename) {
  5685. data = NULL;
  5686. size = 0;
  5687. #ifdef TINYEXR_USE_WIN32_MMAP
  5688. windows_file_mapping = NULL;
  5689. windows_file =
  5690. CreateFileW(tinyexr::UTF8ToWchar(filename).c_str(), // lpFileName
  5691. GENERIC_READ, // dwDesiredAccess
  5692. FILE_SHARE_READ, // dwShareMode
  5693. NULL, // lpSecurityAttributes
  5694. OPEN_EXISTING, // dwCreationDisposition
  5695. FILE_ATTRIBUTE_READONLY, // dwFlagsAndAttributes
  5696. NULL); // hTemplateFile
  5697. if (windows_file == INVALID_HANDLE_VALUE) {
  5698. return;
  5699. }
  5700. windows_file_mapping = CreateFileMapping(windows_file, // hFile
  5701. NULL, // lpFileMappingAttributes
  5702. PAGE_READONLY, // flProtect
  5703. 0, // dwMaximumSizeHigh
  5704. 0, // dwMaximumSizeLow
  5705. NULL); // lpName
  5706. if (windows_file_mapping == NULL) {
  5707. return;
  5708. }
  5709. data = reinterpret_cast<unsigned char *>(
  5710. MapViewOfFile(windows_file_mapping, // hFileMappingObject
  5711. FILE_MAP_READ, // dwDesiredAccess
  5712. 0, // dwFileOffsetHigh
  5713. 0, // dwFileOffsetLow
  5714. 0)); // dwNumberOfBytesToMap
  5715. if (!data) {
  5716. return;
  5717. }
  5718. LARGE_INTEGER windows_file_size = {};
  5719. if (!GetFileSizeEx(windows_file, &windows_file_size) ||
  5720. static_cast<ULONGLONG>(windows_file_size.QuadPart) >
  5721. std::numeric_limits<size_t>::max()) {
  5722. UnmapViewOfFile(data);
  5723. data = NULL;
  5724. return;
  5725. }
  5726. size = static_cast<size_t>(windows_file_size.QuadPart);
  5727. #elif defined(TINYEXR_USE_POSIX_MMAP)
  5728. posix_descriptor = open(filename, O_RDONLY);
  5729. if (posix_descriptor == -1) {
  5730. return;
  5731. }
  5732. struct stat info;
  5733. if (fstat(posix_descriptor, &info) < 0) {
  5734. return;
  5735. }
  5736. // Make sure st_size is in the valid range for a size_t. The second case
  5737. // can only fail if a POSIX implementation defines off_t to be a larger
  5738. // type than size_t - for instance, compiling with _FILE_OFFSET_BITS=64
  5739. // on a 32-bit system. On current 64-bit systems, this check can never
  5740. // fail, so we turn off clang's Wtautological-type-limit-compare warning
  5741. // around this code.
  5742. #ifdef __clang__
  5743. #pragma clang diagnostic push
  5744. #pragma clang diagnostic ignored "-Wtautological-type-limit-compare"
  5745. #endif
  5746. if (info.st_size < 0 ||
  5747. info.st_size > std::numeric_limits<ssize_t>::max()) {
  5748. return;
  5749. }
  5750. #ifdef __clang__
  5751. #pragma clang diagnostic pop
  5752. #endif
  5753. size = static_cast<size_t>(info.st_size);
  5754. data = reinterpret_cast<unsigned char *>(
  5755. mmap(0, size, PROT_READ, MAP_SHARED, posix_descriptor, 0));
  5756. if (data == MAP_FAILED) {
  5757. data = nullptr;
  5758. return;
  5759. }
  5760. #else
  5761. FILE *fp = fopen(filename, "rb");
  5762. if (!fp) {
  5763. return;
  5764. }
  5765. // Calling fseek(fp, 0, SEEK_END) isn't strictly-conforming C code, but
  5766. // since neither the WIN32 nor POSIX APIs are available in this branch, this
  5767. // is a reasonable fallback option.
  5768. if (fseek(fp, 0, SEEK_END) != 0) {
  5769. fclose(fp);
  5770. return;
  5771. }
  5772. const long ftell_result = ftell(fp);
  5773. if (ftell_result < 0) {
  5774. // Error from ftell
  5775. fclose(fp);
  5776. return;
  5777. }
  5778. size = static_cast<size_t>(ftell_result);
  5779. if (fseek(fp, 0, SEEK_SET) != 0) {
  5780. fclose(fp);
  5781. size = 0;
  5782. return;
  5783. }
  5784. data = reinterpret_cast<unsigned char *>(malloc(size));
  5785. if (!data) {
  5786. size = 0;
  5787. fclose(fp);
  5788. return;
  5789. }
  5790. size_t read_bytes = fread(data, 1, size, fp);
  5791. if (read_bytes != size) {
  5792. // TODO: Try to read data until reading `size` bytes.
  5793. fclose(fp);
  5794. size = 0;
  5795. data = nullptr;
  5796. return;
  5797. }
  5798. fclose(fp);
  5799. #endif
  5800. }
  5801. // MemoryMappedFile's destructor closes all its handles.
  5802. ~MemoryMappedFile() {
  5803. #ifdef TINYEXR_USE_WIN32_MMAP
  5804. if (data) {
  5805. (void)UnmapViewOfFile(data);
  5806. data = NULL;
  5807. }
  5808. if (windows_file_mapping != NULL) {
  5809. (void)CloseHandle(windows_file_mapping);
  5810. }
  5811. if (windows_file != INVALID_HANDLE_VALUE) {
  5812. (void)CloseHandle(windows_file);
  5813. }
  5814. #elif defined(TINYEXR_USE_POSIX_MMAP)
  5815. if (data) {
  5816. (void)munmap(data, size);
  5817. data = NULL;
  5818. }
  5819. if (posix_descriptor != -1) {
  5820. (void)close(posix_descriptor);
  5821. }
  5822. #else
  5823. if (data) {
  5824. (void)free(data);
  5825. }
  5826. data = NULL;
  5827. #endif
  5828. }
  5829. // A MemoryMappedFile cannot be copied or moved.
  5830. // Only check for this when compiling with C++11 or higher, since deleted
  5831. // function definitions were added then.
  5832. #if TINYEXR_HAS_CXX11
  5833. #ifdef __clang__
  5834. #pragma clang diagnostic push
  5835. #pragma clang diagnostic ignored "-Wc++98-compat"
  5836. #endif
  5837. MemoryMappedFile(const MemoryMappedFile &) = delete;
  5838. MemoryMappedFile &operator=(const MemoryMappedFile &) = delete;
  5839. MemoryMappedFile(MemoryMappedFile &&other) noexcept = delete;
  5840. MemoryMappedFile &operator=(MemoryMappedFile &&other) noexcept = delete;
  5841. #ifdef __clang__
  5842. #pragma clang diagnostic pop
  5843. #endif
  5844. #endif
  5845. // Returns whether this was successfully opened.
  5846. bool valid() const { return data; }
  5847. };
  5848. int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header,
  5849. const char *filename, const char **err) {
  5850. if (exr_image == NULL) {
  5851. tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromFile", err);
  5852. return TINYEXR_ERROR_INVALID_ARGUMENT;
  5853. }
  5854. MemoryMappedFile file(filename);
  5855. if (!file.valid()) {
  5856. tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
  5857. return TINYEXR_ERROR_CANT_OPEN_FILE;
  5858. }
  5859. if (file.size < 16) {
  5860. tinyexr::SetErrorMessage("File size too short : " + std::string(filename),
  5861. err);
  5862. return TINYEXR_ERROR_INVALID_FILE;
  5863. }
  5864. return LoadEXRImageFromMemory(exr_image, exr_header, file.data, file.size,
  5865. err);
  5866. }
  5867. int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header,
  5868. const unsigned char *memory, const size_t size,
  5869. const char **err) {
  5870. if (exr_image == NULL || memory == NULL ||
  5871. (size < tinyexr::kEXRVersionSize)) {
  5872. tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory",
  5873. err);
  5874. return TINYEXR_ERROR_INVALID_ARGUMENT;
  5875. }
  5876. if (exr_header->header_len == 0) {
  5877. tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err);
  5878. return TINYEXR_ERROR_INVALID_ARGUMENT;
  5879. }
  5880. const unsigned char *head = memory;
  5881. const unsigned char *marker = reinterpret_cast<const unsigned char *>(
  5882. memory + exr_header->header_len +
  5883. 8); // +8 for magic number + version header.
  5884. return tinyexr::DecodeEXRImage(exr_image, exr_header, head, marker, size,
  5885. err);
  5886. }
  5887. namespace tinyexr
  5888. {
  5889. #ifdef __clang__
  5890. #pragma clang diagnostic push
  5891. #pragma clang diagnostic ignored "-Wsign-conversion"
  5892. #endif
  5893. // out_data must be allocated initially with the block-header size
  5894. // of the current image(-part) type
  5895. static bool EncodePixelData(/* out */ std::vector<unsigned char>& out_data,
  5896. const unsigned char* const* images,
  5897. int compression_type,
  5898. int /*line_order*/,
  5899. int width, // for tiled : tile.width
  5900. int /*height*/, // for tiled : header.tile_size_y
  5901. int x_stride, // for tiled : header.tile_size_x
  5902. int line_no, // for tiled : 0
  5903. int num_lines, // for tiled : tile.height
  5904. size_t pixel_data_size,
  5905. const std::vector<ChannelInfo>& channels,
  5906. const std::vector<size_t>& channel_offset_list,
  5907. std::string *err,
  5908. const void* compression_param = 0) // zfp compression param
  5909. {
  5910. size_t buf_size = static_cast<size_t>(width) *
  5911. static_cast<size_t>(num_lines) *
  5912. static_cast<size_t>(pixel_data_size);
  5913. //int last2bit = (buf_size & 3);
  5914. // buf_size must be multiple of four
  5915. //if(last2bit) buf_size += 4 - last2bit;
  5916. std::vector<unsigned char> buf(buf_size);
  5917. size_t start_y = static_cast<size_t>(line_no);
  5918. for (size_t c = 0; c < channels.size(); c++) {
  5919. if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) {
  5920. if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  5921. for (int y = 0; y < num_lines; y++) {
  5922. // Assume increasing Y
  5923. float *line_ptr = reinterpret_cast<float *>(&buf.at(
  5924. static_cast<size_t>(pixel_data_size * size_t(y) * size_t(width)) +
  5925. channel_offset_list[c] *
  5926. static_cast<size_t>(width)));
  5927. for (int x = 0; x < width; x++) {
  5928. tinyexr::FP16 h16;
  5929. h16.u = reinterpret_cast<const unsigned short * const *>(
  5930. images)[c][(y + start_y) * size_t(x_stride) + size_t(x)];
  5931. tinyexr::FP32 f32 = half_to_float(h16);
  5932. tinyexr::swap4(&f32.f);
  5933. // line_ptr[x] = f32.f;
  5934. tinyexr::cpy4(line_ptr + x, &(f32.f));
  5935. }
  5936. }
  5937. } else if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) {
  5938. for (int y = 0; y < num_lines; y++) {
  5939. // Assume increasing Y
  5940. unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
  5941. &buf.at(static_cast<size_t>(pixel_data_size * y *
  5942. width) +
  5943. channel_offset_list[c] *
  5944. static_cast<size_t>(width)));
  5945. for (int x = 0; x < width; x++) {
  5946. unsigned short val = reinterpret_cast<const unsigned short * const *>(
  5947. images)[c][(y + start_y) * x_stride + x];
  5948. tinyexr::swap2(&val);
  5949. // line_ptr[x] = val;
  5950. tinyexr::cpy2(line_ptr + x, &val);
  5951. }
  5952. }
  5953. } else {
  5954. if (err) {
  5955. (*err) += "Invalid requested_pixel_type.\n";
  5956. }
  5957. return false;
  5958. }
  5959. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  5960. if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) {
  5961. for (int y = 0; y < num_lines; y++) {
  5962. // Assume increasing Y
  5963. unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
  5964. &buf.at(static_cast<size_t>(pixel_data_size * y *
  5965. width) +
  5966. channel_offset_list[c] *
  5967. static_cast<size_t>(width)));
  5968. for (int x = 0; x < width; x++) {
  5969. tinyexr::FP32 f32;
  5970. f32.f = reinterpret_cast<const float * const *>(
  5971. images)[c][(y + start_y) * x_stride + x];
  5972. tinyexr::FP16 h16;
  5973. h16 = float_to_half_full(f32);
  5974. tinyexr::swap2(reinterpret_cast<unsigned short *>(&h16.u));
  5975. // line_ptr[x] = h16.u;
  5976. tinyexr::cpy2(line_ptr + x, &(h16.u));
  5977. }
  5978. }
  5979. } else if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
  5980. for (int y = 0; y < num_lines; y++) {
  5981. // Assume increasing Y
  5982. float *line_ptr = reinterpret_cast<float *>(&buf.at(
  5983. static_cast<size_t>(pixel_data_size * y * width) +
  5984. channel_offset_list[c] *
  5985. static_cast<size_t>(width)));
  5986. for (int x = 0; x < width; x++) {
  5987. float val = reinterpret_cast<const float * const *>(
  5988. images)[c][(y + start_y) * x_stride + x];
  5989. tinyexr::swap4(&val);
  5990. // line_ptr[x] = val;
  5991. tinyexr::cpy4(line_ptr + x, &val);
  5992. }
  5993. }
  5994. } else {
  5995. if (err) {
  5996. (*err) += "Invalid requested_pixel_type.\n";
  5997. }
  5998. return false;
  5999. }
  6000. } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) {
  6001. for (int y = 0; y < num_lines; y++) {
  6002. // Assume increasing Y
  6003. unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at(
  6004. static_cast<size_t>(pixel_data_size * y * width) +
  6005. channel_offset_list[c] * static_cast<size_t>(width)));
  6006. for (int x = 0; x < width; x++) {
  6007. unsigned int val = reinterpret_cast<const unsigned int * const *>(
  6008. images)[c][(y + start_y) * x_stride + x];
  6009. tinyexr::swap4(&val);
  6010. // line_ptr[x] = val;
  6011. tinyexr::cpy4(line_ptr + x, &val);
  6012. }
  6013. }
  6014. }
  6015. }
  6016. if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) {
  6017. // 4 byte: scan line
  6018. // 4 byte: data size
  6019. // ~ : pixel data(uncompressed)
  6020. out_data.insert(out_data.end(), buf.begin(), buf.end());
  6021. } else if ((compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
  6022. (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
  6023. #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
  6024. std::vector<unsigned char> block(mz_compressBound(
  6025. static_cast<unsigned long>(buf.size())));
  6026. #elif TINYEXR_USE_STB_ZLIB
  6027. // there is no compressBound() function, so we use a value that
  6028. // is grossly overestimated, but should always work
  6029. std::vector<unsigned char> block(256 + 2 * buf.size());
  6030. #elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB == 1)
  6031. std::vector<unsigned char> block(nanoz_compressBound(
  6032. static_cast<unsigned long>(buf.size())));
  6033. #else
  6034. std::vector<unsigned char> block(
  6035. compressBound(static_cast<uLong>(buf.size())));
  6036. #endif
  6037. tinyexr::tinyexr_uint64 outSize = block.size();
  6038. if (!tinyexr::CompressZip(&block.at(0), outSize,
  6039. reinterpret_cast<const unsigned char *>(&buf.at(0)),
  6040. static_cast<unsigned long>(buf.size()))) {
  6041. if (err) {
  6042. (*err) += "Zip compresssion failed.\n";
  6043. }
  6044. return false;
  6045. }
  6046. // 4 byte: scan line
  6047. // 4 byte: data size
  6048. // ~ : pixel data(compressed)
  6049. unsigned int data_len = static_cast<unsigned int>(outSize); // truncate
  6050. out_data.insert(out_data.end(), block.begin(), block.begin() + data_len);
  6051. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) {
  6052. // (buf.size() * 3) / 2 would be enough.
  6053. std::vector<unsigned char> block((buf.size() * 3) / 2);
  6054. tinyexr::tinyexr_uint64 outSize = block.size();
  6055. if (!tinyexr::CompressRle(&block.at(0), outSize,
  6056. reinterpret_cast<const unsigned char *>(&buf.at(0)),
  6057. static_cast<unsigned long>(buf.size()))) {
  6058. if (err) {
  6059. (*err) += "RLE compresssion failed.\n";
  6060. }
  6061. return false;
  6062. }
  6063. // 4 byte: scan line
  6064. // 4 byte: data size
  6065. // ~ : pixel data(compressed)
  6066. unsigned int data_len = static_cast<unsigned int>(outSize); // truncate
  6067. out_data.insert(out_data.end(), block.begin(), block.begin() + data_len);
  6068. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
  6069. #if TINYEXR_USE_PIZ
  6070. unsigned int bufLen =
  6071. 8192 + static_cast<unsigned int>(
  6072. 2 * static_cast<unsigned int>(
  6073. buf.size())); // @fixme { compute good bound. }
  6074. std::vector<unsigned char> block(bufLen);
  6075. unsigned int outSize = static_cast<unsigned int>(block.size());
  6076. if (!CompressPiz(&block.at(0), &outSize,
  6077. reinterpret_cast<const unsigned char *>(&buf.at(0)),
  6078. buf.size(), channels, width, num_lines)) {
  6079. if (err) {
  6080. (*err) += "PIZ compresssion failed.\n";
  6081. }
  6082. return false;
  6083. }
  6084. // 4 byte: scan line
  6085. // 4 byte: data size
  6086. // ~ : pixel data(compressed)
  6087. unsigned int data_len = outSize;
  6088. out_data.insert(out_data.end(), block.begin(), block.begin() + data_len);
  6089. #else
  6090. if (err) {
  6091. (*err) += "PIZ compression is disabled in this build.\n";
  6092. }
  6093. return false;
  6094. #endif
  6095. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  6096. #if TINYEXR_USE_ZFP
  6097. const ZFPCompressionParam* zfp_compression_param = reinterpret_cast<const ZFPCompressionParam*>(compression_param);
  6098. std::vector<unsigned char> block;
  6099. unsigned int outSize;
  6100. tinyexr::CompressZfp(
  6101. &block, &outSize, reinterpret_cast<const float *>(&buf.at(0)),
  6102. width, num_lines, static_cast<int>(channels.size()), *zfp_compression_param);
  6103. // 4 byte: scan line
  6104. // 4 byte: data size
  6105. // ~ : pixel data(compressed)
  6106. unsigned int data_len = outSize;
  6107. out_data.insert(out_data.end(), block.begin(), block.begin() + data_len);
  6108. #else
  6109. if (err) {
  6110. (*err) += "ZFP compression is disabled in this build.\n";
  6111. }
  6112. (void)compression_param;
  6113. return false;
  6114. #endif
  6115. } else {
  6116. return false;
  6117. }
  6118. return true;
  6119. }
  6120. static int EncodeTiledLevel(const EXRImage* level_image, const EXRHeader* exr_header,
  6121. const std::vector<tinyexr::ChannelInfo>& channels,
  6122. std::vector<std::vector<unsigned char> >& data_list,
  6123. size_t start_index, // for data_list
  6124. int num_x_tiles, int num_y_tiles,
  6125. const std::vector<size_t>& channel_offset_list,
  6126. int pixel_data_size,
  6127. const void* compression_param, // must be set if zfp compression is enabled
  6128. std::string* err) {
  6129. int num_tiles = num_x_tiles * num_y_tiles;
  6130. if (num_tiles != level_image->num_tiles) {
  6131. if (err) {
  6132. (*err) += "Invalid number of tiles in argument.\n";
  6133. }
  6134. return TINYEXR_ERROR_INVALID_ARGUMENT;
  6135. }
  6136. if ((exr_header->tile_size_x > level_image->width || exr_header->tile_size_y > level_image->height) &&
  6137. level_image->level_x == 0 && level_image->level_y == 0) {
  6138. if (err) {
  6139. (*err) += "Failed to encode tile data.\n";
  6140. }
  6141. return TINYEXR_ERROR_INVALID_DATA;
  6142. }
  6143. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  6144. std::atomic<bool> invalid_data(false);
  6145. #else
  6146. bool invalid_data(false);
  6147. #endif
  6148. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  6149. std::vector<std::thread> workers;
  6150. std::atomic<int> tile_count(0);
  6151. int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
  6152. if (num_threads > int(num_tiles)) {
  6153. num_threads = int(num_tiles);
  6154. }
  6155. for (int t = 0; t < num_threads; t++) {
  6156. workers.emplace_back(std::thread([&]() {
  6157. int i = 0;
  6158. while ((i = tile_count++) < num_tiles) {
  6159. #else
  6160. // Use signed int since some OpenMP compiler doesn't allow unsigned type for
  6161. // `parallel for`
  6162. #if TINYEXR_USE_OPENMP
  6163. #pragma omp parallel for
  6164. #endif
  6165. for (int i = 0; i < num_tiles; i++) {
  6166. #endif
  6167. size_t tile_idx = static_cast<size_t>(i);
  6168. size_t data_idx = tile_idx + start_index;
  6169. int x_tile = i % num_x_tiles;
  6170. int y_tile = i / num_x_tiles;
  6171. EXRTile& tile = level_image->tiles[tile_idx];
  6172. const unsigned char* const* images =
  6173. static_cast<const unsigned char* const*>(tile.images);
  6174. data_list[data_idx].resize(5*sizeof(int));
  6175. size_t data_header_size = data_list[data_idx].size();
  6176. bool ret = EncodePixelData(data_list[data_idx],
  6177. images,
  6178. exr_header->compression_type,
  6179. 0, // increasing y
  6180. tile.width,
  6181. exr_header->tile_size_y,
  6182. exr_header->tile_size_x,
  6183. 0,
  6184. tile.height,
  6185. pixel_data_size,
  6186. channels,
  6187. channel_offset_list,
  6188. err, compression_param);
  6189. if (!ret) {
  6190. invalid_data = true;
  6191. continue;
  6192. }
  6193. if (data_list[data_idx].size() <= data_header_size) {
  6194. invalid_data = true;
  6195. continue;
  6196. }
  6197. int data_len = static_cast<int>(data_list[data_idx].size() - data_header_size);
  6198. //tileX, tileY, levelX, levelY // pixel_data_size(int)
  6199. memcpy(&data_list[data_idx][0], &x_tile, sizeof(int));
  6200. memcpy(&data_list[data_idx][4], &y_tile, sizeof(int));
  6201. memcpy(&data_list[data_idx][8], &level_image->level_x, sizeof(int));
  6202. memcpy(&data_list[data_idx][12], &level_image->level_y, sizeof(int));
  6203. memcpy(&data_list[data_idx][16], &data_len, sizeof(int));
  6204. swap4(reinterpret_cast<int*>(&data_list[data_idx][0]));
  6205. swap4(reinterpret_cast<int*>(&data_list[data_idx][4]));
  6206. swap4(reinterpret_cast<int*>(&data_list[data_idx][8]));
  6207. swap4(reinterpret_cast<int*>(&data_list[data_idx][12]));
  6208. swap4(reinterpret_cast<int*>(&data_list[data_idx][16]));
  6209. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  6210. }
  6211. }));
  6212. }
  6213. for (auto &t : workers) {
  6214. t.join();
  6215. }
  6216. #else
  6217. } // omp parallel
  6218. #endif
  6219. if (invalid_data) {
  6220. if (err) {
  6221. (*err) += "Failed to encode tile data.\n";
  6222. }
  6223. return TINYEXR_ERROR_INVALID_DATA;
  6224. }
  6225. return TINYEXR_SUCCESS;
  6226. }
  6227. static int NumScanlines(int compression_type) {
  6228. int num_scanlines = 1;
  6229. if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
  6230. num_scanlines = 16;
  6231. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
  6232. num_scanlines = 32;
  6233. } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  6234. num_scanlines = 16;
  6235. }
  6236. return num_scanlines;
  6237. }
  6238. static int EncodeChunk(const EXRImage* exr_image, const EXRHeader* exr_header,
  6239. const std::vector<ChannelInfo>& channels,
  6240. int num_blocks,
  6241. tinyexr_uint64 chunk_offset, // starting offset of current chunk
  6242. bool is_multipart,
  6243. OffsetData& offset_data, // output block offsets, must be initialized
  6244. std::vector<std::vector<unsigned char> >& data_list, // output
  6245. tinyexr_uint64& total_size, // output: ending offset of current chunk
  6246. std::string* err) {
  6247. int num_scanlines = NumScanlines(exr_header->compression_type);
  6248. data_list.resize(num_blocks);
  6249. std::vector<size_t> channel_offset_list(
  6250. static_cast<size_t>(exr_header->num_channels));
  6251. int pixel_data_size = 0;
  6252. {
  6253. size_t channel_offset = 0;
  6254. for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
  6255. channel_offset_list[c] = channel_offset;
  6256. if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_HALF) {
  6257. pixel_data_size += sizeof(unsigned short);
  6258. channel_offset += sizeof(unsigned short);
  6259. } else if (channels[c].requested_pixel_type ==
  6260. TINYEXR_PIXELTYPE_FLOAT) {
  6261. pixel_data_size += sizeof(float);
  6262. channel_offset += sizeof(float);
  6263. } else if (channels[c].requested_pixel_type == TINYEXR_PIXELTYPE_UINT) {
  6264. pixel_data_size += sizeof(unsigned int);
  6265. channel_offset += sizeof(unsigned int);
  6266. } else {
  6267. if (err) {
  6268. (*err) += "Invalid requested_pixel_type.\n";
  6269. }
  6270. return TINYEXR_ERROR_INVALID_DATA;
  6271. }
  6272. }
  6273. }
  6274. const void* compression_param = 0;
  6275. #if TINYEXR_USE_ZFP
  6276. tinyexr::ZFPCompressionParam zfp_compression_param;
  6277. // Use ZFP compression parameter from custom attributes(if such a parameter
  6278. // exists)
  6279. {
  6280. std::string e;
  6281. bool ret = tinyexr::FindZFPCompressionParam(
  6282. &zfp_compression_param, exr_header->custom_attributes,
  6283. exr_header->num_custom_attributes, &e);
  6284. if (!ret) {
  6285. // Use predefined compression parameter.
  6286. zfp_compression_param.type = 0;
  6287. zfp_compression_param.rate = 2;
  6288. }
  6289. compression_param = &zfp_compression_param;
  6290. }
  6291. #endif
  6292. tinyexr_uint64 offset = chunk_offset;
  6293. tinyexr_uint64 doffset = is_multipart ? 4u : 0u;
  6294. if (exr_image->tiles) {
  6295. const EXRImage* level_image = exr_image;
  6296. size_t block_idx = 0;
  6297. //tinyexr::tinyexr_uint64 block_data_size = 0;
  6298. int num_levels = (exr_header->tile_level_mode != TINYEXR_TILE_RIPMAP_LEVELS) ?
  6299. offset_data.num_x_levels : (offset_data.num_x_levels * offset_data.num_y_levels);
  6300. for (int level_index = 0; level_index < num_levels; ++level_index) {
  6301. if (!level_image) {
  6302. if (err) {
  6303. (*err) += "Invalid number of tiled levels for EncodeChunk\n";
  6304. }
  6305. return TINYEXR_ERROR_INVALID_DATA;
  6306. }
  6307. int level_index_from_image = LevelIndex(level_image->level_x, level_image->level_y,
  6308. exr_header->tile_level_mode, offset_data.num_x_levels);
  6309. if (level_index_from_image < 0) {
  6310. if (err) {
  6311. (*err) += "Invalid tile level mode\n";
  6312. }
  6313. return TINYEXR_ERROR_INVALID_DATA;
  6314. }
  6315. if (level_index_from_image != level_index) {
  6316. if (err) {
  6317. (*err) += "Incorrect level ordering in tiled image\n";
  6318. }
  6319. return TINYEXR_ERROR_INVALID_DATA;
  6320. }
  6321. int num_y_tiles = int(offset_data.offsets[level_index].size());
  6322. if (num_y_tiles <= 0) {
  6323. if (err) {
  6324. (*err) += "Invalid Y tile size\n";
  6325. }
  6326. return TINYEXR_ERROR_INVALID_DATA;
  6327. }
  6328. int num_x_tiles = int(offset_data.offsets[level_index][0].size());
  6329. if (num_x_tiles <= 0) {
  6330. if (err) {
  6331. (*err) += "Invalid X tile size\n";
  6332. }
  6333. return TINYEXR_ERROR_INVALID_DATA;
  6334. }
  6335. std::string e;
  6336. int ret = EncodeTiledLevel(level_image,
  6337. exr_header,
  6338. channels,
  6339. data_list,
  6340. block_idx,
  6341. num_x_tiles,
  6342. num_y_tiles,
  6343. channel_offset_list,
  6344. pixel_data_size,
  6345. compression_param,
  6346. &e);
  6347. if (ret != TINYEXR_SUCCESS) {
  6348. if (!e.empty() && err) {
  6349. (*err) += e;
  6350. }
  6351. return ret;
  6352. }
  6353. for (size_t j = 0; j < static_cast<size_t>(num_y_tiles); ++j)
  6354. for (size_t i = 0; i < static_cast<size_t>(num_x_tiles); ++i) {
  6355. offset_data.offsets[level_index][j][i] = offset;
  6356. swap8(reinterpret_cast<tinyexr_uint64*>(&offset_data.offsets[level_index][j][i]));
  6357. offset += data_list[block_idx].size() + doffset;
  6358. //block_data_size += data_list[block_idx].size();
  6359. ++block_idx;
  6360. }
  6361. level_image = level_image->next_level;
  6362. }
  6363. TINYEXR_CHECK_AND_RETURN_C(static_cast<int>(block_idx) == num_blocks, TINYEXR_ERROR_INVALID_DATA);
  6364. total_size = offset;
  6365. } else { // scanlines
  6366. std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data.offsets[0][0];
  6367. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  6368. std::atomic<bool> invalid_data(false);
  6369. std::vector<std::thread> workers;
  6370. std::atomic<int> block_count(0);
  6371. int num_threads = std::min(std::max(1, int(std::thread::hardware_concurrency())), num_blocks);
  6372. for (int t = 0; t < num_threads; t++) {
  6373. workers.emplace_back(std::thread([&]() {
  6374. int i = 0;
  6375. while ((i = block_count++) < num_blocks) {
  6376. #else
  6377. bool invalid_data(false);
  6378. #if TINYEXR_USE_OPENMP
  6379. #pragma omp parallel for
  6380. #endif
  6381. for (int i = 0; i < num_blocks; i++) {
  6382. #endif
  6383. int start_y = num_scanlines * i;
  6384. int end_Y = (std::min)(num_scanlines * (i + 1), exr_image->height);
  6385. int num_lines = end_Y - start_y;
  6386. const unsigned char* const* images =
  6387. static_cast<const unsigned char* const*>(exr_image->images);
  6388. data_list[i].resize(2*sizeof(int));
  6389. size_t data_header_size = data_list[i].size();
  6390. bool ret = EncodePixelData(data_list[i],
  6391. images,
  6392. exr_header->compression_type,
  6393. 0, // increasing y
  6394. exr_image->width,
  6395. exr_image->height,
  6396. exr_image->width,
  6397. start_y,
  6398. num_lines,
  6399. pixel_data_size,
  6400. channels,
  6401. channel_offset_list,
  6402. err,
  6403. compression_param);
  6404. if (!ret) {
  6405. invalid_data = true;
  6406. continue; // "break" cannot be used with OpenMP
  6407. }
  6408. if (data_list[i].size() <= data_header_size) {
  6409. invalid_data = true;
  6410. continue; // "break" cannot be used with OpenMP
  6411. }
  6412. int data_len = static_cast<int>(data_list[i].size() - data_header_size);
  6413. memcpy(&data_list[i][0], &start_y, sizeof(int));
  6414. memcpy(&data_list[i][4], &data_len, sizeof(int));
  6415. swap4(reinterpret_cast<int*>(&data_list[i][0]));
  6416. swap4(reinterpret_cast<int*>(&data_list[i][4]));
  6417. #if TINYEXR_HAS_CXX11 && (TINYEXR_USE_THREAD > 0)
  6418. }
  6419. }));
  6420. }
  6421. for (auto &t : workers) {
  6422. t.join();
  6423. }
  6424. #else
  6425. } // omp parallel
  6426. #endif
  6427. if (invalid_data) {
  6428. if (err) {
  6429. (*err) += "Failed to encode scanline data.\n";
  6430. }
  6431. return TINYEXR_ERROR_INVALID_DATA;
  6432. }
  6433. for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
  6434. offsets[i] = offset;
  6435. tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offsets[i]));
  6436. offset += data_list[i].size() + doffset;
  6437. }
  6438. total_size = static_cast<size_t>(offset);
  6439. }
  6440. return TINYEXR_SUCCESS;
  6441. }
  6442. // can save a single or multi-part image (no deep* formats)
  6443. static size_t SaveEXRNPartImageToMemory(const EXRImage* exr_images,
  6444. const EXRHeader** exr_headers,
  6445. unsigned int num_parts,
  6446. unsigned char** memory_out, const char** err) {
  6447. if (exr_images == NULL || exr_headers == NULL || num_parts == 0 ||
  6448. memory_out == NULL) {
  6449. SetErrorMessage("Invalid argument for SaveEXRNPartImageToMemory",
  6450. err);
  6451. return 0;
  6452. }
  6453. {
  6454. for (unsigned int i = 0; i < num_parts; ++i) {
  6455. if (exr_headers[i]->compression_type < 0) {
  6456. SetErrorMessage("Invalid argument for SaveEXRNPartImageToMemory",
  6457. err);
  6458. return 0;
  6459. }
  6460. #if !TINYEXR_USE_PIZ
  6461. if (exr_headers[i]->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
  6462. SetErrorMessage("PIZ compression is not supported in this build",
  6463. err);
  6464. return 0;
  6465. }
  6466. #endif
  6467. if (exr_headers[i]->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  6468. #if !TINYEXR_USE_ZFP
  6469. SetErrorMessage("ZFP compression is not supported in this build",
  6470. err);
  6471. return 0;
  6472. #else
  6473. // All channels must be fp32.
  6474. // No fp16 support in ZFP atm(as of 2023 June)
  6475. // https://github.com/LLNL/fpzip/issues/2
  6476. for (int c = 0; c < exr_headers[i]->num_channels; ++c) {
  6477. if (exr_headers[i]->requested_pixel_types[c] != TINYEXR_PIXELTYPE_FLOAT) {
  6478. SetErrorMessage("Pixel type must be FLOAT for ZFP compression",
  6479. err);
  6480. return 0;
  6481. }
  6482. }
  6483. #endif
  6484. }
  6485. }
  6486. }
  6487. std::vector<unsigned char> memory;
  6488. // Header
  6489. {
  6490. const char header[] = { 0x76, 0x2f, 0x31, 0x01 };
  6491. memory.insert(memory.end(), header, header + 4);
  6492. }
  6493. // Version
  6494. // using value from the first header
  6495. int long_name = exr_headers[0]->long_name;
  6496. {
  6497. char marker[] = { 2, 0, 0, 0 };
  6498. /* @todo
  6499. if (exr_header->non_image) {
  6500. marker[1] |= 0x8;
  6501. }
  6502. */
  6503. // tiled
  6504. if (num_parts == 1 && exr_images[0].tiles) {
  6505. marker[1] |= 0x2;
  6506. }
  6507. // long_name
  6508. if (long_name) {
  6509. marker[1] |= 0x4;
  6510. }
  6511. // multipart
  6512. if (num_parts > 1) {
  6513. marker[1] |= 0x10;
  6514. }
  6515. memory.insert(memory.end(), marker, marker + 4);
  6516. }
  6517. int total_chunk_count = 0;
  6518. std::vector<int> chunk_count(num_parts);
  6519. std::vector<OffsetData> offset_data(num_parts);
  6520. for (unsigned int i = 0; i < num_parts; ++i) {
  6521. if (!exr_images[i].tiles) {
  6522. int num_scanlines = NumScanlines(exr_headers[i]->compression_type);
  6523. chunk_count[i] =
  6524. (exr_images[i].height + num_scanlines - 1) / num_scanlines;
  6525. InitSingleResolutionOffsets(offset_data[i], chunk_count[i]);
  6526. total_chunk_count += chunk_count[i];
  6527. } else {
  6528. {
  6529. std::vector<int> num_x_tiles, num_y_tiles;
  6530. if (!PrecalculateTileInfo(num_x_tiles, num_y_tiles, exr_headers[i])) {
  6531. SetErrorMessage("Failed to precalculate Tile info",
  6532. err);
  6533. return TINYEXR_ERROR_INVALID_DATA;
  6534. }
  6535. int ntiles = InitTileOffsets(offset_data[i], exr_headers[i], num_x_tiles, num_y_tiles);
  6536. if (ntiles > 0) {
  6537. chunk_count[i] = ntiles;
  6538. } else {
  6539. SetErrorMessage("Failed to compute Tile offsets",
  6540. err);
  6541. return TINYEXR_ERROR_INVALID_DATA;
  6542. }
  6543. total_chunk_count += chunk_count[i];
  6544. }
  6545. }
  6546. }
  6547. // Write attributes to memory buffer.
  6548. std::vector< std::vector<tinyexr::ChannelInfo> > channels(num_parts);
  6549. {
  6550. std::set<std::string> partnames;
  6551. for (unsigned int i = 0; i < num_parts; ++i) {
  6552. //channels
  6553. {
  6554. std::vector<unsigned char> data;
  6555. for (int c = 0; c < exr_headers[i]->num_channels; c++) {
  6556. tinyexr::ChannelInfo info;
  6557. info.p_linear = 0;
  6558. info.pixel_type = exr_headers[i]->pixel_types[c];
  6559. info.requested_pixel_type = exr_headers[i]->requested_pixel_types[c];
  6560. info.x_sampling = 1;
  6561. info.y_sampling = 1;
  6562. info.name = std::string(exr_headers[i]->channels[c].name);
  6563. channels[i].push_back(info);
  6564. }
  6565. tinyexr::WriteChannelInfo(data, channels[i]);
  6566. tinyexr::WriteAttributeToMemory(&memory, "channels", "chlist", &data.at(0),
  6567. static_cast<int>(data.size()));
  6568. }
  6569. {
  6570. int comp = exr_headers[i]->compression_type;
  6571. swap4(&comp);
  6572. WriteAttributeToMemory(
  6573. &memory, "compression", "compression",
  6574. reinterpret_cast<const unsigned char*>(&comp), 1);
  6575. }
  6576. {
  6577. int data[4] = { 0, 0, exr_images[i].width - 1, exr_images[i].height - 1 };
  6578. swap4(&data[0]);
  6579. swap4(&data[1]);
  6580. swap4(&data[2]);
  6581. swap4(&data[3]);
  6582. WriteAttributeToMemory(
  6583. &memory, "dataWindow", "box2i",
  6584. reinterpret_cast<const unsigned char*>(data), sizeof(int) * 4);
  6585. int data0[4] = { 0, 0, exr_images[0].width - 1, exr_images[0].height - 1 };
  6586. swap4(&data0[0]);
  6587. swap4(&data0[1]);
  6588. swap4(&data0[2]);
  6589. swap4(&data0[3]);
  6590. // Note: must be the same across parts (currently, using value from the first header)
  6591. WriteAttributeToMemory(
  6592. &memory, "displayWindow", "box2i",
  6593. reinterpret_cast<const unsigned char*>(data0), sizeof(int) * 4);
  6594. }
  6595. {
  6596. unsigned char line_order = 0; // @fixme { read line_order from EXRHeader }
  6597. WriteAttributeToMemory(&memory, "lineOrder", "lineOrder",
  6598. &line_order, 1);
  6599. }
  6600. {
  6601. // Note: must be the same across parts
  6602. float aspectRatio = 1.0f;
  6603. swap4(&aspectRatio);
  6604. WriteAttributeToMemory(
  6605. &memory, "pixelAspectRatio", "float",
  6606. reinterpret_cast<const unsigned char*>(&aspectRatio), sizeof(float));
  6607. }
  6608. {
  6609. float center[2] = { 0.0f, 0.0f };
  6610. swap4(&center[0]);
  6611. swap4(&center[1]);
  6612. WriteAttributeToMemory(
  6613. &memory, "screenWindowCenter", "v2f",
  6614. reinterpret_cast<const unsigned char*>(center), 2 * sizeof(float));
  6615. }
  6616. {
  6617. float w = 1.0f;
  6618. swap4(&w);
  6619. WriteAttributeToMemory(&memory, "screenWindowWidth", "float",
  6620. reinterpret_cast<const unsigned char*>(&w),
  6621. sizeof(float));
  6622. }
  6623. if (exr_images[i].tiles) {
  6624. unsigned char tile_mode = static_cast<unsigned char>(exr_headers[i]->tile_level_mode & 0x3);
  6625. if (exr_headers[i]->tile_rounding_mode) tile_mode |= (1u << 4u);
  6626. //unsigned char data[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  6627. unsigned int datai[3] = { 0, 0, 0 };
  6628. unsigned char* data = reinterpret_cast<unsigned char*>(&datai[0]);
  6629. datai[0] = static_cast<unsigned int>(exr_headers[i]->tile_size_x);
  6630. datai[1] = static_cast<unsigned int>(exr_headers[i]->tile_size_y);
  6631. data[8] = tile_mode;
  6632. swap4(reinterpret_cast<unsigned int*>(&data[0]));
  6633. swap4(reinterpret_cast<unsigned int*>(&data[4]));
  6634. WriteAttributeToMemory(
  6635. &memory, "tiles", "tiledesc",
  6636. reinterpret_cast<const unsigned char*>(data), 9);
  6637. }
  6638. // must be present for multi-part files - according to spec.
  6639. if (num_parts > 1) {
  6640. // name
  6641. {
  6642. size_t len = 0;
  6643. if ((len = strlen(exr_headers[i]->name)) > 0) {
  6644. #if TINYEXR_HAS_CXX11
  6645. partnames.emplace(exr_headers[i]->name);
  6646. #else
  6647. partnames.insert(std::string(exr_headers[i]->name));
  6648. #endif
  6649. if (partnames.size() != i + 1) {
  6650. SetErrorMessage("'name' attributes must be unique for a multi-part file", err);
  6651. return 0;
  6652. }
  6653. WriteAttributeToMemory(
  6654. &memory, "name", "string",
  6655. reinterpret_cast<const unsigned char*>(exr_headers[i]->name),
  6656. static_cast<int>(len));
  6657. } else {
  6658. SetErrorMessage("Invalid 'name' attribute for a multi-part file", err);
  6659. return 0;
  6660. }
  6661. }
  6662. // type
  6663. {
  6664. const char* type = "scanlineimage";
  6665. if (exr_images[i].tiles) type = "tiledimage";
  6666. WriteAttributeToMemory(
  6667. &memory, "type", "string",
  6668. reinterpret_cast<const unsigned char*>(type),
  6669. static_cast<int>(strlen(type)));
  6670. }
  6671. // chunkCount
  6672. {
  6673. WriteAttributeToMemory(
  6674. &memory, "chunkCount", "int",
  6675. reinterpret_cast<const unsigned char*>(&chunk_count[i]),
  6676. 4);
  6677. }
  6678. }
  6679. // Custom attributes
  6680. if (exr_headers[i]->num_custom_attributes > 0) {
  6681. for (int j = 0; j < exr_headers[i]->num_custom_attributes; j++) {
  6682. tinyexr::WriteAttributeToMemory(
  6683. &memory, exr_headers[i]->custom_attributes[j].name,
  6684. exr_headers[i]->custom_attributes[j].type,
  6685. reinterpret_cast<const unsigned char*>(
  6686. exr_headers[i]->custom_attributes[j].value),
  6687. exr_headers[i]->custom_attributes[j].size);
  6688. }
  6689. }
  6690. { // end of header
  6691. memory.push_back(0);
  6692. }
  6693. }
  6694. }
  6695. if (num_parts > 1) {
  6696. // end of header list
  6697. memory.push_back(0);
  6698. }
  6699. tinyexr_uint64 chunk_offset = memory.size() + size_t(total_chunk_count) * sizeof(tinyexr_uint64);
  6700. tinyexr_uint64 total_size = 0;
  6701. std::vector< std::vector< std::vector<unsigned char> > > data_lists(num_parts);
  6702. for (unsigned int i = 0; i < num_parts; ++i) {
  6703. std::string e;
  6704. int ret = EncodeChunk(&exr_images[i], exr_headers[i],
  6705. channels[i],
  6706. chunk_count[i],
  6707. // starting offset of current chunk after part-number
  6708. chunk_offset,
  6709. num_parts > 1,
  6710. offset_data[i], // output: block offsets, must be initialized
  6711. data_lists[i], // output
  6712. total_size, // output
  6713. &e);
  6714. if (ret != TINYEXR_SUCCESS) {
  6715. if (!e.empty()) {
  6716. tinyexr::SetErrorMessage(e, err);
  6717. }
  6718. return 0;
  6719. }
  6720. chunk_offset = total_size;
  6721. }
  6722. // Allocating required memory
  6723. if (total_size == 0) { // something went wrong
  6724. tinyexr::SetErrorMessage("Output memory size is zero", err);
  6725. return TINYEXR_ERROR_INVALID_DATA;
  6726. }
  6727. (*memory_out) = static_cast<unsigned char*>(malloc(size_t(total_size)));
  6728. // Writing header
  6729. memcpy((*memory_out), &memory[0], memory.size());
  6730. unsigned char* memory_ptr = *memory_out + memory.size();
  6731. size_t sum = memory.size();
  6732. // Writing offset data for chunks
  6733. for (unsigned int i = 0; i < num_parts; ++i) {
  6734. if (exr_images[i].tiles) {
  6735. const EXRImage* level_image = &exr_images[i];
  6736. int num_levels = (exr_headers[i]->tile_level_mode != TINYEXR_TILE_RIPMAP_LEVELS) ?
  6737. offset_data[i].num_x_levels : (offset_data[i].num_x_levels * offset_data[i].num_y_levels);
  6738. for (int level_index = 0; level_index < num_levels; ++level_index) {
  6739. for (size_t j = 0; j < offset_data[i].offsets[level_index].size(); ++j) {
  6740. size_t num_bytes = sizeof(tinyexr_uint64) * offset_data[i].offsets[level_index][j].size();
  6741. sum += num_bytes;
  6742. if (sum > total_size) {
  6743. tinyexr::SetErrorMessage("Invalid offset bytes in Tiled Part image.", err);
  6744. return TINYEXR_ERROR_INVALID_DATA;
  6745. }
  6746. memcpy(memory_ptr,
  6747. reinterpret_cast<unsigned char*>(&offset_data[i].offsets[level_index][j][0]),
  6748. num_bytes);
  6749. memory_ptr += num_bytes;
  6750. }
  6751. level_image = level_image->next_level;
  6752. }
  6753. } else {
  6754. size_t num_bytes = sizeof(tinyexr::tinyexr_uint64) * static_cast<size_t>(chunk_count[i]);
  6755. sum += num_bytes;
  6756. if (sum > total_size) {
  6757. tinyexr::SetErrorMessage("Invalid offset bytes in Part image.", err);
  6758. return TINYEXR_ERROR_INVALID_DATA;
  6759. }
  6760. std::vector<tinyexr::tinyexr_uint64>& offsets = offset_data[i].offsets[0][0];
  6761. memcpy(memory_ptr, reinterpret_cast<unsigned char*>(&offsets[0]), num_bytes);
  6762. memory_ptr += num_bytes;
  6763. }
  6764. }
  6765. // Writing chunk data
  6766. for (unsigned int i = 0; i < num_parts; ++i) {
  6767. for (size_t j = 0; j < static_cast<size_t>(chunk_count[i]); ++j) {
  6768. if (num_parts > 1) {
  6769. sum += 4;
  6770. if (sum > total_size) {
  6771. tinyexr::SetErrorMessage("Buffer overrun in reading Part image chunk data.", err);
  6772. return TINYEXR_ERROR_INVALID_DATA;
  6773. }
  6774. unsigned int part_number = i;
  6775. swap4(&part_number);
  6776. memcpy(memory_ptr, &part_number, 4);
  6777. memory_ptr += 4;
  6778. }
  6779. sum += data_lists[i][j].size();
  6780. if (sum > total_size) {
  6781. tinyexr::SetErrorMessage("Buffer overrun in reading Part image chunk data.", err);
  6782. return TINYEXR_ERROR_INVALID_DATA;
  6783. }
  6784. memcpy(memory_ptr, &data_lists[i][j][0], data_lists[i][j].size());
  6785. memory_ptr += data_lists[i][j].size();
  6786. }
  6787. }
  6788. if (sum != total_size) {
  6789. tinyexr::SetErrorMessage("Corrupted Part image chunk data.", err);
  6790. return TINYEXR_ERROR_INVALID_DATA;
  6791. }
  6792. return size_t(total_size); // OK
  6793. }
  6794. #ifdef __clang__
  6795. #pragma clang diagnostic pop
  6796. #endif
  6797. } // tinyexr
  6798. size_t SaveEXRImageToMemory(const EXRImage* exr_image,
  6799. const EXRHeader* exr_header,
  6800. unsigned char** memory_out, const char** err) {
  6801. return tinyexr::SaveEXRNPartImageToMemory(exr_image, &exr_header, 1, memory_out, err);
  6802. }
  6803. int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
  6804. const char *filename, const char **err) {
  6805. if (exr_image == NULL || filename == NULL ||
  6806. exr_header->compression_type < 0) {
  6807. tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToFile", err);
  6808. return TINYEXR_ERROR_INVALID_ARGUMENT;
  6809. }
  6810. #if !TINYEXR_USE_PIZ
  6811. if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
  6812. tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
  6813. err);
  6814. return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
  6815. }
  6816. #endif
  6817. #if !TINYEXR_USE_ZFP
  6818. if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
  6819. tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
  6820. err);
  6821. return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
  6822. }
  6823. #endif
  6824. FILE *fp = NULL;
  6825. #ifdef _WIN32
  6826. #if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) // MSVC, MinGW GCC, or Clang
  6827. errno_t errcode =
  6828. _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"wb");
  6829. if (errcode != 0) {
  6830. tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename),
  6831. err);
  6832. return TINYEXR_ERROR_CANT_WRITE_FILE;
  6833. }
  6834. #else
  6835. // Unknown compiler or MinGW without MINGW_HAS_SECURE_API.
  6836. fp = fopen(filename, "wb");
  6837. #endif
  6838. #else
  6839. fp = fopen(filename, "wb");
  6840. #endif
  6841. if (!fp) {
  6842. tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename),
  6843. err);
  6844. return TINYEXR_ERROR_CANT_WRITE_FILE;
  6845. }
  6846. unsigned char *mem = NULL;
  6847. size_t mem_size = SaveEXRImageToMemory(exr_image, exr_header, &mem, err);
  6848. if (mem_size == 0) {
  6849. fclose(fp);
  6850. return TINYEXR_ERROR_SERIALIZATION_FAILED;
  6851. }
  6852. size_t written_size = 0;
  6853. if ((mem_size > 0) && mem) {
  6854. written_size = fwrite(mem, 1, mem_size, fp);
  6855. }
  6856. free(mem);
  6857. fclose(fp);
  6858. if (written_size != mem_size) {
  6859. tinyexr::SetErrorMessage("Cannot write a file", err);
  6860. return TINYEXR_ERROR_CANT_WRITE_FILE;
  6861. }
  6862. return TINYEXR_SUCCESS;
  6863. }
  6864. size_t SaveEXRMultipartImageToMemory(const EXRImage* exr_images,
  6865. const EXRHeader** exr_headers,
  6866. unsigned int num_parts,
  6867. unsigned char** memory_out, const char** err) {
  6868. if (exr_images == NULL || exr_headers == NULL || num_parts < 2 ||
  6869. memory_out == NULL) {
  6870. tinyexr::SetErrorMessage("Invalid argument for SaveEXRNPartImageToMemory",
  6871. err);
  6872. return 0;
  6873. }
  6874. return tinyexr::SaveEXRNPartImageToMemory(exr_images, exr_headers, num_parts, memory_out, err);
  6875. }
  6876. int SaveEXRMultipartImageToFile(const EXRImage* exr_images,
  6877. const EXRHeader** exr_headers,
  6878. unsigned int num_parts,
  6879. const char* filename,
  6880. const char** err) {
  6881. if (exr_images == NULL || exr_headers == NULL || num_parts < 2) {
  6882. tinyexr::SetErrorMessage("Invalid argument for SaveEXRMultipartImageToFile",
  6883. err);
  6884. return TINYEXR_ERROR_INVALID_ARGUMENT;
  6885. }
  6886. FILE *fp = NULL;
  6887. #ifdef _WIN32
  6888. #if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) // MSVC, MinGW GCC, or Clang.
  6889. errno_t errcode =
  6890. _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"wb");
  6891. if (errcode != 0) {
  6892. tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename),
  6893. err);
  6894. return TINYEXR_ERROR_CANT_WRITE_FILE;
  6895. }
  6896. #else
  6897. // Unknown compiler or MinGW without MINGW_HAS_SECURE_API.
  6898. fp = fopen(filename, "wb");
  6899. #endif
  6900. #else
  6901. fp = fopen(filename, "wb");
  6902. #endif
  6903. if (!fp) {
  6904. tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename),
  6905. err);
  6906. return TINYEXR_ERROR_CANT_WRITE_FILE;
  6907. }
  6908. unsigned char *mem = NULL;
  6909. size_t mem_size = SaveEXRMultipartImageToMemory(exr_images, exr_headers, num_parts, &mem, err);
  6910. if (mem_size == 0) {
  6911. fclose(fp);
  6912. return TINYEXR_ERROR_SERIALIZATION_FAILED;
  6913. }
  6914. size_t written_size = 0;
  6915. if ((mem_size > 0) && mem) {
  6916. written_size = fwrite(mem, 1, mem_size, fp);
  6917. }
  6918. free(mem);
  6919. fclose(fp);
  6920. if (written_size != mem_size) {
  6921. tinyexr::SetErrorMessage("Cannot write a file", err);
  6922. return TINYEXR_ERROR_CANT_WRITE_FILE;
  6923. }
  6924. return TINYEXR_SUCCESS;
  6925. }
  6926. int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
  6927. if (deep_image == NULL) {
  6928. tinyexr::SetErrorMessage("Invalid argument for LoadDeepEXR", err);
  6929. return TINYEXR_ERROR_INVALID_ARGUMENT;
  6930. }
  6931. MemoryMappedFile file(filename);
  6932. if (!file.valid()) {
  6933. tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
  6934. return TINYEXR_ERROR_CANT_OPEN_FILE;
  6935. }
  6936. if (file.size == 0) {
  6937. tinyexr::SetErrorMessage("File size is zero : " + std::string(filename),
  6938. err);
  6939. return TINYEXR_ERROR_INVALID_FILE;
  6940. }
  6941. const char *head = reinterpret_cast<const char *>(file.data);
  6942. const char *marker = reinterpret_cast<const char *>(file.data);
  6943. // Header check.
  6944. {
  6945. const char header[] = {0x76, 0x2f, 0x31, 0x01};
  6946. if (memcmp(marker, header, 4) != 0) {
  6947. tinyexr::SetErrorMessage("Invalid magic number", err);
  6948. return TINYEXR_ERROR_INVALID_MAGIC_NUMBER;
  6949. }
  6950. marker += 4;
  6951. }
  6952. // Version, scanline.
  6953. {
  6954. // ver 2.0, scanline, deep bit on(0x800)
  6955. // must be [2, 0, 0, 0]
  6956. if (marker[0] != 2 || marker[1] != 8 || marker[2] != 0 || marker[3] != 0) {
  6957. tinyexr::SetErrorMessage("Unsupported version or scanline", err);
  6958. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  6959. }
  6960. marker += 4;
  6961. }
  6962. int dx = -1;
  6963. int dy = -1;
  6964. int dw = -1;
  6965. int dh = -1;
  6966. int num_scanline_blocks = 1; // 16 for ZIP compression.
  6967. int compression_type = -1;
  6968. int num_channels = -1;
  6969. std::vector<tinyexr::ChannelInfo> channels;
  6970. // Read attributes
  6971. size_t size = file.size - tinyexr::kEXRVersionSize;
  6972. for (;;) {
  6973. if (0 == size) {
  6974. return TINYEXR_ERROR_INVALID_DATA;
  6975. } else if (marker[0] == '\0') {
  6976. marker++;
  6977. size--;
  6978. break;
  6979. }
  6980. std::string attr_name;
  6981. std::string attr_type;
  6982. std::vector<unsigned char> data;
  6983. size_t marker_size;
  6984. if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
  6985. marker, size)) {
  6986. std::stringstream ss;
  6987. ss << "Failed to parse attribute\n";
  6988. tinyexr::SetErrorMessage(ss.str(), err);
  6989. return TINYEXR_ERROR_INVALID_DATA;
  6990. }
  6991. marker += marker_size;
  6992. size -= marker_size;
  6993. if (attr_name.compare("compression") == 0) {
  6994. compression_type = data[0];
  6995. if (compression_type > TINYEXR_COMPRESSIONTYPE_PIZ) {
  6996. std::stringstream ss;
  6997. ss << "Unsupported compression type : " << compression_type;
  6998. tinyexr::SetErrorMessage(ss.str(), err);
  6999. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  7000. }
  7001. if (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) {
  7002. num_scanline_blocks = 16;
  7003. }
  7004. } else if (attr_name.compare("channels") == 0) {
  7005. // name: zero-terminated string, from 1 to 255 bytes long
  7006. // pixel type: int, possible values are: UINT = 0 HALF = 1 FLOAT = 2
  7007. // pLinear: unsigned char, possible values are 0 and 1
  7008. // reserved: three chars, should be zero
  7009. // xSampling: int
  7010. // ySampling: int
  7011. if (!tinyexr::ReadChannelInfo(channels, data)) {
  7012. tinyexr::SetErrorMessage("Failed to parse channel info", err);
  7013. return TINYEXR_ERROR_INVALID_DATA;
  7014. }
  7015. num_channels = static_cast<int>(channels.size());
  7016. if (num_channels < 1) {
  7017. tinyexr::SetErrorMessage("Invalid channels format", err);
  7018. return TINYEXR_ERROR_INVALID_DATA;
  7019. }
  7020. } else if (attr_name.compare("dataWindow") == 0) {
  7021. memcpy(&dx, &data.at(0), sizeof(int));
  7022. memcpy(&dy, &data.at(4), sizeof(int));
  7023. memcpy(&dw, &data.at(8), sizeof(int));
  7024. memcpy(&dh, &data.at(12), sizeof(int));
  7025. tinyexr::swap4(&dx);
  7026. tinyexr::swap4(&dy);
  7027. tinyexr::swap4(&dw);
  7028. tinyexr::swap4(&dh);
  7029. } else if (attr_name.compare("displayWindow") == 0) {
  7030. int x;
  7031. int y;
  7032. int w;
  7033. int h;
  7034. memcpy(&x, &data.at(0), sizeof(int));
  7035. memcpy(&y, &data.at(4), sizeof(int));
  7036. memcpy(&w, &data.at(8), sizeof(int));
  7037. memcpy(&h, &data.at(12), sizeof(int));
  7038. tinyexr::swap4(&x);
  7039. tinyexr::swap4(&y);
  7040. tinyexr::swap4(&w);
  7041. tinyexr::swap4(&h);
  7042. }
  7043. }
  7044. TINYEXR_CHECK_AND_RETURN_C(dx >= 0, TINYEXR_ERROR_INVALID_DATA);
  7045. TINYEXR_CHECK_AND_RETURN_C(dy >= 0, TINYEXR_ERROR_INVALID_DATA);
  7046. TINYEXR_CHECK_AND_RETURN_C(dw >= 0, TINYEXR_ERROR_INVALID_DATA);
  7047. TINYEXR_CHECK_AND_RETURN_C(dh >= 0, TINYEXR_ERROR_INVALID_DATA);
  7048. TINYEXR_CHECK_AND_RETURN_C(num_channels >= 1, TINYEXR_ERROR_INVALID_DATA);
  7049. int data_width = dw - dx + 1;
  7050. int data_height = dh - dy + 1;
  7051. // Read offset tables.
  7052. int num_blocks = data_height / num_scanline_blocks;
  7053. if (num_blocks * num_scanline_blocks < data_height) {
  7054. num_blocks++;
  7055. }
  7056. std::vector<tinyexr::tinyexr_int64> offsets(static_cast<size_t>(num_blocks));
  7057. for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) {
  7058. tinyexr::tinyexr_int64 offset;
  7059. memcpy(&offset, marker, sizeof(tinyexr::tinyexr_int64));
  7060. tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offset));
  7061. marker += sizeof(tinyexr::tinyexr_int64); // = 8
  7062. offsets[y] = offset;
  7063. }
  7064. #if TINYEXR_USE_PIZ
  7065. if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) ||
  7066. (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) ||
  7067. (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
  7068. (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP) ||
  7069. (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ)) {
  7070. #else
  7071. if ((compression_type == TINYEXR_COMPRESSIONTYPE_NONE) ||
  7072. (compression_type == TINYEXR_COMPRESSIONTYPE_RLE) ||
  7073. (compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
  7074. (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
  7075. #endif
  7076. // OK
  7077. } else {
  7078. tinyexr::SetErrorMessage("Unsupported compression format", err);
  7079. return TINYEXR_ERROR_UNSUPPORTED_FORMAT;
  7080. }
  7081. deep_image->image = static_cast<float ***>(
  7082. malloc(sizeof(float **) * static_cast<size_t>(num_channels)));
  7083. for (int c = 0; c < num_channels; c++) {
  7084. deep_image->image[c] = static_cast<float **>(
  7085. malloc(sizeof(float *) * static_cast<size_t>(data_height)));
  7086. for (int y = 0; y < data_height; y++) {
  7087. }
  7088. }
  7089. deep_image->offset_table = static_cast<int **>(
  7090. malloc(sizeof(int *) * static_cast<size_t>(data_height)));
  7091. for (int y = 0; y < data_height; y++) {
  7092. deep_image->offset_table[y] = static_cast<int *>(
  7093. malloc(sizeof(int) * static_cast<size_t>(data_width)));
  7094. }
  7095. for (size_t y = 0; y < static_cast<size_t>(num_blocks); y++) {
  7096. const unsigned char *data_ptr =
  7097. reinterpret_cast<const unsigned char *>(head + offsets[y]);
  7098. // int: y coordinate
  7099. // int64: packed size of pixel offset table
  7100. // int64: packed size of sample data
  7101. // int64: unpacked size of sample data
  7102. // compressed pixel offset table
  7103. // compressed sample data
  7104. int line_no;
  7105. tinyexr::tinyexr_int64 packedOffsetTableSize;
  7106. tinyexr::tinyexr_int64 packedSampleDataSize;
  7107. tinyexr::tinyexr_int64 unpackedSampleDataSize;
  7108. memcpy(&line_no, data_ptr, sizeof(int));
  7109. memcpy(&packedOffsetTableSize, data_ptr + 4,
  7110. sizeof(tinyexr::tinyexr_int64));
  7111. memcpy(&packedSampleDataSize, data_ptr + 12,
  7112. sizeof(tinyexr::tinyexr_int64));
  7113. memcpy(&unpackedSampleDataSize, data_ptr + 20,
  7114. sizeof(tinyexr::tinyexr_int64));
  7115. tinyexr::swap4(&line_no);
  7116. tinyexr::swap8(
  7117. reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedOffsetTableSize));
  7118. tinyexr::swap8(
  7119. reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedSampleDataSize));
  7120. tinyexr::swap8(
  7121. reinterpret_cast<tinyexr::tinyexr_uint64 *>(&unpackedSampleDataSize));
  7122. std::vector<int> pixelOffsetTable(static_cast<size_t>(data_width));
  7123. // decode pixel offset table.
  7124. {
  7125. unsigned long dstLen =
  7126. static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int));
  7127. if (!tinyexr::DecompressZip(
  7128. reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)),
  7129. &dstLen, data_ptr + 28,
  7130. static_cast<unsigned long>(packedOffsetTableSize))) {
  7131. return false;
  7132. }
  7133. TINYEXR_CHECK_AND_RETURN_C(dstLen == pixelOffsetTable.size() * sizeof(int), TINYEXR_ERROR_INVALID_DATA);
  7134. for (size_t i = 0; i < static_cast<size_t>(data_width); i++) {
  7135. deep_image->offset_table[y][i] = pixelOffsetTable[i];
  7136. }
  7137. }
  7138. std::vector<unsigned char> sample_data(
  7139. static_cast<size_t>(unpackedSampleDataSize));
  7140. // decode sample data.
  7141. {
  7142. unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize);
  7143. if (dstLen) {
  7144. if (!tinyexr::DecompressZip(
  7145. reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
  7146. data_ptr + 28 + packedOffsetTableSize,
  7147. static_cast<unsigned long>(packedSampleDataSize))) {
  7148. return false;
  7149. }
  7150. TINYEXR_CHECK_AND_RETURN_C(dstLen == static_cast<unsigned long>(unpackedSampleDataSize), TINYEXR_ERROR_INVALID_DATA);
  7151. }
  7152. }
  7153. // decode sample
  7154. int sampleSize = -1;
  7155. std::vector<int> channel_offset_list(static_cast<size_t>(num_channels));
  7156. {
  7157. int channel_offset = 0;
  7158. for (size_t i = 0; i < static_cast<size_t>(num_channels); i++) {
  7159. channel_offset_list[i] = channel_offset;
  7160. if (channels[i].pixel_type == TINYEXR_PIXELTYPE_UINT) { // UINT
  7161. channel_offset += 4;
  7162. } else if (channels[i].pixel_type == TINYEXR_PIXELTYPE_HALF) { // half
  7163. channel_offset += 2;
  7164. } else if (channels[i].pixel_type ==
  7165. TINYEXR_PIXELTYPE_FLOAT) { // float
  7166. channel_offset += 4;
  7167. } else {
  7168. tinyexr::SetErrorMessage("Invalid pixel_type in chnnels.", err);
  7169. return TINYEXR_ERROR_INVALID_DATA;
  7170. }
  7171. }
  7172. sampleSize = channel_offset;
  7173. }
  7174. TINYEXR_CHECK_AND_RETURN_C(sampleSize >= 2, TINYEXR_ERROR_INVALID_DATA);
  7175. TINYEXR_CHECK_AND_RETURN_C(static_cast<size_t>(
  7176. pixelOffsetTable[static_cast<size_t>(data_width - 1)] *
  7177. sampleSize) == sample_data.size(), TINYEXR_ERROR_INVALID_DATA);
  7178. int samples_per_line = static_cast<int>(sample_data.size()) / sampleSize;
  7179. //
  7180. // Alloc memory
  7181. //
  7182. //
  7183. // pixel data is stored as image[channels][pixel_samples]
  7184. //
  7185. {
  7186. tinyexr::tinyexr_uint64 data_offset = 0;
  7187. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  7188. deep_image->image[c][y] = static_cast<float *>(
  7189. malloc(sizeof(float) * static_cast<size_t>(samples_per_line)));
  7190. if (channels[c].pixel_type == 0) { // UINT
  7191. for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
  7192. unsigned int ui;
  7193. unsigned int *src_ptr = reinterpret_cast<unsigned int *>(
  7194. &sample_data.at(size_t(data_offset) + x * sizeof(int)));
  7195. tinyexr::cpy4(&ui, src_ptr);
  7196. deep_image->image[c][y][x] = static_cast<float>(ui); // @fixme
  7197. }
  7198. data_offset +=
  7199. sizeof(unsigned int) * static_cast<size_t>(samples_per_line);
  7200. } else if (channels[c].pixel_type == 1) { // half
  7201. for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
  7202. tinyexr::FP16 f16;
  7203. const unsigned short *src_ptr = reinterpret_cast<unsigned short *>(
  7204. &sample_data.at(size_t(data_offset) + x * sizeof(short)));
  7205. tinyexr::cpy2(&(f16.u), src_ptr);
  7206. tinyexr::FP32 f32 = half_to_float(f16);
  7207. deep_image->image[c][y][x] = f32.f;
  7208. }
  7209. data_offset += sizeof(short) * static_cast<size_t>(samples_per_line);
  7210. } else { // float
  7211. for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
  7212. float f;
  7213. const float *src_ptr = reinterpret_cast<float *>(
  7214. &sample_data.at(size_t(data_offset) + x * sizeof(float)));
  7215. tinyexr::cpy4(&f, src_ptr);
  7216. deep_image->image[c][y][x] = f;
  7217. }
  7218. data_offset += sizeof(float) * static_cast<size_t>(samples_per_line);
  7219. }
  7220. }
  7221. }
  7222. } // y
  7223. deep_image->width = data_width;
  7224. deep_image->height = data_height;
  7225. deep_image->channel_names = static_cast<const char **>(
  7226. malloc(sizeof(const char *) * static_cast<size_t>(num_channels)));
  7227. for (size_t c = 0; c < static_cast<size_t>(num_channels); c++) {
  7228. #ifdef _WIN32
  7229. deep_image->channel_names[c] = _strdup(channels[c].name.c_str());
  7230. #else
  7231. deep_image->channel_names[c] = strdup(channels[c].name.c_str());
  7232. #endif
  7233. }
  7234. deep_image->num_channels = num_channels;
  7235. return TINYEXR_SUCCESS;
  7236. }
  7237. void InitEXRImage(EXRImage *exr_image) {
  7238. if (exr_image == NULL) {
  7239. return;
  7240. }
  7241. exr_image->width = 0;
  7242. exr_image->height = 0;
  7243. exr_image->num_channels = 0;
  7244. exr_image->images = NULL;
  7245. exr_image->tiles = NULL;
  7246. exr_image->next_level = NULL;
  7247. exr_image->level_x = 0;
  7248. exr_image->level_y = 0;
  7249. exr_image->num_tiles = 0;
  7250. }
  7251. void FreeEXRErrorMessage(const char *msg) {
  7252. if (msg) {
  7253. free(reinterpret_cast<void *>(const_cast<char *>(msg)));
  7254. }
  7255. return;
  7256. }
  7257. void InitEXRHeader(EXRHeader *exr_header) {
  7258. if (exr_header == NULL) {
  7259. return;
  7260. }
  7261. memset(exr_header, 0, sizeof(EXRHeader));
  7262. }
  7263. int FreeEXRHeader(EXRHeader *exr_header) {
  7264. if (exr_header == NULL) {
  7265. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7266. }
  7267. if (exr_header->channels) {
  7268. free(exr_header->channels);
  7269. }
  7270. if (exr_header->pixel_types) {
  7271. free(exr_header->pixel_types);
  7272. }
  7273. if (exr_header->requested_pixel_types) {
  7274. free(exr_header->requested_pixel_types);
  7275. }
  7276. for (int i = 0; i < exr_header->num_custom_attributes; i++) {
  7277. if (exr_header->custom_attributes[i].value) {
  7278. free(exr_header->custom_attributes[i].value);
  7279. }
  7280. }
  7281. if (exr_header->custom_attributes) {
  7282. free(exr_header->custom_attributes);
  7283. }
  7284. EXRSetNameAttr(exr_header, NULL);
  7285. return TINYEXR_SUCCESS;
  7286. }
  7287. void EXRSetNameAttr(EXRHeader* exr_header, const char* name) {
  7288. if (exr_header == NULL) {
  7289. return;
  7290. }
  7291. memset(exr_header->name, 0, 256);
  7292. if (name != NULL) {
  7293. size_t len = std::min(strlen(name), size_t(255));
  7294. if (len) {
  7295. memcpy(exr_header->name, name, len);
  7296. }
  7297. }
  7298. }
  7299. int EXRNumLevels(const EXRImage* exr_image) {
  7300. if (exr_image == NULL) return 0;
  7301. if(exr_image->images) return 1; // scanlines
  7302. int levels = 1;
  7303. const EXRImage* level_image = exr_image;
  7304. while((level_image = level_image->next_level)) ++levels;
  7305. return levels;
  7306. }
  7307. int FreeEXRImage(EXRImage *exr_image) {
  7308. if (exr_image == NULL) {
  7309. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7310. }
  7311. if (exr_image->next_level) {
  7312. FreeEXRImage(exr_image->next_level);
  7313. delete exr_image->next_level;
  7314. }
  7315. for (int i = 0; i < exr_image->num_channels; i++) {
  7316. if (exr_image->images && exr_image->images[i]) {
  7317. free(exr_image->images[i]);
  7318. }
  7319. }
  7320. if (exr_image->images) {
  7321. free(exr_image->images);
  7322. }
  7323. if (exr_image->tiles) {
  7324. for (int tid = 0; tid < exr_image->num_tiles; tid++) {
  7325. for (int i = 0; i < exr_image->num_channels; i++) {
  7326. if (exr_image->tiles[tid].images && exr_image->tiles[tid].images[i]) {
  7327. free(exr_image->tiles[tid].images[i]);
  7328. }
  7329. }
  7330. if (exr_image->tiles[tid].images) {
  7331. free(exr_image->tiles[tid].images);
  7332. }
  7333. }
  7334. free(exr_image->tiles);
  7335. }
  7336. return TINYEXR_SUCCESS;
  7337. }
  7338. int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version,
  7339. const char *filename, const char **err) {
  7340. if (exr_header == NULL || exr_version == NULL || filename == NULL) {
  7341. tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile",
  7342. err);
  7343. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7344. }
  7345. MemoryMappedFile file(filename);
  7346. if (!file.valid()) {
  7347. tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
  7348. return TINYEXR_ERROR_CANT_OPEN_FILE;
  7349. }
  7350. return ParseEXRHeaderFromMemory(exr_header, exr_version, file.data, file.size,
  7351. err);
  7352. }
  7353. int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers,
  7354. int *num_headers,
  7355. const EXRVersion *exr_version,
  7356. const unsigned char *memory, size_t size,
  7357. const char **err) {
  7358. if (memory == NULL || exr_headers == NULL || num_headers == NULL ||
  7359. exr_version == NULL) {
  7360. // Invalid argument
  7361. tinyexr::SetErrorMessage(
  7362. "Invalid argument for ParseEXRMultipartHeaderFromMemory", err);
  7363. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7364. }
  7365. if (size < tinyexr::kEXRVersionSize) {
  7366. tinyexr::SetErrorMessage("Data size too short", err);
  7367. return TINYEXR_ERROR_INVALID_DATA;
  7368. }
  7369. const unsigned char *marker = memory + tinyexr::kEXRVersionSize;
  7370. size_t marker_size = size - tinyexr::kEXRVersionSize;
  7371. std::vector<tinyexr::HeaderInfo> infos;
  7372. for (;;) {
  7373. tinyexr::HeaderInfo info;
  7374. info.clear();
  7375. std::string err_str;
  7376. bool empty_header = false;
  7377. int ret = ParseEXRHeader(&info, &empty_header, exr_version, &err_str,
  7378. marker, marker_size);
  7379. if (ret != TINYEXR_SUCCESS) {
  7380. // Free malloc-allocated memory here.
  7381. for (size_t i = 0; i < info.attributes.size(); i++) {
  7382. if (info.attributes[i].value) {
  7383. free(info.attributes[i].value);
  7384. }
  7385. }
  7386. tinyexr::SetErrorMessage(err_str, err);
  7387. return ret;
  7388. }
  7389. if (empty_header) {
  7390. marker += 1; // skip '\0'
  7391. break;
  7392. }
  7393. // `chunkCount` must exist in the header.
  7394. if (info.chunk_count == 0) {
  7395. // Free malloc-allocated memory here.
  7396. for (size_t i = 0; i < info.attributes.size(); i++) {
  7397. if (info.attributes[i].value) {
  7398. free(info.attributes[i].value);
  7399. }
  7400. }
  7401. tinyexr::SetErrorMessage(
  7402. "`chunkCount' attribute is not found in the header.", err);
  7403. return TINYEXR_ERROR_INVALID_DATA;
  7404. }
  7405. infos.push_back(info);
  7406. // move to next header.
  7407. marker += info.header_len;
  7408. size -= info.header_len;
  7409. }
  7410. // allocate memory for EXRHeader and create array of EXRHeader pointers.
  7411. (*exr_headers) =
  7412. static_cast<EXRHeader **>(malloc(sizeof(EXRHeader *) * infos.size()));
  7413. int retcode = TINYEXR_SUCCESS;
  7414. for (size_t i = 0; i < infos.size(); i++) {
  7415. EXRHeader *exr_header = static_cast<EXRHeader *>(malloc(sizeof(EXRHeader)));
  7416. memset(exr_header, 0, sizeof(EXRHeader));
  7417. std::string warn;
  7418. std::string _err;
  7419. if (!ConvertHeader(exr_header, infos[i], &warn, &_err)) {
  7420. // Free malloc-allocated memory here.
  7421. for (size_t k = 0; k < infos[i].attributes.size(); k++) {
  7422. if (infos[i].attributes[k].value) {
  7423. free(infos[i].attributes[k].value);
  7424. }
  7425. }
  7426. if (!_err.empty()) {
  7427. tinyexr::SetErrorMessage(
  7428. _err, err);
  7429. }
  7430. // continue to converting headers
  7431. retcode = TINYEXR_ERROR_INVALID_HEADER;
  7432. }
  7433. exr_header->multipart = exr_version->multipart ? 1 : 0;
  7434. (*exr_headers)[i] = exr_header;
  7435. }
  7436. (*num_headers) = static_cast<int>(infos.size());
  7437. return retcode;
  7438. }
  7439. int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers,
  7440. const EXRVersion *exr_version,
  7441. const char *filename, const char **err) {
  7442. if (exr_headers == NULL || num_headers == NULL || exr_version == NULL ||
  7443. filename == NULL) {
  7444. tinyexr::SetErrorMessage(
  7445. "Invalid argument for ParseEXRMultipartHeaderFromFile()", err);
  7446. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7447. }
  7448. MemoryMappedFile file(filename);
  7449. if (!file.valid()) {
  7450. tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
  7451. return TINYEXR_ERROR_CANT_OPEN_FILE;
  7452. }
  7453. return ParseEXRMultipartHeaderFromMemory(
  7454. exr_headers, num_headers, exr_version, file.data, file.size, err);
  7455. }
  7456. int ParseEXRVersionFromMemory(EXRVersion *version, const unsigned char *memory,
  7457. size_t size) {
  7458. if (version == NULL || memory == NULL) {
  7459. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7460. }
  7461. if (size < tinyexr::kEXRVersionSize) {
  7462. return TINYEXR_ERROR_INVALID_DATA;
  7463. }
  7464. const unsigned char *marker = memory;
  7465. // Header check.
  7466. {
  7467. const char header[] = {0x76, 0x2f, 0x31, 0x01};
  7468. if (memcmp(marker, header, 4) != 0) {
  7469. return TINYEXR_ERROR_INVALID_MAGIC_NUMBER;
  7470. }
  7471. marker += 4;
  7472. }
  7473. version->tiled = false;
  7474. version->long_name = false;
  7475. version->non_image = false;
  7476. version->multipart = false;
  7477. // Parse version header.
  7478. {
  7479. // must be 2
  7480. if (marker[0] != 2) {
  7481. return TINYEXR_ERROR_INVALID_EXR_VERSION;
  7482. }
  7483. if (version == NULL) {
  7484. return TINYEXR_SUCCESS; // May OK
  7485. }
  7486. version->version = 2;
  7487. if (marker[1] & 0x2) { // 9th bit
  7488. version->tiled = true;
  7489. }
  7490. if (marker[1] & 0x4) { // 10th bit
  7491. version->long_name = true;
  7492. }
  7493. if (marker[1] & 0x8) { // 11th bit
  7494. version->non_image = true; // (deep image)
  7495. }
  7496. if (marker[1] & 0x10) { // 12th bit
  7497. version->multipart = true;
  7498. }
  7499. }
  7500. return TINYEXR_SUCCESS;
  7501. }
  7502. int ParseEXRVersionFromFile(EXRVersion *version, const char *filename) {
  7503. if (filename == NULL) {
  7504. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7505. }
  7506. FILE *fp = NULL;
  7507. #ifdef _WIN32
  7508. #if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) // MSVC, MinGW GCC, or Clang.
  7509. errno_t err = _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb");
  7510. if (err != 0) {
  7511. // TODO(syoyo): return wfopen_s erro code
  7512. return TINYEXR_ERROR_CANT_OPEN_FILE;
  7513. }
  7514. #else
  7515. // Unknown compiler or MinGW without MINGW_HAS_SECURE_API.
  7516. fp = fopen(filename, "rb");
  7517. #endif
  7518. #else
  7519. fp = fopen(filename, "rb");
  7520. #endif
  7521. if (!fp) {
  7522. return TINYEXR_ERROR_CANT_OPEN_FILE;
  7523. }
  7524. // Try to read kEXRVersionSize bytes; if the file is shorter than
  7525. // kEXRVersionSize, this will produce an error. This avoids a call to
  7526. // fseek(fp, 0, SEEK_END), which is not required to be supported by C
  7527. // implementations.
  7528. unsigned char buf[tinyexr::kEXRVersionSize];
  7529. size_t ret = fread(&buf[0], 1, tinyexr::kEXRVersionSize, fp);
  7530. fclose(fp);
  7531. if (ret != tinyexr::kEXRVersionSize) {
  7532. return TINYEXR_ERROR_INVALID_FILE;
  7533. }
  7534. return ParseEXRVersionFromMemory(version, buf, tinyexr::kEXRVersionSize);
  7535. }
  7536. int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
  7537. const EXRHeader **exr_headers,
  7538. unsigned int num_parts,
  7539. const unsigned char *memory,
  7540. const size_t size, const char **err) {
  7541. if (exr_images == NULL || exr_headers == NULL || num_parts == 0 ||
  7542. memory == NULL || (size <= tinyexr::kEXRVersionSize)) {
  7543. tinyexr::SetErrorMessage(
  7544. "Invalid argument for LoadEXRMultipartImageFromMemory()", err);
  7545. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7546. }
  7547. // compute total header size.
  7548. size_t total_header_size = 0;
  7549. for (unsigned int i = 0; i < num_parts; i++) {
  7550. if (exr_headers[i]->header_len == 0) {
  7551. tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err);
  7552. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7553. }
  7554. total_header_size += exr_headers[i]->header_len;
  7555. }
  7556. const char *marker = reinterpret_cast<const char *>(
  7557. memory + total_header_size + 4 +
  7558. 4); // +8 for magic number and version header.
  7559. marker += 1; // Skip empty header.
  7560. // NOTE 1:
  7561. // In multipart image, There is 'part number' before chunk data.
  7562. // 4 byte : part number
  7563. // 4+ : chunk
  7564. //
  7565. // NOTE 2:
  7566. // EXR spec says 'part number' is 'unsigned long' but actually this is
  7567. // 'unsigned int(4 bytes)' in OpenEXR implementation...
  7568. // http://www.openexr.com/openexrfilelayout.pdf
  7569. // Load chunk offset table.
  7570. std::vector<tinyexr::OffsetData> chunk_offset_table_list;
  7571. chunk_offset_table_list.reserve(num_parts);
  7572. for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) {
  7573. chunk_offset_table_list.resize(chunk_offset_table_list.size() + 1);
  7574. tinyexr::OffsetData& offset_data = chunk_offset_table_list.back();
  7575. if (!exr_headers[i]->tiled || exr_headers[i]->tile_level_mode == TINYEXR_TILE_ONE_LEVEL) {
  7576. tinyexr::InitSingleResolutionOffsets(offset_data, size_t(exr_headers[i]->chunk_count));
  7577. std::vector<tinyexr::tinyexr_uint64>& offset_table = offset_data.offsets[0][0];
  7578. for (size_t c = 0; c < offset_table.size(); c++) {
  7579. tinyexr::tinyexr_uint64 offset;
  7580. memcpy(&offset, marker, 8);
  7581. tinyexr::swap8(&offset);
  7582. if (offset >= size) {
  7583. tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.",
  7584. err);
  7585. return TINYEXR_ERROR_INVALID_DATA;
  7586. }
  7587. offset_table[c] = offset + 4; // +4 to skip 'part number'
  7588. marker += 8;
  7589. }
  7590. } else {
  7591. {
  7592. std::vector<int> num_x_tiles, num_y_tiles;
  7593. if (!tinyexr::PrecalculateTileInfo(num_x_tiles, num_y_tiles, exr_headers[i])) {
  7594. tinyexr::SetErrorMessage("Invalid tile info.", err);
  7595. return TINYEXR_ERROR_INVALID_DATA;
  7596. }
  7597. int num_blocks = InitTileOffsets(offset_data, exr_headers[i], num_x_tiles, num_y_tiles);
  7598. if (num_blocks != exr_headers[i]->chunk_count) {
  7599. tinyexr::SetErrorMessage("Invalid offset table size.", err);
  7600. return TINYEXR_ERROR_INVALID_DATA;
  7601. }
  7602. }
  7603. for (unsigned int l = 0; l < offset_data.offsets.size(); ++l) {
  7604. for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy) {
  7605. for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) {
  7606. tinyexr::tinyexr_uint64 offset;
  7607. memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64));
  7608. tinyexr::swap8(&offset);
  7609. if (offset >= size) {
  7610. tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.",
  7611. err);
  7612. return TINYEXR_ERROR_INVALID_DATA;
  7613. }
  7614. offset_data.offsets[l][dy][dx] = offset + 4; // +4 to skip 'part number'
  7615. marker += sizeof(tinyexr::tinyexr_uint64); // = 8
  7616. }
  7617. }
  7618. }
  7619. }
  7620. }
  7621. // Decode image.
  7622. for (size_t i = 0; i < static_cast<size_t>(num_parts); i++) {
  7623. tinyexr::OffsetData &offset_data = chunk_offset_table_list[i];
  7624. // First check 'part number' is identical to 'i'
  7625. for (unsigned int l = 0; l < offset_data.offsets.size(); ++l)
  7626. for (unsigned int dy = 0; dy < offset_data.offsets[l].size(); ++dy)
  7627. for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) {
  7628. const unsigned char *part_number_addr =
  7629. memory + offset_data.offsets[l][dy][dx] - 4; // -4 to move to 'part number' field.
  7630. unsigned int part_no;
  7631. memcpy(&part_no, part_number_addr, sizeof(unsigned int)); // 4
  7632. tinyexr::swap4(&part_no);
  7633. if (part_no != i) {
  7634. tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.",
  7635. err);
  7636. return TINYEXR_ERROR_INVALID_DATA;
  7637. }
  7638. }
  7639. std::string e;
  7640. int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_data,
  7641. memory, size, &e);
  7642. if (ret != TINYEXR_SUCCESS) {
  7643. if (!e.empty()) {
  7644. tinyexr::SetErrorMessage(e, err);
  7645. }
  7646. return ret;
  7647. }
  7648. }
  7649. return TINYEXR_SUCCESS;
  7650. }
  7651. int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
  7652. const EXRHeader **exr_headers,
  7653. unsigned int num_parts, const char *filename,
  7654. const char **err) {
  7655. if (exr_images == NULL || exr_headers == NULL || num_parts == 0) {
  7656. tinyexr::SetErrorMessage(
  7657. "Invalid argument for LoadEXRMultipartImageFromFile", err);
  7658. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7659. }
  7660. MemoryMappedFile file(filename);
  7661. if (!file.valid()) {
  7662. tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err);
  7663. return TINYEXR_ERROR_CANT_OPEN_FILE;
  7664. }
  7665. return LoadEXRMultipartImageFromMemory(exr_images, exr_headers, num_parts,
  7666. file.data, file.size, err);
  7667. }
  7668. int SaveEXRToMemory(const float *data, int width, int height, int components,
  7669. const int save_as_fp16, unsigned char **outbuf, const char **err) {
  7670. if ((components == 1) || components == 3 || components == 4) {
  7671. // OK
  7672. } else {
  7673. std::stringstream ss;
  7674. ss << "Unsupported component value : " << components << std::endl;
  7675. tinyexr::SetErrorMessage(ss.str(), err);
  7676. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7677. }
  7678. EXRHeader header;
  7679. InitEXRHeader(&header);
  7680. if ((width < 16) && (height < 16)) {
  7681. // No compression for small image.
  7682. header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE;
  7683. } else {
  7684. header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
  7685. }
  7686. EXRImage image;
  7687. InitEXRImage(&image);
  7688. image.num_channels = components;
  7689. std::vector<float> images[4];
  7690. if (components == 1) {
  7691. images[0].resize(static_cast<size_t>(width * height));
  7692. memcpy(images[0].data(), data, sizeof(float) * size_t(width * height));
  7693. } else {
  7694. images[0].resize(static_cast<size_t>(width * height));
  7695. images[1].resize(static_cast<size_t>(width * height));
  7696. images[2].resize(static_cast<size_t>(width * height));
  7697. images[3].resize(static_cast<size_t>(width * height));
  7698. // Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers
  7699. for (size_t i = 0; i < static_cast<size_t>(width * height); i++) {
  7700. images[0][i] = data[static_cast<size_t>(components) * i + 0];
  7701. images[1][i] = data[static_cast<size_t>(components) * i + 1];
  7702. images[2][i] = data[static_cast<size_t>(components) * i + 2];
  7703. if (components == 4) {
  7704. images[3][i] = data[static_cast<size_t>(components) * i + 3];
  7705. }
  7706. }
  7707. }
  7708. float *image_ptr[4] = {0, 0, 0, 0};
  7709. if (components == 4) {
  7710. image_ptr[0] = &(images[3].at(0)); // A
  7711. image_ptr[1] = &(images[2].at(0)); // B
  7712. image_ptr[2] = &(images[1].at(0)); // G
  7713. image_ptr[3] = &(images[0].at(0)); // R
  7714. } else if (components == 3) {
  7715. image_ptr[0] = &(images[2].at(0)); // B
  7716. image_ptr[1] = &(images[1].at(0)); // G
  7717. image_ptr[2] = &(images[0].at(0)); // R
  7718. } else if (components == 1) {
  7719. image_ptr[0] = &(images[0].at(0)); // A
  7720. }
  7721. image.images = reinterpret_cast<unsigned char **>(image_ptr);
  7722. image.width = width;
  7723. image.height = height;
  7724. header.num_channels = components;
  7725. header.channels = static_cast<EXRChannelInfo *>(malloc(
  7726. sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels)));
  7727. // Must be (A)BGR order, since most of EXR viewers expect this channel order.
  7728. if (components == 4) {
  7729. #ifdef _MSC_VER
  7730. strncpy_s(header.channels[0].name, "A", 255);
  7731. strncpy_s(header.channels[1].name, "B", 255);
  7732. strncpy_s(header.channels[2].name, "G", 255);
  7733. strncpy_s(header.channels[3].name, "R", 255);
  7734. #else
  7735. strncpy(header.channels[0].name, "A", 255);
  7736. strncpy(header.channels[1].name, "B", 255);
  7737. strncpy(header.channels[2].name, "G", 255);
  7738. strncpy(header.channels[3].name, "R", 255);
  7739. #endif
  7740. header.channels[0].name[strlen("A")] = '\0';
  7741. header.channels[1].name[strlen("B")] = '\0';
  7742. header.channels[2].name[strlen("G")] = '\0';
  7743. header.channels[3].name[strlen("R")] = '\0';
  7744. } else if (components == 3) {
  7745. #ifdef _MSC_VER
  7746. strncpy_s(header.channels[0].name, "B", 255);
  7747. strncpy_s(header.channels[1].name, "G", 255);
  7748. strncpy_s(header.channels[2].name, "R", 255);
  7749. #else
  7750. strncpy(header.channels[0].name, "B", 255);
  7751. strncpy(header.channels[1].name, "G", 255);
  7752. strncpy(header.channels[2].name, "R", 255);
  7753. #endif
  7754. header.channels[0].name[strlen("B")] = '\0';
  7755. header.channels[1].name[strlen("G")] = '\0';
  7756. header.channels[2].name[strlen("R")] = '\0';
  7757. } else {
  7758. #ifdef _MSC_VER
  7759. strncpy_s(header.channels[0].name, "A", 255);
  7760. #else
  7761. strncpy(header.channels[0].name, "A", 255);
  7762. #endif
  7763. header.channels[0].name[strlen("A")] = '\0';
  7764. }
  7765. header.pixel_types = static_cast<int *>(
  7766. malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
  7767. header.requested_pixel_types = static_cast<int *>(
  7768. malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
  7769. for (int i = 0; i < header.num_channels; i++) {
  7770. header.pixel_types[i] =
  7771. TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image
  7772. if (save_as_fp16 > 0) {
  7773. header.requested_pixel_types[i] =
  7774. TINYEXR_PIXELTYPE_HALF; // save with half(fp16) pixel format
  7775. } else {
  7776. header.requested_pixel_types[i] =
  7777. TINYEXR_PIXELTYPE_FLOAT; // save with float(fp32) pixel format(i.e.
  7778. // no precision reduction)
  7779. }
  7780. }
  7781. unsigned char *mem_buf;
  7782. size_t mem_size = SaveEXRImageToMemory(&image, &header, &mem_buf, err);
  7783. if (mem_size == 0) {
  7784. return TINYEXR_ERROR_SERIALIZATION_FAILED;
  7785. }
  7786. free(header.channels);
  7787. free(header.pixel_types);
  7788. free(header.requested_pixel_types);
  7789. if (mem_size > size_t(std::numeric_limits<int>::max())) {
  7790. free(mem_buf);
  7791. return TINYEXR_ERROR_DATA_TOO_LARGE;
  7792. }
  7793. (*outbuf) = mem_buf;
  7794. return int(mem_size);
  7795. }
  7796. int SaveEXR(const float *data, int width, int height, int components,
  7797. const int save_as_fp16, const char *outfilename, const char **err) {
  7798. if ((components == 1) || components == 3 || components == 4) {
  7799. // OK
  7800. } else {
  7801. std::stringstream ss;
  7802. ss << "Unsupported component value : " << components << std::endl;
  7803. tinyexr::SetErrorMessage(ss.str(), err);
  7804. return TINYEXR_ERROR_INVALID_ARGUMENT;
  7805. }
  7806. EXRHeader header;
  7807. InitEXRHeader(&header);
  7808. if ((width < 16) && (height < 16)) {
  7809. // No compression for small image.
  7810. header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE;
  7811. } else {
  7812. header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
  7813. }
  7814. EXRImage image;
  7815. InitEXRImage(&image);
  7816. image.num_channels = components;
  7817. std::vector<float> images[4];
  7818. const size_t pixel_count =
  7819. static_cast<size_t>(width) * static_cast<size_t>(height);
  7820. if (components == 1) {
  7821. images[0].resize(pixel_count);
  7822. memcpy(images[0].data(), data, sizeof(float) * pixel_count);
  7823. } else {
  7824. images[0].resize(pixel_count);
  7825. images[1].resize(pixel_count);
  7826. images[2].resize(pixel_count);
  7827. images[3].resize(pixel_count);
  7828. // Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers
  7829. for (size_t i = 0; i < pixel_count; i++) {
  7830. images[0][i] = data[static_cast<size_t>(components) * i + 0];
  7831. images[1][i] = data[static_cast<size_t>(components) * i + 1];
  7832. images[2][i] = data[static_cast<size_t>(components) * i + 2];
  7833. if (components == 4) {
  7834. images[3][i] = data[static_cast<size_t>(components) * i + 3];
  7835. }
  7836. }
  7837. }
  7838. float *image_ptr[4] = {0, 0, 0, 0};
  7839. if (components == 4) {
  7840. image_ptr[0] = &(images[3].at(0)); // A
  7841. image_ptr[1] = &(images[2].at(0)); // B
  7842. image_ptr[2] = &(images[1].at(0)); // G
  7843. image_ptr[3] = &(images[0].at(0)); // R
  7844. } else if (components == 3) {
  7845. image_ptr[0] = &(images[2].at(0)); // B
  7846. image_ptr[1] = &(images[1].at(0)); // G
  7847. image_ptr[2] = &(images[0].at(0)); // R
  7848. } else if (components == 1) {
  7849. image_ptr[0] = &(images[0].at(0)); // A
  7850. }
  7851. image.images = reinterpret_cast<unsigned char **>(image_ptr);
  7852. image.width = width;
  7853. image.height = height;
  7854. header.num_channels = components;
  7855. header.channels = static_cast<EXRChannelInfo *>(malloc(
  7856. sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels)));
  7857. // Must be (A)BGR order, since most of EXR viewers expect this channel order.
  7858. if (components == 4) {
  7859. #ifdef _MSC_VER
  7860. strncpy_s(header.channels[0].name, "A", 255);
  7861. strncpy_s(header.channels[1].name, "B", 255);
  7862. strncpy_s(header.channels[2].name, "G", 255);
  7863. strncpy_s(header.channels[3].name, "R", 255);
  7864. #else
  7865. strncpy(header.channels[0].name, "A", 255);
  7866. strncpy(header.channels[1].name, "B", 255);
  7867. strncpy(header.channels[2].name, "G", 255);
  7868. strncpy(header.channels[3].name, "R", 255);
  7869. #endif
  7870. header.channels[0].name[strlen("A")] = '\0';
  7871. header.channels[1].name[strlen("B")] = '\0';
  7872. header.channels[2].name[strlen("G")] = '\0';
  7873. header.channels[3].name[strlen("R")] = '\0';
  7874. } else if (components == 3) {
  7875. #ifdef _MSC_VER
  7876. strncpy_s(header.channels[0].name, "B", 255);
  7877. strncpy_s(header.channels[1].name, "G", 255);
  7878. strncpy_s(header.channels[2].name, "R", 255);
  7879. #else
  7880. strncpy(header.channels[0].name, "B", 255);
  7881. strncpy(header.channels[1].name, "G", 255);
  7882. strncpy(header.channels[2].name, "R", 255);
  7883. #endif
  7884. header.channels[0].name[strlen("B")] = '\0';
  7885. header.channels[1].name[strlen("G")] = '\0';
  7886. header.channels[2].name[strlen("R")] = '\0';
  7887. } else {
  7888. #ifdef _MSC_VER
  7889. strncpy_s(header.channels[0].name, "A", 255);
  7890. #else
  7891. strncpy(header.channels[0].name, "A", 255);
  7892. #endif
  7893. header.channels[0].name[strlen("A")] = '\0';
  7894. }
  7895. header.pixel_types = static_cast<int *>(
  7896. malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
  7897. header.requested_pixel_types = static_cast<int *>(
  7898. malloc(sizeof(int) * static_cast<size_t>(header.num_channels)));
  7899. for (int i = 0; i < header.num_channels; i++) {
  7900. header.pixel_types[i] =
  7901. TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image
  7902. if (save_as_fp16 > 0) {
  7903. header.requested_pixel_types[i] =
  7904. TINYEXR_PIXELTYPE_HALF; // save with half(fp16) pixel format
  7905. } else {
  7906. header.requested_pixel_types[i] =
  7907. TINYEXR_PIXELTYPE_FLOAT; // save with float(fp32) pixel format(i.e.
  7908. // no precision reduction)
  7909. }
  7910. }
  7911. int ret = SaveEXRImageToFile(&image, &header, outfilename, err);
  7912. if (ret != TINYEXR_SUCCESS) {
  7913. return ret;
  7914. }
  7915. free(header.channels);
  7916. free(header.pixel_types);
  7917. free(header.requested_pixel_types);
  7918. return ret;
  7919. }
  7920. #ifdef __clang__
  7921. // zero-as-null-pointer-constant
  7922. #pragma clang diagnostic pop
  7923. #endif
  7924. #endif // TINYEXR_IMPLEMENTATION_DEFINED
  7925. #endif // TINYEXR_IMPLEMENTATION