pngstest.c 105 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808
  1. /*-
  2. * pngstest.c
  3. *
  4. * Copyright (c) 2013 John Cunningham Bowler
  5. *
  6. * Last changed in libpng 1.6.8 [December 19, 2013]
  7. *
  8. * This code is released under the libpng license.
  9. * For conditions of distribution and use, see the disclaimer
  10. * and license in png.h
  11. *
  12. * Test for the PNG 'simplified' APIs.
  13. */
  14. #define _ISOC90_SOURCE 1
  15. #define MALLOC_CHECK_ 2/*glibc facility: turn on debugging*/
  16. #include <stddef.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <errno.h>
  21. #include <ctype.h>
  22. #include <math.h>
  23. #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
  24. # include <config.h>
  25. #endif
  26. /* Define the following to use this test against your installed libpng, rather
  27. * than the one being built here:
  28. */
  29. #ifdef PNG_FREESTANDING_TESTS
  30. # include <png.h>
  31. #else
  32. # include "../../png.h"
  33. #endif
  34. #ifdef PNG_SIMPLIFIED_READ_SUPPORTED /* Else nothing can be done */
  35. #include "../tools/sRGB.h"
  36. /* KNOWN ISSUES
  37. *
  38. * These defines switch on alternate algorithms for format conversions to match
  39. * the current libpng implementation; they are set to allow pngstest to pass
  40. * even though libpng is producing answers that are not as correct as they
  41. * should be.
  42. */
  43. #define ALLOW_UNUSED_GPC 0
  44. /* If true include unused static GPC functions and declare an external array
  45. * of them to hide the fact that they are unused. This is for development
  46. * use while testing the correct function to use to take into account libpng
  47. * misbehavior, such as using a simple power law to correct sRGB to linear.
  48. */
  49. /* The following is to support direct compilation of this file as C++ */
  50. #ifdef __cplusplus
  51. # define voidcast(type, value) static_cast<type>(value)
  52. # define aligncastconst(type, value) \
  53. static_cast<type>(static_cast<const void*>(value))
  54. #else
  55. # define voidcast(type, value) (value)
  56. # define aligncastconst(type, value) ((const void*)(value))
  57. #endif /* __cplusplus */
  58. /* During parallel runs of pngstest each temporary file needs a unique name,
  59. * this is used to permit uniqueness using a command line argument which can be
  60. * up to 22 characters long.
  61. */
  62. static char tmpf[23] = "TMP";
  63. /* Generate random bytes. This uses a boring repeatable algorithm and it
  64. * is implemented here so that it gives the same set of numbers on every
  65. * architecture. It's a linear congruential generator (Knuth or Sedgewick
  66. * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
  67. * Hill, "The Art of Electronics".
  68. */
  69. static void
  70. make_random_bytes(png_uint_32* seed, void* pv, size_t size)
  71. {
  72. png_uint_32 u0 = seed[0], u1 = seed[1];
  73. png_bytep bytes = voidcast(png_bytep, pv);
  74. /* There are thirty three bits, the next bit in the sequence is bit-33 XOR
  75. * bit-20. The top 1 bit is in u1, the bottom 32 are in u0.
  76. */
  77. size_t i;
  78. for (i=0; i<size; ++i)
  79. {
  80. /* First generate 8 new bits then shift them in at the end. */
  81. png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
  82. u1 <<= 8;
  83. u1 |= u0 >> 24;
  84. u0 <<= 8;
  85. u0 |= u;
  86. *bytes++ = (png_byte)u;
  87. }
  88. seed[0] = u0;
  89. seed[1] = u1;
  90. }
  91. static void
  92. random_color(png_colorp color)
  93. {
  94. static png_uint_32 color_seed[2] = { 0x12345678, 0x9abcdef };
  95. make_random_bytes(color_seed, color, sizeof *color);
  96. }
  97. /* Math support - neither Cygwin nor Visual Studio have C99 support and we need
  98. * a predictable rounding function, so make one here:
  99. */
  100. static double
  101. closestinteger(double x)
  102. {
  103. return floor(x + .5);
  104. }
  105. /* Cast support: remove GCC whines. */
  106. static png_byte
  107. u8d(double d)
  108. {
  109. d = closestinteger(d);
  110. return (png_byte)d;
  111. }
  112. static png_uint_16
  113. u16d(double d)
  114. {
  115. d = closestinteger(d);
  116. return (png_uint_16)d;
  117. }
  118. /* sRGB support: use exact calculations rounded to the nearest int, see the
  119. * fesetround() call in main(). sRGB_to_d optimizes the 8 to 16-bit conversion.
  120. */
  121. static double sRGB_to_d[256];
  122. static double g22_to_d[256];
  123. static void
  124. init_sRGB_to_d(void)
  125. {
  126. int i;
  127. sRGB_to_d[0] = 0;
  128. for (i=1; i<255; ++i)
  129. sRGB_to_d[i] = linear_from_sRGB(i/255.);
  130. sRGB_to_d[255] = 1;
  131. g22_to_d[0] = 0;
  132. for (i=1; i<255; ++i)
  133. g22_to_d[i] = pow(i/255., 1/.45455);
  134. g22_to_d[255] = 1;
  135. }
  136. static png_byte
  137. sRGB(double linear /*range 0.0 .. 1.0*/)
  138. {
  139. return u8d(255 * sRGB_from_linear(linear));
  140. }
  141. static png_byte
  142. isRGB(int fixed_linear)
  143. {
  144. return sRGB(fixed_linear / 65535.);
  145. }
  146. #if 0 /* not used */
  147. static png_byte
  148. unpremultiply(int component, int alpha)
  149. {
  150. if (alpha <= component)
  151. return 255; /* Arbitrary, but consistent with the libpng code */
  152. else if (alpha >= 65535)
  153. return isRGB(component);
  154. else
  155. return sRGB((double)component / alpha);
  156. }
  157. #endif
  158. static png_uint_16
  159. ilinear(int fixed_srgb)
  160. {
  161. return u16d(65535 * sRGB_to_d[fixed_srgb]);
  162. }
  163. static png_uint_16
  164. ilineara(int fixed_srgb, int alpha)
  165. {
  166. return u16d((257 * alpha) * sRGB_to_d[fixed_srgb]);
  167. }
  168. static png_uint_16
  169. ilinear_g22(int fixed_srgb)
  170. {
  171. return u16d(65535 * g22_to_d[fixed_srgb]);
  172. }
  173. #if ALLOW_UNUSED_GPC
  174. static png_uint_16
  175. ilineara_g22(int fixed_srgb, int alpha)
  176. {
  177. return u16d((257 * alpha) * g22_to_d[fixed_srgb]);
  178. }
  179. #endif
  180. static double
  181. YfromRGBint(int ir, int ig, int ib)
  182. {
  183. double r = ir;
  184. double g = ig;
  185. double b = ib;
  186. return YfromRGB(r, g, b);
  187. }
  188. #if 0 /* unused */
  189. /* The error that results from using a 2.2 power law in place of the correct
  190. * sRGB transform, given an 8-bit value which might be either sRGB or power-law.
  191. */
  192. static int
  193. power_law_error8(int value)
  194. {
  195. if (value > 0 && value < 255)
  196. {
  197. double vd = value / 255.;
  198. double e = fabs(
  199. pow(sRGB_to_d[value], 1/2.2) - sRGB_from_linear(pow(vd, 2.2)));
  200. /* Always allow an extra 1 here for rounding errors */
  201. e = 1+floor(255 * e);
  202. return (int)e;
  203. }
  204. return 0;
  205. }
  206. static int error_in_sRGB_roundtrip = 56; /* by experiment */
  207. static int
  208. power_law_error16(int value)
  209. {
  210. if (value > 0 && value < 65535)
  211. {
  212. /* Round trip the value through an 8-bit representation but using
  213. * non-matching to/from conversions.
  214. */
  215. double vd = value / 65535.;
  216. double e = fabs(
  217. pow(sRGB_from_linear(vd), 2.2) - linear_from_sRGB(pow(vd, 1/2.2)));
  218. /* Always allow an extra 1 here for rounding errors */
  219. e = error_in_sRGB_roundtrip+floor(65535 * e);
  220. return (int)e;
  221. }
  222. return 0;
  223. }
  224. static int
  225. compare_8bit(int v1, int v2, int error_limit, int multiple_algorithms)
  226. {
  227. int e = abs(v1-v2);
  228. int ev1, ev2;
  229. if (e <= error_limit)
  230. return 1;
  231. if (!multiple_algorithms)
  232. return 0;
  233. ev1 = power_law_error8(v1);
  234. if (e <= ev1)
  235. return 1;
  236. ev2 = power_law_error8(v2);
  237. if (e <= ev2)
  238. return 1;
  239. return 0;
  240. }
  241. static int
  242. compare_16bit(int v1, int v2, int error_limit, int multiple_algorithms)
  243. {
  244. int e = abs(v1-v2);
  245. int ev1, ev2;
  246. if (e <= error_limit)
  247. return 1;
  248. /* "multiple_algorithms" in this case means that a color-map has been
  249. * involved somewhere, so we can deduce that the values were forced to 8-bit
  250. * (like the via_linear case for 8-bit.)
  251. */
  252. if (!multiple_algorithms)
  253. return 0;
  254. ev1 = power_law_error16(v1);
  255. if (e <= ev1)
  256. return 1;
  257. ev2 = power_law_error16(v2);
  258. if (e <= ev2)
  259. return 1;
  260. return 0;
  261. }
  262. #endif /* unused */
  263. #define READ_FILE 1 /* else memory */
  264. #define USE_STDIO 2 /* else use file name */
  265. #define STRICT 4 /* fail on warnings too */
  266. #define VERBOSE 8
  267. #define KEEP_TMPFILES 16 /* else delete temporary files */
  268. #define KEEP_GOING 32
  269. #define ACCUMULATE 64
  270. #define FAST_WRITE 128
  271. #define sRGB_16BIT 256
  272. static void
  273. print_opts(png_uint_32 opts)
  274. {
  275. if (opts & READ_FILE)
  276. printf(" --file");
  277. if (opts & USE_STDIO)
  278. printf(" --stdio");
  279. if (opts & STRICT)
  280. printf(" --strict");
  281. if (opts & VERBOSE)
  282. printf(" --verbose");
  283. if (opts & KEEP_TMPFILES)
  284. printf(" --preserve");
  285. if (opts & KEEP_GOING)
  286. printf(" --keep-going");
  287. if (opts & ACCUMULATE)
  288. printf(" --accumulate");
  289. if (!(opts & FAST_WRITE)) /* --fast is currently the default */
  290. printf(" --slow");
  291. if (opts & sRGB_16BIT)
  292. printf(" --sRGB-16bit");
  293. }
  294. #define FORMAT_NO_CHANGE 0x80000000 /* additional flag */
  295. /* A name table for all the formats - defines the format of the '+' arguments to
  296. * pngstest.
  297. */
  298. #define FORMAT_COUNT 64
  299. #define FORMAT_MASK 0x3f
  300. static PNG_CONST char * PNG_CONST format_names[FORMAT_COUNT] =
  301. {
  302. "sRGB-gray",
  303. "sRGB-gray+alpha",
  304. "sRGB-rgb",
  305. "sRGB-rgb+alpha",
  306. "linear-gray",
  307. "linear-gray+alpha",
  308. "linear-rgb",
  309. "linear-rgb+alpha",
  310. "color-mapped-sRGB-gray",
  311. "color-mapped-sRGB-gray+alpha",
  312. "color-mapped-sRGB-rgb",
  313. "color-mapped-sRGB-rgb+alpha",
  314. "color-mapped-linear-gray",
  315. "color-mapped-linear-gray+alpha",
  316. "color-mapped-linear-rgb",
  317. "color-mapped-linear-rgb+alpha",
  318. "sRGB-gray",
  319. "sRGB-gray+alpha",
  320. "sRGB-bgr",
  321. "sRGB-bgr+alpha",
  322. "linear-gray",
  323. "linear-gray+alpha",
  324. "linear-bgr",
  325. "linear-bgr+alpha",
  326. "color-mapped-sRGB-gray",
  327. "color-mapped-sRGB-gray+alpha",
  328. "color-mapped-sRGB-bgr",
  329. "color-mapped-sRGB-bgr+alpha",
  330. "color-mapped-linear-gray",
  331. "color-mapped-linear-gray+alpha",
  332. "color-mapped-linear-bgr",
  333. "color-mapped-linear-bgr+alpha",
  334. "sRGB-gray",
  335. "alpha+sRGB-gray",
  336. "sRGB-rgb",
  337. "alpha+sRGB-rgb",
  338. "linear-gray",
  339. "alpha+linear-gray",
  340. "linear-rgb",
  341. "alpha+linear-rgb",
  342. "color-mapped-sRGB-gray",
  343. "color-mapped-alpha+sRGB-gray",
  344. "color-mapped-sRGB-rgb",
  345. "color-mapped-alpha+sRGB-rgb",
  346. "color-mapped-linear-gray",
  347. "color-mapped-alpha+linear-gray",
  348. "color-mapped-linear-rgb",
  349. "color-mapped-alpha+linear-rgb",
  350. "sRGB-gray",
  351. "alpha+sRGB-gray",
  352. "sRGB-bgr",
  353. "alpha+sRGB-bgr",
  354. "linear-gray",
  355. "alpha+linear-gray",
  356. "linear-bgr",
  357. "alpha+linear-bgr",
  358. "color-mapped-sRGB-gray",
  359. "color-mapped-alpha+sRGB-gray",
  360. "color-mapped-sRGB-bgr",
  361. "color-mapped-alpha+sRGB-bgr",
  362. "color-mapped-linear-gray",
  363. "color-mapped-alpha+linear-gray",
  364. "color-mapped-linear-bgr",
  365. "color-mapped-alpha+linear-bgr",
  366. };
  367. /* Decode an argument to a format number. */
  368. static png_uint_32
  369. formatof(const char *arg)
  370. {
  371. char *ep;
  372. unsigned long format = strtoul(arg, &ep, 0);
  373. if (ep > arg && *ep == 0 && format < FORMAT_COUNT)
  374. return (png_uint_32)format;
  375. else for (format=0; format < FORMAT_COUNT; ++format)
  376. {
  377. if (strcmp(format_names[format], arg) == 0)
  378. return (png_uint_32)format;
  379. }
  380. fprintf(stderr, "pngstest: format name '%s' invalid\n", arg);
  381. return FORMAT_COUNT;
  382. }
  383. /* Bitset/test functions for formats */
  384. #define FORMAT_SET_COUNT (FORMAT_COUNT / 32)
  385. typedef struct
  386. {
  387. png_uint_32 bits[FORMAT_SET_COUNT];
  388. }
  389. format_list;
  390. static void format_init(format_list *pf)
  391. {
  392. int i;
  393. for (i=0; i<FORMAT_SET_COUNT; ++i)
  394. pf->bits[i] = 0; /* All off */
  395. }
  396. #if 0 /* currently unused */
  397. static void format_clear(format_list *pf)
  398. {
  399. int i;
  400. for (i=0; i<FORMAT_SET_COUNT; ++i)
  401. pf->bits[i] = 0;
  402. }
  403. #endif
  404. static int format_is_initial(format_list *pf)
  405. {
  406. int i;
  407. for (i=0; i<FORMAT_SET_COUNT; ++i)
  408. if (pf->bits[i] != 0)
  409. return 0;
  410. return 1;
  411. }
  412. static int format_set(format_list *pf, png_uint_32 format)
  413. {
  414. if (format < FORMAT_COUNT)
  415. return pf->bits[format >> 5] |= ((png_uint_32)1) << (format & 31);
  416. return 0;
  417. }
  418. #if 0 /* currently unused */
  419. static int format_unset(format_list *pf, png_uint_32 format)
  420. {
  421. if (format < FORMAT_COUNT)
  422. return pf->bits[format >> 5] &= ~((png_uint_32)1) << (format & 31);
  423. return 0;
  424. }
  425. #endif
  426. static int format_isset(format_list *pf, png_uint_32 format)
  427. {
  428. return format < FORMAT_COUNT &&
  429. (pf->bits[format >> 5] & (((png_uint_32)1) << (format & 31))) != 0;
  430. }
  431. static void format_default(format_list *pf, int redundant)
  432. {
  433. if (redundant)
  434. {
  435. int i;
  436. /* set everything, including flags that are pointless */
  437. for (i=0; i<FORMAT_SET_COUNT; ++i)
  438. pf->bits[i] = ~(png_uint_32)0;
  439. }
  440. else
  441. {
  442. png_uint_32 f;
  443. for (f=0; f<FORMAT_COUNT; ++f)
  444. {
  445. /* Eliminate redundant and unsupported settings. */
  446. # ifdef PNG_FORMAT_BGR_SUPPORTED
  447. /* BGR is meaningless if no color: */
  448. if ((f & PNG_FORMAT_FLAG_COLOR) == 0 &&
  449. (f & PNG_FORMAT_FLAG_BGR) != 0)
  450. # else
  451. if ((f & 0x10U/*HACK: fixed value*/) != 0)
  452. # endif
  453. continue;
  454. /* AFIRST is meaningless if no alpha: */
  455. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  456. if ((f & PNG_FORMAT_FLAG_ALPHA) == 0 &&
  457. (f & PNG_FORMAT_FLAG_AFIRST) != 0)
  458. # else
  459. if ((f & 0x20U/*HACK: fixed value*/) != 0)
  460. # endif
  461. continue;
  462. format_set(pf, f);
  463. }
  464. }
  465. }
  466. /* THE Image STRUCTURE */
  467. /* The super-class of a png_image, contains the decoded image plus the input
  468. * data necessary to re-read the file with a different format.
  469. */
  470. typedef struct
  471. {
  472. png_image image;
  473. png_uint_32 opts;
  474. const char *file_name;
  475. int stride_extra;
  476. FILE *input_file;
  477. png_voidp input_memory;
  478. png_size_t input_memory_size;
  479. png_bytep buffer;
  480. ptrdiff_t stride;
  481. png_size_t bufsize;
  482. png_size_t allocsize;
  483. char tmpfile_name[32];
  484. png_uint_16 colormap[256*4];
  485. }
  486. Image;
  487. /* Initializer: also sets the permitted error limit for 16-bit operations. */
  488. static void
  489. newimage(Image *image)
  490. {
  491. memset(image, 0, sizeof *image);
  492. }
  493. /* Reset the image to be read again - only needs to rewind the FILE* at present.
  494. */
  495. static void
  496. resetimage(Image *image)
  497. {
  498. if (image->input_file != NULL)
  499. rewind(image->input_file);
  500. }
  501. /* Free the image buffer; the buffer is re-used on a re-read, this is just for
  502. * cleanup.
  503. */
  504. static void
  505. freebuffer(Image *image)
  506. {
  507. if (image->buffer) free(image->buffer);
  508. image->buffer = NULL;
  509. image->bufsize = 0;
  510. image->allocsize = 0;
  511. }
  512. /* Delete function; cleans out all the allocated data and the temporary file in
  513. * the image.
  514. */
  515. static void
  516. freeimage(Image *image)
  517. {
  518. freebuffer(image);
  519. png_image_free(&image->image);
  520. if (image->input_file != NULL)
  521. {
  522. fclose(image->input_file);
  523. image->input_file = NULL;
  524. }
  525. if (image->input_memory != NULL)
  526. {
  527. free(image->input_memory);
  528. image->input_memory = NULL;
  529. image->input_memory_size = 0;
  530. }
  531. if (image->tmpfile_name[0] != 0 && (image->opts & KEEP_TMPFILES) == 0)
  532. {
  533. remove(image->tmpfile_name);
  534. image->tmpfile_name[0] = 0;
  535. }
  536. }
  537. /* This is actually a re-initializer; allows an image structure to be re-used by
  538. * freeing everything that relates to an old image.
  539. */
  540. static void initimage(Image *image, png_uint_32 opts, const char *file_name,
  541. int stride_extra)
  542. {
  543. freeimage(image);
  544. memset(&image->image, 0, sizeof image->image);
  545. image->opts = opts;
  546. image->file_name = file_name;
  547. image->stride_extra = stride_extra;
  548. }
  549. /* Make sure the image buffer is big enough; allows re-use of the buffer if the
  550. * image is re-read.
  551. */
  552. #define BUFFER_INIT8 73
  553. static void
  554. allocbuffer(Image *image)
  555. {
  556. png_size_t size = PNG_IMAGE_BUFFER_SIZE(image->image, image->stride);
  557. if (size+32 > image->bufsize)
  558. {
  559. freebuffer(image);
  560. image->buffer = voidcast(png_bytep, malloc(size+32));
  561. if (image->buffer == NULL)
  562. {
  563. fflush(stdout);
  564. fprintf(stderr,
  565. "simpletest: out of memory allocating %lu(+32) byte buffer\n",
  566. (unsigned long)size);
  567. exit(1);
  568. }
  569. image->bufsize = size+32;
  570. }
  571. memset(image->buffer, 95, image->bufsize);
  572. memset(image->buffer+16, BUFFER_INIT8, size);
  573. image->allocsize = size;
  574. }
  575. /* Make sure 16 bytes match the given byte. */
  576. static int
  577. check16(png_const_bytep bp, int b)
  578. {
  579. int i = 16;
  580. do
  581. if (*bp != b) return 1;
  582. while (--i);
  583. return 0;
  584. }
  585. /* Check for overwrite in the image buffer. */
  586. static void
  587. checkbuffer(Image *image, const char *arg)
  588. {
  589. if (check16(image->buffer, 95))
  590. {
  591. fflush(stdout);
  592. fprintf(stderr, "%s: overwrite at start of image buffer\n", arg);
  593. exit(1);
  594. }
  595. if (check16(image->buffer+16+image->allocsize, 95))
  596. {
  597. fflush(stdout);
  598. fprintf(stderr, "%s: overwrite at end of image buffer\n", arg);
  599. exit(1);
  600. }
  601. }
  602. /* ERROR HANDLING */
  603. /* Log a terminal error, also frees the libpng part of the image if necessary.
  604. */
  605. static int
  606. logerror(Image *image, const char *a1, const char *a2, const char *a3)
  607. {
  608. fflush(stdout);
  609. if (image->image.warning_or_error)
  610. fprintf(stderr, "%s%s%s: %s\n", a1, a2, a3, image->image.message);
  611. else
  612. fprintf(stderr, "%s%s%s\n", a1, a2, a3);
  613. if (image->image.opaque != NULL)
  614. {
  615. fprintf(stderr, "%s: image opaque pointer non-NULL on error\n",
  616. image->file_name);
  617. png_image_free(&image->image);
  618. }
  619. return 0;
  620. }
  621. /* Log an error and close a file (just a utility to do both things in one
  622. * function call.)
  623. */
  624. static int
  625. logclose(Image *image, FILE *f, const char *name, const char *operation)
  626. {
  627. int e = errno;
  628. fclose(f);
  629. return logerror(image, name, operation, strerror(e));
  630. }
  631. /* Make sure the png_image has been freed - validates that libpng is doing what
  632. * the spec says and freeing the image.
  633. */
  634. static int
  635. checkopaque(Image *image)
  636. {
  637. if (image->image.opaque != NULL)
  638. {
  639. png_image_free(&image->image);
  640. return logerror(image, image->file_name, ": opaque not NULL", "");
  641. }
  642. else if (image->image.warning_or_error != 0 && (image->opts & STRICT) != 0)
  643. return logerror(image, image->file_name, " --strict", "");
  644. else
  645. return 1;
  646. }
  647. /* IMAGE COMPARISON/CHECKING */
  648. /* Compare the pixels of two images, which should be the same but aren't. The
  649. * images must have been checked for a size match.
  650. */
  651. typedef struct
  652. {
  653. /* The components, for grayscale images the gray value is in 'g' and if alpha
  654. * is not present 'a' is set to 255 or 65535 according to format.
  655. */
  656. int r, g, b, a;
  657. } Pixel;
  658. typedef struct
  659. {
  660. /* The background as the original sRGB 8-bit value converted to the final
  661. * integer format and as a double precision linear value in the range 0..1
  662. * for with partially transparent pixels.
  663. */
  664. int ir, ig, ib;
  665. double dr, dg, db; /* linear r,g,b scaled to 0..1 */
  666. } Background;
  667. /* Basic image formats; control the data but not the layout thereof. */
  668. #define BASE_FORMATS\
  669. (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_LINEAR)
  670. /* Read a Pixel from a buffer. The code below stores the correct routine for
  671. * the format in a function pointer, these are the routines:
  672. */
  673. static void
  674. gp_g8(Pixel *p, png_const_voidp pb)
  675. {
  676. png_const_bytep pp = voidcast(png_const_bytep, pb);
  677. p->r = p->g = p->b = pp[0];
  678. p->a = 255;
  679. }
  680. static void
  681. gp_ga8(Pixel *p, png_const_voidp pb)
  682. {
  683. png_const_bytep pp = voidcast(png_const_bytep, pb);
  684. p->r = p->g = p->b = pp[0];
  685. p->a = pp[1];
  686. }
  687. #ifdef PNG_FORMAT_AFIRST_SUPPORTED
  688. static void
  689. gp_ag8(Pixel *p, png_const_voidp pb)
  690. {
  691. png_const_bytep pp = voidcast(png_const_bytep, pb);
  692. p->r = p->g = p->b = pp[1];
  693. p->a = pp[0];
  694. }
  695. #endif
  696. static void
  697. gp_rgb8(Pixel *p, png_const_voidp pb)
  698. {
  699. png_const_bytep pp = voidcast(png_const_bytep, pb);
  700. p->r = pp[0];
  701. p->g = pp[1];
  702. p->b = pp[2];
  703. p->a = 255;
  704. }
  705. #ifdef PNG_FORMAT_BGR_SUPPORTED
  706. static void
  707. gp_bgr8(Pixel *p, png_const_voidp pb)
  708. {
  709. png_const_bytep pp = voidcast(png_const_bytep, pb);
  710. p->r = pp[2];
  711. p->g = pp[1];
  712. p->b = pp[0];
  713. p->a = 255;
  714. }
  715. #endif
  716. static void
  717. gp_rgba8(Pixel *p, png_const_voidp pb)
  718. {
  719. png_const_bytep pp = voidcast(png_const_bytep, pb);
  720. p->r = pp[0];
  721. p->g = pp[1];
  722. p->b = pp[2];
  723. p->a = pp[3];
  724. }
  725. #ifdef PNG_FORMAT_BGR_SUPPORTED
  726. static void
  727. gp_bgra8(Pixel *p, png_const_voidp pb)
  728. {
  729. png_const_bytep pp = voidcast(png_const_bytep, pb);
  730. p->r = pp[2];
  731. p->g = pp[1];
  732. p->b = pp[0];
  733. p->a = pp[3];
  734. }
  735. #endif
  736. #ifdef PNG_FORMAT_AFIRST_SUPPORTED
  737. static void
  738. gp_argb8(Pixel *p, png_const_voidp pb)
  739. {
  740. png_const_bytep pp = voidcast(png_const_bytep, pb);
  741. p->r = pp[1];
  742. p->g = pp[2];
  743. p->b = pp[3];
  744. p->a = pp[0];
  745. }
  746. #endif
  747. #if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED)
  748. static void
  749. gp_abgr8(Pixel *p, png_const_voidp pb)
  750. {
  751. png_const_bytep pp = voidcast(png_const_bytep, pb);
  752. p->r = pp[3];
  753. p->g = pp[2];
  754. p->b = pp[1];
  755. p->a = pp[0];
  756. }
  757. #endif
  758. static void
  759. gp_g16(Pixel *p, png_const_voidp pb)
  760. {
  761. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  762. p->r = p->g = p->b = pp[0];
  763. p->a = 65535;
  764. }
  765. static void
  766. gp_ga16(Pixel *p, png_const_voidp pb)
  767. {
  768. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  769. p->r = p->g = p->b = pp[0];
  770. p->a = pp[1];
  771. }
  772. #ifdef PNG_FORMAT_AFIRST_SUPPORTED
  773. static void
  774. gp_ag16(Pixel *p, png_const_voidp pb)
  775. {
  776. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  777. p->r = p->g = p->b = pp[1];
  778. p->a = pp[0];
  779. }
  780. #endif
  781. static void
  782. gp_rgb16(Pixel *p, png_const_voidp pb)
  783. {
  784. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  785. p->r = pp[0];
  786. p->g = pp[1];
  787. p->b = pp[2];
  788. p->a = 65535;
  789. }
  790. #ifdef PNG_FORMAT_BGR_SUPPORTED
  791. static void
  792. gp_bgr16(Pixel *p, png_const_voidp pb)
  793. {
  794. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  795. p->r = pp[2];
  796. p->g = pp[1];
  797. p->b = pp[0];
  798. p->a = 65535;
  799. }
  800. #endif
  801. static void
  802. gp_rgba16(Pixel *p, png_const_voidp pb)
  803. {
  804. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  805. p->r = pp[0];
  806. p->g = pp[1];
  807. p->b = pp[2];
  808. p->a = pp[3];
  809. }
  810. #ifdef PNG_FORMAT_BGR_SUPPORTED
  811. static void
  812. gp_bgra16(Pixel *p, png_const_voidp pb)
  813. {
  814. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  815. p->r = pp[2];
  816. p->g = pp[1];
  817. p->b = pp[0];
  818. p->a = pp[3];
  819. }
  820. #endif
  821. #ifdef PNG_FORMAT_AFIRST_SUPPORTED
  822. static void
  823. gp_argb16(Pixel *p, png_const_voidp pb)
  824. {
  825. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  826. p->r = pp[1];
  827. p->g = pp[2];
  828. p->b = pp[3];
  829. p->a = pp[0];
  830. }
  831. #endif
  832. #if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED)
  833. static void
  834. gp_abgr16(Pixel *p, png_const_voidp pb)
  835. {
  836. png_const_uint_16p pp = voidcast(png_const_uint_16p, pb);
  837. p->r = pp[3];
  838. p->g = pp[2];
  839. p->b = pp[1];
  840. p->a = pp[0];
  841. }
  842. #endif
  843. /* Given a format, return the correct one of the above functions. */
  844. static void (*
  845. get_pixel(png_uint_32 format))(Pixel *p, png_const_voidp pb)
  846. {
  847. /* The color-map flag is irrelevant here - the caller of the function
  848. * returned must either pass the buffer or, for a color-mapped image, the
  849. * correct entry in the color-map.
  850. */
  851. if (format & PNG_FORMAT_FLAG_LINEAR)
  852. {
  853. if (format & PNG_FORMAT_FLAG_COLOR)
  854. {
  855. # ifdef PNG_FORMAT_BGR_SUPPORTED
  856. if (format & PNG_FORMAT_FLAG_BGR)
  857. {
  858. if (format & PNG_FORMAT_FLAG_ALPHA)
  859. {
  860. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  861. if (format & PNG_FORMAT_FLAG_AFIRST)
  862. return gp_abgr16;
  863. else
  864. # endif
  865. return gp_bgra16;
  866. }
  867. else
  868. return gp_bgr16;
  869. }
  870. else
  871. # endif
  872. {
  873. if (format & PNG_FORMAT_FLAG_ALPHA)
  874. {
  875. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  876. if (format & PNG_FORMAT_FLAG_AFIRST)
  877. return gp_argb16;
  878. else
  879. # endif
  880. return gp_rgba16;
  881. }
  882. else
  883. return gp_rgb16;
  884. }
  885. }
  886. else
  887. {
  888. if (format & PNG_FORMAT_FLAG_ALPHA)
  889. {
  890. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  891. if (format & PNG_FORMAT_FLAG_AFIRST)
  892. return gp_ag16;
  893. else
  894. # endif
  895. return gp_ga16;
  896. }
  897. else
  898. return gp_g16;
  899. }
  900. }
  901. else
  902. {
  903. if (format & PNG_FORMAT_FLAG_COLOR)
  904. {
  905. # ifdef PNG_FORMAT_BGR_SUPPORTED
  906. if (format & PNG_FORMAT_FLAG_BGR)
  907. {
  908. if (format & PNG_FORMAT_FLAG_ALPHA)
  909. {
  910. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  911. if (format & PNG_FORMAT_FLAG_AFIRST)
  912. return gp_abgr8;
  913. else
  914. # endif
  915. return gp_bgra8;
  916. }
  917. else
  918. return gp_bgr8;
  919. }
  920. else
  921. # endif
  922. {
  923. if (format & PNG_FORMAT_FLAG_ALPHA)
  924. {
  925. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  926. if (format & PNG_FORMAT_FLAG_AFIRST)
  927. return gp_argb8;
  928. else
  929. # endif
  930. return gp_rgba8;
  931. }
  932. else
  933. return gp_rgb8;
  934. }
  935. }
  936. else
  937. {
  938. if (format & PNG_FORMAT_FLAG_ALPHA)
  939. {
  940. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  941. if (format & PNG_FORMAT_FLAG_AFIRST)
  942. return gp_ag8;
  943. else
  944. # endif
  945. return gp_ga8;
  946. }
  947. else
  948. return gp_g8;
  949. }
  950. }
  951. }
  952. /* Convertion between pixel formats. The code above effectively eliminates the
  953. * component ordering changes leaving three basic changes:
  954. *
  955. * 1) Remove an alpha channel by pre-multiplication or compositing on a
  956. * background color. (Adding an alpha channel is a no-op.)
  957. *
  958. * 2) Remove color by mapping to grayscale. (Grayscale to color is a no-op.)
  959. *
  960. * 3) Convert between 8-bit and 16-bit components. (Both directtions are
  961. * relevant.)
  962. *
  963. * This gives the following base format conversion matrix:
  964. *
  965. * OUT: ----- 8-bit ----- ----- 16-bit -----
  966. * IN G GA RGB RGBA G GA RGB RGBA
  967. * 8 G . . . . lin lin lin lin
  968. * 8 GA bckg . bckc . pre' pre pre' pre
  969. * 8 RGB g8 g8 . . glin glin lin lin
  970. * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre
  971. * 16 G sRGB sRGB sRGB sRGB . . . .
  972. * 16 GA b16g unpg b16c unpc A . A .
  973. * 16 RGB sG sG sRGB sRGB g16 g16 . .
  974. * 16 RGBA gb16 sGp cb16 sCp g16 g16' A .
  975. *
  976. * 8-bit to 8-bit:
  977. * bckg: composite on gray background
  978. * bckc: composite on color background
  979. * g8: convert sRGB components to sRGB grayscale
  980. * g8b: convert sRGB components to grayscale and composite on gray background
  981. *
  982. * 8-bit to 16-bit:
  983. * lin: make sRGB components linear, alpha := 65535
  984. * pre: make sRGB components linear and premultiply by alpha (scale alpha)
  985. * pre': as 'pre' but alpha := 65535
  986. * glin: make sRGB components linear, convert to grayscale, alpha := 65535
  987. * gpre: make sRGB components grayscale and linear and premultiply by alpha
  988. * gpr': as 'gpre' but alpha := 65535
  989. *
  990. * 16-bit to 8-bit:
  991. * sRGB: convert linear components to sRGB, alpha := 255
  992. * unpg: unpremultiply gray component and convert to sRGB (scale alpha)
  993. * unpc: unpremultiply color components and convert to sRGB (scale alpha)
  994. * b16g: composite linear onto gray background and convert the result to sRGB
  995. * b16c: composite linear onto color background and convert the result to sRGB
  996. * sG: convert linear RGB to sRGB grayscale
  997. * sGp: unpremultiply RGB then convert to sRGB grayscale
  998. * sCp: unpremultiply RGB then convert to sRGB
  999. * gb16: composite linear onto background and convert to sRGB grayscale
  1000. * (order doesn't matter, the composite and grayscale operations permute)
  1001. * cb16: composite linear onto background and convert to sRGB
  1002. *
  1003. * 16-bit to 16-bit:
  1004. * A: set alpha to 65535
  1005. * g16: convert linear RGB to linear grayscale (alpha := 65535)
  1006. * g16': as 'g16' but alpha is unchanged
  1007. */
  1008. /* Simple copy: */
  1009. static void
  1010. gpc_noop(Pixel *out, const Pixel *in, const Background *back)
  1011. {
  1012. (void)back;
  1013. out->r = in->r;
  1014. out->g = in->g;
  1015. out->b = in->b;
  1016. out->a = in->a;
  1017. }
  1018. #if ALLOW_UNUSED_GPC
  1019. static void
  1020. gpc_nop8(Pixel *out, const Pixel *in, const Background *back)
  1021. {
  1022. (void)back;
  1023. if (in->a == 0)
  1024. out->r = out->g = out->b = 255;
  1025. else
  1026. {
  1027. out->r = in->r;
  1028. out->g = in->g;
  1029. out->b = in->b;
  1030. }
  1031. out->a = in->a;
  1032. }
  1033. #endif
  1034. #if ALLOW_UNUSED_GPC
  1035. static void
  1036. gpc_nop6(Pixel *out, const Pixel *in, const Background *back)
  1037. {
  1038. (void)back;
  1039. if (in->a == 0)
  1040. out->r = out->g = out->b = 65535;
  1041. else
  1042. {
  1043. out->r = in->r;
  1044. out->g = in->g;
  1045. out->b = in->b;
  1046. }
  1047. out->a = in->a;
  1048. }
  1049. #endif
  1050. /* 8-bit to 8-bit conversions */
  1051. /* bckg: composite on gray background */
  1052. static void
  1053. gpc_bckg(Pixel *out, const Pixel *in, const Background *back)
  1054. {
  1055. if (in->a <= 0)
  1056. out->r = out->g = out->b = back->ig;
  1057. else if (in->a >= 255)
  1058. out->r = out->g = out->b = in->g;
  1059. else
  1060. {
  1061. double a = in->a / 255.;
  1062. out->r = out->g = out->b = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a));
  1063. }
  1064. out->a = 255;
  1065. }
  1066. /* bckc: composite on color background */
  1067. static void
  1068. gpc_bckc(Pixel *out, const Pixel *in, const Background *back)
  1069. {
  1070. if (in->a <= 0)
  1071. {
  1072. out->r = back->ir;
  1073. out->g = back->ig;
  1074. out->b = back->ib;
  1075. }
  1076. else if (in->a >= 255)
  1077. {
  1078. out->r = in->r;
  1079. out->g = in->g;
  1080. out->b = in->b;
  1081. }
  1082. else
  1083. {
  1084. double a = in->a / 255.;
  1085. out->r = sRGB(sRGB_to_d[in->r] * a + back->dr * (1-a));
  1086. out->g = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a));
  1087. out->b = sRGB(sRGB_to_d[in->b] * a + back->db * (1-a));
  1088. }
  1089. out->a = 255;
  1090. }
  1091. /* g8: convert sRGB components to sRGB grayscale */
  1092. static void
  1093. gpc_g8(Pixel *out, const Pixel *in, const Background *back)
  1094. {
  1095. (void)back;
  1096. if (in->r == in->g && in->g == in->b)
  1097. out->r = out->g = out->b = in->g;
  1098. else
  1099. out->r = out->g = out->b =
  1100. sRGB(YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b]));
  1101. out->a = in->a;
  1102. }
  1103. /* g8b: convert sRGB components to grayscale and composite on gray background */
  1104. static void
  1105. gpc_g8b(Pixel *out, const Pixel *in, const Background *back)
  1106. {
  1107. if (in->a <= 0)
  1108. out->r = out->g = out->b = back->ig;
  1109. else if (in->a >= 255)
  1110. {
  1111. if (in->r == in->g && in->g == in->b)
  1112. out->r = out->g = out->b = in->g;
  1113. else
  1114. out->r = out->g = out->b = sRGB(YfromRGB(
  1115. sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b]));
  1116. }
  1117. else
  1118. {
  1119. double a = in->a/255.;
  1120. out->r = out->g = out->b = sRGB(a * YfromRGB(sRGB_to_d[in->r],
  1121. sRGB_to_d[in->g], sRGB_to_d[in->b]) + back->dg * (1-a));
  1122. }
  1123. out->a = 255;
  1124. }
  1125. /* 8-bit to 16-bit conversions */
  1126. /* lin: make sRGB components linear, alpha := 65535 */
  1127. static void
  1128. gpc_lin(Pixel *out, const Pixel *in, const Background *back)
  1129. {
  1130. (void)back;
  1131. out->r = ilinear(in->r);
  1132. if (in->g == in->r)
  1133. {
  1134. out->g = out->r;
  1135. if (in->b == in->r)
  1136. out->b = out->r;
  1137. else
  1138. out->b = ilinear(in->b);
  1139. }
  1140. else
  1141. {
  1142. out->g = ilinear(in->g);
  1143. if (in->b == in->r)
  1144. out->b = out->r;
  1145. else if (in->b == in->g)
  1146. out->b = out->g;
  1147. else
  1148. out->b = ilinear(in->b);
  1149. }
  1150. out->a = 65535;
  1151. }
  1152. /* pre: make sRGB components linear and premultiply by alpha (scale alpha) */
  1153. static void
  1154. gpc_pre(Pixel *out, const Pixel *in, const Background *back)
  1155. {
  1156. (void)back;
  1157. out->r = ilineara(in->r, in->a);
  1158. if (in->g == in->r)
  1159. {
  1160. out->g = out->r;
  1161. if (in->b == in->r)
  1162. out->b = out->r;
  1163. else
  1164. out->b = ilineara(in->b, in->a);
  1165. }
  1166. else
  1167. {
  1168. out->g = ilineara(in->g, in->a);
  1169. if (in->b == in->r)
  1170. out->b = out->r;
  1171. else if (in->b == in->g)
  1172. out->b = out->g;
  1173. else
  1174. out->b = ilineara(in->b, in->a);
  1175. }
  1176. out->a = in->a * 257;
  1177. }
  1178. /* pre': as 'pre' but alpha := 65535 */
  1179. static void
  1180. gpc_preq(Pixel *out, const Pixel *in, const Background *back)
  1181. {
  1182. (void)back;
  1183. out->r = ilineara(in->r, in->a);
  1184. if (in->g == in->r)
  1185. {
  1186. out->g = out->r;
  1187. if (in->b == in->r)
  1188. out->b = out->r;
  1189. else
  1190. out->b = ilineara(in->b, in->a);
  1191. }
  1192. else
  1193. {
  1194. out->g = ilineara(in->g, in->a);
  1195. if (in->b == in->r)
  1196. out->b = out->r;
  1197. else if (in->b == in->g)
  1198. out->b = out->g;
  1199. else
  1200. out->b = ilineara(in->b, in->a);
  1201. }
  1202. out->a = 65535;
  1203. }
  1204. /* glin: make sRGB components linear, convert to grayscale, alpha := 65535 */
  1205. static void
  1206. gpc_glin(Pixel *out, const Pixel *in, const Background *back)
  1207. {
  1208. (void)back;
  1209. if (in->r == in->g && in->g == in->b)
  1210. out->r = out->g = out->b = ilinear(in->g);
  1211. else
  1212. out->r = out->g = out->b = u16d(65535 *
  1213. YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b]));
  1214. out->a = 65535;
  1215. }
  1216. /* gpre: make sRGB components grayscale and linear and premultiply by alpha */
  1217. static void
  1218. gpc_gpre(Pixel *out, const Pixel *in, const Background *back)
  1219. {
  1220. (void)back;
  1221. if (in->r == in->g && in->g == in->b)
  1222. out->r = out->g = out->b = ilineara(in->g, in->a);
  1223. else
  1224. out->r = out->g = out->b = u16d(in->a * 257 *
  1225. YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b]));
  1226. out->a = 257 * in->a;
  1227. }
  1228. /* gpr': as 'gpre' but alpha := 65535 */
  1229. static void
  1230. gpc_gprq(Pixel *out, const Pixel *in, const Background *back)
  1231. {
  1232. (void)back;
  1233. if (in->r == in->g && in->g == in->b)
  1234. out->r = out->g = out->b = ilineara(in->g, in->a);
  1235. else
  1236. out->r = out->g = out->b = u16d(in->a * 257 *
  1237. YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b]));
  1238. out->a = 65535;
  1239. }
  1240. /* 8-bit to 16-bit conversions for gAMA 45455 encoded values */
  1241. /* Lin: make gAMA 45455 components linear, alpha := 65535 */
  1242. static void
  1243. gpc_Lin(Pixel *out, const Pixel *in, const Background *back)
  1244. {
  1245. (void)back;
  1246. out->r = ilinear_g22(in->r);
  1247. if (in->g == in->r)
  1248. {
  1249. out->g = out->r;
  1250. if (in->b == in->r)
  1251. out->b = out->r;
  1252. else
  1253. out->b = ilinear_g22(in->b);
  1254. }
  1255. else
  1256. {
  1257. out->g = ilinear_g22(in->g);
  1258. if (in->b == in->r)
  1259. out->b = out->r;
  1260. else if (in->b == in->g)
  1261. out->b = out->g;
  1262. else
  1263. out->b = ilinear_g22(in->b);
  1264. }
  1265. out->a = 65535;
  1266. }
  1267. #if ALLOW_UNUSED_GPC
  1268. /* Pre: make gAMA 45455 components linear and premultiply by alpha (scale alpha)
  1269. */
  1270. static void
  1271. gpc_Pre(Pixel *out, const Pixel *in, const Background *back)
  1272. {
  1273. (void)back;
  1274. out->r = ilineara_g22(in->r, in->a);
  1275. if (in->g == in->r)
  1276. {
  1277. out->g = out->r;
  1278. if (in->b == in->r)
  1279. out->b = out->r;
  1280. else
  1281. out->b = ilineara_g22(in->b, in->a);
  1282. }
  1283. else
  1284. {
  1285. out->g = ilineara_g22(in->g, in->a);
  1286. if (in->b == in->r)
  1287. out->b = out->r;
  1288. else if (in->b == in->g)
  1289. out->b = out->g;
  1290. else
  1291. out->b = ilineara_g22(in->b, in->a);
  1292. }
  1293. out->a = in->a * 257;
  1294. }
  1295. #endif
  1296. #if ALLOW_UNUSED_GPC
  1297. /* Pre': as 'Pre' but alpha := 65535 */
  1298. static void
  1299. gpc_Preq(Pixel *out, const Pixel *in, const Background *back)
  1300. {
  1301. (void)back;
  1302. out->r = ilineara_g22(in->r, in->a);
  1303. if (in->g == in->r)
  1304. {
  1305. out->g = out->r;
  1306. if (in->b == in->r)
  1307. out->b = out->r;
  1308. else
  1309. out->b = ilineara_g22(in->b, in->a);
  1310. }
  1311. else
  1312. {
  1313. out->g = ilineara_g22(in->g, in->a);
  1314. if (in->b == in->r)
  1315. out->b = out->r;
  1316. else if (in->b == in->g)
  1317. out->b = out->g;
  1318. else
  1319. out->b = ilineara_g22(in->b, in->a);
  1320. }
  1321. out->a = 65535;
  1322. }
  1323. #endif
  1324. #if ALLOW_UNUSED_GPC
  1325. /* Glin: make gAMA 45455 components linear, convert to grayscale, alpha := 65535
  1326. */
  1327. static void
  1328. gpc_Glin(Pixel *out, const Pixel *in, const Background *back)
  1329. {
  1330. (void)back;
  1331. if (in->r == in->g && in->g == in->b)
  1332. out->r = out->g = out->b = ilinear_g22(in->g);
  1333. else
  1334. out->r = out->g = out->b = u16d(65535 *
  1335. YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b]));
  1336. out->a = 65535;
  1337. }
  1338. #endif
  1339. #if ALLOW_UNUSED_GPC
  1340. /* Gpre: make gAMA 45455 components grayscale and linear and premultiply by
  1341. * alpha.
  1342. */
  1343. static void
  1344. gpc_Gpre(Pixel *out, const Pixel *in, const Background *back)
  1345. {
  1346. (void)back;
  1347. if (in->r == in->g && in->g == in->b)
  1348. out->r = out->g = out->b = ilineara_g22(in->g, in->a);
  1349. else
  1350. out->r = out->g = out->b = u16d(in->a * 257 *
  1351. YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b]));
  1352. out->a = 257 * in->a;
  1353. }
  1354. #endif
  1355. #if ALLOW_UNUSED_GPC
  1356. /* Gpr': as 'Gpre' but alpha := 65535 */
  1357. static void
  1358. gpc_Gprq(Pixel *out, const Pixel *in, const Background *back)
  1359. {
  1360. (void)back;
  1361. if (in->r == in->g && in->g == in->b)
  1362. out->r = out->g = out->b = ilineara_g22(in->g, in->a);
  1363. else
  1364. out->r = out->g = out->b = u16d(in->a * 257 *
  1365. YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b]));
  1366. out->a = 65535;
  1367. }
  1368. #endif
  1369. /* 16-bit to 8-bit conversions */
  1370. /* sRGB: convert linear components to sRGB, alpha := 255 */
  1371. static void
  1372. gpc_sRGB(Pixel *out, const Pixel *in, const Background *back)
  1373. {
  1374. (void)back;
  1375. out->r = isRGB(in->r);
  1376. if (in->g == in->r)
  1377. {
  1378. out->g = out->r;
  1379. if (in->b == in->r)
  1380. out->b = out->r;
  1381. else
  1382. out->b = isRGB(in->b);
  1383. }
  1384. else
  1385. {
  1386. out->g = isRGB(in->g);
  1387. if (in->b == in->r)
  1388. out->b = out->r;
  1389. else if (in->b == in->g)
  1390. out->b = out->g;
  1391. else
  1392. out->b = isRGB(in->b);
  1393. }
  1394. out->a = 255;
  1395. }
  1396. /* unpg: unpremultiply gray component and convert to sRGB (scale alpha) */
  1397. static void
  1398. gpc_unpg(Pixel *out, const Pixel *in, const Background *back)
  1399. {
  1400. (void)back;
  1401. if (in->a <= 128)
  1402. {
  1403. out->r = out->g = out->b = 255;
  1404. out->a = 0;
  1405. }
  1406. else
  1407. {
  1408. out->r = out->g = out->b = sRGB((double)in->g / in->a);
  1409. out->a = u8d(in->a / 257.);
  1410. }
  1411. }
  1412. /* unpc: unpremultiply color components and convert to sRGB (scale alpha) */
  1413. static void
  1414. gpc_unpc(Pixel *out, const Pixel *in, const Background *back)
  1415. {
  1416. (void)back;
  1417. if (in->a <= 128)
  1418. {
  1419. out->r = out->g = out->b = 255;
  1420. out->a = 0;
  1421. }
  1422. else
  1423. {
  1424. out->r = sRGB((double)in->r / in->a);
  1425. out->g = sRGB((double)in->g / in->a);
  1426. out->b = sRGB((double)in->b / in->a);
  1427. out->a = u8d(in->a / 257.);
  1428. }
  1429. }
  1430. /* b16g: composite linear onto gray background and convert the result to sRGB */
  1431. static void
  1432. gpc_b16g(Pixel *out, const Pixel *in, const Background *back)
  1433. {
  1434. if (in->a <= 0)
  1435. out->r = out->g = out->b = back->ig;
  1436. else
  1437. {
  1438. double a = in->a/65535.;
  1439. double a1 = 1-a;
  1440. a /= 65535;
  1441. out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1);
  1442. }
  1443. out->a = 255;
  1444. }
  1445. /* b16c: composite linear onto color background and convert the result to sRGB*/
  1446. static void
  1447. gpc_b16c(Pixel *out, const Pixel *in, const Background *back)
  1448. {
  1449. if (in->a <= 0)
  1450. {
  1451. out->r = back->ir;
  1452. out->g = back->ig;
  1453. out->b = back->ib;
  1454. }
  1455. else
  1456. {
  1457. double a = in->a/65535.;
  1458. double a1 = 1-a;
  1459. a /= 65535;
  1460. out->r = sRGB(in->r * a + back->dr * a1);
  1461. out->g = sRGB(in->g * a + back->dg * a1);
  1462. out->b = sRGB(in->b * a + back->db * a1);
  1463. }
  1464. out->a = 255;
  1465. }
  1466. /* sG: convert linear RGB to sRGB grayscale */
  1467. static void
  1468. gpc_sG(Pixel *out, const Pixel *in, const Background *back)
  1469. {
  1470. (void)back;
  1471. out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/65535);
  1472. out->a = 255;
  1473. }
  1474. /* sGp: unpremultiply RGB then convert to sRGB grayscale */
  1475. static void
  1476. gpc_sGp(Pixel *out, const Pixel *in, const Background *back)
  1477. {
  1478. (void)back;
  1479. if (in->a <= 128)
  1480. {
  1481. out->r = out->g = out->b = 255;
  1482. out->a = 0;
  1483. }
  1484. else
  1485. {
  1486. out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/in->a);
  1487. out->a = u8d(in->a / 257.);
  1488. }
  1489. }
  1490. /* sCp: unpremultiply RGB then convert to sRGB */
  1491. static void
  1492. gpc_sCp(Pixel *out, const Pixel *in, const Background *back)
  1493. {
  1494. (void)back;
  1495. if (in->a <= 128)
  1496. {
  1497. out->r = out->g = out->b = 255;
  1498. out->a = 0;
  1499. }
  1500. else
  1501. {
  1502. out->r = sRGB((double)in->r / in->a);
  1503. out->g = sRGB((double)in->g / in->a);
  1504. out->b = sRGB((double)in->b / in->a);
  1505. out->a = u8d(in->a / 257.);
  1506. }
  1507. }
  1508. /* gb16: composite linear onto background and convert to sRGB grayscale */
  1509. /* (order doesn't matter, the composite and grayscale operations permute) */
  1510. static void
  1511. gpc_gb16(Pixel *out, const Pixel *in, const Background *back)
  1512. {
  1513. if (in->a <= 0)
  1514. out->r = out->g = out->b = back->ig;
  1515. else if (in->a >= 65535)
  1516. out->r = out->g = out->b = isRGB(in->g);
  1517. else
  1518. {
  1519. double a = in->a / 65535.;
  1520. double a1 = 1-a;
  1521. a /= 65535;
  1522. out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1);
  1523. }
  1524. out->a = 255;
  1525. }
  1526. /* cb16: composite linear onto background and convert to sRGB */
  1527. static void
  1528. gpc_cb16(Pixel *out, const Pixel *in, const Background *back)
  1529. {
  1530. if (in->a <= 0)
  1531. {
  1532. out->r = back->ir;
  1533. out->g = back->ig;
  1534. out->b = back->ib;
  1535. }
  1536. else if (in->a >= 65535)
  1537. {
  1538. out->r = isRGB(in->r);
  1539. out->g = isRGB(in->g);
  1540. out->b = isRGB(in->b);
  1541. }
  1542. else
  1543. {
  1544. double a = in->a / 65535.;
  1545. double a1 = 1-a;
  1546. a /= 65535;
  1547. out->r = sRGB(in->r * a + back->dr * a1);
  1548. out->g = sRGB(in->g * a + back->dg * a1);
  1549. out->b = sRGB(in->b * a + back->db * a1);
  1550. }
  1551. out->a = 255;
  1552. }
  1553. /* 16-bit to 16-bit conversions */
  1554. /* A: set alpha to 65535 */
  1555. static void
  1556. gpc_A(Pixel *out, const Pixel *in, const Background *back)
  1557. {
  1558. (void)back;
  1559. out->r = in->r;
  1560. out->g = in->g;
  1561. out->b = in->b;
  1562. out->a = 65535;
  1563. }
  1564. /* g16: convert linear RGB to linear grayscale (alpha := 65535) */
  1565. static void
  1566. gpc_g16(Pixel *out, const Pixel *in, const Background *back)
  1567. {
  1568. (void)back;
  1569. out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b));
  1570. out->a = 65535;
  1571. }
  1572. /* g16': as 'g16' but alpha is unchanged */
  1573. static void
  1574. gpc_g16q(Pixel *out, const Pixel *in, const Background *back)
  1575. {
  1576. (void)back;
  1577. out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b));
  1578. out->a = in->a;
  1579. }
  1580. #if ALLOW_UNUSED_GPC
  1581. /* Unused functions (to hide them from GCC unused function warnings) */
  1582. void (* const gpc_unused[])
  1583. (Pixel *out, const Pixel *in, const Background *back) =
  1584. {
  1585. gpc_Pre, gpc_Preq, gpc_Glin, gpc_Gpre, gpc_Gprq, gpc_nop8, gpc_nop6
  1586. };
  1587. #endif
  1588. /* OUT: ----- 8-bit ----- ----- 16-bit -----
  1589. * IN G GA RGB RGBA G GA RGB RGBA
  1590. * 8 G . . . . lin lin lin lin
  1591. * 8 GA bckg . bckc . pre' pre pre' pre
  1592. * 8 RGB g8 g8 . . glin glin lin lin
  1593. * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre
  1594. * 16 G sRGB sRGB sRGB sRGB . . . .
  1595. * 16 GA b16g unpg b16c unpc A . A .
  1596. * 16 RGB sG sG sRGB sRGB g16 g16 . .
  1597. * 16 RGBA gb16 sGp cb16 sCp g16 g16' A .
  1598. *
  1599. * The matrix is held in an array indexed thus:
  1600. *
  1601. * gpc_fn[out_format & BASE_FORMATS][in_format & BASE_FORMATS];
  1602. */
  1603. /* This will produce a compile time error if the FORMAT_FLAG values don't
  1604. * match the above matrix!
  1605. */
  1606. #if PNG_FORMAT_FLAG_ALPHA == 1 && PNG_FORMAT_FLAG_COLOR == 2 &&\
  1607. PNG_FORMAT_FLAG_LINEAR == 4
  1608. static void (* const gpc_fn[8/*in*/][8/*out*/])
  1609. (Pixel *out, const Pixel *in, const Background *back) =
  1610. {
  1611. /*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */
  1612. {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_Lin, gpc_Lin, gpc_Lin, gpc_Lin },
  1613. {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre },
  1614. {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin },
  1615. {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre },
  1616. {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop},
  1617. {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop},
  1618. {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop},
  1619. {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop}
  1620. };
  1621. /* The array is repeated for the cases where both the input and output are color
  1622. * mapped because then different algorithms are used.
  1623. */
  1624. static void (* const gpc_fn_colormapped[8/*in*/][8/*out*/])
  1625. (Pixel *out, const Pixel *in, const Background *back) =
  1626. {
  1627. /*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */
  1628. {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_lin, gpc_lin, gpc_lin, gpc_lin },
  1629. {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre },
  1630. {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin },
  1631. {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre },
  1632. {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop},
  1633. {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop},
  1634. {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop},
  1635. {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop}
  1636. };
  1637. /* The error arrays record the error in the same matrix; 64 entries, however
  1638. * the different algorithms used in libpng for colormap and direct conversions
  1639. * mean that four separate matrices are used (for each combination of
  1640. * colormapped and direct.)
  1641. *
  1642. * In some cases the conversion between sRGB formats goes via a linear
  1643. * intermediate; an sRGB to linear conversion (as above) is followed by a simple
  1644. * linear to sRGB step with no other conversions. This is done by a separate
  1645. * error array from an arbitrary 'in' format to one of the four basic outputs
  1646. * (since final output is always sRGB not colormapped).
  1647. *
  1648. * These arrays may be modified if the --accumulate flag is set during the run;
  1649. * then instead of logging errors they are simply added in.
  1650. *
  1651. * The three entries are currently for transparent, partially transparent and
  1652. * opaque input pixel values. Notice that alpha should be exact in each case.
  1653. *
  1654. * Errors in alpha should only occur when converting from a direct format
  1655. * to a colormapped format, when alpha is effectively smashed (so large
  1656. * errors can occur.) There should be no error in the '0' and 'opaque'
  1657. * values. The fourth entry in the array is used for the alpha error (and it
  1658. * should always be zero for the 'via linear' case since this is never color
  1659. * mapped.)
  1660. *
  1661. * Mapping to a colormap smashes the colors, it is necessary to have separate
  1662. * values for these cases because they are much larger; it is very much
  1663. * impossible to obtain a reasonable result, these are held in
  1664. * gpc_error_to_colormap.
  1665. */
  1666. #if PNG_FORMAT_FLAG_COLORMAP == 8 /* extra check also required */
  1667. /* START MACHINE GENERATED */
  1668. static png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] =
  1669. {
  1670. { /* input: sRGB-gray */
  1671. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1672. { 0, 0, 372, 0 }, { 0, 0, 372, 0 }, { 0, 0, 372, 0 }, { 0, 0, 372, 0 },
  1673. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1674. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1675. }, { /* input: sRGB-gray+alpha */
  1676. { 0, 18, 0, 0 }, { 0, 0, 0, 0 }, { 0, 20, 0, 0 }, { 0, 0, 0, 0 },
  1677. { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 },
  1678. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1679. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1680. }, { /* input: sRGB-rgb */
  1681. { 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1682. { 0, 0, 893, 0 }, { 0, 0, 893, 0 }, { 0, 0, 811, 0 }, { 0, 0, 811, 0 },
  1683. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1684. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1685. }, { /* input: sRGB-rgb+alpha */
  1686. { 0, 4, 13, 0 }, { 0, 14, 13, 0 }, { 0, 19, 0, 0 }, { 0, 0, 0, 0 },
  1687. { 0, 832, 764, 0 }, { 0, 832, 764, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 },
  1688. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1689. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1690. }, { /* input: linear-gray */
  1691. { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
  1692. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1693. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1694. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1695. }, { /* input: linear-gray+alpha */
  1696. { 0, 74, 9, 0 }, { 0, 20, 9, 0 }, { 0, 74, 9, 0 }, { 0, 20, 9, 0 },
  1697. { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 1, 0, 0 },
  1698. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1699. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1700. }, { /* input: linear-rgb */
  1701. { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
  1702. { 0, 0, 4, 0 }, { 0, 0, 4, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1703. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1704. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1705. }, { /* input: linear-rgb+alpha */
  1706. { 0, 126, 143, 0 }, { 0, 9, 7, 0 }, { 0, 74, 9, 0 }, { 0, 16, 9, 0 },
  1707. { 0, 4, 4, 0 }, { 0, 5, 4, 0 }, { 0, 0, 0, 0 }, { 0, 1, 0, 0 },
  1708. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1709. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1710. }, { /* input: color-mapped-sRGB-gray */
  1711. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1712. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1713. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1714. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1715. }, { /* input: color-mapped-sRGB-gray+alpha */
  1716. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1717. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1718. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1719. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1720. }, { /* input: color-mapped-sRGB-rgb */
  1721. { 0, 0, 13, 0 }, { 0, 0, 13, 0 }, { 0, 0, 8, 0 }, { 0, 0, 8, 0 },
  1722. { 0, 0, 673, 0 }, { 0, 0, 673, 0 }, { 0, 0, 674, 0 }, { 0, 0, 674, 0 },
  1723. { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1724. { 0, 0, 460, 0 }, { 0, 0, 460, 0 }, { 0, 0, 263, 0 }, { 0, 0, 263, 0 }
  1725. }, { /* input: color-mapped-sRGB-rgb+alpha */
  1726. { 0, 6, 8, 0 }, { 0, 7, 8, 0 }, { 0, 75, 8, 0 }, { 0, 9, 8, 0 },
  1727. { 0, 585, 427, 0 }, { 0, 585, 427, 0 }, { 0, 717, 409, 0 }, { 0, 717, 409, 0 },
  1728. { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 },
  1729. { 0, 13323, 460, 0 }, { 0, 334, 460, 0 }, { 0, 16480, 263, 0 }, { 0, 243, 263, 0 }
  1730. }, { /* input: color-mapped-linear-gray */
  1731. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1732. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1733. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1734. { 0, 0, 282, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1735. }, { /* input: color-mapped-linear-gray+alpha */
  1736. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1737. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1738. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1739. { 0, 0, 0, 0 }, { 0, 253, 282, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1740. }, { /* input: color-mapped-linear-rgb */
  1741. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1742. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1743. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1744. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 265, 0 }, { 0, 0, 0, 0 }
  1745. }, { /* input: color-mapped-linear-rgb+alpha */
  1746. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1747. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1748. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
  1749. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 243, 265, 0 }
  1750. }
  1751. };
  1752. static png_uint_16 gpc_error_via_linear[16][4/*out*/][4] =
  1753. {
  1754. { /* input: sRGB-gray */
  1755. { 0, 0, 7, 0 }, { 0, 0, 7, 0 }, { 0, 0, 7, 0 }, { 0, 0, 7, 0 }
  1756. }, { /* input: sRGB-gray+alpha */
  1757. { 0, 15, 15, 0 }, { 0, 186, 15, 0 }, { 0, 15, 15, 0 }, { 0, 186, 15, 0 }
  1758. }, { /* input: sRGB-rgb */
  1759. { 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 15, 0 }, { 0, 0, 15, 0 }
  1760. }, { /* input: sRGB-rgb+alpha */
  1761. { 0, 12, 14, 0 }, { 0, 180, 14, 0 }, { 0, 14, 15, 0 }, { 0, 186, 15, 0 }
  1762. }, { /* input: linear-gray */
  1763. { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }
  1764. }, { /* input: linear-gray+alpha */
  1765. { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
  1766. }, { /* input: linear-rgb */
  1767. { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }
  1768. }, { /* input: linear-rgb+alpha */
  1769. { 0, 1, 1, 0 }, { 0, 8, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
  1770. }, { /* input: color-mapped-sRGB-gray */
  1771. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1772. }, { /* input: color-mapped-sRGB-gray+alpha */
  1773. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1774. }, { /* input: color-mapped-sRGB-rgb */
  1775. { 0, 0, 13, 0 }, { 0, 0, 13, 0 }, { 0, 0, 14, 0 }, { 0, 0, 14, 0 }
  1776. }, { /* input: color-mapped-sRGB-rgb+alpha */
  1777. { 0, 4, 8, 0 }, { 0, 9, 8, 0 }, { 0, 8, 3, 0 }, { 0, 32, 3, 0 }
  1778. }, { /* input: color-mapped-linear-gray */
  1779. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1780. }, { /* input: color-mapped-linear-gray+alpha */
  1781. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1782. }, { /* input: color-mapped-linear-rgb */
  1783. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1784. }, { /* input: color-mapped-linear-rgb+alpha */
  1785. { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
  1786. }
  1787. };
  1788. static png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] =
  1789. {
  1790. { /* input: sRGB-gray */
  1791. { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
  1792. { 0, 0, 560, 0 }, { 0, 0, 560, 0 }, { 0, 0, 560, 0 }, { 0, 0, 560, 0 }
  1793. }, { /* input: sRGB-gray+alpha */
  1794. { 0, 19, 2, 0 }, { 0, 255, 2, 25 }, { 0, 88, 2, 0 }, { 0, 255, 2, 25 },
  1795. { 0, 1012, 745, 0 }, { 0, 16026, 745, 6425 }, { 0, 1012, 745, 0 }, { 0, 16026, 745, 6425 }
  1796. }, { /* input: sRGB-rgb */
  1797. { 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 25, 0 }, { 0, 0, 25, 0 },
  1798. { 0, 0, 937, 0 }, { 0, 0, 937, 0 }, { 0, 0, 13677, 0 }, { 0, 0, 13677, 0 }
  1799. }, { /* input: sRGB-rgb+alpha */
  1800. { 0, 63, 77, 0 }, { 0, 255, 19, 25 }, { 0, 220, 25, 0 }, { 0, 255, 25, 67 },
  1801. { 0, 17534, 18491, 0 }, { 0, 15614, 2824, 6425 }, { 0, 14019, 13677, 0 }, { 0, 48573, 13677, 17219 }
  1802. }, { /* input: linear-gray */
  1803. { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 73, 0 },
  1804. { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }
  1805. }, { /* input: linear-gray+alpha */
  1806. { 0, 74, 74, 0 }, { 0, 255, 74, 25 }, { 0, 97, 74, 0 }, { 0, 255, 74, 25 },
  1807. { 0, 18919, 18907, 0 }, { 0, 24549, 18907, 6552 }, { 0, 18919, 18907, 0 }, { 0, 24549, 18907, 6552 }
  1808. }, { /* input: linear-rgb */
  1809. { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 98, 0 }, { 0, 0, 98, 0 },
  1810. { 0, 0, 18664, 0 }, { 0, 0, 18664, 0 }, { 0, 0, 24998, 0 }, { 0, 0, 24998, 0 }
  1811. }, { /* input: linear-rgb+alpha */
  1812. { 0, 181, 196, 0 }, { 0, 255, 61, 25 }, { 206, 187, 98, 0 }, { 0, 255, 98, 67 },
  1813. { 0, 18141, 18137, 0 }, { 0, 17494, 17504, 6553 }, { 0, 24979, 24992, 0 }, { 0, 46509, 24992, 17347 }
  1814. }
  1815. };
  1816. /* END MACHINE GENERATED */
  1817. #endif /* COLORMAP flag check */
  1818. #endif /* flag checks */
  1819. typedef struct
  1820. {
  1821. /* Basic pixel information: */
  1822. Image* in_image; /* Input image */
  1823. const Image* out_image; /* Output image */
  1824. /* 'background' is the value passed to the gpc_ routines, it may be NULL if
  1825. * it should not be used (*this* program has an error if it crashes as a
  1826. * result!)
  1827. */
  1828. Background background_color;
  1829. const Background* background;
  1830. /* Precalculated values: */
  1831. int in_opaque; /* Value of input alpha that is opaque */
  1832. int is_palette; /* Sample values come from the palette */
  1833. int accumulate; /* Accumlate component errors (don't log) */
  1834. int output_8bit; /* Output is 8 bit (else 16 bit) */
  1835. void (*in_gp)(Pixel*, png_const_voidp);
  1836. void (*out_gp)(Pixel*, png_const_voidp);
  1837. void (*transform)(Pixel *out, const Pixel *in, const Background *back);
  1838. /* A function to perform the required transform */
  1839. void (*from_linear)(Pixel *out, const Pixel *in, const Background *back);
  1840. /* For 'via_linear' transforms the final, from linear, step, else NULL */
  1841. png_uint_16 error[4];
  1842. /* Three error values for transparent, partially transparent and opaque
  1843. * input pixels (in turn).
  1844. */
  1845. png_uint_16 *error_ptr;
  1846. /* Where these are stored in the static array (for 'accumulate') */
  1847. }
  1848. Transform;
  1849. /* Return a 'transform' as above for the given format conversion. */
  1850. static void
  1851. transform_from_formats(Transform *result, Image *in_image,
  1852. const Image *out_image, png_const_colorp background, int via_linear)
  1853. {
  1854. png_uint_32 in_format, out_format;
  1855. png_uint_32 in_base, out_base;
  1856. memset(result, 0, sizeof *result);
  1857. /* Store the original images for error messages */
  1858. result->in_image = in_image;
  1859. result->out_image = out_image;
  1860. in_format = in_image->image.format;
  1861. out_format = out_image->image.format;
  1862. if (in_format & PNG_FORMAT_FLAG_LINEAR)
  1863. result->in_opaque = 65535;
  1864. else
  1865. result->in_opaque = 255;
  1866. result->output_8bit = (out_format & PNG_FORMAT_FLAG_LINEAR) == 0;
  1867. result->is_palette = 0; /* set by caller if required */
  1868. result->accumulate = (in_image->opts & ACCUMULATE) != 0;
  1869. /* The loaders (which need the ordering information) */
  1870. result->in_gp = get_pixel(in_format);
  1871. result->out_gp = get_pixel(out_format);
  1872. /* Remove the ordering information: */
  1873. in_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP;
  1874. in_base = in_format & BASE_FORMATS;
  1875. out_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP;
  1876. out_base = out_format & BASE_FORMATS;
  1877. if (via_linear)
  1878. {
  1879. /* Check for an error in this program: */
  1880. if (out_format & (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLORMAP))
  1881. {
  1882. fprintf(stderr, "internal transform via linear error 0x%x->0x%x\n",
  1883. in_format, out_format);
  1884. exit(1);
  1885. }
  1886. result->transform = gpc_fn[in_base][out_base | PNG_FORMAT_FLAG_LINEAR];
  1887. result->from_linear = gpc_fn[out_base | PNG_FORMAT_FLAG_LINEAR][out_base];
  1888. result->error_ptr = gpc_error_via_linear[in_format][out_format];
  1889. }
  1890. else if (~in_format & out_format & PNG_FORMAT_FLAG_COLORMAP)
  1891. {
  1892. /* The input is not colormapped but the output is, the errors will
  1893. * typically be large (only the grayscale-no-alpha case permits preserving
  1894. * even 8-bit values.)
  1895. */
  1896. result->transform = gpc_fn[in_base][out_base];
  1897. result->from_linear = NULL;
  1898. result->error_ptr = gpc_error_to_colormap[in_base][out_base];
  1899. }
  1900. else
  1901. {
  1902. /* The caller handles the colormap->pixel value conversion, so the
  1903. * transform function just gets a pixel value, however because libpng
  1904. * currently contains a different implementation for mapping a colormap if
  1905. * both input and output are colormapped we need different conversion
  1906. * functions to deal with errors in the libpng implementation.
  1907. */
  1908. if (in_format & out_format & PNG_FORMAT_FLAG_COLORMAP)
  1909. result->transform = gpc_fn_colormapped[in_base][out_base];
  1910. else
  1911. result->transform = gpc_fn[in_base][out_base];
  1912. result->from_linear = NULL;
  1913. result->error_ptr = gpc_error[in_format][out_format];
  1914. }
  1915. /* Follow the libpng simplified API rules to work out what to pass to the gpc
  1916. * routines as a background value, if one is not required pass NULL so that
  1917. * this program crashes in the even of a programming error.
  1918. */
  1919. result->background = NULL; /* default: not required */
  1920. /* Rule 1: background only need be supplied if alpha is to be removed */
  1921. if (in_format & ~out_format & PNG_FORMAT_FLAG_ALPHA)
  1922. {
  1923. /* The input value is 'NULL' to use the background and (otherwise) an sRGB
  1924. * background color (to use a solid color). The code above uses a fixed
  1925. * byte value, BUFFER_INIT8, for buffer even for 16-bit output. For
  1926. * linear (16-bit) output the sRGB background color is ignored; the
  1927. * composition is always on the background (so BUFFER_INIT8 * 257), except
  1928. * that for the colormap (i.e. linear colormapped output) black is used.
  1929. */
  1930. result->background = &result->background_color;
  1931. if (out_format & PNG_FORMAT_FLAG_LINEAR || via_linear)
  1932. {
  1933. if (out_format & PNG_FORMAT_FLAG_COLORMAP)
  1934. {
  1935. result->background_color.ir =
  1936. result->background_color.ig =
  1937. result->background_color.ib = 0;
  1938. result->background_color.dr =
  1939. result->background_color.dg =
  1940. result->background_color.db = 0;
  1941. }
  1942. else
  1943. {
  1944. result->background_color.ir =
  1945. result->background_color.ig =
  1946. result->background_color.ib = BUFFER_INIT8 * 257;
  1947. result->background_color.dr =
  1948. result->background_color.dg =
  1949. result->background_color.db = 0;
  1950. }
  1951. }
  1952. else /* sRGB output */
  1953. {
  1954. if (background != NULL)
  1955. {
  1956. if (out_format & PNG_FORMAT_FLAG_COLOR)
  1957. {
  1958. result->background_color.ir = background->red;
  1959. result->background_color.ig = background->green;
  1960. result->background_color.ib = background->blue;
  1961. /* TODO: sometimes libpng uses the power law conversion here, how
  1962. * to handle this?
  1963. */
  1964. result->background_color.dr = sRGB_to_d[background->red];
  1965. result->background_color.dg = sRGB_to_d[background->green];
  1966. result->background_color.db = sRGB_to_d[background->blue];
  1967. }
  1968. else /* grayscale: libpng only looks at 'g' */
  1969. {
  1970. result->background_color.ir =
  1971. result->background_color.ig =
  1972. result->background_color.ib = background->green;
  1973. /* TODO: sometimes libpng uses the power law conversion here, how
  1974. * to handle this?
  1975. */
  1976. result->background_color.dr =
  1977. result->background_color.dg =
  1978. result->background_color.db = sRGB_to_d[background->green];
  1979. }
  1980. }
  1981. else if ((out_format & PNG_FORMAT_FLAG_COLORMAP) == 0)
  1982. {
  1983. result->background_color.ir =
  1984. result->background_color.ig =
  1985. result->background_color.ib = BUFFER_INIT8;
  1986. /* TODO: sometimes libpng uses the power law conversion here, how
  1987. * to handle this?
  1988. */
  1989. result->background_color.dr =
  1990. result->background_color.dg =
  1991. result->background_color.db = sRGB_to_d[BUFFER_INIT8];
  1992. }
  1993. /* Else the output is colormapped and a background color must be
  1994. * provided; if pngstest crashes then that is a bug in this program
  1995. * (though libpng should png_error as well.)
  1996. */
  1997. else
  1998. result->background = NULL;
  1999. }
  2000. }
  2001. if (result->background == NULL)
  2002. {
  2003. result->background_color.ir =
  2004. result->background_color.ig =
  2005. result->background_color.ib = -1; /* not used */
  2006. result->background_color.dr =
  2007. result->background_color.dg =
  2008. result->background_color.db = 1E30; /* not used */
  2009. }
  2010. /* Copy the error values into the Transform: */
  2011. result->error[0] = result->error_ptr[0];
  2012. result->error[1] = result->error_ptr[1];
  2013. result->error[2] = result->error_ptr[2];
  2014. result->error[3] = result->error_ptr[3];
  2015. }
  2016. /* Compare two pixels.
  2017. *
  2018. * OLD error values:
  2019. static int error_to_linear = 811; * by experiment *
  2020. static int error_to_linear_grayscale = 424; * by experiment *
  2021. static int error_to_sRGB = 6; * by experiment *
  2022. static int error_to_sRGB_grayscale = 17; * libpng error by calculation +
  2023. 2 by experiment *
  2024. static int error_in_compose = 2; * by experiment *
  2025. static int error_in_premultiply = 1;
  2026. *
  2027. * The following is *just* the result of a round trip from 8-bit sRGB to linear
  2028. * then back to 8-bit sRGB when it is done by libpng. There are two problems:
  2029. *
  2030. * 1) libpng currently uses a 2.2 power law with no linear segment, this results
  2031. * in instability in the low values and even with 16-bit precision sRGB(1) ends
  2032. * up mapping to sRGB(0) as a result of rounding in the 16-bit representation.
  2033. * This gives an error of 1 in the handling of value 1 only.
  2034. *
  2035. * 2) libpng currently uses an intermediate 8-bit linear value in gamma
  2036. * correction of 8-bit values. This results in many more errors, the worse of
  2037. * which is mapping sRGB(14) to sRGB(0).
  2038. *
  2039. * The general 'error_via_linear' is more complex because of pre-multiplication,
  2040. * this compounds the 8-bit errors according to the alpha value of the pixel.
  2041. * As a result 256 values are pre-calculated for error_via_linear.
  2042. */
  2043. #if 0
  2044. static int error_in_libpng_gamma;
  2045. static int error_via_linear[256]; /* Indexed by 8-bit alpha */
  2046. static void
  2047. init_error_via_linear(void)
  2048. {
  2049. int alpha;
  2050. error_via_linear[0] = 255; /* transparent pixel */
  2051. for (alpha=1; alpha<=255; ++alpha)
  2052. {
  2053. /* 16-bit values less than 128.5 get rounded to 8-bit 0 and so the worst
  2054. * case error arises with 16-bit 128.5, work out what sRGB
  2055. * (non-associated) value generates 128.5; any value less than this is
  2056. * going to map to 0, so the worst error is floor(value).
  2057. *
  2058. * Note that errors are considerably higher (more than a factor of 2)
  2059. * because libpng uses a simple power law for sRGB data at present.
  2060. *
  2061. * Add .1 for arithmetic errors inside libpng.
  2062. */
  2063. double v = floor(255*pow(.5/*(128.5 * 255 / 65535)*/ / alpha, 1/2.2)+.1);
  2064. error_via_linear[alpha] = (int)v;
  2065. }
  2066. /* This is actually 14.99, but, despite the closeness to 15, 14 seems to work
  2067. * ok in this case.
  2068. */
  2069. error_in_libpng_gamma = 14;
  2070. }
  2071. #endif
  2072. static void
  2073. print_pixel(char string[64], const Pixel *pixel, png_uint_32 format)
  2074. {
  2075. switch (format & (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR))
  2076. {
  2077. case 0:
  2078. sprintf(string, "%s(%d)", format_names[format], pixel->g);
  2079. break;
  2080. case PNG_FORMAT_FLAG_ALPHA:
  2081. sprintf(string, "%s(%d,%d)", format_names[format], pixel->g,
  2082. pixel->a);
  2083. break;
  2084. case PNG_FORMAT_FLAG_COLOR:
  2085. sprintf(string, "%s(%d,%d,%d)", format_names[format],
  2086. pixel->r, pixel->g, pixel->b);
  2087. break;
  2088. case PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA:
  2089. sprintf(string, "%s(%d,%d,%d,%d)", format_names[format],
  2090. pixel->r, pixel->g, pixel->b, pixel->a);
  2091. break;
  2092. default:
  2093. sprintf(string, "invalid-format");
  2094. break;
  2095. }
  2096. }
  2097. static int
  2098. logpixel(const Transform *transform, png_uint_32 x, png_uint_32 y,
  2099. const Pixel *in, const Pixel *calc, const Pixel *out, const char *reason)
  2100. {
  2101. const png_uint_32 in_format = transform->in_image->image.format;
  2102. const png_uint_32 out_format = transform->out_image->image.format;
  2103. png_uint_32 back_format = out_format & ~PNG_FORMAT_FLAG_ALPHA;
  2104. const char *via_linear = "";
  2105. char pixel_in[64], pixel_calc[64], pixel_out[64], pixel_loc[64];
  2106. char background_info[100];
  2107. print_pixel(pixel_in, in, in_format);
  2108. print_pixel(pixel_calc, calc, out_format);
  2109. print_pixel(pixel_out, out, out_format);
  2110. if (transform->is_palette)
  2111. sprintf(pixel_loc, "palette: %lu", (unsigned long)y);
  2112. else
  2113. sprintf(pixel_loc, "%lu,%lu", (unsigned long)x, (unsigned long)y);
  2114. if (transform->from_linear != NULL)
  2115. {
  2116. via_linear = " (via linear)";
  2117. /* And as a result the *read* format which did any background processing
  2118. * was itself linear, so the background color information is also
  2119. * linear.
  2120. */
  2121. back_format |= PNG_FORMAT_FLAG_LINEAR;
  2122. }
  2123. if (transform->background != NULL)
  2124. {
  2125. Pixel back;
  2126. char pixel_back[64];
  2127. back.r = transform->background->ir;
  2128. back.g = transform->background->ig;
  2129. back.b = transform->background->ib;
  2130. back.a = -1; /* not used */
  2131. print_pixel(pixel_back, &back, back_format);
  2132. sprintf(background_info, " on background %s", pixel_back);
  2133. }
  2134. else
  2135. background_info[0] = 0;
  2136. if (transform->in_image->file_name != transform->out_image->file_name)
  2137. {
  2138. char error_buffer[512];
  2139. sprintf(error_buffer,
  2140. "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n"
  2141. "Use --preserve and examine: ", pixel_loc, reason, via_linear,
  2142. pixel_in, background_info, pixel_out, pixel_calc);
  2143. return logerror(transform->in_image, transform->in_image->file_name,
  2144. error_buffer, transform->out_image->file_name);
  2145. }
  2146. else
  2147. {
  2148. char error_buffer[512];
  2149. sprintf(error_buffer,
  2150. "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n"
  2151. " The error happened when reading the original file with this format.",
  2152. pixel_loc, reason, via_linear, pixel_in, background_info, pixel_out,
  2153. pixel_calc);
  2154. return logerror(transform->in_image, transform->in_image->file_name,
  2155. error_buffer, "");
  2156. }
  2157. }
  2158. static int
  2159. cmppixel(Transform *transform, png_const_voidp in, png_const_voidp out,
  2160. png_uint_32 x, png_uint_32 y/*or palette index*/)
  2161. {
  2162. int maxerr;
  2163. png_const_charp errmsg;
  2164. Pixel pixel_in, pixel_calc, pixel_out;
  2165. transform->in_gp(&pixel_in, in);
  2166. if (transform->from_linear == NULL)
  2167. transform->transform(&pixel_calc, &pixel_in, transform->background);
  2168. else
  2169. {
  2170. transform->transform(&pixel_out, &pixel_in, transform->background);
  2171. transform->from_linear(&pixel_calc, &pixel_out, NULL);
  2172. }
  2173. transform->out_gp(&pixel_out, out);
  2174. /* Eliminate the case where the input and output values match exactly. */
  2175. if (pixel_calc.a == pixel_out.a && pixel_calc.r == pixel_out.r &&
  2176. pixel_calc.g == pixel_out.g && pixel_calc.b == pixel_out.b)
  2177. return 1;
  2178. /* Eliminate the case where the output pixel is transparent and the output
  2179. * is 8-bit - any component values are valid. Don't check the input alpha
  2180. * here to also skip the 16-bit small alpha cases.
  2181. */
  2182. if (transform->output_8bit && pixel_calc.a == 0 && pixel_out.a == 0)
  2183. return 1;
  2184. /* Check for alpha errors first; an alpha error can damage the components too
  2185. * so avoid spurious checks on components if one is found.
  2186. */
  2187. errmsg = NULL;
  2188. {
  2189. int err_a = abs(pixel_calc.a-pixel_out.a);
  2190. if (err_a > transform->error[3])
  2191. {
  2192. /* If accumulating check the components too */
  2193. if (transform->accumulate)
  2194. transform->error[3] = (png_uint_16)err_a;
  2195. else
  2196. errmsg = "alpha";
  2197. }
  2198. }
  2199. /* Now if *either* of the output alphas are 0 but alpha is within tolerance
  2200. * eliminate the 8-bit component comparison.
  2201. */
  2202. if (errmsg == NULL && transform->output_8bit &&
  2203. (pixel_calc.a == 0 || pixel_out.a == 0))
  2204. return 1;
  2205. if (errmsg == NULL) /* else just signal an alpha error */
  2206. {
  2207. int err_r = abs(pixel_calc.r - pixel_out.r);
  2208. int err_g = abs(pixel_calc.g - pixel_out.g);
  2209. int err_b = abs(pixel_calc.b - pixel_out.b);
  2210. int limit;
  2211. if ((err_r | err_g | err_b) == 0)
  2212. return 1; /* exact match */
  2213. /* Mismatch on a component, check the input alpha */
  2214. if (pixel_in.a >= transform->in_opaque)
  2215. {
  2216. errmsg = "opaque component";
  2217. limit = 2; /* opaque */
  2218. }
  2219. else if (pixel_in.a > 0)
  2220. {
  2221. errmsg = "alpha component";
  2222. limit = 1; /* partially transparent */
  2223. }
  2224. else
  2225. {
  2226. errmsg = "transparent component (background)";
  2227. limit = 0; /* transparent */
  2228. }
  2229. maxerr = err_r;
  2230. if (maxerr < err_g) maxerr = err_g;
  2231. if (maxerr < err_b) maxerr = err_b;
  2232. if (maxerr <= transform->error[limit])
  2233. return 1; /* within the error limits */
  2234. /* Handle a component mis-match; log it, just return an error code, or
  2235. * accumulate it.
  2236. */
  2237. if (transform->accumulate)
  2238. {
  2239. transform->error[limit] = (png_uint_16)maxerr;
  2240. return 1; /* to cause the caller to keep going */
  2241. }
  2242. }
  2243. /* Failure to match and not accumulating, so the error must be logged. */
  2244. return logpixel(transform, x, y, &pixel_in, &pixel_calc, &pixel_out, errmsg);
  2245. }
  2246. static png_byte
  2247. component_loc(png_byte loc[4], png_uint_32 format)
  2248. {
  2249. /* Given a format return the number of channels and the location of
  2250. * each channel.
  2251. *
  2252. * The mask 'loc' contains the component offset of the channels in the
  2253. * following order. Note that if 'format' is grayscale the entries 1-3 must
  2254. * all contain the location of the gray channel.
  2255. *
  2256. * 0: alpha
  2257. * 1: red or gray
  2258. * 2: green or gray
  2259. * 3: blue or gray
  2260. */
  2261. png_byte channels;
  2262. if (format & PNG_FORMAT_FLAG_COLOR)
  2263. {
  2264. channels = 3;
  2265. loc[2] = 1;
  2266. # ifdef PNG_FORMAT_BGR_SUPPORTED
  2267. if (format & PNG_FORMAT_FLAG_BGR)
  2268. {
  2269. loc[1] = 2;
  2270. loc[3] = 0;
  2271. }
  2272. else
  2273. # endif
  2274. {
  2275. loc[1] = 0;
  2276. loc[3] = 2;
  2277. }
  2278. }
  2279. else
  2280. {
  2281. channels = 1;
  2282. loc[1] = loc[2] = loc[3] = 0;
  2283. }
  2284. if (format & PNG_FORMAT_FLAG_ALPHA)
  2285. {
  2286. # ifdef PNG_FORMAT_AFIRST_SUPPORTED
  2287. if (format & PNG_FORMAT_FLAG_AFIRST)
  2288. {
  2289. loc[0] = 0;
  2290. ++loc[1];
  2291. ++loc[2];
  2292. ++loc[3];
  2293. }
  2294. else
  2295. # endif
  2296. loc[0] = channels;
  2297. ++channels;
  2298. }
  2299. else
  2300. loc[0] = 4; /* not present */
  2301. return channels;
  2302. }
  2303. /* Compare two images, the original 'a', which was written out then read back in
  2304. * to * give image 'b'. The formats may have been changed.
  2305. */
  2306. static int
  2307. compare_two_images(Image *a, Image *b, int via_linear,
  2308. png_const_colorp background)
  2309. {
  2310. ptrdiff_t stridea = a->stride;
  2311. ptrdiff_t strideb = b->stride;
  2312. png_const_bytep rowa = a->buffer+16;
  2313. png_const_bytep rowb = b->buffer+16;
  2314. const png_uint_32 width = a->image.width;
  2315. const png_uint_32 height = a->image.height;
  2316. const png_uint_32 formata = a->image.format;
  2317. const png_uint_32 formatb = b->image.format;
  2318. const unsigned int a_sample = PNG_IMAGE_SAMPLE_SIZE(formata);
  2319. const unsigned int b_sample = PNG_IMAGE_SAMPLE_SIZE(formatb);
  2320. int alpha_added, alpha_removed;
  2321. int bchannels;
  2322. int btoa[4];
  2323. png_uint_32 y;
  2324. Transform tr;
  2325. /* This should never happen: */
  2326. if (width != b->image.width || height != b->image.height)
  2327. return logerror(a, a->file_name, ": width x height changed: ",
  2328. b->file_name);
  2329. /* Set up the background and the transform */
  2330. transform_from_formats(&tr, a, b, background, via_linear);
  2331. /* Find the first row and inter-row space. */
  2332. if (!(formata & PNG_FORMAT_FLAG_COLORMAP) &&
  2333. (formata & PNG_FORMAT_FLAG_LINEAR))
  2334. stridea *= 2;
  2335. if (!(formatb & PNG_FORMAT_FLAG_COLORMAP) &&
  2336. (formatb & PNG_FORMAT_FLAG_LINEAR))
  2337. strideb *= 2;
  2338. if (stridea < 0) rowa += (height-1) * (-stridea);
  2339. if (strideb < 0) rowb += (height-1) * (-strideb);
  2340. /* First shortcut the two colormap case by comparing the image data; if it
  2341. * matches then we expect the colormaps to match, although this is not
  2342. * absolutely necessary for an image match. If the colormaps fail to match
  2343. * then there is a problem in libpng.
  2344. */
  2345. if (formata & formatb & PNG_FORMAT_FLAG_COLORMAP)
  2346. {
  2347. /* Only check colormap entries that actually exist; */
  2348. png_const_bytep ppa, ppb;
  2349. int match;
  2350. png_byte in_use[256], amax = 0, bmax = 0;
  2351. memset(in_use, 0, sizeof in_use);
  2352. ppa = rowa;
  2353. ppb = rowb;
  2354. /* Do this the slow way to accumulate the 'in_use' flags, don't break out
  2355. * of the loop until the end; this validates the color-mapped data to
  2356. * ensure all pixels are valid color-map indexes.
  2357. */
  2358. for (y=0, match=1; y<height && match; ++y, ppa += stridea, ppb += strideb)
  2359. {
  2360. png_uint_32 x;
  2361. for (x=0; x<width; ++x)
  2362. {
  2363. png_byte bval = ppb[x];
  2364. png_byte aval = ppa[x];
  2365. if (bval > bmax)
  2366. bmax = bval;
  2367. if (bval != aval)
  2368. match = 0;
  2369. in_use[aval] = 1;
  2370. if (aval > amax)
  2371. amax = aval;
  2372. }
  2373. }
  2374. /* If the buffers match then the colormaps must too. */
  2375. if (match)
  2376. {
  2377. /* Do the color-maps match, entry by entry? Only check the 'in_use'
  2378. * entries. An error here should be logged as a color-map error.
  2379. */
  2380. png_const_bytep a_cmap = (png_const_bytep)a->colormap;
  2381. png_const_bytep b_cmap = (png_const_bytep)b->colormap;
  2382. int result = 1; /* match by default */
  2383. /* This is used in logpixel to get the error message correct. */
  2384. tr.is_palette = 1;
  2385. for (y=0; y<256; ++y, a_cmap += a_sample, b_cmap += b_sample)
  2386. if (in_use[y])
  2387. {
  2388. /* The colormap entries should be valid, but because libpng doesn't
  2389. * do any checking at present the original image may contain invalid
  2390. * pixel values. These cause an error here (at present) unless
  2391. * accumulating errors in which case the program just ignores them.
  2392. */
  2393. if (y >= a->image.colormap_entries)
  2394. {
  2395. if ((a->opts & ACCUMULATE) == 0)
  2396. {
  2397. char pindex[9];
  2398. sprintf(pindex, "%lu[%lu]", (unsigned long)y,
  2399. (unsigned long)a->image.colormap_entries);
  2400. logerror(a, a->file_name, ": bad pixel index: ", pindex);
  2401. }
  2402. result = 0;
  2403. }
  2404. else if (y >= b->image.colormap_entries)
  2405. {
  2406. if ((a->opts & ACCUMULATE) == 0)
  2407. {
  2408. char pindex[9];
  2409. sprintf(pindex, "%lu[%lu]", (unsigned long)y,
  2410. (unsigned long)b->image.colormap_entries);
  2411. logerror(b, b->file_name, ": bad pixel index: ", pindex);
  2412. }
  2413. result = 0;
  2414. }
  2415. /* All the mismatches are logged here; there can only be 256! */
  2416. else if (!cmppixel(&tr, a_cmap, b_cmap, 0, y))
  2417. result = 0;
  2418. }
  2419. /* If reqested copy the error values back from the Transform. */
  2420. if (a->opts & ACCUMULATE)
  2421. {
  2422. tr.error_ptr[0] = tr.error[0];
  2423. tr.error_ptr[1] = tr.error[1];
  2424. tr.error_ptr[2] = tr.error[2];
  2425. tr.error_ptr[3] = tr.error[3];
  2426. result = 1; /* force a continue */
  2427. }
  2428. return result;
  2429. }
  2430. /* else the image buffers don't match pixel-wise so compare sample values
  2431. * instead, but first validate that the pixel indexes are in range (but
  2432. * only if not accumulating, when the error is ignored.)
  2433. */
  2434. else if ((a->opts & ACCUMULATE) == 0)
  2435. {
  2436. /* Check the original image first,
  2437. * TODO: deal with input images with bad pixel values?
  2438. */
  2439. if (amax >= a->image.colormap_entries)
  2440. {
  2441. char pindex[9];
  2442. sprintf(pindex, "%d[%lu]", amax,
  2443. (unsigned long)a->image.colormap_entries);
  2444. return logerror(a, a->file_name, ": bad pixel index: ", pindex);
  2445. }
  2446. else if (bmax >= b->image.colormap_entries)
  2447. {
  2448. char pindex[9];
  2449. sprintf(pindex, "%d[%lu]", bmax,
  2450. (unsigned long)b->image.colormap_entries);
  2451. return logerror(b, b->file_name, ": bad pixel index: ", pindex);
  2452. }
  2453. }
  2454. }
  2455. /* We can directly compare pixel values without the need to use the read
  2456. * or transform support (i.e. a memory compare) if:
  2457. *
  2458. * 1) The bit depth has not changed.
  2459. * 2) RGB to grayscale has not been done (the reverse is ok; we just compare
  2460. * the three RGB values to the original grayscale.)
  2461. * 3) An alpha channel has not been removed from an 8-bit format, or the
  2462. * 8-bit alpha value of the pixel was 255 (opaque).
  2463. *
  2464. * If an alpha channel has been *added* then it must have the relevant opaque
  2465. * value (255 or 65535).
  2466. *
  2467. * The fist two the tests (in the order given above) (using the boolean
  2468. * equivalence !a && !b == !(a || b))
  2469. */
  2470. if (!(((formata ^ formatb) & PNG_FORMAT_FLAG_LINEAR) |
  2471. (formata & (formatb ^ PNG_FORMAT_FLAG_COLOR) & PNG_FORMAT_FLAG_COLOR)))
  2472. {
  2473. /* Was an alpha channel changed? */
  2474. const png_uint_32 alpha_changed = (formata ^ formatb) &
  2475. PNG_FORMAT_FLAG_ALPHA;
  2476. /* Was an alpha channel removed? (The third test.) If so the direct
  2477. * comparison is only possible if the input alpha is opaque.
  2478. */
  2479. alpha_removed = (formata & alpha_changed) != 0;
  2480. /* Was an alpha channel added? */
  2481. alpha_added = (formatb & alpha_changed) != 0;
  2482. /* The channels may have been moved between input and output, this finds
  2483. * out how, recording the result in the btoa array, which says where in
  2484. * 'a' to find each channel of 'b'. If alpha was added then btoa[alpha]
  2485. * ends up as 4 (and is not used.)
  2486. */
  2487. {
  2488. int i;
  2489. png_byte aloc[4];
  2490. png_byte bloc[4];
  2491. /* The following are used only if the formats match, except that
  2492. * 'bchannels' is a flag for matching formats. btoa[x] says, for each
  2493. * channel in b, where to find the corresponding value in a, for the
  2494. * bchannels. achannels may be different for a gray to rgb transform
  2495. * (a will be 1 or 2, b will be 3 or 4 channels.)
  2496. */
  2497. (void)component_loc(aloc, formata);
  2498. bchannels = component_loc(bloc, formatb);
  2499. /* Hence the btoa array. */
  2500. for (i=0; i<4; ++i) if (bloc[i] < 4)
  2501. btoa[bloc[i]] = aloc[i]; /* may be '4' for alpha */
  2502. if (alpha_added)
  2503. alpha_added = bloc[0]; /* location of alpha channel in image b */
  2504. else
  2505. alpha_added = 4; /* Won't match an image b channel */
  2506. if (alpha_removed)
  2507. alpha_removed = aloc[0]; /* location of alpha channel in image a */
  2508. else
  2509. alpha_removed = 4;
  2510. }
  2511. }
  2512. else
  2513. {
  2514. /* Direct compare is not possible, cancel out all the corresponding local
  2515. * variables.
  2516. */
  2517. bchannels = 0;
  2518. alpha_removed = alpha_added = 4;
  2519. btoa[3] = btoa[2] = btoa[1] = btoa[0] = 4; /* 4 == not present */
  2520. }
  2521. for (y=0; y<height; ++y, rowa += stridea, rowb += strideb)
  2522. {
  2523. png_const_bytep ppa, ppb;
  2524. png_uint_32 x;
  2525. for (x=0, ppa=rowa, ppb=rowb; x<width; ++x)
  2526. {
  2527. png_const_bytep psa, psb;
  2528. if (formata & PNG_FORMAT_FLAG_COLORMAP)
  2529. psa = (png_const_bytep)a->colormap + a_sample * *ppa++;
  2530. else
  2531. psa = ppa, ppa += a_sample;
  2532. if (formatb & PNG_FORMAT_FLAG_COLORMAP)
  2533. psb = (png_const_bytep)b->colormap + b_sample * *ppb++;
  2534. else
  2535. psb = ppb, ppb += b_sample;
  2536. /* Do the fast test if possible. */
  2537. if (bchannels)
  2538. {
  2539. /* Check each 'b' channel against either the corresponding 'a'
  2540. * channel or the opaque alpha value, as appropriate. If
  2541. * alpha_removed value is set (not 4) then also do this only if the
  2542. * 'a' alpha channel (alpha_removed) is opaque; only relevant for
  2543. * the 8-bit case.
  2544. */
  2545. if (formatb & PNG_FORMAT_FLAG_LINEAR) /* 16-bit checks */
  2546. {
  2547. png_const_uint_16p pua = aligncastconst(png_const_uint_16p, psa);
  2548. png_const_uint_16p pub = aligncastconst(png_const_uint_16p, psb);
  2549. switch (bchannels)
  2550. {
  2551. case 4:
  2552. if (pua[btoa[3]] != pub[3]) break;
  2553. case 3:
  2554. if (pua[btoa[2]] != pub[2]) break;
  2555. case 2:
  2556. if (pua[btoa[1]] != pub[1]) break;
  2557. case 1:
  2558. if (pua[btoa[0]] != pub[0]) break;
  2559. if (alpha_added != 4 && pub[alpha_added] != 65535) break;
  2560. continue; /* x loop */
  2561. default:
  2562. break; /* impossible */
  2563. }
  2564. }
  2565. else if (alpha_removed == 4 || psa[alpha_removed] == 255)
  2566. {
  2567. switch (bchannels)
  2568. {
  2569. case 4:
  2570. if (psa[btoa[3]] != psb[3]) break;
  2571. case 3:
  2572. if (psa[btoa[2]] != psb[2]) break;
  2573. case 2:
  2574. if (psa[btoa[1]] != psb[1]) break;
  2575. case 1:
  2576. if (psa[btoa[0]] != psb[0]) break;
  2577. if (alpha_added != 4 && psb[alpha_added] != 255) break;
  2578. continue; /* x loop */
  2579. default:
  2580. break; /* impossible */
  2581. }
  2582. }
  2583. }
  2584. /* If we get to here the fast match failed; do the slow match for this
  2585. * pixel.
  2586. */
  2587. if (!cmppixel(&tr, psa, psb, x, y) && (a->opts & KEEP_GOING) == 0)
  2588. return 0; /* error case */
  2589. }
  2590. }
  2591. /* If reqested copy the error values back from the Transform. */
  2592. if (a->opts & ACCUMULATE)
  2593. {
  2594. tr.error_ptr[0] = tr.error[0];
  2595. tr.error_ptr[1] = tr.error[1];
  2596. tr.error_ptr[2] = tr.error[2];
  2597. tr.error_ptr[3] = tr.error[3];
  2598. }
  2599. return 1;
  2600. }
  2601. /* Read the file; how the read gets done depends on which of input_file and
  2602. * input_memory have been set.
  2603. */
  2604. static int
  2605. read_file(Image *image, png_uint_32 format, png_const_colorp background)
  2606. {
  2607. memset(&image->image, 0, sizeof image->image);
  2608. image->image.version = PNG_IMAGE_VERSION;
  2609. if (image->input_memory != NULL)
  2610. {
  2611. if (!png_image_begin_read_from_memory(&image->image, image->input_memory,
  2612. image->input_memory_size))
  2613. return logerror(image, "memory init: ", image->file_name, "");
  2614. }
  2615. # ifdef PNG_STDIO_SUPPORTED
  2616. else if (image->input_file != NULL)
  2617. {
  2618. if (!png_image_begin_read_from_stdio(&image->image, image->input_file))
  2619. return logerror(image, "stdio init: ", image->file_name, "");
  2620. }
  2621. else
  2622. {
  2623. if (!png_image_begin_read_from_file(&image->image, image->file_name))
  2624. return logerror(image, "file init: ", image->file_name, "");
  2625. }
  2626. # else
  2627. else
  2628. {
  2629. return logerror(image, "unsupported file/stdio init: ",
  2630. image->file_name, "");
  2631. }
  2632. # endif
  2633. /* This must be set after the begin_read call: */
  2634. if (image->opts & sRGB_16BIT)
  2635. image->image.flags |= PNG_IMAGE_FLAG_16BIT_sRGB;
  2636. /* Have an initialized image with all the data we need plus, maybe, an
  2637. * allocated file (myfile) or buffer (mybuffer) that need to be freed.
  2638. */
  2639. {
  2640. int result;
  2641. png_uint_32 image_format;
  2642. /* Print both original and output formats. */
  2643. image_format = image->image.format;
  2644. if (image->opts & VERBOSE)
  2645. {
  2646. printf("%s %lu x %lu %s -> %s", image->file_name,
  2647. (unsigned long)image->image.width,
  2648. (unsigned long)image->image.height,
  2649. format_names[image_format & FORMAT_MASK],
  2650. (format & FORMAT_NO_CHANGE) != 0 || image->image.format == format
  2651. ? "no change" : format_names[format & FORMAT_MASK]);
  2652. if (background != NULL)
  2653. printf(" background(%d,%d,%d)\n", background->red,
  2654. background->green, background->blue);
  2655. else
  2656. printf("\n");
  2657. fflush(stdout);
  2658. }
  2659. /* 'NO_CHANGE' combined with the color-map flag forces the base format
  2660. * flags to be set on read to ensure that the original representation is
  2661. * not lost in the pass through a colormap format.
  2662. */
  2663. if ((format & FORMAT_NO_CHANGE) != 0)
  2664. {
  2665. if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 &&
  2666. (image_format & PNG_FORMAT_FLAG_COLORMAP) != 0)
  2667. format = (image_format & ~BASE_FORMATS) | (format & BASE_FORMATS);
  2668. else
  2669. format = image_format;
  2670. }
  2671. image->image.format = format;
  2672. image->stride = PNG_IMAGE_ROW_STRIDE(image->image) + image->stride_extra;
  2673. allocbuffer(image);
  2674. result = png_image_finish_read(&image->image, background,
  2675. image->buffer+16, (png_int_32)image->stride, image->colormap);
  2676. checkbuffer(image, image->file_name);
  2677. if (result)
  2678. return checkopaque(image);
  2679. else
  2680. return logerror(image, image->file_name, ": image read failed", "");
  2681. }
  2682. }
  2683. /* Reads from a filename, which must be in image->file_name, but uses
  2684. * image->opts to choose the method. The file is always read in its native
  2685. * format (the one the simplified API suggests).
  2686. */
  2687. static int
  2688. read_one_file(Image *image)
  2689. {
  2690. if (!(image->opts & READ_FILE) || (image->opts & USE_STDIO))
  2691. {
  2692. /* memory or stdio. */
  2693. FILE *f = fopen(image->file_name, "rb");
  2694. if (f != NULL)
  2695. {
  2696. if (image->opts & READ_FILE)
  2697. image->input_file = f;
  2698. else /* memory */
  2699. {
  2700. if (fseek(f, 0, SEEK_END) == 0)
  2701. {
  2702. long int cb = ftell(f);
  2703. if (cb > 0 && (unsigned long int)cb < (size_t)~(size_t)0)
  2704. {
  2705. png_bytep b = voidcast(png_bytep, malloc((size_t)cb));
  2706. if (b != NULL)
  2707. {
  2708. rewind(f);
  2709. if (fread(b, (size_t)cb, 1, f) == 1)
  2710. {
  2711. fclose(f);
  2712. image->input_memory_size = cb;
  2713. image->input_memory = b;
  2714. }
  2715. else
  2716. {
  2717. free(b);
  2718. return logclose(image, f, image->file_name,
  2719. ": read failed: ");
  2720. }
  2721. }
  2722. else
  2723. return logclose(image, f, image->file_name,
  2724. ": out of memory: ");
  2725. }
  2726. else if (cb == 0)
  2727. return logclose(image, f, image->file_name,
  2728. ": zero length: ");
  2729. else
  2730. return logclose(image, f, image->file_name,
  2731. ": tell failed: ");
  2732. }
  2733. else
  2734. return logclose(image, f, image->file_name, ": seek failed: ");
  2735. }
  2736. }
  2737. else
  2738. return logerror(image, image->file_name, ": open failed: ",
  2739. strerror(errno));
  2740. }
  2741. return read_file(image, FORMAT_NO_CHANGE, NULL);
  2742. }
  2743. #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
  2744. static int
  2745. write_one_file(Image *output, Image *image, int convert_to_8bit)
  2746. {
  2747. if (image->opts & FAST_WRITE)
  2748. image->image.flags |= PNG_IMAGE_FLAG_FAST;
  2749. if (image->opts & USE_STDIO)
  2750. {
  2751. FILE *f = tmpfile();
  2752. if (f != NULL)
  2753. {
  2754. if (png_image_write_to_stdio(&image->image, f, convert_to_8bit,
  2755. image->buffer+16, (png_int_32)image->stride, image->colormap))
  2756. {
  2757. if (fflush(f) == 0)
  2758. {
  2759. rewind(f);
  2760. initimage(output, image->opts, "tmpfile", image->stride_extra);
  2761. output->input_file = f;
  2762. if (!checkopaque(image))
  2763. return 0;
  2764. }
  2765. else
  2766. return logclose(image, f, "tmpfile", ": flush: ");
  2767. }
  2768. else
  2769. {
  2770. fclose(f);
  2771. return logerror(image, "tmpfile", ": write failed", "");
  2772. }
  2773. }
  2774. else
  2775. return logerror(image, "tmpfile", ": open: ", strerror(errno));
  2776. }
  2777. else
  2778. {
  2779. static int counter = 0;
  2780. char name[32];
  2781. sprintf(name, "%s%d.png", tmpf, ++counter);
  2782. if (png_image_write_to_file(&image->image, name, convert_to_8bit,
  2783. image->buffer+16, (png_int_32)image->stride, image->colormap))
  2784. {
  2785. initimage(output, image->opts, output->tmpfile_name,
  2786. image->stride_extra);
  2787. /* Afterwards, or freeimage will delete it! */
  2788. strcpy(output->tmpfile_name, name);
  2789. if (!checkopaque(image))
  2790. return 0;
  2791. }
  2792. else
  2793. return logerror(image, name, ": write failed", "");
  2794. }
  2795. /* 'output' has an initialized temporary image, read this back in and compare
  2796. * this against the original: there should be no change since the original
  2797. * format was written unmodified unless 'convert_to_8bit' was specified.
  2798. * However, if the original image was color-mapped, a simple read will zap
  2799. * the linear, color and maybe alpha flags, this will cause spurious failures
  2800. * under some circumstances.
  2801. */
  2802. if (read_file(output, image->image.format | FORMAT_NO_CHANGE, NULL))
  2803. {
  2804. png_uint_32 original_format = image->image.format;
  2805. if (convert_to_8bit)
  2806. original_format &= ~PNG_FORMAT_FLAG_LINEAR;
  2807. if ((output->image.format & BASE_FORMATS) !=
  2808. (original_format & BASE_FORMATS))
  2809. return logerror(image, image->file_name, ": format changed on read: ",
  2810. output->file_name);
  2811. return compare_two_images(image, output, 0/*via linear*/, NULL);
  2812. }
  2813. else
  2814. return logerror(output, output->tmpfile_name,
  2815. ": read of new file failed", "");
  2816. }
  2817. #endif
  2818. static int
  2819. testimage(Image *image, png_uint_32 opts, format_list *pf)
  2820. {
  2821. int result;
  2822. Image copy;
  2823. /* Copy the original data, stealing it from 'image' */
  2824. checkopaque(image);
  2825. copy = *image;
  2826. copy.opts = opts;
  2827. copy.buffer = NULL;
  2828. copy.bufsize = 0;
  2829. copy.allocsize = 0;
  2830. image->input_file = NULL;
  2831. image->input_memory = NULL;
  2832. image->input_memory_size = 0;
  2833. image->tmpfile_name[0] = 0;
  2834. {
  2835. png_uint_32 counter;
  2836. Image output;
  2837. newimage(&output);
  2838. result = 1;
  2839. /* Use the low bit of 'counter' to indicate whether or not to do alpha
  2840. * removal with a background color or by composting onto the image; this
  2841. * step gets skipped if it isn't relevant
  2842. */
  2843. for (counter=0; counter<2*FORMAT_COUNT; ++counter)
  2844. if (format_isset(pf, counter >> 1))
  2845. {
  2846. png_uint_32 format = counter >> 1;
  2847. png_color background_color;
  2848. png_colorp background = NULL;
  2849. /* If there is a format change that removes the alpha channel then
  2850. * the background is relevant. If the output is 8-bit color-mapped
  2851. * then a background color *must* be provided, otherwise there are
  2852. * two tests to do - one with a color, the other with NULL. The
  2853. * NULL test happens second.
  2854. */
  2855. if ((counter & 1) == 0)
  2856. {
  2857. if ((format & PNG_FORMAT_FLAG_ALPHA) == 0 &&
  2858. (image->image.format & PNG_FORMAT_FLAG_ALPHA) != 0)
  2859. {
  2860. /* Alpha/transparency will be removed, the background is
  2861. * relevant: make it a color the first time
  2862. */
  2863. random_color(&background_color);
  2864. background = &background_color;
  2865. /* BUT if the output is to a color-mapped 8-bit format then
  2866. * the background must always be a color, so increment 'counter'
  2867. * to skip the NULL test.
  2868. */
  2869. if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 &&
  2870. (format & PNG_FORMAT_FLAG_LINEAR) == 0)
  2871. ++counter;
  2872. }
  2873. /* Otherwise an alpha channel is not being eliminated, just leave
  2874. * background NULL and skip the (counter & 1) NULL test.
  2875. */
  2876. else
  2877. ++counter;
  2878. }
  2879. /* else just use NULL for background */
  2880. resetimage(&copy);
  2881. copy.opts = opts; /* in case read_file needs to change it */
  2882. result = read_file(&copy, format, background);
  2883. if (!result)
  2884. break;
  2885. /* Make sure the file just read matches the original file. */
  2886. result = compare_two_images(image, &copy, 0/*via linear*/, background);
  2887. if (!result)
  2888. break;
  2889. # ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
  2890. /* Write the *copy* just made to a new file to make sure the write
  2891. * side works ok. Check the conversion to sRGB if the copy is
  2892. * linear.
  2893. */
  2894. output.opts = opts;
  2895. result = write_one_file(&output, &copy, 0/*convert to 8bit*/);
  2896. if (!result)
  2897. break;
  2898. /* Validate against the original too; the background is needed here
  2899. * as well so that compare_two_images knows what color was used.
  2900. */
  2901. result = compare_two_images(image, &output, 0, background);
  2902. if (!result)
  2903. break;
  2904. if ((format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
  2905. (format & PNG_FORMAT_FLAG_COLORMAP) == 0)
  2906. {
  2907. /* 'output' is linear, convert to the corresponding sRGB format.
  2908. */
  2909. output.opts = opts;
  2910. result = write_one_file(&output, &copy, 1/*convert to 8bit*/);
  2911. if (!result)
  2912. break;
  2913. /* This may involve a conversion via linear; in the ideal world
  2914. * this would round-trip correctly, but libpng 1.5.7 is not the
  2915. * ideal world so allow a drift (error_via_linear).
  2916. *
  2917. * 'image' has an alpha channel but 'output' does not then there
  2918. * will a strip-alpha-channel operation (because 'output' is
  2919. * linear), handle this by composing on black when doing the
  2920. * comparison.
  2921. */
  2922. result = compare_two_images(image, &output, 1/*via_linear*/,
  2923. background);
  2924. if (!result)
  2925. break;
  2926. }
  2927. # endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */
  2928. }
  2929. freeimage(&output);
  2930. }
  2931. freeimage(&copy);
  2932. return result;
  2933. }
  2934. static int
  2935. test_one_file(const char *file_name, format_list *formats, png_uint_32 opts,
  2936. int stride_extra, int log_pass)
  2937. {
  2938. int result;
  2939. Image image;
  2940. newimage(&image);
  2941. initimage(&image, opts, file_name, stride_extra);
  2942. result = read_one_file(&image);
  2943. if (result)
  2944. result = testimage(&image, opts, formats);
  2945. freeimage(&image);
  2946. /* Ensure that stderr is flushed into any log file */
  2947. fflush(stderr);
  2948. if (log_pass)
  2949. {
  2950. if (result)
  2951. printf("PASS:");
  2952. else
  2953. printf("FAIL:");
  2954. # ifndef PNG_SIMPLIFIED_WRITE_SUPPORTED
  2955. printf(" (no write)");
  2956. # endif
  2957. print_opts(opts);
  2958. printf(" %s\n", file_name);
  2959. /* stdout may not be line-buffered if it is piped to a file, so: */
  2960. fflush(stdout);
  2961. }
  2962. else if (!result)
  2963. exit(1);
  2964. return result;
  2965. }
  2966. int
  2967. main(int argc, char **argv)
  2968. {
  2969. png_uint_32 opts = FAST_WRITE;
  2970. format_list formats;
  2971. const char *touch = NULL;
  2972. int log_pass = 0;
  2973. int redundant = 0;
  2974. int stride_extra = 0;
  2975. int retval = 0;
  2976. int c;
  2977. init_sRGB_to_d();
  2978. #if 0
  2979. init_error_via_linear();
  2980. #endif
  2981. format_init(&formats);
  2982. for (c=1; c<argc; ++c)
  2983. {
  2984. const char *arg = argv[c];
  2985. if (strcmp(arg, "--log") == 0)
  2986. log_pass = 1;
  2987. else if (strcmp(arg, "--fresh") == 0)
  2988. {
  2989. memset(gpc_error, 0, sizeof gpc_error);
  2990. memset(gpc_error_via_linear, 0, sizeof gpc_error_via_linear);
  2991. }
  2992. else if (strcmp(arg, "--file") == 0)
  2993. # ifdef PNG_STDIO_SUPPORTED
  2994. opts |= READ_FILE;
  2995. # else
  2996. return 77; /* skipped: no support */
  2997. # endif
  2998. else if (strcmp(arg, "--memory") == 0)
  2999. opts &= ~READ_FILE;
  3000. else if (strcmp(arg, "--stdio") == 0)
  3001. # ifdef PNG_STDIO_SUPPORTED
  3002. opts |= USE_STDIO;
  3003. # else
  3004. return 77; /* skipped: no support */
  3005. # endif
  3006. else if (strcmp(arg, "--name") == 0)
  3007. opts &= ~USE_STDIO;
  3008. else if (strcmp(arg, "--verbose") == 0)
  3009. opts |= VERBOSE;
  3010. else if (strcmp(arg, "--quiet") == 0)
  3011. opts &= ~VERBOSE;
  3012. else if (strcmp(arg, "--preserve") == 0)
  3013. opts |= KEEP_TMPFILES;
  3014. else if (strcmp(arg, "--nopreserve") == 0)
  3015. opts &= ~KEEP_TMPFILES;
  3016. else if (strcmp(arg, "--keep-going") == 0)
  3017. opts |= KEEP_GOING;
  3018. else if (strcmp(arg, "--fast") == 0)
  3019. opts |= FAST_WRITE;
  3020. else if (strcmp(arg, "--slow") == 0)
  3021. opts &= ~FAST_WRITE;
  3022. else if (strcmp(arg, "--accumulate") == 0)
  3023. opts |= ACCUMULATE;
  3024. else if (strcmp(arg, "--redundant") == 0)
  3025. redundant = 1;
  3026. else if (strcmp(arg, "--stop") == 0)
  3027. opts &= ~KEEP_GOING;
  3028. else if (strcmp(arg, "--strict") == 0)
  3029. opts |= STRICT;
  3030. else if (strcmp(arg, "--sRGB-16bit") == 0)
  3031. opts |= sRGB_16BIT;
  3032. else if (strcmp(arg, "--linear-16bit") == 0)
  3033. opts &= ~sRGB_16BIT;
  3034. else if (strcmp(arg, "--tmpfile") == 0)
  3035. {
  3036. if (c+1 < argc)
  3037. {
  3038. if (strlen(argv[++c]) >= sizeof tmpf)
  3039. {
  3040. fflush(stdout);
  3041. fprintf(stderr, "%s: %s is too long for a temp file prefix\n",
  3042. argv[0], argv[c]);
  3043. exit(99);
  3044. }
  3045. /* Safe: checked above */
  3046. strcpy(tmpf, argv[c]);
  3047. }
  3048. else
  3049. {
  3050. fflush(stdout);
  3051. fprintf(stderr, "%s: %s requires a temporary file prefix\n",
  3052. argv[0], arg);
  3053. exit(99);
  3054. }
  3055. }
  3056. else if (strcmp(arg, "--touch") == 0)
  3057. {
  3058. if (c+1 < argc)
  3059. touch = argv[++c];
  3060. else
  3061. {
  3062. fflush(stdout);
  3063. fprintf(stderr, "%s: %s requires a file name argument\n",
  3064. argv[0], arg);
  3065. exit(99);
  3066. }
  3067. }
  3068. else if (arg[0] == '+')
  3069. {
  3070. png_uint_32 format = formatof(arg+1);
  3071. if (format > FORMAT_COUNT)
  3072. exit(99);
  3073. format_set(&formats, format);
  3074. }
  3075. else if (arg[0] == '-' && arg[1] != 0 && (arg[1] != '0' || arg[2] != 0))
  3076. {
  3077. fflush(stdout);
  3078. fprintf(stderr, "%s: unknown option: %s\n", argv[0], arg);
  3079. exit(99);
  3080. }
  3081. else
  3082. {
  3083. if (format_is_initial(&formats))
  3084. format_default(&formats, redundant);
  3085. if (arg[0] == '-')
  3086. {
  3087. const int term = (arg[1] == '0' ? 0 : '\n');
  3088. unsigned int ich = 0;
  3089. /* Loop reading files, use a static buffer to simplify this and just
  3090. * stop if the name gets to long.
  3091. */
  3092. static char buffer[4096];
  3093. do
  3094. {
  3095. int ch = getchar();
  3096. /* Don't allow '\0' in file names, and terminate with '\n' or,
  3097. * for -0, just '\0' (use -print0 to find to make this work!)
  3098. */
  3099. if (ch == EOF || ch == term || ch == 0)
  3100. {
  3101. buffer[ich] = 0;
  3102. if (ich > 0 && !test_one_file(buffer, &formats, opts,
  3103. stride_extra, log_pass))
  3104. retval = 1;
  3105. if (ch == EOF)
  3106. break;
  3107. ich = 0;
  3108. --ich; /* so that the increment below sets it to 0 again */
  3109. }
  3110. else
  3111. buffer[ich] = (char)ch;
  3112. } while (++ich < sizeof buffer);
  3113. if (ich)
  3114. {
  3115. buffer[32] = 0;
  3116. buffer[4095] = 0;
  3117. fprintf(stderr, "%s...%s: file name too long\n", buffer,
  3118. buffer+(4096-32));
  3119. exit(99);
  3120. }
  3121. }
  3122. else if (!test_one_file(arg, &formats, opts, stride_extra, log_pass))
  3123. retval = 1;
  3124. }
  3125. }
  3126. if (opts & ACCUMULATE)
  3127. {
  3128. unsigned int in;
  3129. printf("static png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] =\n");
  3130. printf("{\n");
  3131. for (in=0; in<16; ++in)
  3132. {
  3133. unsigned int out;
  3134. printf(" { /* input: %s */\n ", format_names[in]);
  3135. for (out=0; out<16; ++out)
  3136. {
  3137. unsigned int alpha;
  3138. printf(" {");
  3139. for (alpha=0; alpha<4; ++alpha)
  3140. {
  3141. printf(" %d", gpc_error[in][out][alpha]);
  3142. if (alpha < 3) putchar(',');
  3143. }
  3144. printf(" }");
  3145. if (out < 15)
  3146. {
  3147. putchar(',');
  3148. if (out % 4 == 3) printf("\n ");
  3149. }
  3150. }
  3151. printf("\n }");
  3152. if (in < 15)
  3153. putchar(',');
  3154. else
  3155. putchar('\n');
  3156. }
  3157. printf("};\n");
  3158. printf("static png_uint_16 gpc_error_via_linear[16][4/*out*/][4] =\n");
  3159. printf("{\n");
  3160. for (in=0; in<16; ++in)
  3161. {
  3162. unsigned int out;
  3163. printf(" { /* input: %s */\n ", format_names[in]);
  3164. for (out=0; out<4; ++out)
  3165. {
  3166. unsigned int alpha;
  3167. printf(" {");
  3168. for (alpha=0; alpha<4; ++alpha)
  3169. {
  3170. printf(" %d", gpc_error_via_linear[in][out][alpha]);
  3171. if (alpha < 3) putchar(',');
  3172. }
  3173. printf(" }");
  3174. if (out < 3)
  3175. putchar(',');
  3176. }
  3177. printf("\n }");
  3178. if (in < 15)
  3179. putchar(',');
  3180. else
  3181. putchar('\n');
  3182. }
  3183. printf("};\n");
  3184. printf("static png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] =\n");
  3185. printf("{\n");
  3186. for (in=0; in<8; ++in)
  3187. {
  3188. unsigned int out;
  3189. printf(" { /* input: %s */\n ", format_names[in]);
  3190. for (out=0; out<8; ++out)
  3191. {
  3192. unsigned int alpha;
  3193. printf(" {");
  3194. for (alpha=0; alpha<4; ++alpha)
  3195. {
  3196. printf(" %d", gpc_error_to_colormap[in][out][alpha]);
  3197. if (alpha < 3) putchar(',');
  3198. }
  3199. printf(" }");
  3200. if (out < 7)
  3201. {
  3202. putchar(',');
  3203. if (out % 4 == 3) printf("\n ");
  3204. }
  3205. }
  3206. printf("\n }");
  3207. if (in < 7)
  3208. putchar(',');
  3209. else
  3210. putchar('\n');
  3211. }
  3212. printf("};\n");
  3213. }
  3214. if (retval == 0 && touch != NULL)
  3215. {
  3216. FILE *fsuccess = fopen(touch, "wt");
  3217. if (fsuccess != NULL)
  3218. {
  3219. int error = 0;
  3220. fprintf(fsuccess, "PNG simple API tests succeeded\n");
  3221. fflush(fsuccess);
  3222. error = ferror(fsuccess);
  3223. if (fclose(fsuccess) || error)
  3224. {
  3225. fflush(stdout);
  3226. fprintf(stderr, "%s: write failed\n", touch);
  3227. exit(99);
  3228. }
  3229. }
  3230. else
  3231. {
  3232. fflush(stdout);
  3233. fprintf(stderr, "%s: open failed\n", touch);
  3234. exit(99);
  3235. }
  3236. }
  3237. return retval;
  3238. }
  3239. #else /* !PNG_SIMPLIFIED_READ_SUPPORTED */
  3240. int main(void)
  3241. {
  3242. fprintf(stderr, "pngstest: no read support in libpng, test skipped\n");
  3243. /* So the test is skipped: */
  3244. return 77;
  3245. }
  3246. #endif /* PNG_SIMPLIFIED_READ_SUPPORTED */