jas_cm.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  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. /*
  61. * Color Management
  62. *
  63. * $Id: jas_cm.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
  64. */
  65. #include <jasper/jas_config.h>
  66. #include <math.h>
  67. #include <stdlib.h>
  68. #include <assert.h>
  69. #include <jasper/jas_cm.h>
  70. #include <jasper/jas_icc.h>
  71. #include <jasper/jas_init.h>
  72. #include <jasper/jas_stream.h>
  73. #include <jasper/jas_malloc.h>
  74. #include <jasper/jas_math.h>
  75. static jas_cmprof_t *jas_cmprof_create(void);
  76. static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *);
  77. static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x);
  78. static void jas_cmpxform_destroy(jas_cmpxform_t *pxform);
  79. static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform);
  80. static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform);
  81. static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in,
  82. jas_cmreal_t *out, int cnt);
  83. static int jas_cmputint(long **bufptr, int sgnd, int prec, long val);
  84. static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val);
  85. static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq,
  86. jas_cmpxformseq_t *othpxformseq);
  87. static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
  88. int, int);
  89. static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n);
  90. static int mono(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **pxformseq);
  91. static int triclr(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq);
  92. static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq);
  93. static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i);
  94. static jas_cmpxformseq_t *jas_cmpxformseq_create(void);
  95. static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq);
  96. static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]);
  97. static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
  98. int i, jas_cmpxform_t *pxform);
  99. #define SEQFWD(intent) (intent)
  100. #define SEQREV(intent) (4 + (intent))
  101. #define SEQSIM(intent) (8 + (intent))
  102. #define SEQGAM 12
  103. #define fwdpxformseq(prof, intent) \
  104. (((prof)->pxformseqs[SEQFWD(intent)]) ? \
  105. ((prof)->pxformseqs[SEQFWD(intent)]) : \
  106. ((prof)->pxformseqs[SEQFWD(0)]))
  107. #define revpxformseq(prof, intent) \
  108. (((prof)->pxformseqs[SEQREV(intent)]) ? \
  109. ((prof)->pxformseqs[SEQREV(intent)]) : \
  110. ((prof)->pxformseqs[SEQREV(0)]))
  111. #define simpxformseq(prof, intent) \
  112. (((prof)->pxformseqs[SEQSIM(intent)]) ? \
  113. ((prof)->pxformseqs[SEQSIM(intent)]) : \
  114. ((prof)->pxformseqs[SEQSIM(0)]))
  115. #define gampxformseq(prof) ((prof)->pxformseqs[SEQGAM])
  116. static int icctoclrspc(int iccclrspc, int refflag);
  117. static jas_cmpxform_t *jas_cmpxform_create0(void);
  118. static jas_cmpxform_t *jas_cmpxform_createshapmat(void);
  119. static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut);
  120. static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv);
  121. static jas_cmpxformops_t shapmat_ops = {jas_cmshapmat_destroy, jas_cmshapmat_apply, 0};
  122. static jas_cmprof_t *jas_cmprof_createsycc(void);
  123. /******************************************************************************\
  124. * Color profile class.
  125. \******************************************************************************/
  126. jas_cmprof_t *jas_cmprof_createfromclrspc(int clrspc)
  127. {
  128. jas_iccprof_t *iccprof;
  129. jas_cmprof_t *prof;
  130. iccprof = 0;
  131. prof = 0;
  132. switch (clrspc) {
  133. case JAS_CLRSPC_SYCBCR:
  134. if (!(prof = jas_cmprof_createsycc()))
  135. goto error;
  136. break;
  137. default:
  138. if (!(iccprof = jas_iccprof_createfromclrspc(clrspc)))
  139. goto error;
  140. if (!(prof = jas_cmprof_createfromiccprof(iccprof)))
  141. goto error;
  142. jas_iccprof_destroy(iccprof);
  143. iccprof = 0;
  144. if (!jas_clrspc_isgeneric(clrspc))
  145. prof->clrspc = clrspc;
  146. break;
  147. }
  148. return prof;
  149. error:
  150. if (iccprof)
  151. jas_iccprof_destroy(iccprof);
  152. return 0;
  153. }
  154. static jas_cmprof_t *jas_cmprof_createsycc()
  155. {
  156. jas_cmprof_t *prof;
  157. jas_cmpxform_t *fwdpxform;
  158. jas_cmpxform_t *revpxform;
  159. jas_cmshapmat_t *fwdshapmat;
  160. jas_cmshapmat_t *revshapmat;
  161. int i;
  162. int j;
  163. if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB)))
  164. goto error;
  165. prof->clrspc = JAS_CLRSPC_SYCBCR;
  166. assert(prof->numchans == 3 && prof->numrefchans == 3);
  167. assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ);
  168. if (!(fwdpxform = jas_cmpxform_createshapmat()))
  169. goto error;
  170. fwdpxform->numinchans = 3;
  171. fwdpxform->numoutchans = 3;
  172. fwdshapmat = &fwdpxform->data.shapmat;
  173. fwdshapmat->mono = 0;
  174. fwdshapmat->order = 0;
  175. fwdshapmat->useluts = 0;
  176. fwdshapmat->usemat = 1;
  177. fwdshapmat->mat[0][0] = 1.0;
  178. fwdshapmat->mat[0][1] = 0.0;
  179. fwdshapmat->mat[0][2] = 1.402;
  180. fwdshapmat->mat[1][0] = 1.0;
  181. fwdshapmat->mat[1][1] = -0.34413;
  182. fwdshapmat->mat[1][2] = -0.71414;
  183. fwdshapmat->mat[2][0] = 1.0;
  184. fwdshapmat->mat[2][1] = 1.772;
  185. fwdshapmat->mat[2][2] = 0.0;
  186. fwdshapmat->mat[0][3] = -0.5 * (1.402);
  187. fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414);
  188. fwdshapmat->mat[2][3] = -0.5 * (1.772);
  189. if (!(revpxform = jas_cmpxform_createshapmat()))
  190. goto error;
  191. revpxform->numinchans = 3;
  192. revpxform->numoutchans = 3;
  193. revshapmat = &revpxform->data.shapmat;
  194. revshapmat->mono = 0;
  195. revshapmat->order = 1;
  196. revshapmat->useluts = 0;
  197. revshapmat->usemat = 1;
  198. jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat);
  199. for (i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) {
  200. j = SEQFWD(i);
  201. if (prof->pxformseqs[j]) {
  202. if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0,
  203. fwdpxform))
  204. goto error;
  205. }
  206. j = SEQREV(i);
  207. if (prof->pxformseqs[j]) {
  208. if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j],
  209. -1, revpxform))
  210. goto error;
  211. }
  212. }
  213. jas_cmpxform_destroy(fwdpxform);
  214. jas_cmpxform_destroy(revpxform);
  215. return prof;
  216. error:
  217. return 0;
  218. }
  219. jas_cmprof_t *jas_cmprof_createfromiccprof(jas_iccprof_t *iccprof)
  220. {
  221. jas_cmprof_t *prof;
  222. jas_icchdr_t icchdr;
  223. jas_cmpxformseq_t *fwdpxformseq;
  224. jas_cmpxformseq_t *revpxformseq;
  225. prof = 0;
  226. fwdpxformseq = 0;
  227. revpxformseq = 0;
  228. if (!(prof = jas_cmprof_create()))
  229. goto error;
  230. jas_iccprof_gethdr(iccprof, &icchdr);
  231. if (!(prof->iccprof = jas_iccprof_copy(iccprof)))
  232. goto error;
  233. prof->clrspc = icctoclrspc(icchdr.colorspc, 0);
  234. prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1);
  235. prof->numchans = jas_clrspc_numchans(prof->clrspc);
  236. prof->numrefchans = jas_clrspc_numchans(prof->refclrspc);
  237. if (prof->numchans == 1) {
  238. if (mono(prof->iccprof, 0, &fwdpxformseq))
  239. goto error;
  240. if (mono(prof->iccprof, 1, &revpxformseq))
  241. goto error;
  242. } else if (prof->numchans == 3) {
  243. if (triclr(prof->iccprof, 0, &fwdpxformseq))
  244. goto error;
  245. if (triclr(prof->iccprof, 1, &revpxformseq))
  246. goto error;
  247. }
  248. prof->pxformseqs[SEQFWD(0)] = fwdpxformseq;
  249. prof->pxformseqs[SEQREV(0)] = revpxformseq;
  250. #if 0
  251. if (prof->numchans > 1) {
  252. lut(prof->iccprof, 0, PER, &pxformseq);
  253. pxformseqs_set(prof, SEQFWD(PER), pxformseq);
  254. lut(prof->iccprof, 1, PER, &pxformseq);
  255. pxformseqs_set(prof, SEQREV(PER), pxformseq);
  256. lut(prof->iccprof, 0, CLR, &pxformseq);
  257. pxformseqs_set(prof, SEQREV(CLR), pxformseq);
  258. lut(prof->iccprof, 1, CLR, &pxformseq);
  259. pxformseqs_set(prof, SEQREV(CLR), pxformseq);
  260. lut(prof->iccprof, 0, SAT, &pxformseq);
  261. pxformseqs_set(prof, SEQREV(SAT), pxformseq);
  262. lut(prof->iccprof, 1, SAT, &pxformseq);
  263. pxformseqs_set(prof, SEQREV(SAT), pxformseq);
  264. }
  265. #endif
  266. return prof;
  267. error:
  268. if (fwdpxformseq) {
  269. jas_cmpxformseq_destroy(fwdpxformseq);
  270. }
  271. if (revpxformseq) {
  272. jas_cmpxformseq_destroy(revpxformseq);
  273. }
  274. if (prof) {
  275. jas_cmprof_destroy(prof);
  276. }
  277. return 0;
  278. }
  279. static jas_cmprof_t *jas_cmprof_create()
  280. {
  281. int i;
  282. jas_cmprof_t *prof;
  283. if (!(prof = jas_malloc(sizeof(jas_cmprof_t))))
  284. return 0;
  285. memset(prof, 0, sizeof(jas_cmprof_t));
  286. prof->iccprof = 0;
  287. for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i)
  288. prof->pxformseqs[i] = 0;
  289. return prof;
  290. }
  291. void jas_cmprof_destroy(jas_cmprof_t *prof)
  292. {
  293. int i;
  294. for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
  295. if (prof->pxformseqs[i]) {
  296. jas_cmpxformseq_destroy(prof->pxformseqs[i]);
  297. prof->pxformseqs[i] = 0;
  298. }
  299. }
  300. if (prof->iccprof)
  301. jas_iccprof_destroy(prof->iccprof);
  302. jas_free(prof);
  303. }
  304. jas_cmprof_t *jas_cmprof_copy(jas_cmprof_t *prof)
  305. {
  306. jas_cmprof_t *newprof;
  307. int i;
  308. if (!(newprof = jas_cmprof_create()))
  309. goto error;
  310. newprof->clrspc = prof->clrspc;
  311. newprof->numchans = prof->numchans;
  312. newprof->refclrspc = prof->refclrspc;
  313. newprof->numrefchans = prof->numrefchans;
  314. newprof->iccprof = jas_iccprof_copy(prof->iccprof);
  315. for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) {
  316. if (prof->pxformseqs[i]) {
  317. if (!(newprof->pxformseqs[i] = jas_cmpxformseq_copy(prof->pxformseqs[i])))
  318. goto error;
  319. }
  320. }
  321. return newprof;
  322. error:
  323. return 0;
  324. }
  325. /******************************************************************************\
  326. * Transform class.
  327. \******************************************************************************/
  328. jas_cmxform_t *jas_cmxform_create(jas_cmprof_t *inprof, jas_cmprof_t *outprof,
  329. jas_cmprof_t *prfprof, int op, int intent, int optimize)
  330. {
  331. jas_cmxform_t *xform;
  332. jas_cmpxformseq_t *inpxformseq;
  333. jas_cmpxformseq_t *outpxformseq;
  334. jas_cmpxformseq_t *altoutpxformseq;
  335. jas_cmpxformseq_t *prfpxformseq;
  336. int prfintent;
  337. /* Avoid compiler warnings about unused parameters. */
  338. optimize = 0;
  339. prfintent = intent;
  340. if (!(xform = jas_malloc(sizeof(jas_cmxform_t))))
  341. goto error;
  342. if (!(xform->pxformseq = jas_cmpxformseq_create()))
  343. goto error;
  344. switch (op) {
  345. case JAS_CMXFORM_OP_FWD:
  346. inpxformseq = fwdpxformseq(inprof, intent);
  347. outpxformseq = revpxformseq(outprof, intent);
  348. if (!inpxformseq || !outpxformseq)
  349. goto error;
  350. if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
  351. jas_cmpxformseq_appendcnvt(xform->pxformseq,
  352. inprof->refclrspc, outprof->refclrspc) ||
  353. jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
  354. goto error;
  355. xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
  356. xform->numoutchans = jas_clrspc_numchans(outprof->clrspc);
  357. break;
  358. case JAS_CMXFORM_OP_REV:
  359. outpxformseq = fwdpxformseq(outprof, intent);
  360. inpxformseq = revpxformseq(inprof, intent);
  361. if (!outpxformseq || !inpxformseq)
  362. goto error;
  363. if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
  364. jas_cmpxformseq_appendcnvt(xform->pxformseq,
  365. outprof->refclrspc, inprof->refclrspc) ||
  366. jas_cmpxformseq_append(xform->pxformseq, inpxformseq))
  367. goto error;
  368. xform->numinchans = jas_clrspc_numchans(outprof->clrspc);
  369. xform->numoutchans = jas_clrspc_numchans(inprof->clrspc);
  370. break;
  371. case JAS_CMXFORM_OP_PROOF:
  372. assert(prfprof);
  373. inpxformseq = fwdpxformseq(inprof, intent);
  374. prfpxformseq = fwdpxformseq(prfprof, prfintent);
  375. if (!inpxformseq || !prfpxformseq)
  376. goto error;
  377. outpxformseq = simpxformseq(outprof, intent);
  378. altoutpxformseq = 0;
  379. if (!outpxformseq) {
  380. outpxformseq = revpxformseq(outprof, intent);
  381. altoutpxformseq = fwdpxformseq(outprof, intent);
  382. if (!outpxformseq || !altoutpxformseq)
  383. goto error;
  384. }
  385. if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
  386. jas_cmpxformseq_appendcnvt(xform->pxformseq,
  387. inprof->refclrspc, outprof->refclrspc))
  388. goto error;
  389. if (altoutpxformseq) {
  390. if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
  391. jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq))
  392. goto error;
  393. } else {
  394. if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
  395. goto error;
  396. }
  397. if (jas_cmpxformseq_appendcnvt(xform->pxformseq,
  398. outprof->refclrspc, inprof->refclrspc) ||
  399. jas_cmpxformseq_append(xform->pxformseq, prfpxformseq))
  400. goto error;
  401. xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
  402. xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc);
  403. break;
  404. case JAS_CMXFORM_OP_GAMUT:
  405. inpxformseq = fwdpxformseq(inprof, intent);
  406. outpxformseq = gampxformseq(outprof);
  407. if (!inpxformseq || !outpxformseq)
  408. goto error;
  409. if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
  410. jas_cmpxformseq_appendcnvt(xform->pxformseq,
  411. inprof->refclrspc, outprof->refclrspc) ||
  412. jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
  413. goto error;
  414. xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
  415. xform->numoutchans = 1;
  416. break;
  417. }
  418. return xform;
  419. error:
  420. return 0;
  421. }
  422. #define APPLYBUFSIZ 2048
  423. int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out)
  424. {
  425. jas_cmcmptfmt_t *fmt;
  426. jas_cmreal_t buf[2][APPLYBUFSIZ];
  427. jas_cmpxformseq_t *pxformseq;
  428. int i;
  429. int j;
  430. int width;
  431. int height;
  432. int total;
  433. int n;
  434. jas_cmreal_t *inbuf;
  435. jas_cmreal_t *outbuf;
  436. jas_cmpxform_t *pxform;
  437. long *dataptr;
  438. int maxchans;
  439. int bufmax;
  440. int m;
  441. int bias;
  442. jas_cmreal_t scale;
  443. long v;
  444. jas_cmreal_t *bufptr;
  445. if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts)
  446. goto error;
  447. fmt = &in->cmptfmts[0];
  448. width = fmt->width;
  449. height = fmt->height;
  450. for (i = 1; i < xform->numinchans; ++i) {
  451. fmt = &in->cmptfmts[i];
  452. if (fmt->width != width || fmt->height != height) {
  453. goto error;
  454. }
  455. }
  456. for (i = 0; i < xform->numoutchans; ++i) {
  457. fmt = &out->cmptfmts[i];
  458. if (fmt->width != width || fmt->height != height) {
  459. goto error;
  460. }
  461. }
  462. maxchans = 0;
  463. pxformseq = xform->pxformseq;
  464. for (i = 0; i < pxformseq->numpxforms; ++i) {
  465. pxform = pxformseq->pxforms[i];
  466. if (pxform->numinchans > maxchans) {
  467. maxchans = pxform->numinchans;
  468. }
  469. if (pxform->numoutchans > maxchans) {
  470. maxchans = pxform->numoutchans;
  471. }
  472. }
  473. bufmax = APPLYBUFSIZ / maxchans;
  474. assert(bufmax > 0);
  475. total = width * height;
  476. n = 0;
  477. while (n < total) {
  478. inbuf = &buf[0][0];
  479. m = JAS_MIN(total - n, bufmax);
  480. for (i = 0; i < xform->numinchans; ++i) {
  481. fmt = &in->cmptfmts[i];
  482. scale = (double)((1 << fmt->prec) - 1);
  483. bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
  484. dataptr = &fmt->buf[n];
  485. bufptr = &inbuf[i];
  486. for (j = 0; j < m; ++j) {
  487. if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v))
  488. goto error;
  489. *bufptr = (v - bias) / scale;
  490. bufptr += xform->numinchans;
  491. }
  492. }
  493. inbuf = &buf[0][0];
  494. outbuf = inbuf;
  495. for (i = 0; i < pxformseq->numpxforms; ++i) {
  496. pxform = pxformseq->pxforms[i];
  497. if (pxform->numoutchans > pxform->numinchans) {
  498. outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0];
  499. } else {
  500. outbuf = inbuf;
  501. }
  502. if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m))
  503. goto error;
  504. inbuf = outbuf;
  505. }
  506. for (i = 0; i < xform->numoutchans; ++i) {
  507. fmt = &out->cmptfmts[i];
  508. scale = (double)((1 << fmt->prec) - 1);
  509. bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
  510. bufptr = &outbuf[i];
  511. dataptr = &fmt->buf[n];
  512. for (j = 0; j < m; ++j) {
  513. v = (*bufptr) * scale + bias;
  514. bufptr += xform->numoutchans;
  515. if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v))
  516. goto error;
  517. }
  518. }
  519. n += m;
  520. }
  521. return 0;
  522. error:
  523. return -1;
  524. }
  525. void jas_cmxform_destroy(jas_cmxform_t *xform)
  526. {
  527. if (xform->pxformseq)
  528. jas_cmpxformseq_destroy(xform->pxformseq);
  529. jas_free(xform);
  530. }
  531. /******************************************************************************\
  532. * Primitive transform sequence class.
  533. \******************************************************************************/
  534. static jas_cmpxformseq_t *jas_cmpxformseq_create()
  535. {
  536. jas_cmpxformseq_t *pxformseq;
  537. pxformseq = 0;
  538. if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t))))
  539. goto error;
  540. pxformseq->pxforms = 0;
  541. pxformseq->numpxforms = 0;
  542. pxformseq->maxpxforms = 0;
  543. if (jas_cmpxformseq_resize(pxformseq, 16))
  544. goto error;
  545. return pxformseq;
  546. error:
  547. if (pxformseq)
  548. jas_cmpxformseq_destroy(pxformseq);
  549. return 0;
  550. }
  551. static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq)
  552. {
  553. jas_cmpxformseq_t *newpxformseq;
  554. if (!(newpxformseq = jas_cmpxformseq_create()))
  555. goto error;
  556. if (jas_cmpxformseq_append(newpxformseq, pxformseq))
  557. goto error;
  558. return newpxformseq;
  559. error:
  560. return 0;
  561. }
  562. static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq)
  563. {
  564. while (pxformseq->numpxforms > 0)
  565. jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1);
  566. if (pxformseq->pxforms)
  567. jas_free(pxformseq->pxforms);
  568. jas_free(pxformseq);
  569. }
  570. static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i)
  571. {
  572. assert(i >= 0 && i < pxformseq->numpxforms);
  573. if (i != pxformseq->numpxforms - 1)
  574. abort();
  575. jas_cmpxform_destroy(pxformseq->pxforms[i]);
  576. pxformseq->pxforms[i] = 0;
  577. --pxformseq->numpxforms;
  578. return 0;
  579. }
  580. static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
  581. int dstclrspc, int srcclrspc)
  582. {
  583. if (dstclrspc == srcclrspc)
  584. return 0;
  585. abort();
  586. /* Avoid compiler warnings about unused parameters. */
  587. pxformseq = 0;
  588. return -1;
  589. }
  590. static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
  591. int i, jas_cmpxform_t *pxform)
  592. {
  593. jas_cmpxform_t *tmppxform;
  594. int n;
  595. if (i < 0)
  596. i = pxformseq->numpxforms;
  597. assert(i >= 0 && i <= pxformseq->numpxforms);
  598. if (pxformseq->numpxforms >= pxformseq->maxpxforms) {
  599. if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms +
  600. 16))
  601. goto error;
  602. }
  603. assert(pxformseq->numpxforms < pxformseq->maxpxforms);
  604. if (!(tmppxform = jas_cmpxform_copy(pxform)))
  605. goto error;
  606. n = pxformseq->numpxforms - i;
  607. if (n > 0) {
  608. memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i],
  609. n * sizeof(jas_cmpxform_t *));
  610. }
  611. pxformseq->pxforms[i] = tmppxform;
  612. ++pxformseq->numpxforms;
  613. return 0;
  614. error:
  615. return -1;
  616. }
  617. static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq,
  618. jas_cmpxformseq_t *othpxformseq)
  619. {
  620. int n;
  621. int i;
  622. jas_cmpxform_t *pxform;
  623. jas_cmpxform_t *othpxform;
  624. n = pxformseq->numpxforms + othpxformseq->numpxforms;
  625. if (n > pxformseq->maxpxforms) {
  626. if (jas_cmpxformseq_resize(pxformseq, n))
  627. goto error;
  628. }
  629. for (i = 0; i < othpxformseq->numpxforms; ++i) {
  630. othpxform = othpxformseq->pxforms[i];
  631. if (!(pxform = jas_cmpxform_copy(othpxform)))
  632. goto error;
  633. pxformseq->pxforms[pxformseq->numpxforms] = pxform;
  634. ++pxformseq->numpxforms;
  635. }
  636. return 0;
  637. error:
  638. return -1;
  639. }
  640. static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n)
  641. {
  642. jas_cmpxform_t **p;
  643. assert(n >= pxformseq->numpxforms);
  644. p = jas_realloc2(pxformseq->pxforms, n, sizeof(jas_cmpxform_t *));
  645. if (!p) {
  646. return -1;
  647. }
  648. pxformseq->pxforms = p;
  649. pxformseq->maxpxforms = n;
  650. return 0;
  651. }
  652. /******************************************************************************\
  653. * Primitive transform class.
  654. \******************************************************************************/
  655. static jas_cmpxform_t *jas_cmpxform_create0()
  656. {
  657. jas_cmpxform_t *pxform;
  658. if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t))))
  659. return 0;
  660. memset(pxform, 0, sizeof(jas_cmpxform_t));
  661. pxform->refcnt = 0;
  662. pxform->ops = 0;
  663. return pxform;
  664. }
  665. static void jas_cmpxform_destroy(jas_cmpxform_t *pxform)
  666. {
  667. if (--pxform->refcnt <= 0) {
  668. (*pxform->ops->destroy)(pxform);
  669. jas_free(pxform);
  670. }
  671. }
  672. static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform)
  673. {
  674. ++pxform->refcnt;
  675. return pxform;
  676. }
  677. /******************************************************************************\
  678. * Shaper matrix class.
  679. \******************************************************************************/
  680. static jas_cmpxform_t *jas_cmpxform_createshapmat()
  681. {
  682. int i;
  683. int j;
  684. jas_cmpxform_t *pxform;
  685. jas_cmshapmat_t *shapmat;
  686. if (!(pxform = jas_cmpxform_create0()))
  687. return 0;
  688. pxform->ops = &shapmat_ops;
  689. shapmat = &pxform->data.shapmat;
  690. shapmat->mono = 0;
  691. shapmat->order = 0;
  692. shapmat->useluts = 0;
  693. shapmat->usemat = 0;
  694. for (i = 0; i < 3; ++i)
  695. jas_cmshapmatlut_init(&shapmat->luts[i]);
  696. for (i = 0; i < 3; ++i) {
  697. for (j = 0; j < 4; ++j)
  698. shapmat->mat[i][j] = 0.0;
  699. }
  700. ++pxform->refcnt;
  701. return pxform;
  702. }
  703. static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform)
  704. {
  705. jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
  706. int i;
  707. for (i = 0; i < 3; ++i)
  708. jas_cmshapmatlut_cleanup(&shapmat->luts[i]);
  709. }
  710. static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in,
  711. jas_cmreal_t *out, int cnt)
  712. {
  713. jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
  714. jas_cmreal_t *src;
  715. jas_cmreal_t *dst;
  716. jas_cmreal_t a0;
  717. jas_cmreal_t a1;
  718. jas_cmreal_t a2;
  719. jas_cmreal_t b0;
  720. jas_cmreal_t b1;
  721. jas_cmreal_t b2;
  722. src = in;
  723. dst = out;
  724. if (!shapmat->mono) {
  725. while (--cnt >= 0) {
  726. a0 = *src++;
  727. a1 = *src++;
  728. a2 = *src++;
  729. if (!shapmat->order && shapmat->useluts) {
  730. a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
  731. a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
  732. a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
  733. }
  734. if (shapmat->usemat) {
  735. b0 = shapmat->mat[0][0] * a0
  736. + shapmat->mat[0][1] * a1
  737. + shapmat->mat[0][2] * a2
  738. + shapmat->mat[0][3];
  739. b1 = shapmat->mat[1][0] * a0
  740. + shapmat->mat[1][1] * a1
  741. + shapmat->mat[1][2] * a2
  742. + shapmat->mat[1][3];
  743. b2 = shapmat->mat[2][0] * a0
  744. + shapmat->mat[2][1] * a1
  745. + shapmat->mat[2][2] * a2
  746. + shapmat->mat[2][3];
  747. a0 = b0;
  748. a1 = b1;
  749. a2 = b2;
  750. }
  751. if (shapmat->order && shapmat->useluts) {
  752. a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
  753. a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
  754. a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
  755. }
  756. *dst++ = a0;
  757. *dst++ = a1;
  758. *dst++ = a2;
  759. }
  760. } else {
  761. if (!shapmat->order) {
  762. while (--cnt >= 0) {
  763. a0 = *src++;
  764. if (shapmat->useluts)
  765. a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
  766. a2 = a0 * shapmat->mat[2][0];
  767. a1 = a0 * shapmat->mat[1][0];
  768. a0 = a0 * shapmat->mat[0][0];
  769. *dst++ = a0;
  770. *dst++ = a1;
  771. *dst++ = a2;
  772. }
  773. } else {
  774. while (--cnt >= 0) {
  775. a0 = *src++;
  776. src++;
  777. src++;
  778. a0 = a0 * shapmat->mat[0][0];
  779. if (shapmat->useluts)
  780. a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
  781. *dst++ = a0;
  782. }
  783. }
  784. }
  785. return 0;
  786. }
  787. static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut)
  788. {
  789. lut->data = 0;
  790. lut->size = 0;
  791. }
  792. static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut)
  793. {
  794. if (lut->data) {
  795. jas_free(lut->data);
  796. lut->data = 0;
  797. }
  798. lut->size = 0;
  799. }
  800. static double gammafn(double x, double gamma)
  801. {
  802. if (x == 0.0)
  803. return 0.0;
  804. return pow(x, gamma);
  805. }
  806. static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv)
  807. {
  808. jas_cmreal_t gamma;
  809. int i;
  810. gamma = 0;
  811. jas_cmshapmatlut_cleanup(lut);
  812. if (curv->numents == 0) {
  813. lut->size = 2;
  814. if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t))))
  815. goto error;
  816. lut->data[0] = 0.0;
  817. lut->data[1] = 1.0;
  818. } else if (curv->numents == 1) {
  819. lut->size = 256;
  820. if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t))))
  821. goto error;
  822. gamma = curv->ents[0] / 256.0;
  823. for (i = 0; i < lut->size; ++i) {
  824. lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma);
  825. }
  826. } else {
  827. lut->size = curv->numents;
  828. if (!(lut->data = jas_alloc2(lut->size, sizeof(jas_cmreal_t))))
  829. goto error;
  830. for (i = 0; i < lut->size; ++i) {
  831. lut->data[i] = curv->ents[i] / 65535.0;
  832. }
  833. }
  834. return 0;
  835. error:
  836. return -1;
  837. }
  838. static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x)
  839. {
  840. jas_cmreal_t t;
  841. int lo;
  842. int hi;
  843. t = x * (lut->size - 1);
  844. lo = floor(t);
  845. if (lo < 0)
  846. return lut->data[0];
  847. hi = ceil(t);
  848. if (hi >= lut->size)
  849. return lut->data[lut->size - 1];
  850. return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]);
  851. }
  852. static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut,
  853. jas_cmshapmatlut_t *lut, int n)
  854. {
  855. int i;
  856. int j;
  857. int k;
  858. jas_cmreal_t ax;
  859. jas_cmreal_t ay;
  860. jas_cmreal_t bx;
  861. jas_cmreal_t by;
  862. jas_cmreal_t sx;
  863. jas_cmreal_t sy;
  864. assert(n >= 2);
  865. if (invlut->data) {
  866. jas_free(invlut->data);
  867. invlut->data = 0;
  868. }
  869. /* The sample values should be nondecreasing. */
  870. for (i = 1; i < lut->size; ++i) {
  871. if (lut->data[i - 1] > lut->data[i]) {
  872. assert(0);
  873. return -1;
  874. }
  875. }
  876. if (!(invlut->data = jas_alloc2(n, sizeof(jas_cmreal_t))))
  877. return -1;
  878. invlut->size = n;
  879. for (i = 0; i < invlut->size; ++i) {
  880. sy = ((double) i) / (invlut->size - 1);
  881. sx = 1.0;
  882. for (j = 0; j < lut->size; ++j) {
  883. ay = lut->data[j];
  884. if (sy == ay) {
  885. for (k = j + 1; k < lut->size; ++k) {
  886. by = lut->data[k];
  887. if (by != sy)
  888. break;
  889. #if 0
  890. assert(0);
  891. #endif
  892. }
  893. if (k < lut->size) {
  894. --k;
  895. ax = ((double) j) / (lut->size - 1);
  896. bx = ((double) k) / (lut->size - 1);
  897. sx = (ax + bx) / 2.0;
  898. }
  899. break;
  900. }
  901. if (j < lut->size - 1) {
  902. by = lut->data[j + 1];
  903. if (sy > ay && sy < by) {
  904. ax = ((double) j) / (lut->size - 1);
  905. bx = ((double) j + 1) / (lut->size - 1);
  906. sx = ax +
  907. (sy - ay) / (by - ay) * (bx - ax);
  908. break;
  909. }
  910. }
  911. }
  912. invlut->data[i] = sx;
  913. }
  914. #if 0
  915. for (i=0;i<lut->size;++i)
  916. jas_eprintf("lut[%d]=%f ", i, lut->data[i]);
  917. for (i=0;i<invlut->size;++i)
  918. jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]);
  919. #endif
  920. return 0;
  921. }
  922. static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4])
  923. {
  924. jas_cmreal_t d;
  925. d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1])
  926. - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0])
  927. + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
  928. #if 0
  929. jas_eprintf("delta=%f\n", d);
  930. #endif
  931. if (JAS_ABS(d) < 1e-6)
  932. return -1;
  933. out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d;
  934. out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d;
  935. out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d;
  936. out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d;
  937. out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d;
  938. out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d;
  939. out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d;
  940. out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d;
  941. out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d;
  942. out[0][3] = -in[0][3];
  943. out[1][3] = -in[1][3];
  944. out[2][3] = -in[2][3];
  945. #if 0
  946. jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
  947. in[0][0], in[0][1], in[0][2], in[0][3],
  948. in[1][0], in[1][1], in[1][2], in[1][3],
  949. in[2][0], in[2][1], in[2][2], in[2][3]);
  950. jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
  951. out[0][0], out[0][1], out[0][2], out[0][3],
  952. out[1][0], out[1][1], out[1][2], out[1][3],
  953. out[2][0], out[2][1], out[2][2], out[2][3]);
  954. #endif
  955. return 0;
  956. }
  957. /******************************************************************************\
  958. *
  959. \******************************************************************************/
  960. static int icctoclrspc(int iccclrspc, int refflag)
  961. {
  962. if (refflag) {
  963. switch (iccclrspc) {
  964. case JAS_ICC_COLORSPC_XYZ:
  965. return JAS_CLRSPC_CIEXYZ;
  966. case JAS_ICC_COLORSPC_LAB:
  967. return JAS_CLRSPC_CIELAB;
  968. default:
  969. abort();
  970. break;
  971. }
  972. } else {
  973. switch (iccclrspc) {
  974. case JAS_ICC_COLORSPC_YCBCR:
  975. return JAS_CLRSPC_GENYCBCR;
  976. case JAS_ICC_COLORSPC_RGB:
  977. return JAS_CLRSPC_GENRGB;
  978. case JAS_ICC_COLORSPC_GRAY:
  979. return JAS_CLRSPC_GENGRAY;
  980. default:
  981. abort();
  982. break;
  983. }
  984. }
  985. }
  986. static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
  987. {
  988. jas_iccattrval_t *graytrc;
  989. jas_cmshapmat_t *shapmat;
  990. jas_cmpxform_t *pxform;
  991. jas_cmpxformseq_t *pxformseq;
  992. jas_cmshapmatlut_t lut;
  993. jas_cmshapmatlut_init(&lut);
  994. if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) ||
  995. graytrc->type != JAS_ICC_TYPE_CURV)
  996. goto error;
  997. if (!(pxform = jas_cmpxform_createshapmat()))
  998. goto error;
  999. shapmat = &pxform->data.shapmat;
  1000. if (!(pxformseq = jas_cmpxformseq_create()))
  1001. goto error;
  1002. if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
  1003. goto error;
  1004. pxform->numinchans = 1;
  1005. pxform->numoutchans = 3;
  1006. shapmat->mono = 1;
  1007. shapmat->useluts = 1;
  1008. shapmat->usemat = 1;
  1009. if (!op) {
  1010. shapmat->order = 0;
  1011. shapmat->mat[0][0] = 0.9642;
  1012. shapmat->mat[1][0] = 1.0;
  1013. shapmat->mat[2][0] = 0.8249;
  1014. if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv))
  1015. goto error;
  1016. } else {
  1017. shapmat->order = 1;
  1018. shapmat->mat[0][0] = 1.0 / 0.9642;
  1019. shapmat->mat[1][0] = 1.0;
  1020. shapmat->mat[2][0] = 1.0 / 0.8249;
  1021. jas_cmshapmatlut_init(&lut);
  1022. if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv))
  1023. goto error;
  1024. if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size))
  1025. goto error;
  1026. jas_cmshapmatlut_cleanup(&lut);
  1027. }
  1028. jas_iccattrval_destroy(graytrc);
  1029. jas_cmpxform_destroy(pxform);
  1030. *retpxformseq = pxformseq;
  1031. return 0;
  1032. error:
  1033. return -1;
  1034. }
  1035. static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
  1036. {
  1037. int i;
  1038. jas_iccattrval_t *trcs[3];
  1039. jas_iccattrval_t *cols[3];
  1040. jas_cmshapmat_t *shapmat;
  1041. jas_cmpxform_t *pxform;
  1042. jas_cmpxformseq_t *pxformseq;
  1043. jas_cmreal_t mat[3][4];
  1044. jas_cmshapmatlut_t lut;
  1045. pxform = 0;
  1046. pxformseq = 0;
  1047. for (i = 0; i < 3; ++i) {
  1048. trcs[i] = 0;
  1049. cols[i] = 0;
  1050. }
  1051. jas_cmshapmatlut_init(&lut);
  1052. if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) ||
  1053. !(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) ||
  1054. !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) ||
  1055. !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) ||
  1056. !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) ||
  1057. !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL)))
  1058. goto error;
  1059. for (i = 0; i < 3; ++i) {
  1060. if (trcs[i]->type != JAS_ICC_TYPE_CURV ||
  1061. cols[i]->type != JAS_ICC_TYPE_XYZ)
  1062. goto error;
  1063. }
  1064. if (!(pxform = jas_cmpxform_createshapmat()))
  1065. goto error;
  1066. pxform->numinchans = 3;
  1067. pxform->numoutchans = 3;
  1068. shapmat = &pxform->data.shapmat;
  1069. if (!(pxformseq = jas_cmpxformseq_create()))
  1070. goto error;
  1071. if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
  1072. goto error;
  1073. shapmat->mono = 0;
  1074. shapmat->useluts = 1;
  1075. shapmat->usemat = 1;
  1076. if (!op) {
  1077. shapmat->order = 0;
  1078. for (i = 0; i < 3; ++i) {
  1079. shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0;
  1080. shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0;
  1081. shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0;
  1082. }
  1083. for (i = 0; i < 3; ++i)
  1084. shapmat->mat[i][3] = 0.0;
  1085. for (i = 0; i < 3; ++i) {
  1086. if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv))
  1087. goto error;
  1088. }
  1089. } else {
  1090. shapmat->order = 1;
  1091. for (i = 0; i < 3; ++i) {
  1092. mat[0][i] = cols[i]->data.xyz.x / 65536.0;
  1093. mat[1][i] = cols[i]->data.xyz.y / 65536.0;
  1094. mat[2][i] = cols[i]->data.xyz.z / 65536.0;
  1095. }
  1096. for (i = 0; i < 3; ++i)
  1097. mat[i][3] = 0.0;
  1098. if (jas_cmshapmat_invmat(shapmat->mat, mat))
  1099. goto error;
  1100. for (i = 0; i < 3; ++i) {
  1101. jas_cmshapmatlut_init(&lut);
  1102. if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv))
  1103. goto error;
  1104. if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size))
  1105. goto error;
  1106. jas_cmshapmatlut_cleanup(&lut);
  1107. }
  1108. }
  1109. for (i = 0; i < 3; ++i) {
  1110. jas_iccattrval_destroy(trcs[i]);
  1111. jas_iccattrval_destroy(cols[i]);
  1112. }
  1113. jas_cmpxform_destroy(pxform);
  1114. *retpxformseq = pxformseq;
  1115. return 0;
  1116. error:
  1117. for (i = 0; i < 3; ++i) {
  1118. if (trcs[i]) {
  1119. jas_iccattrval_destroy(trcs[i]);
  1120. }
  1121. if (cols[i]) {
  1122. jas_iccattrval_destroy(cols[i]);
  1123. }
  1124. }
  1125. if (pxformseq) {
  1126. jas_cmpxformseq_destroy(pxformseq);
  1127. }
  1128. if (pxform) {
  1129. jas_cmpxform_destroy(pxform);
  1130. }
  1131. return -1;
  1132. }
  1133. static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val)
  1134. {
  1135. long v;
  1136. int m;
  1137. v = **bufptr;
  1138. if (sgnd) {
  1139. m = (1 << (prec - 1));
  1140. if (v < -m || v >= m)
  1141. return -1;
  1142. } else {
  1143. if (v < 0 || v >= (1 << prec))
  1144. return -1;
  1145. }
  1146. ++(*bufptr);
  1147. *val = v;
  1148. return 0;
  1149. }
  1150. static int jas_cmputint(long **bufptr, int sgnd, int prec, long val)
  1151. {
  1152. int m;
  1153. if (sgnd) {
  1154. m = (1 << (prec - 1));
  1155. if (val < -m || val >= m)
  1156. return -1;
  1157. } else {
  1158. if (val < 0 || val >= (1 << prec))
  1159. return -1;
  1160. }
  1161. **bufptr = val;
  1162. ++(*bufptr);
  1163. return 0;
  1164. }
  1165. int jas_clrspc_numchans(int clrspc)
  1166. {
  1167. switch (jas_clrspc_fam(clrspc)) {
  1168. case JAS_CLRSPC_FAM_XYZ:
  1169. case JAS_CLRSPC_FAM_LAB:
  1170. case JAS_CLRSPC_FAM_RGB:
  1171. case JAS_CLRSPC_FAM_YCBCR:
  1172. return 3;
  1173. break;
  1174. case JAS_CLRSPC_FAM_GRAY:
  1175. return 1;
  1176. break;
  1177. default:
  1178. abort();
  1179. break;
  1180. }
  1181. }
  1182. jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof)
  1183. {
  1184. return jas_iccprof_copy(prof->iccprof);
  1185. }