jas_icc.c 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721
  1. /*
  2. * Copyright (c) 2002-2003 Michael David Adams.
  3. * All rights reserved.
  4. */
  5. /* __START_OF_JASPER_LICENSE__
  6. *
  7. * JasPer License Version 2.0
  8. *
  9. * Copyright (c) 2001-2006 Michael David Adams
  10. * Copyright (c) 1999-2000 Image Power, Inc.
  11. * Copyright (c) 1999-2000 The University of British Columbia
  12. *
  13. * All rights reserved.
  14. *
  15. * Permission is hereby granted, free of charge, to any person (the
  16. * "User") obtaining a copy of this software and associated documentation
  17. * files (the "Software"), to deal in the Software without restriction,
  18. * including without limitation the rights to use, copy, modify, merge,
  19. * publish, distribute, and/or sell copies of the Software, and to permit
  20. * persons to whom the Software is furnished to do so, subject to the
  21. * following conditions:
  22. *
  23. * 1. The above copyright notices and this permission notice (which
  24. * includes the disclaimer below) shall be included in all copies or
  25. * substantial portions of the Software.
  26. *
  27. * 2. The name of a copyright holder shall not be used to endorse or
  28. * promote products derived from the Software without specific prior
  29. * written permission.
  30. *
  31. * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
  32. * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  33. * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
  34. * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  35. * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  36. * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
  37. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
  38. * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
  39. * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  40. * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  41. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
  42. * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
  43. * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
  44. * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
  45. * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
  46. * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
  47. * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
  48. * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
  49. * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
  50. * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
  51. * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
  52. * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
  53. * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
  54. * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
  55. * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
  56. * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
  57. *
  58. * __END_OF_JASPER_LICENSE__
  59. */
  60. #include <assert.h>
  61. #include <jasper/jas_config.h>
  62. #include <jasper/jas_types.h>
  63. #include <jasper/jas_malloc.h>
  64. #include <jasper/jas_debug.h>
  65. #include <jasper/jas_icc.h>
  66. #include <jasper/jas_cm.h>
  67. #include <jasper/jas_stream.h>
  68. #include <jasper/jas_string.h>
  69. #include <stdlib.h>
  70. #include <ctype.h>
  71. #define jas_iccputuint8(out, val) jas_iccputuint(out, 1, val)
  72. #define jas_iccputuint16(out, val) jas_iccputuint(out, 2, val)
  73. #define jas_iccputsint32(out, val) jas_iccputsint(out, 4, val)
  74. #define jas_iccputuint32(out, val) jas_iccputuint(out, 4, val)
  75. #define jas_iccputuint64(out, val) jas_iccputuint(out, 8, val)
  76. static jas_iccattrval_t *jas_iccattrval_create0(void);
  77. static int jas_iccgetuint(jas_stream_t *in, int n, ulonglong *val);
  78. static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val);
  79. static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val);
  80. static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val);
  81. static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val);
  82. static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val);
  83. static int jas_iccputuint(jas_stream_t *out, int n, ulonglong val);
  84. static int jas_iccputsint(jas_stream_t *out, int n, longlong val);
  85. static jas_iccprof_t *jas_iccprof_create(void);
  86. static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr);
  87. static int jas_iccprof_writehdr(jas_stream_t *out, jas_icchdr_t *hdr);
  88. static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab);
  89. static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab);
  90. static int jas_iccattrtab_lookup(jas_iccattrtab_t *attrtab, jas_iccuint32_t name);
  91. static jas_iccattrtab_t *jas_iccattrtab_copy(jas_iccattrtab_t *attrtab);
  92. static jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t name);
  93. static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time);
  94. static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz);
  95. static int jas_icctagtabent_cmp(const void *src, const void *dst);
  96. static void jas_icccurv_destroy(jas_iccattrval_t *attrval);
  97. static int jas_icccurv_copy(jas_iccattrval_t *attrval,
  98. jas_iccattrval_t *othattrval);
  99. static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  100. int cnt);
  101. static int jas_icccurv_getsize(jas_iccattrval_t *attrval);
  102. static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out);
  103. static void jas_icccurv_dump(jas_iccattrval_t *attrval, FILE *out);
  104. static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval);
  105. static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval,
  106. jas_iccattrval_t *othattrval);
  107. static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  108. int cnt);
  109. static int jas_icctxtdesc_getsize(jas_iccattrval_t *attrval);
  110. static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out);
  111. static void jas_icctxtdesc_dump(jas_iccattrval_t *attrval, FILE *out);
  112. static void jas_icctxt_destroy(jas_iccattrval_t *attrval);
  113. static int jas_icctxt_copy(jas_iccattrval_t *attrval,
  114. jas_iccattrval_t *othattrval);
  115. static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  116. int cnt);
  117. static int jas_icctxt_getsize(jas_iccattrval_t *attrval);
  118. static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out);
  119. static void jas_icctxt_dump(jas_iccattrval_t *attrval, FILE *out);
  120. static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  121. int cnt);
  122. static int jas_iccxyz_getsize(jas_iccattrval_t *attrval);
  123. static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out);
  124. static void jas_iccxyz_dump(jas_iccattrval_t *attrval, FILE *out);
  125. static jas_iccattrtab_t *jas_iccattrtab_create(void);
  126. static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab);
  127. static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, int maxents);
  128. static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i,
  129. jas_iccuint32_t name, jas_iccattrval_t *val);
  130. static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, int i,
  131. jas_iccuint32_t name, jas_iccattrval_t *val);
  132. static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, int i);
  133. static long jas_iccpadtomult(long x, long y);
  134. static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, int i,
  135. jas_iccattrname_t *name, jas_iccattrval_t **val);
  136. static int jas_iccprof_puttagtab(jas_stream_t *out, jas_icctagtab_t *tagtab);
  137. static void jas_icclut16_destroy(jas_iccattrval_t *attrval);
  138. static int jas_icclut16_copy(jas_iccattrval_t *attrval,
  139. jas_iccattrval_t *othattrval);
  140. static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  141. int cnt);
  142. static int jas_icclut16_getsize(jas_iccattrval_t *attrval);
  143. static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out);
  144. static void jas_icclut16_dump(jas_iccattrval_t *attrval, FILE *out);
  145. static void jas_icclut8_destroy(jas_iccattrval_t *attrval);
  146. static int jas_icclut8_copy(jas_iccattrval_t *attrval,
  147. jas_iccattrval_t *othattrval);
  148. static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  149. int cnt);
  150. static int jas_icclut8_getsize(jas_iccattrval_t *attrval);
  151. static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out);
  152. static void jas_icclut8_dump(jas_iccattrval_t *attrval, FILE *out);
  153. static int jas_iccputtime(jas_stream_t *out, jas_icctime_t *ctime);
  154. static int jas_iccputxyz(jas_stream_t *out, jas_iccxyz_t *xyz);
  155. static long jas_iccpowi(int x, int n);
  156. static char *jas_iccsigtostr(int sig, char *buf);
  157. jas_iccattrvalinfo_t jas_iccattrvalinfos[] = {
  158. {JAS_ICC_TYPE_CURV, {jas_icccurv_destroy, jas_icccurv_copy,
  159. jas_icccurv_input, jas_icccurv_output, jas_icccurv_getsize,
  160. jas_icccurv_dump}},
  161. {JAS_ICC_TYPE_XYZ, {0, 0, jas_iccxyz_input, jas_iccxyz_output,
  162. jas_iccxyz_getsize, jas_iccxyz_dump}},
  163. {JAS_ICC_TYPE_TXTDESC, {jas_icctxtdesc_destroy,
  164. jas_icctxtdesc_copy, jas_icctxtdesc_input, jas_icctxtdesc_output,
  165. jas_icctxtdesc_getsize, jas_icctxtdesc_dump}},
  166. {JAS_ICC_TYPE_TXT, {jas_icctxt_destroy, jas_icctxt_copy,
  167. jas_icctxt_input, jas_icctxt_output, jas_icctxt_getsize,
  168. jas_icctxt_dump}},
  169. {JAS_ICC_TYPE_LUT8, {jas_icclut8_destroy, jas_icclut8_copy,
  170. jas_icclut8_input, jas_icclut8_output, jas_icclut8_getsize,
  171. jas_icclut8_dump}},
  172. {JAS_ICC_TYPE_LUT16, {jas_icclut16_destroy, jas_icclut16_copy,
  173. jas_icclut16_input, jas_icclut16_output, jas_icclut16_getsize,
  174. jas_icclut16_dump}},
  175. {0, {0, 0, 0, 0, 0, 0}}
  176. };
  177. typedef struct {
  178. jas_iccuint32_t tag;
  179. char *name;
  180. } jas_icctaginfo_t;
  181. /******************************************************************************\
  182. * profile class
  183. \******************************************************************************/
  184. static jas_iccprof_t *jas_iccprof_create()
  185. {
  186. jas_iccprof_t *prof;
  187. prof = 0;
  188. if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) {
  189. goto error;
  190. }
  191. if (!(prof->attrtab = jas_iccattrtab_create()))
  192. goto error;
  193. memset(&prof->hdr, 0, sizeof(jas_icchdr_t));
  194. prof->tagtab.numents = 0;
  195. prof->tagtab.ents = 0;
  196. return prof;
  197. error:
  198. if (prof)
  199. jas_iccprof_destroy(prof);
  200. return 0;
  201. }
  202. jas_iccprof_t *jas_iccprof_copy(jas_iccprof_t *prof)
  203. {
  204. jas_iccprof_t *newprof;
  205. newprof = 0;
  206. if (!(newprof = jas_iccprof_create()))
  207. goto error;
  208. newprof->hdr = prof->hdr;
  209. newprof->tagtab.numents = 0;
  210. newprof->tagtab.ents = 0;
  211. assert(newprof->attrtab);
  212. jas_iccattrtab_destroy(newprof->attrtab);
  213. if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab)))
  214. goto error;
  215. return newprof;
  216. error:
  217. if (newprof)
  218. jas_iccprof_destroy(newprof);
  219. return 0;
  220. }
  221. void jas_iccprof_destroy(jas_iccprof_t *prof)
  222. {
  223. if (prof->attrtab)
  224. jas_iccattrtab_destroy(prof->attrtab);
  225. if (prof->tagtab.ents)
  226. jas_free(prof->tagtab.ents);
  227. jas_free(prof);
  228. }
  229. void jas_iccprof_dump(jas_iccprof_t *prof, FILE *out)
  230. {
  231. jas_iccattrtab_dump(prof->attrtab, out);
  232. }
  233. jas_iccprof_t *jas_iccprof_load(jas_stream_t *in)
  234. {
  235. jas_iccprof_t *prof;
  236. int numtags;
  237. long curoff;
  238. long reloff;
  239. long prevoff;
  240. jas_iccsig_t type;
  241. jas_iccattrval_t *attrval;
  242. jas_iccattrval_t *prevattrval;
  243. jas_icctagtabent_t *tagtabent;
  244. jas_iccattrvalinfo_t *attrvalinfo;
  245. int i;
  246. int len;
  247. prof = 0;
  248. attrval = 0;
  249. if (!(prof = jas_iccprof_create())) {
  250. goto error;
  251. }
  252. if (jas_iccprof_readhdr(in, &prof->hdr)) {
  253. jas_eprintf("cannot get header\n");
  254. goto error;
  255. }
  256. if (jas_iccprof_gettagtab(in, &prof->tagtab)) {
  257. jas_eprintf("cannot get tab table\n");
  258. goto error;
  259. }
  260. jas_iccprof_sorttagtab(&prof->tagtab);
  261. numtags = prof->tagtab.numents;
  262. curoff = JAS_ICC_HDRLEN + 4 + 12 * numtags;
  263. prevoff = 0;
  264. prevattrval = 0;
  265. for (i = 0; i < numtags; ++i) {
  266. tagtabent = &prof->tagtab.ents[i];
  267. if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) {
  268. if (prevattrval) {
  269. if (!(attrval = jas_iccattrval_clone(prevattrval)))
  270. goto error;
  271. if (jas_iccprof_setattr(prof, tagtabent->tag, attrval))
  272. goto error;
  273. jas_iccattrval_destroy(attrval);
  274. } else {
  275. #if 0
  276. jas_eprintf("warning: skipping unknown tag type\n");
  277. #endif
  278. }
  279. continue;
  280. }
  281. reloff = tagtabent->off - curoff;
  282. if (reloff > 0) {
  283. if (jas_stream_gobble(in, reloff) != reloff)
  284. goto error;
  285. curoff += reloff;
  286. } else if (reloff < 0) {
  287. /* This should never happen since we read the tagged
  288. element data in a single pass. */
  289. abort();
  290. }
  291. prevoff = curoff;
  292. if (jas_iccgetuint32(in, &type)) {
  293. goto error;
  294. }
  295. if (jas_stream_gobble(in, 4) != 4) {
  296. goto error;
  297. }
  298. curoff += 8;
  299. if (!(attrvalinfo = jas_iccattrvalinfo_lookup(type))) {
  300. #if 0
  301. jas_eprintf("warning: skipping unknown tag type\n");
  302. #endif
  303. prevattrval = 0;
  304. continue;
  305. }
  306. if (!(attrval = jas_iccattrval_create(type))) {
  307. goto error;
  308. }
  309. len = tagtabent->len - 8;
  310. if ((*attrval->ops->input)(attrval, in, len)) {
  311. goto error;
  312. }
  313. curoff += len;
  314. if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) {
  315. goto error;
  316. }
  317. prevattrval = attrval; /* This is correct, but slimey. */
  318. jas_iccattrval_destroy(attrval);
  319. attrval = 0;
  320. }
  321. return prof;
  322. error:
  323. if (prof)
  324. jas_iccprof_destroy(prof);
  325. if (attrval)
  326. jas_iccattrval_destroy(attrval);
  327. return 0;
  328. }
  329. int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out)
  330. {
  331. long curoff;
  332. long reloff;
  333. long newoff;
  334. int i;
  335. int j;
  336. jas_icctagtabent_t *tagtabent;
  337. jas_icctagtabent_t *sharedtagtabent;
  338. jas_icctagtabent_t *tmptagtabent;
  339. jas_iccuint32_t attrname;
  340. jas_iccattrval_t *attrval;
  341. jas_icctagtab_t *tagtab;
  342. tagtab = &prof->tagtab;
  343. if (!(tagtab->ents = jas_alloc2(prof->attrtab->numattrs,
  344. sizeof(jas_icctagtabent_t))))
  345. goto error;
  346. tagtab->numents = prof->attrtab->numattrs;
  347. curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
  348. for (i = 0; i < JAS_CAST(int, tagtab->numents); ++i) {
  349. tagtabent = &tagtab->ents[i];
  350. if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval))
  351. goto error;
  352. assert(attrval->ops->output);
  353. tagtabent->tag = attrname;
  354. tagtabent->data = &attrval->data;
  355. sharedtagtabent = 0;
  356. for (j = 0; j < i; ++j) {
  357. tmptagtabent = &tagtab->ents[j];
  358. if (tagtabent->data == tmptagtabent->data) {
  359. sharedtagtabent = tmptagtabent;
  360. break;
  361. }
  362. }
  363. if (sharedtagtabent) {
  364. tagtabent->off = sharedtagtabent->off;
  365. tagtabent->len = sharedtagtabent->len;
  366. tagtabent->first = sharedtagtabent;
  367. } else {
  368. tagtabent->off = curoff;
  369. tagtabent->len = (*attrval->ops->getsize)(attrval) + 8;
  370. tagtabent->first = 0;
  371. if (i < JAS_CAST(int, tagtab->numents - 1)) {
  372. curoff = jas_iccpadtomult(curoff + tagtabent->len, 4);
  373. } else {
  374. curoff += tagtabent->len;
  375. }
  376. }
  377. jas_iccattrval_destroy(attrval);
  378. }
  379. prof->hdr.size = curoff;
  380. if (jas_iccprof_writehdr(out, &prof->hdr))
  381. goto error;
  382. if (jas_iccprof_puttagtab(out, &prof->tagtab))
  383. goto error;
  384. curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents;
  385. for (i = 0; i < JAS_CAST(int, tagtab->numents);) {
  386. tagtabent = &tagtab->ents[i];
  387. assert(curoff == JAS_CAST(long, tagtabent->off));
  388. if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval))
  389. goto error;
  390. if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out,
  391. 4, 0) != 4)
  392. goto error;
  393. if ((*attrval->ops->output)(attrval, out))
  394. goto error;
  395. jas_iccattrval_destroy(attrval);
  396. curoff += tagtabent->len;
  397. ++i;
  398. while (i < JAS_CAST(int, tagtab->numents) &&
  399. tagtab->ents[i].first)
  400. ++i;
  401. newoff = (i < JAS_CAST(int, tagtab->numents)) ?
  402. tagtab->ents[i].off : prof->hdr.size;
  403. reloff = newoff - curoff;
  404. assert(reloff >= 0);
  405. if (reloff > 0) {
  406. if (jas_stream_pad(out, reloff, 0) != reloff)
  407. goto error;
  408. curoff += reloff;
  409. }
  410. }
  411. return 0;
  412. error:
  413. /* XXX - need to free some resources here */
  414. return -1;
  415. }
  416. static int jas_iccprof_writehdr(jas_stream_t *out, jas_icchdr_t *hdr)
  417. {
  418. if (jas_iccputuint32(out, hdr->size) ||
  419. jas_iccputuint32(out, hdr->cmmtype) ||
  420. jas_iccputuint32(out, hdr->version) ||
  421. jas_iccputuint32(out, hdr->clas) ||
  422. jas_iccputuint32(out, hdr->colorspc) ||
  423. jas_iccputuint32(out, hdr->refcolorspc) ||
  424. jas_iccputtime(out, &hdr->ctime) ||
  425. jas_iccputuint32(out, hdr->magic) ||
  426. jas_iccputuint32(out, hdr->platform) ||
  427. jas_iccputuint32(out, hdr->flags) ||
  428. jas_iccputuint32(out, hdr->maker) ||
  429. jas_iccputuint32(out, hdr->model) ||
  430. jas_iccputuint64(out, hdr->attr) ||
  431. jas_iccputuint32(out, hdr->intent) ||
  432. jas_iccputxyz(out, &hdr->illum) ||
  433. jas_iccputuint32(out, hdr->creator) ||
  434. jas_stream_pad(out, 44, 0) != 44)
  435. return -1;
  436. return 0;
  437. }
  438. static int jas_iccprof_puttagtab(jas_stream_t *out, jas_icctagtab_t *tagtab)
  439. {
  440. int i;
  441. jas_icctagtabent_t *tagtabent;
  442. if (jas_iccputuint32(out, tagtab->numents))
  443. goto error;
  444. for (i = 0; i < JAS_CAST(int, tagtab->numents); ++i) {
  445. tagtabent = &tagtab->ents[i];
  446. if (jas_iccputuint32(out, tagtabent->tag) ||
  447. jas_iccputuint32(out, tagtabent->off) ||
  448. jas_iccputuint32(out, tagtabent->len))
  449. goto error;
  450. }
  451. return 0;
  452. error:
  453. return -1;
  454. }
  455. static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr)
  456. {
  457. if (jas_iccgetuint32(in, &hdr->size) ||
  458. jas_iccgetuint32(in, &hdr->cmmtype) ||
  459. jas_iccgetuint32(in, &hdr->version) ||
  460. jas_iccgetuint32(in, &hdr->clas) ||
  461. jas_iccgetuint32(in, &hdr->colorspc) ||
  462. jas_iccgetuint32(in, &hdr->refcolorspc) ||
  463. jas_iccgettime(in, &hdr->ctime) ||
  464. jas_iccgetuint32(in, &hdr->magic) ||
  465. jas_iccgetuint32(in, &hdr->platform) ||
  466. jas_iccgetuint32(in, &hdr->flags) ||
  467. jas_iccgetuint32(in, &hdr->maker) ||
  468. jas_iccgetuint32(in, &hdr->model) ||
  469. jas_iccgetuint64(in, &hdr->attr) ||
  470. jas_iccgetuint32(in, &hdr->intent) ||
  471. jas_iccgetxyz(in, &hdr->illum) ||
  472. jas_iccgetuint32(in, &hdr->creator) ||
  473. jas_stream_gobble(in, 44) != 44)
  474. return -1;
  475. return 0;
  476. }
  477. static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab)
  478. {
  479. int i;
  480. jas_icctagtabent_t *tagtabent;
  481. if (tagtab->ents) {
  482. jas_free(tagtab->ents);
  483. tagtab->ents = 0;
  484. }
  485. if (jas_iccgetuint32(in, &tagtab->numents))
  486. goto error;
  487. if (!(tagtab->ents = jas_alloc2(tagtab->numents,
  488. sizeof(jas_icctagtabent_t))))
  489. goto error;
  490. tagtabent = tagtab->ents;
  491. for (i = 0; i < JAS_CAST(long, tagtab->numents); ++i) {
  492. if (jas_iccgetuint32(in, &tagtabent->tag) ||
  493. jas_iccgetuint32(in, &tagtabent->off) ||
  494. jas_iccgetuint32(in, &tagtabent->len))
  495. goto error;
  496. ++tagtabent;
  497. }
  498. return 0;
  499. error:
  500. if (tagtab->ents) {
  501. jas_free(tagtab->ents);
  502. tagtab->ents = 0;
  503. }
  504. return -1;
  505. }
  506. jas_iccattrval_t *jas_iccprof_getattr(jas_iccprof_t *prof,
  507. jas_iccattrname_t name)
  508. {
  509. int i;
  510. jas_iccattrval_t *attrval;
  511. if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0)
  512. goto error;
  513. if (!(attrval = jas_iccattrval_clone(prof->attrtab->attrs[i].val)))
  514. goto error;
  515. return attrval;
  516. error:
  517. return 0;
  518. }
  519. int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name,
  520. jas_iccattrval_t *val)
  521. {
  522. int i;
  523. if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) {
  524. if (val) {
  525. if (jas_iccattrtab_replace(prof->attrtab, i, name, val))
  526. goto error;
  527. } else {
  528. jas_iccattrtab_delete(prof->attrtab, i);
  529. }
  530. } else {
  531. if (val) {
  532. if (jas_iccattrtab_add(prof->attrtab, -1, name, val))
  533. goto error;
  534. } else {
  535. /* NOP */
  536. }
  537. }
  538. return 0;
  539. error:
  540. return -1;
  541. }
  542. int jas_iccprof_gethdr(jas_iccprof_t *prof, jas_icchdr_t *hdr)
  543. {
  544. *hdr = prof->hdr;
  545. return 0;
  546. }
  547. int jas_iccprof_sethdr(jas_iccprof_t *prof, jas_icchdr_t *hdr)
  548. {
  549. prof->hdr = *hdr;
  550. return 0;
  551. }
  552. static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab)
  553. {
  554. qsort(tagtab->ents, tagtab->numents, sizeof(jas_icctagtabent_t),
  555. jas_icctagtabent_cmp);
  556. }
  557. static int jas_icctagtabent_cmp(const void *src, const void *dst)
  558. {
  559. jas_icctagtabent_t *srctagtabent = JAS_CAST(jas_icctagtabent_t *, src);
  560. jas_icctagtabent_t *dsttagtabent = JAS_CAST(jas_icctagtabent_t *, dst);
  561. if (srctagtabent->off > dsttagtabent->off) {
  562. return 1;
  563. } else if (srctagtabent->off < dsttagtabent->off) {
  564. return -1;
  565. }
  566. return 0;
  567. }
  568. static jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t type)
  569. {
  570. jas_iccattrvalinfo_t *info;
  571. info = jas_iccattrvalinfos;
  572. for (info = jas_iccattrvalinfos; info->type; ++info) {
  573. if (info->type == type) {
  574. return info;
  575. }
  576. }
  577. return 0;
  578. }
  579. static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time)
  580. {
  581. if (jas_iccgetuint16(in, &time->year) ||
  582. jas_iccgetuint16(in, &time->month) ||
  583. jas_iccgetuint16(in, &time->day) ||
  584. jas_iccgetuint16(in, &time->hour) ||
  585. jas_iccgetuint16(in, &time->min) ||
  586. jas_iccgetuint16(in, &time->sec)) {
  587. return -1;
  588. }
  589. return 0;
  590. }
  591. static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz)
  592. {
  593. if (jas_iccgetsint32(in, &xyz->x) ||
  594. jas_iccgetsint32(in, &xyz->y) ||
  595. jas_iccgetsint32(in, &xyz->z)) {
  596. return -1;
  597. }
  598. return 0;
  599. }
  600. static int jas_iccputtime(jas_stream_t *out, jas_icctime_t *time)
  601. {
  602. jas_iccputuint16(out, time->year);
  603. jas_iccputuint16(out, time->month);
  604. jas_iccputuint16(out, time->day);
  605. jas_iccputuint16(out, time->hour);
  606. jas_iccputuint16(out, time->min);
  607. jas_iccputuint16(out, time->sec);
  608. return 0;
  609. }
  610. static int jas_iccputxyz(jas_stream_t *out, jas_iccxyz_t *xyz)
  611. {
  612. jas_iccputuint32(out, xyz->x);
  613. jas_iccputuint32(out, xyz->y);
  614. jas_iccputuint32(out, xyz->z);
  615. return 0;
  616. }
  617. /******************************************************************************\
  618. * attribute table class
  619. \******************************************************************************/
  620. static jas_iccattrtab_t *jas_iccattrtab_create()
  621. {
  622. jas_iccattrtab_t *tab;
  623. tab = 0;
  624. if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t))))
  625. goto error;
  626. tab->maxattrs = 0;
  627. tab->numattrs = 0;
  628. tab->attrs = 0;
  629. if (jas_iccattrtab_resize(tab, 32))
  630. goto error;
  631. return tab;
  632. error:
  633. if (tab)
  634. jas_iccattrtab_destroy(tab);
  635. return 0;
  636. }
  637. static jas_iccattrtab_t *jas_iccattrtab_copy(jas_iccattrtab_t *attrtab)
  638. {
  639. jas_iccattrtab_t *newattrtab;
  640. int i;
  641. if (!(newattrtab = jas_iccattrtab_create()))
  642. goto error;
  643. for (i = 0; i < attrtab->numattrs; ++i) {
  644. if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name,
  645. attrtab->attrs[i].val))
  646. goto error;
  647. }
  648. return newattrtab;
  649. error:
  650. return 0;
  651. }
  652. static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab)
  653. {
  654. if (tab->attrs) {
  655. while (tab->numattrs > 0) {
  656. jas_iccattrtab_delete(tab, 0);
  657. }
  658. jas_free(tab->attrs);
  659. }
  660. jas_free(tab);
  661. }
  662. void jas_iccattrtab_dump(jas_iccattrtab_t *attrtab, FILE *out)
  663. {
  664. int i;
  665. jas_iccattr_t *attr;
  666. jas_iccattrval_t *attrval;
  667. jas_iccattrvalinfo_t *info;
  668. char buf[16];
  669. fprintf(out, "numattrs=%d\n", attrtab->numattrs);
  670. fprintf(out, "---\n");
  671. for (i = 0; i < attrtab->numattrs; ++i) {
  672. attr = &attrtab->attrs[i];
  673. attrval = attr->val;
  674. info = jas_iccattrvalinfo_lookup(attrval->type);
  675. if (!info) abort();
  676. fprintf(out, "attrno=%d; attrname=\"%s\"(0x%08x); attrtype=\"%s\"(0x%08x)\n",
  677. i,
  678. jas_iccsigtostr(attr->name, &buf[0]),
  679. (unsigned)attr->name,
  680. jas_iccsigtostr(attrval->type, &buf[8]),
  681. (unsigned)attrval->type
  682. );
  683. jas_iccattrval_dump(attrval, out);
  684. fprintf(out, "---\n");
  685. }
  686. }
  687. static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, int maxents)
  688. {
  689. jas_iccattr_t *newattrs;
  690. assert(maxents >= tab->numattrs);
  691. newattrs = jas_realloc2(tab->attrs, maxents, sizeof(jas_iccattr_t));
  692. if (!newattrs)
  693. return -1;
  694. tab->attrs = newattrs;
  695. tab->maxattrs = maxents;
  696. return 0;
  697. }
  698. static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i,
  699. jas_iccuint32_t name, jas_iccattrval_t *val)
  700. {
  701. int n;
  702. jas_iccattr_t *attr;
  703. jas_iccattrval_t *tmpattrval;
  704. tmpattrval = 0;
  705. if (i < 0) {
  706. i = attrtab->numattrs;
  707. }
  708. assert(i >= 0 && i <= attrtab->numattrs);
  709. if (attrtab->numattrs >= attrtab->maxattrs) {
  710. if (jas_iccattrtab_resize(attrtab, attrtab->numattrs + 32)) {
  711. goto error;
  712. }
  713. }
  714. if (!(tmpattrval = jas_iccattrval_clone(val)))
  715. goto error;
  716. n = attrtab->numattrs - i;
  717. if (n > 0)
  718. memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i],
  719. n * sizeof(jas_iccattr_t));
  720. attr = &attrtab->attrs[i];
  721. attr->name = name;
  722. attr->val = tmpattrval;
  723. ++attrtab->numattrs;
  724. return 0;
  725. error:
  726. if (tmpattrval)
  727. jas_iccattrval_destroy(tmpattrval);
  728. return -1;
  729. }
  730. static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, int i,
  731. jas_iccuint32_t name, jas_iccattrval_t *val)
  732. {
  733. jas_iccattrval_t *newval;
  734. jas_iccattr_t *attr;
  735. if (!(newval = jas_iccattrval_clone(val)))
  736. goto error;
  737. attr = &attrtab->attrs[i];
  738. jas_iccattrval_destroy(attr->val);
  739. attr->name = name;
  740. attr->val = newval;
  741. return 0;
  742. error:
  743. return -1;
  744. }
  745. static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, int i)
  746. {
  747. int n;
  748. jas_iccattrval_destroy(attrtab->attrs[i].val);
  749. if ((n = attrtab->numattrs - i - 1) > 0)
  750. memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1],
  751. n * sizeof(jas_iccattr_t));
  752. --attrtab->numattrs;
  753. }
  754. static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, int i,
  755. jas_iccattrname_t *name, jas_iccattrval_t **val)
  756. {
  757. jas_iccattr_t *attr;
  758. if (i < 0 || i >= attrtab->numattrs)
  759. goto error;
  760. attr = &attrtab->attrs[i];
  761. *name = attr->name;
  762. if (!(*val = jas_iccattrval_clone(attr->val)))
  763. goto error;
  764. return 0;
  765. error:
  766. return -1;
  767. }
  768. static int jas_iccattrtab_lookup(jas_iccattrtab_t *attrtab,
  769. jas_iccuint32_t name)
  770. {
  771. int i;
  772. jas_iccattr_t *attr;
  773. for (i = 0; i < attrtab->numattrs; ++i) {
  774. attr = &attrtab->attrs[i];
  775. if (attr->name == name)
  776. return i;
  777. }
  778. return -1;
  779. }
  780. /******************************************************************************\
  781. * attribute value class
  782. \******************************************************************************/
  783. jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type)
  784. {
  785. jas_iccattrval_t *attrval;
  786. jas_iccattrvalinfo_t *info;
  787. if (!(info = jas_iccattrvalinfo_lookup(type)))
  788. goto error;
  789. if (!(attrval = jas_iccattrval_create0()))
  790. goto error;
  791. attrval->ops = &info->ops;
  792. attrval->type = type;
  793. ++attrval->refcnt;
  794. memset(&attrval->data, 0, sizeof(attrval->data));
  795. return attrval;
  796. error:
  797. return 0;
  798. }
  799. jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval)
  800. {
  801. ++attrval->refcnt;
  802. return attrval;
  803. }
  804. void jas_iccattrval_destroy(jas_iccattrval_t *attrval)
  805. {
  806. #if 0
  807. jas_eprintf("refcnt=%d\n", attrval->refcnt);
  808. #endif
  809. if (--attrval->refcnt <= 0) {
  810. if (attrval->ops->destroy)
  811. (*attrval->ops->destroy)(attrval);
  812. jas_free(attrval);
  813. }
  814. }
  815. void jas_iccattrval_dump(jas_iccattrval_t *attrval, FILE *out)
  816. {
  817. char buf[8];
  818. jas_iccsigtostr(attrval->type, buf);
  819. fprintf(out, "refcnt = %d; type = 0x%08x %s\n", attrval->refcnt,
  820. (unsigned)attrval->type, jas_iccsigtostr(attrval->type, &buf[0]));
  821. if (attrval->ops->dump) {
  822. (*attrval->ops->dump)(attrval, out);
  823. }
  824. }
  825. int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx)
  826. {
  827. jas_iccattrval_t *newattrval;
  828. jas_iccattrval_t *attrval = *attrvalx;
  829. newattrval = 0;
  830. if (attrval->refcnt > 1) {
  831. if (!(newattrval = jas_iccattrval_create0()))
  832. goto error;
  833. newattrval->ops = attrval->ops;
  834. newattrval->type = attrval->type;
  835. ++newattrval->refcnt;
  836. if (newattrval->ops->copy) {
  837. if ((*newattrval->ops->copy)(newattrval, attrval))
  838. goto error;
  839. } else {
  840. memcpy(&newattrval->data, &attrval->data,
  841. sizeof(newattrval->data));
  842. }
  843. *attrvalx = newattrval;
  844. }
  845. return 0;
  846. error:
  847. if (newattrval) {
  848. jas_free(newattrval);
  849. }
  850. return -1;
  851. }
  852. static jas_iccattrval_t *jas_iccattrval_create0()
  853. {
  854. jas_iccattrval_t *attrval;
  855. if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t))))
  856. return 0;
  857. memset(attrval, 0, sizeof(jas_iccattrval_t));
  858. attrval->refcnt = 0;
  859. attrval->ops = 0;
  860. attrval->type = 0;
  861. return attrval;
  862. }
  863. /******************************************************************************\
  864. *
  865. \******************************************************************************/
  866. static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  867. int len)
  868. {
  869. if (len != 4 * 3) abort();
  870. return jas_iccgetxyz(in, &attrval->data.xyz);
  871. }
  872. static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out)
  873. {
  874. jas_iccxyz_t *xyz = &attrval->data.xyz;
  875. if (jas_iccputuint32(out, xyz->x) ||
  876. jas_iccputuint32(out, xyz->y) ||
  877. jas_iccputuint32(out, xyz->z))
  878. return -1;
  879. return 0;
  880. }
  881. static int jas_iccxyz_getsize(jas_iccattrval_t *attrval)
  882. {
  883. /* Avoid compiler warnings about unused parameters. */
  884. attrval = 0;
  885. return 12;
  886. }
  887. static void jas_iccxyz_dump(jas_iccattrval_t *attrval, FILE *out)
  888. {
  889. jas_iccxyz_t *xyz = &attrval->data.xyz;
  890. fprintf(out, "(%f, %f, %f)\n", xyz->x / 65536.0, xyz->y / 65536.0, xyz->z / 65536.0);
  891. }
  892. /******************************************************************************\
  893. * attribute table class
  894. \******************************************************************************/
  895. static void jas_icccurv_destroy(jas_iccattrval_t *attrval)
  896. {
  897. jas_icccurv_t *curv = &attrval->data.curv;
  898. if (curv->ents)
  899. jas_free(curv->ents);
  900. }
  901. static int jas_icccurv_copy(jas_iccattrval_t *attrval,
  902. jas_iccattrval_t *othattrval)
  903. {
  904. /* Avoid compiler warnings about unused parameters. */
  905. attrval = 0;
  906. othattrval = 0;
  907. /* Not yet implemented. */
  908. abort();
  909. return -1;
  910. }
  911. static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  912. int cnt)
  913. {
  914. jas_icccurv_t *curv = &attrval->data.curv;
  915. unsigned int i;
  916. curv->numents = 0;
  917. curv->ents = 0;
  918. if (jas_iccgetuint32(in, &curv->numents))
  919. goto error;
  920. if (!(curv->ents = jas_alloc2(curv->numents, sizeof(jas_iccuint16_t))))
  921. goto error;
  922. for (i = 0; i < curv->numents; ++i) {
  923. if (jas_iccgetuint16(in, &curv->ents[i]))
  924. goto error;
  925. }
  926. if (JAS_CAST(int, 4 + 2 * curv->numents) != cnt)
  927. goto error;
  928. return 0;
  929. error:
  930. jas_icccurv_destroy(attrval);
  931. return -1;
  932. }
  933. static int jas_icccurv_getsize(jas_iccattrval_t *attrval)
  934. {
  935. jas_icccurv_t *curv = &attrval->data.curv;
  936. return 4 + 2 * curv->numents;
  937. }
  938. static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out)
  939. {
  940. jas_icccurv_t *curv = &attrval->data.curv;
  941. unsigned int i;
  942. if (jas_iccputuint32(out, curv->numents))
  943. goto error;
  944. for (i = 0; i < curv->numents; ++i) {
  945. if (jas_iccputuint16(out, curv->ents[i]))
  946. goto error;
  947. }
  948. return 0;
  949. error:
  950. return -1;
  951. }
  952. static void jas_icccurv_dump(jas_iccattrval_t *attrval, FILE *out)
  953. {
  954. int i;
  955. jas_icccurv_t *curv = &attrval->data.curv;
  956. fprintf(out, "number of entires = %d\n", (int)curv->numents);
  957. if (curv->numents == 1) {
  958. fprintf(out, "gamma = %f\n", curv->ents[0] / 256.0);
  959. } else {
  960. for (i = 0; i < JAS_CAST(int, curv->numents); ++i) {
  961. if (i < 3 || i >= JAS_CAST(int, curv->numents) - 3) {
  962. fprintf(out, "entry[%d] = %f\n", i, curv->ents[i] / 65535.0);
  963. }
  964. }
  965. }
  966. }
  967. /******************************************************************************\
  968. *
  969. \******************************************************************************/
  970. static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval)
  971. {
  972. jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
  973. if (txtdesc->ascdata)
  974. jas_free(txtdesc->ascdata);
  975. if (txtdesc->ucdata)
  976. jas_free(txtdesc->ucdata);
  977. }
  978. static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval,
  979. jas_iccattrval_t *othattrval)
  980. {
  981. jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
  982. /* Avoid compiler warnings about unused parameters. */
  983. attrval = 0;
  984. othattrval = 0;
  985. txtdesc = 0;
  986. /* Not yet implemented. */
  987. abort();
  988. return -1;
  989. }
  990. static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  991. int cnt)
  992. {
  993. int n;
  994. int c;
  995. jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
  996. txtdesc->ascdata = 0;
  997. txtdesc->ucdata = 0;
  998. if (jas_iccgetuint32(in, &txtdesc->asclen))
  999. goto error;
  1000. if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen)))
  1001. goto error;
  1002. if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) !=
  1003. JAS_CAST(int, txtdesc->asclen))
  1004. goto error;
  1005. txtdesc->ascdata[txtdesc->asclen - 1] = '\0';
  1006. if (jas_iccgetuint32(in, &txtdesc->uclangcode) ||
  1007. jas_iccgetuint32(in, &txtdesc->uclen))
  1008. goto error;
  1009. if (!(txtdesc->ucdata = jas_alloc2(txtdesc->uclen, 2)))
  1010. goto error;
  1011. if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) !=
  1012. JAS_CAST(int, txtdesc->uclen * 2))
  1013. goto error;
  1014. if (jas_iccgetuint16(in, &txtdesc->sccode))
  1015. goto error;
  1016. if ((c = jas_stream_getc(in)) == EOF)
  1017. goto error;
  1018. txtdesc->maclen = c;
  1019. if (jas_stream_read(in, txtdesc->macdata, 67) != 67)
  1020. goto error;
  1021. txtdesc->asclen = strlen(txtdesc->ascdata) + 1;
  1022. #define WORKAROUND_BAD_PROFILES
  1023. #ifdef WORKAROUND_BAD_PROFILES
  1024. n = txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67;
  1025. if (n > cnt) {
  1026. return -1;
  1027. }
  1028. if (n < cnt) {
  1029. if (jas_stream_gobble(in, cnt - n) != cnt - n)
  1030. goto error;
  1031. }
  1032. #else
  1033. if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt)
  1034. return -1;
  1035. #endif
  1036. return 0;
  1037. error:
  1038. jas_icctxtdesc_destroy(attrval);
  1039. return -1;
  1040. }
  1041. static int jas_icctxtdesc_getsize(jas_iccattrval_t *attrval)
  1042. {
  1043. jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
  1044. return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67;
  1045. }
  1046. static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out)
  1047. {
  1048. jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
  1049. if (jas_iccputuint32(out, txtdesc->asclen) ||
  1050. jas_stream_puts(out, txtdesc->ascdata) ||
  1051. jas_stream_putc(out, 0) == EOF ||
  1052. jas_iccputuint32(out, txtdesc->uclangcode) ||
  1053. jas_iccputuint32(out, txtdesc->uclen) ||
  1054. jas_stream_write(out, txtdesc->ucdata, txtdesc->uclen * 2) != JAS_CAST(int, txtdesc->uclen * 2) ||
  1055. jas_iccputuint16(out, txtdesc->sccode) ||
  1056. jas_stream_putc(out, txtdesc->maclen) == EOF)
  1057. goto error;
  1058. if (txtdesc->maclen > 0) {
  1059. if (jas_stream_write(out, txtdesc->macdata, 67) != 67)
  1060. goto error;
  1061. } else {
  1062. if (jas_stream_pad(out, 67, 0) != 67)
  1063. goto error;
  1064. }
  1065. return 0;
  1066. error:
  1067. return -1;
  1068. }
  1069. static void jas_icctxtdesc_dump(jas_iccattrval_t *attrval, FILE *out)
  1070. {
  1071. jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc;
  1072. fprintf(out, "ascii = \"%s\"\n", txtdesc->ascdata);
  1073. fprintf(out, "uclangcode = %d; uclen = %d\n", (int)txtdesc->uclangcode,
  1074. (int)txtdesc->uclen);
  1075. fprintf(out, "sccode = %d\n", (int)txtdesc->sccode);
  1076. fprintf(out, "maclen = %d\n", txtdesc->maclen);
  1077. }
  1078. /******************************************************************************\
  1079. *
  1080. \******************************************************************************/
  1081. static void jas_icctxt_destroy(jas_iccattrval_t *attrval)
  1082. {
  1083. jas_icctxt_t *txt = &attrval->data.txt;
  1084. if (txt->string)
  1085. jas_free(txt->string);
  1086. }
  1087. static int jas_icctxt_copy(jas_iccattrval_t *attrval,
  1088. jas_iccattrval_t *othattrval)
  1089. {
  1090. jas_icctxt_t *txt = &attrval->data.txt;
  1091. jas_icctxt_t *othtxt = &othattrval->data.txt;
  1092. if (!(txt->string = jas_strdup(othtxt->string)))
  1093. return -1;
  1094. return 0;
  1095. }
  1096. static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  1097. int cnt)
  1098. {
  1099. jas_icctxt_t *txt = &attrval->data.txt;
  1100. txt->string = 0;
  1101. if (!(txt->string = jas_malloc(cnt)))
  1102. goto error;
  1103. if (jas_stream_read(in, txt->string, cnt) != cnt)
  1104. goto error;
  1105. txt->string[cnt - 1] = '\0';
  1106. if (JAS_CAST(int, strlen(txt->string)) + 1 != cnt)
  1107. goto error;
  1108. return 0;
  1109. error:
  1110. if (txt->string)
  1111. jas_free(txt->string);
  1112. return -1;
  1113. }
  1114. static int jas_icctxt_getsize(jas_iccattrval_t *attrval)
  1115. {
  1116. jas_icctxt_t *txt = &attrval->data.txt;
  1117. return strlen(txt->string) + 1;
  1118. }
  1119. static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out)
  1120. {
  1121. jas_icctxt_t *txt = &attrval->data.txt;
  1122. if (jas_stream_puts(out, txt->string) ||
  1123. jas_stream_putc(out, 0) == EOF)
  1124. return -1;
  1125. return 0;
  1126. }
  1127. static void jas_icctxt_dump(jas_iccattrval_t *attrval, FILE *out)
  1128. {
  1129. jas_icctxt_t *txt = &attrval->data.txt;
  1130. fprintf(out, "string = \"%s\"\n", txt->string);
  1131. }
  1132. /******************************************************************************\
  1133. *
  1134. \******************************************************************************/
  1135. static void jas_icclut8_destroy(jas_iccattrval_t *attrval)
  1136. {
  1137. jas_icclut8_t *lut8 = &attrval->data.lut8;
  1138. if (lut8->clut)
  1139. jas_free(lut8->clut);
  1140. if (lut8->intabs)
  1141. jas_free(lut8->intabs);
  1142. if (lut8->intabsbuf)
  1143. jas_free(lut8->intabsbuf);
  1144. if (lut8->outtabs)
  1145. jas_free(lut8->outtabs);
  1146. if (lut8->outtabsbuf)
  1147. jas_free(lut8->outtabsbuf);
  1148. }
  1149. static int jas_icclut8_copy(jas_iccattrval_t *attrval,
  1150. jas_iccattrval_t *othattrval)
  1151. {
  1152. jas_icclut8_t *lut8 = &attrval->data.lut8;
  1153. /* Avoid compiler warnings about unused parameters. */
  1154. attrval = 0;
  1155. othattrval = 0;
  1156. lut8 = 0;
  1157. abort();
  1158. return -1;
  1159. }
  1160. static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  1161. int cnt)
  1162. {
  1163. int i;
  1164. int j;
  1165. int clutsize;
  1166. jas_icclut8_t *lut8 = &attrval->data.lut8;
  1167. lut8->clut = 0;
  1168. lut8->intabs = 0;
  1169. lut8->intabsbuf = 0;
  1170. lut8->outtabs = 0;
  1171. lut8->outtabsbuf = 0;
  1172. if (jas_iccgetuint8(in, &lut8->numinchans) ||
  1173. jas_iccgetuint8(in, &lut8->numoutchans) ||
  1174. jas_iccgetuint8(in, &lut8->clutlen) ||
  1175. jas_stream_getc(in) == EOF)
  1176. goto error;
  1177. for (i = 0; i < 3; ++i) {
  1178. for (j = 0; j < 3; ++j) {
  1179. if (jas_iccgetsint32(in, &lut8->e[i][j]))
  1180. goto error;
  1181. }
  1182. }
  1183. if (jas_iccgetuint16(in, &lut8->numintabents) ||
  1184. jas_iccgetuint16(in, &lut8->numouttabents))
  1185. goto error;
  1186. clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
  1187. if (!(lut8->clut = jas_alloc2(clutsize, sizeof(jas_iccuint8_t))) ||
  1188. !(lut8->intabsbuf = jas_alloc3(lut8->numinchans,
  1189. lut8->numintabents, sizeof(jas_iccuint8_t))) ||
  1190. !(lut8->intabs = jas_alloc2(lut8->numinchans,
  1191. sizeof(jas_iccuint8_t *))))
  1192. goto error;
  1193. for (i = 0; i < lut8->numinchans; ++i)
  1194. lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents];
  1195. if (!(lut8->outtabsbuf = jas_alloc3(lut8->numoutchans,
  1196. lut8->numouttabents, sizeof(jas_iccuint8_t))) ||
  1197. !(lut8->outtabs = jas_alloc2(lut8->numoutchans,
  1198. sizeof(jas_iccuint8_t *))))
  1199. goto error;
  1200. for (i = 0; i < lut8->numoutchans; ++i)
  1201. lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents];
  1202. for (i = 0; i < lut8->numinchans; ++i) {
  1203. for (j = 0; j < JAS_CAST(int, lut8->numintabents); ++j) {
  1204. if (jas_iccgetuint8(in, &lut8->intabs[i][j]))
  1205. goto error;
  1206. }
  1207. }
  1208. for (i = 0; i < lut8->numoutchans; ++i) {
  1209. for (j = 0; j < JAS_CAST(int, lut8->numouttabents); ++j) {
  1210. if (jas_iccgetuint8(in, &lut8->outtabs[i][j]))
  1211. goto error;
  1212. }
  1213. }
  1214. for (i = 0; i < clutsize; ++i) {
  1215. if (jas_iccgetuint8(in, &lut8->clut[i]))
  1216. goto error;
  1217. }
  1218. if (JAS_CAST(int, 44 + lut8->numinchans * lut8->numintabents +
  1219. lut8->numoutchans * lut8->numouttabents +
  1220. jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans) !=
  1221. cnt)
  1222. goto error;
  1223. return 0;
  1224. error:
  1225. jas_icclut8_destroy(attrval);
  1226. return -1;
  1227. }
  1228. static int jas_icclut8_getsize(jas_iccattrval_t *attrval)
  1229. {
  1230. jas_icclut8_t *lut8 = &attrval->data.lut8;
  1231. return 44 + lut8->numinchans * lut8->numintabents +
  1232. lut8->numoutchans * lut8->numouttabents +
  1233. jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
  1234. }
  1235. static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out)
  1236. {
  1237. jas_icclut8_t *lut8 = &attrval->data.lut8;
  1238. int i;
  1239. int j;
  1240. int n;
  1241. lut8->clut = 0;
  1242. lut8->intabs = 0;
  1243. lut8->intabsbuf = 0;
  1244. lut8->outtabs = 0;
  1245. lut8->outtabsbuf = 0;
  1246. if (jas_stream_putc(out, lut8->numinchans) == EOF ||
  1247. jas_stream_putc(out, lut8->numoutchans) == EOF ||
  1248. jas_stream_putc(out, lut8->clutlen) == EOF ||
  1249. jas_stream_putc(out, 0) == EOF)
  1250. goto error;
  1251. for (i = 0; i < 3; ++i) {
  1252. for (j = 0; j < 3; ++j) {
  1253. if (jas_iccputsint32(out, lut8->e[i][j]))
  1254. goto error;
  1255. }
  1256. }
  1257. if (jas_iccputuint16(out, lut8->numintabents) ||
  1258. jas_iccputuint16(out, lut8->numouttabents))
  1259. goto error;
  1260. n = lut8->numinchans * lut8->numintabents;
  1261. for (i = 0; i < n; ++i) {
  1262. if (jas_iccputuint8(out, lut8->intabsbuf[i]))
  1263. goto error;
  1264. }
  1265. n = lut8->numoutchans * lut8->numouttabents;
  1266. for (i = 0; i < n; ++i) {
  1267. if (jas_iccputuint8(out, lut8->outtabsbuf[i]))
  1268. goto error;
  1269. }
  1270. n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans;
  1271. for (i = 0; i < n; ++i) {
  1272. if (jas_iccputuint8(out, lut8->clut[i]))
  1273. goto error;
  1274. }
  1275. return 0;
  1276. error:
  1277. return -1;
  1278. }
  1279. static void jas_icclut8_dump(jas_iccattrval_t *attrval, FILE *out)
  1280. {
  1281. jas_icclut8_t *lut8 = &attrval->data.lut8;
  1282. int i;
  1283. int j;
  1284. fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n",
  1285. lut8->numinchans, lut8->numoutchans, lut8->clutlen);
  1286. for (i = 0; i < 3; ++i) {
  1287. for (j = 0; j < 3; ++j) {
  1288. fprintf(out, "e[%d][%d]=%f ", i, j, lut8->e[i][j] / 65536.0);
  1289. }
  1290. fprintf(out, "\n");
  1291. }
  1292. fprintf(out, "numintabents=%d, numouttabents=%d\n",
  1293. (int)lut8->numintabents, (int)lut8->numouttabents);
  1294. }
  1295. /******************************************************************************\
  1296. *
  1297. \******************************************************************************/
  1298. static void jas_icclut16_destroy(jas_iccattrval_t *attrval)
  1299. {
  1300. jas_icclut16_t *lut16 = &attrval->data.lut16;
  1301. if (lut16->clut)
  1302. jas_free(lut16->clut);
  1303. if (lut16->intabs)
  1304. jas_free(lut16->intabs);
  1305. if (lut16->intabsbuf)
  1306. jas_free(lut16->intabsbuf);
  1307. if (lut16->outtabs)
  1308. jas_free(lut16->outtabs);
  1309. if (lut16->outtabsbuf)
  1310. jas_free(lut16->outtabsbuf);
  1311. }
  1312. static int jas_icclut16_copy(jas_iccattrval_t *attrval,
  1313. jas_iccattrval_t *othattrval)
  1314. {
  1315. /* Avoid compiler warnings about unused parameters. */
  1316. attrval = 0;
  1317. othattrval = 0;
  1318. /* Not yet implemented. */
  1319. abort();
  1320. return -1;
  1321. }
  1322. static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in,
  1323. int cnt)
  1324. {
  1325. int i;
  1326. int j;
  1327. int clutsize;
  1328. jas_icclut16_t *lut16 = &attrval->data.lut16;
  1329. lut16->clut = 0;
  1330. lut16->intabs = 0;
  1331. lut16->intabsbuf = 0;
  1332. lut16->outtabs = 0;
  1333. lut16->outtabsbuf = 0;
  1334. if (jas_iccgetuint8(in, &lut16->numinchans) ||
  1335. jas_iccgetuint8(in, &lut16->numoutchans) ||
  1336. jas_iccgetuint8(in, &lut16->clutlen) ||
  1337. jas_stream_getc(in) == EOF)
  1338. goto error;
  1339. for (i = 0; i < 3; ++i) {
  1340. for (j = 0; j < 3; ++j) {
  1341. if (jas_iccgetsint32(in, &lut16->e[i][j]))
  1342. goto error;
  1343. }
  1344. }
  1345. if (jas_iccgetuint16(in, &lut16->numintabents) ||
  1346. jas_iccgetuint16(in, &lut16->numouttabents))
  1347. goto error;
  1348. clutsize = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans;
  1349. if (!(lut16->clut = jas_alloc2(clutsize, sizeof(jas_iccuint16_t))) ||
  1350. !(lut16->intabsbuf = jas_alloc3(lut16->numinchans,
  1351. lut16->numintabents, sizeof(jas_iccuint16_t))) ||
  1352. !(lut16->intabs = jas_alloc2(lut16->numinchans,
  1353. sizeof(jas_iccuint16_t *))))
  1354. goto error;
  1355. for (i = 0; i < lut16->numinchans; ++i)
  1356. lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents];
  1357. if (!(lut16->outtabsbuf = jas_alloc3(lut16->numoutchans,
  1358. lut16->numouttabents, sizeof(jas_iccuint16_t))) ||
  1359. !(lut16->outtabs = jas_alloc2(lut16->numoutchans,
  1360. sizeof(jas_iccuint16_t *))))
  1361. goto error;
  1362. for (i = 0; i < lut16->numoutchans; ++i)
  1363. lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents];
  1364. for (i = 0; i < lut16->numinchans; ++i) {
  1365. for (j = 0; j < JAS_CAST(int, lut16->numintabents); ++j) {
  1366. if (jas_iccgetuint16(in, &lut16->intabs[i][j]))
  1367. goto error;
  1368. }
  1369. }
  1370. for (i = 0; i < lut16->numoutchans; ++i) {
  1371. for (j = 0; j < JAS_CAST(int, lut16->numouttabents); ++j) {
  1372. if (jas_iccgetuint16(in, &lut16->outtabs[i][j]))
  1373. goto error;
  1374. }
  1375. }
  1376. for (i = 0; i < clutsize; ++i) {
  1377. if (jas_iccgetuint16(in, &lut16->clut[i]))
  1378. goto error;
  1379. }
  1380. if (JAS_CAST(int, 44 + 2 * (lut16->numinchans * lut16->numintabents +
  1381. lut16->numoutchans * lut16->numouttabents +
  1382. jas_iccpowi(lut16->clutlen, lut16->numinchans) *
  1383. lut16->numoutchans)) != cnt)
  1384. goto error;
  1385. return 0;
  1386. error:
  1387. jas_icclut16_destroy(attrval);
  1388. return -1;
  1389. }
  1390. static int jas_icclut16_getsize(jas_iccattrval_t *attrval)
  1391. {
  1392. jas_icclut16_t *lut16 = &attrval->data.lut16;
  1393. return 44 + 2 * (lut16->numinchans * lut16->numintabents +
  1394. lut16->numoutchans * lut16->numouttabents +
  1395. jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans);
  1396. }
  1397. static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out)
  1398. {
  1399. jas_icclut16_t *lut16 = &attrval->data.lut16;
  1400. int i;
  1401. int j;
  1402. int n;
  1403. if (jas_stream_putc(out, lut16->numinchans) == EOF ||
  1404. jas_stream_putc(out, lut16->numoutchans) == EOF ||
  1405. jas_stream_putc(out, lut16->clutlen) == EOF ||
  1406. jas_stream_putc(out, 0) == EOF)
  1407. goto error;
  1408. for (i = 0; i < 3; ++i) {
  1409. for (j = 0; j < 3; ++j) {
  1410. if (jas_iccputsint32(out, lut16->e[i][j]))
  1411. goto error;
  1412. }
  1413. }
  1414. if (jas_iccputuint16(out, lut16->numintabents) ||
  1415. jas_iccputuint16(out, lut16->numouttabents))
  1416. goto error;
  1417. n = lut16->numinchans * lut16->numintabents;
  1418. for (i = 0; i < n; ++i) {
  1419. if (jas_iccputuint16(out, lut16->intabsbuf[i]))
  1420. goto error;
  1421. }
  1422. n = lut16->numoutchans * lut16->numouttabents;
  1423. for (i = 0; i < n; ++i) {
  1424. if (jas_iccputuint16(out, lut16->outtabsbuf[i]))
  1425. goto error;
  1426. }
  1427. n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans;
  1428. for (i = 0; i < n; ++i) {
  1429. if (jas_iccputuint16(out, lut16->clut[i]))
  1430. goto error;
  1431. }
  1432. return 0;
  1433. error:
  1434. return -1;
  1435. }
  1436. static void jas_icclut16_dump(jas_iccattrval_t *attrval, FILE *out)
  1437. {
  1438. jas_icclut16_t *lut16 = &attrval->data.lut16;
  1439. int i;
  1440. int j;
  1441. fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n",
  1442. lut16->numinchans, lut16->numoutchans, lut16->clutlen);
  1443. for (i = 0; i < 3; ++i) {
  1444. for (j = 0; j < 3; ++j) {
  1445. fprintf(out, "e[%d][%d]=%f ", i, j, lut16->e[i][j] / 65536.0);
  1446. }
  1447. fprintf(out, "\n");
  1448. }
  1449. fprintf(out, "numintabents=%d, numouttabents=%d\n",
  1450. (int)lut16->numintabents, (int)lut16->numouttabents);
  1451. }
  1452. /******************************************************************************\
  1453. *
  1454. \******************************************************************************/
  1455. static int jas_iccgetuint(jas_stream_t *in, int n, ulonglong *val)
  1456. {
  1457. int i;
  1458. int c;
  1459. ulonglong v;
  1460. v = 0;
  1461. for (i = n; i > 0; --i) {
  1462. if ((c = jas_stream_getc(in)) == EOF)
  1463. return -1;
  1464. v = (v << 8) | c;
  1465. }
  1466. *val = v;
  1467. return 0;
  1468. }
  1469. static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val)
  1470. {
  1471. int c;
  1472. if ((c = jas_stream_getc(in)) == EOF)
  1473. return -1;
  1474. *val = c;
  1475. return 0;
  1476. }
  1477. static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val)
  1478. {
  1479. ulonglong tmp;
  1480. if (jas_iccgetuint(in, 2, &tmp))
  1481. return -1;
  1482. *val = tmp;
  1483. return 0;
  1484. }
  1485. static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val)
  1486. {
  1487. ulonglong tmp;
  1488. if (jas_iccgetuint(in, 4, &tmp))
  1489. return -1;
  1490. *val = (tmp & 0x80000000) ? (-JAS_CAST(longlong, (((~tmp) &
  1491. 0x7fffffff) + 1))) : JAS_CAST(longlong, tmp);
  1492. return 0;
  1493. }
  1494. static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val)
  1495. {
  1496. ulonglong tmp;
  1497. if (jas_iccgetuint(in, 4, &tmp))
  1498. return -1;
  1499. *val = tmp;
  1500. return 0;
  1501. }
  1502. static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val)
  1503. {
  1504. ulonglong tmp;
  1505. if (jas_iccgetuint(in, 8, &tmp))
  1506. return -1;
  1507. *val = tmp;
  1508. return 0;
  1509. }
  1510. static int jas_iccputuint(jas_stream_t *out, int n, ulonglong val)
  1511. {
  1512. int i;
  1513. int c;
  1514. for (i = n; i > 0; --i) {
  1515. c = (val >> (8 * (i - 1))) & 0xff;
  1516. if (jas_stream_putc(out, c) == EOF)
  1517. return -1;
  1518. }
  1519. return 0;
  1520. }
  1521. static int jas_iccputsint(jas_stream_t *out, int n, longlong val)
  1522. {
  1523. ulonglong tmp;
  1524. tmp = (val < 0) ? (abort(), 0) : val;
  1525. return jas_iccputuint(out, n, tmp);
  1526. }
  1527. /******************************************************************************\
  1528. *
  1529. \******************************************************************************/
  1530. static char *jas_iccsigtostr(int sig, char *buf)
  1531. {
  1532. int n;
  1533. int c;
  1534. char *bufptr;
  1535. bufptr = buf;
  1536. for (n = 4; n > 0; --n) {
  1537. c = (sig >> 24) & 0xff;
  1538. if (isalpha(c) || isdigit(c)) {
  1539. *bufptr++ = c;
  1540. }
  1541. sig <<= 8;
  1542. }
  1543. *bufptr = '\0';
  1544. return buf;
  1545. }
  1546. static long jas_iccpadtomult(long x, long y)
  1547. {
  1548. return ((x + y - 1) / y) * y;
  1549. }
  1550. static long jas_iccpowi(int x, int n)
  1551. {
  1552. long y;
  1553. y = 1;
  1554. while (--n >= 0)
  1555. y *= x;
  1556. return y;
  1557. }
  1558. jas_iccprof_t *jas_iccprof_createfrombuf(uchar *buf, int len)
  1559. {
  1560. jas_stream_t *in;
  1561. jas_iccprof_t *prof;
  1562. if (!(in = jas_stream_memopen(JAS_CAST(char *, buf), len)))
  1563. goto error;
  1564. if (!(prof = jas_iccprof_load(in)))
  1565. goto error;
  1566. jas_stream_close(in);
  1567. return prof;
  1568. error:
  1569. return 0;
  1570. }
  1571. jas_iccprof_t *jas_iccprof_createfromclrspc(int clrspc)
  1572. {
  1573. jas_iccprof_t *prof;
  1574. switch (clrspc) {
  1575. case JAS_CLRSPC_SRGB:
  1576. prof = jas_iccprof_createfrombuf(jas_iccprofdata_srgb,
  1577. jas_iccprofdata_srgblen);
  1578. break;
  1579. case JAS_CLRSPC_SGRAY:
  1580. prof = jas_iccprof_createfrombuf(jas_iccprofdata_sgray,
  1581. jas_iccprofdata_sgraylen);
  1582. break;
  1583. default:
  1584. prof = 0;
  1585. break;
  1586. }
  1587. return prof;
  1588. }