jas_image.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  1. /*
  2. * Copyright (c) 1999-2000 Image Power, Inc. and the University of
  3. * British Columbia.
  4. * Copyright (c) 2001-2003 Michael David Adams.
  5. * All rights reserved.
  6. */
  7. /* __START_OF_JASPER_LICENSE__
  8. *
  9. * JasPer License Version 2.0
  10. *
  11. * Copyright (c) 2001-2006 Michael David Adams
  12. * Copyright (c) 1999-2000 Image Power, Inc.
  13. * Copyright (c) 1999-2000 The University of British Columbia
  14. *
  15. * All rights reserved.
  16. *
  17. * Permission is hereby granted, free of charge, to any person (the
  18. * "User") obtaining a copy of this software and associated documentation
  19. * files (the "Software"), to deal in the Software without restriction,
  20. * including without limitation the rights to use, copy, modify, merge,
  21. * publish, distribute, and/or sell copies of the Software, and to permit
  22. * persons to whom the Software is furnished to do so, subject to the
  23. * following conditions:
  24. *
  25. * 1. The above copyright notices and this permission notice (which
  26. * includes the disclaimer below) shall be included in all copies or
  27. * substantial portions of the Software.
  28. *
  29. * 2. The name of a copyright holder shall not be used to endorse or
  30. * promote products derived from the Software without specific prior
  31. * written permission.
  32. *
  33. * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
  34. * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  35. * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
  36. * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  37. * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  38. * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
  39. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
  40. * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
  41. * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  42. * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  43. * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
  44. * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
  45. * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
  46. * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
  47. * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
  48. * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
  49. * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
  50. * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
  51. * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
  52. * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
  53. * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
  54. * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
  55. * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
  56. * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
  57. * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
  58. * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
  59. *
  60. * __END_OF_JASPER_LICENSE__
  61. */
  62. /*
  63. * Image Library
  64. *
  65. * $Id: jas_image.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
  66. */
  67. /******************************************************************************\
  68. * Includes.
  69. \******************************************************************************/
  70. #include <stdlib.h>
  71. #include <stdio.h>
  72. #include <string.h>
  73. #include <assert.h>
  74. #include <ctype.h>
  75. #include "jasper/jas_math.h"
  76. #include "jasper/jas_image.h"
  77. #include "jasper/jas_malloc.h"
  78. #include "jasper/jas_string.h"
  79. /******************************************************************************\
  80. * Types.
  81. \******************************************************************************/
  82. #define FLOORDIV(x, y) ((x) / (y))
  83. /******************************************************************************\
  84. * Local prototypes.
  85. \******************************************************************************/
  86. static jas_image_cmpt_t *jas_image_cmpt_create0(void);
  87. static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt);
  88. static jas_image_cmpt_t *jas_image_cmpt_create(uint_fast32_t tlx, uint_fast32_t tly,
  89. uint_fast32_t hstep, uint_fast32_t vstep, uint_fast32_t width, uint_fast32_t
  90. height, uint_fast16_t depth, bool sgnd, uint_fast32_t inmem);
  91. static void jas_image_setbbox(jas_image_t *image);
  92. static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt);
  93. static int jas_image_growcmpts(jas_image_t *image, int maxcmpts);
  94. static uint_fast32_t inttobits(jas_seqent_t v, int prec, bool sgnd);
  95. static jas_seqent_t bitstoint(uint_fast32_t v, int prec, bool sgnd);
  96. static int putint(jas_stream_t *out, int sgnd, int prec, long val);
  97. static int getint(jas_stream_t *in, int sgnd, int prec, long *val);
  98. static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
  99. jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry);
  100. static long uptomult(long x, long y);
  101. static long downtomult(long x, long y);
  102. static long convert(long val, int oldsgnd, int oldprec, int newsgnd,
  103. int newprec);
  104. static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
  105. jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry);
  106. /******************************************************************************\
  107. * Global data.
  108. \******************************************************************************/
  109. static int jas_image_numfmts = 0;
  110. static jas_image_fmtinfo_t jas_image_fmtinfos[JAS_IMAGE_MAXFMTS];
  111. /******************************************************************************\
  112. * Create and destroy operations.
  113. \******************************************************************************/
  114. jas_image_t *jas_image_create(int numcmpts, jas_image_cmptparm_t *cmptparms,
  115. int clrspc)
  116. {
  117. jas_image_t *image;
  118. uint_fast32_t rawsize;
  119. uint_fast32_t inmem;
  120. int cmptno;
  121. jas_image_cmptparm_t *cmptparm;
  122. if (!(image = jas_image_create0())) {
  123. return 0;
  124. }
  125. image->clrspc_ = clrspc;
  126. image->maxcmpts_ = numcmpts;
  127. image->inmem_ = true;
  128. /* Allocate memory for the per-component information. */
  129. if (!(image->cmpts_ = jas_alloc2(image->maxcmpts_,
  130. sizeof(jas_image_cmpt_t *)))) {
  131. jas_image_destroy(image);
  132. return 0;
  133. }
  134. /* Initialize in case of failure. */
  135. for (cmptno = 0; cmptno < image->maxcmpts_; ++cmptno) {
  136. image->cmpts_[cmptno] = 0;
  137. }
  138. /* Compute the approximate raw size of the image. */
  139. rawsize = 0;
  140. for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno,
  141. ++cmptparm) {
  142. rawsize += cmptparm->width * cmptparm->height *
  143. (cmptparm->prec + 7) / 8;
  144. }
  145. /* Decide whether to buffer the image data in memory, based on the
  146. raw size of the image. */
  147. inmem = (rawsize < JAS_IMAGE_INMEMTHRESH);
  148. /* Create the individual image components. */
  149. for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno,
  150. ++cmptparm) {
  151. if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx,
  152. cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
  153. cmptparm->width, cmptparm->height, cmptparm->prec,
  154. cmptparm->sgnd, inmem))) {
  155. jas_image_destroy(image);
  156. return 0;
  157. }
  158. ++image->numcmpts_;
  159. }
  160. /* Determine the bounding box for all of the components on the
  161. reference grid (i.e., the image area) */
  162. jas_image_setbbox(image);
  163. return image;
  164. }
  165. jas_image_t *jas_image_create0()
  166. {
  167. jas_image_t *image;
  168. if (!(image = jas_malloc(sizeof(jas_image_t)))) {
  169. return 0;
  170. }
  171. image->tlx_ = 0;
  172. image->tly_ = 0;
  173. image->brx_ = 0;
  174. image->bry_ = 0;
  175. image->clrspc_ = JAS_CLRSPC_UNKNOWN;
  176. image->numcmpts_ = 0;
  177. image->maxcmpts_ = 0;
  178. image->cmpts_ = 0;
  179. image->inmem_ = true;
  180. image->cmprof_ = 0;
  181. return image;
  182. }
  183. jas_image_t *jas_image_copy(jas_image_t *image)
  184. {
  185. jas_image_t *newimage;
  186. int cmptno;
  187. newimage = jas_image_create0();
  188. if (jas_image_growcmpts(newimage, image->numcmpts_)) {
  189. goto error;
  190. }
  191. for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
  192. if (!(newimage->cmpts_[cmptno] = jas_image_cmpt_copy(image->cmpts_[cmptno]))) {
  193. goto error;
  194. }
  195. ++newimage->numcmpts_;
  196. }
  197. jas_image_setbbox(newimage);
  198. if (image->cmprof_) {
  199. if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_)))
  200. goto error;
  201. }
  202. return newimage;
  203. error:
  204. if (newimage) {
  205. jas_image_destroy(newimage);
  206. }
  207. return 0;
  208. }
  209. static jas_image_cmpt_t *jas_image_cmpt_create0()
  210. {
  211. jas_image_cmpt_t *cmpt;
  212. if (!(cmpt = jas_malloc(sizeof(jas_image_cmpt_t)))) {
  213. return 0;
  214. }
  215. memset(cmpt, 0, sizeof(jas_image_cmpt_t));
  216. cmpt->type_ = JAS_IMAGE_CT_UNKNOWN;
  217. return cmpt;
  218. }
  219. static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt)
  220. {
  221. jas_image_cmpt_t *newcmpt;
  222. if (!(newcmpt = jas_image_cmpt_create0())) {
  223. return 0;
  224. }
  225. newcmpt->tlx_ = cmpt->tlx_;
  226. newcmpt->tly_ = cmpt->tly_;
  227. newcmpt->hstep_ = cmpt->hstep_;
  228. newcmpt->vstep_ = cmpt->vstep_;
  229. newcmpt->width_ = cmpt->width_;
  230. newcmpt->height_ = cmpt->height_;
  231. newcmpt->prec_ = cmpt->prec_;
  232. newcmpt->sgnd_ = cmpt->sgnd_;
  233. newcmpt->cps_ = cmpt->cps_;
  234. newcmpt->type_ = cmpt->type_;
  235. if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) {
  236. return 0;
  237. }
  238. if (jas_stream_seek(cmpt->stream_, 0, SEEK_SET)) {
  239. return 0;
  240. }
  241. if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) {
  242. return 0;
  243. }
  244. if (jas_stream_seek(newcmpt->stream_, 0, SEEK_SET)) {
  245. return 0;
  246. }
  247. return newcmpt;
  248. }
  249. void jas_image_destroy(jas_image_t *image)
  250. {
  251. int i;
  252. if (image->cmpts_) {
  253. for (i = 0; i < image->numcmpts_; ++i) {
  254. jas_image_cmpt_destroy(image->cmpts_[i]);
  255. image->cmpts_[i] = 0;
  256. }
  257. jas_free(image->cmpts_);
  258. }
  259. if (image->cmprof_)
  260. jas_cmprof_destroy(image->cmprof_);
  261. jas_free(image);
  262. }
  263. static jas_image_cmpt_t *jas_image_cmpt_create(uint_fast32_t tlx, uint_fast32_t tly,
  264. uint_fast32_t hstep, uint_fast32_t vstep, uint_fast32_t width, uint_fast32_t
  265. height, uint_fast16_t depth, bool sgnd, uint_fast32_t inmem)
  266. {
  267. jas_image_cmpt_t *cmpt;
  268. long size;
  269. if (!(cmpt = jas_malloc(sizeof(jas_image_cmpt_t)))) {
  270. return 0;
  271. }
  272. cmpt->type_ = JAS_IMAGE_CT_UNKNOWN;
  273. cmpt->tlx_ = tlx;
  274. cmpt->tly_ = tly;
  275. cmpt->hstep_ = hstep;
  276. cmpt->vstep_ = vstep;
  277. cmpt->width_ = width;
  278. cmpt->height_ = height;
  279. cmpt->prec_ = depth;
  280. cmpt->sgnd_ = sgnd;
  281. cmpt->stream_ = 0;
  282. cmpt->cps_ = (depth + 7) / 8;
  283. size = cmpt->width_ * cmpt->height_ * cmpt->cps_;
  284. cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) : jas_stream_tmpfile();
  285. if (!cmpt->stream_) {
  286. jas_image_cmpt_destroy(cmpt);
  287. return 0;
  288. }
  289. /* Zero the component data. This isn't necessary, but it is
  290. convenient for debugging purposes. */
  291. if (jas_stream_seek(cmpt->stream_, size - 1, SEEK_SET) < 0 ||
  292. jas_stream_putc(cmpt->stream_, 0) == EOF ||
  293. jas_stream_seek(cmpt->stream_, 0, SEEK_SET) < 0) {
  294. jas_image_cmpt_destroy(cmpt);
  295. return 0;
  296. }
  297. return cmpt;
  298. }
  299. static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt)
  300. {
  301. if (cmpt->stream_) {
  302. jas_stream_close(cmpt->stream_);
  303. }
  304. jas_free(cmpt);
  305. }
  306. /******************************************************************************\
  307. * Load and save operations.
  308. \******************************************************************************/
  309. jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, char *optstr)
  310. {
  311. jas_image_fmtinfo_t *fmtinfo;
  312. jas_image_t *image;
  313. image = 0;
  314. /* If possible, try to determine the format of the input data. */
  315. if (fmt < 0) {
  316. if ((fmt = jas_image_getfmt(in)) < 0)
  317. goto error;
  318. }
  319. /* Is it possible to decode an image represented in this format? */
  320. if (!(fmtinfo = jas_image_lookupfmtbyid(fmt)))
  321. goto error;
  322. if (!fmtinfo->ops.decode)
  323. goto error;
  324. /* Decode the image. */
  325. if (!(image = (*fmtinfo->ops.decode)(in, optstr)))
  326. goto error;
  327. /* Create a color profile if needed. */
  328. if (!jas_clrspc_isunknown(image->clrspc_) &&
  329. !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) {
  330. if (!(image->cmprof_ =
  331. jas_cmprof_createfromclrspc(jas_image_clrspc(image))))
  332. goto error;
  333. }
  334. return image;
  335. error:
  336. if (image)
  337. jas_image_destroy(image);
  338. return 0;
  339. }
  340. int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, char *optstr)
  341. {
  342. jas_image_fmtinfo_t *fmtinfo;
  343. if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
  344. return -1;
  345. }
  346. return (fmtinfo->ops.encode) ? (*fmtinfo->ops.encode)(image, out,
  347. optstr) : (-1);
  348. }
  349. /******************************************************************************\
  350. * Component read and write operations.
  351. \******************************************************************************/
  352. int jas_image_readcmpt(jas_image_t *image, int cmptno, jas_image_coord_t x,
  353. jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
  354. jas_matrix_t *data)
  355. {
  356. jas_image_cmpt_t *cmpt;
  357. jas_image_coord_t i;
  358. jas_image_coord_t j;
  359. int k;
  360. jas_seqent_t v;
  361. int c;
  362. jas_seqent_t *dr;
  363. jas_seqent_t *d;
  364. int drs;
  365. if (cmptno < 0 || cmptno >= image->numcmpts_) {
  366. return -1;
  367. }
  368. cmpt = image->cmpts_[cmptno];
  369. if (x >= cmpt->width_ || y >= cmpt->height_ ||
  370. x + width > cmpt->width_ ||
  371. y + height > cmpt->height_) {
  372. return -1;
  373. }
  374. if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) {
  375. if (jas_matrix_resize(data, height, width)) {
  376. return -1;
  377. }
  378. }
  379. dr = jas_matrix_getref(data, 0, 0);
  380. drs = jas_matrix_rowstep(data);
  381. for (i = 0; i < height; ++i, dr += drs) {
  382. d = dr;
  383. if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
  384. * cmpt->cps_, SEEK_SET) < 0) {
  385. return -1;
  386. }
  387. for (j = width; j > 0; --j, ++d) {
  388. v = 0;
  389. for (k = cmpt->cps_; k > 0; --k) {
  390. if ((c = jas_stream_getc(cmpt->stream_)) == EOF) {
  391. return -1;
  392. }
  393. v = (v << 8) | (c & 0xff);
  394. }
  395. *d = bitstoint(v, cmpt->prec_, cmpt->sgnd_);
  396. }
  397. }
  398. return 0;
  399. }
  400. int jas_image_writecmpt(jas_image_t *image, int cmptno, jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width,
  401. jas_image_coord_t height, jas_matrix_t *data)
  402. {
  403. jas_image_cmpt_t *cmpt;
  404. jas_image_coord_t i;
  405. jas_image_coord_t j;
  406. jas_seqent_t *d;
  407. jas_seqent_t *dr;
  408. int drs;
  409. jas_seqent_t v;
  410. int k;
  411. int c;
  412. if (cmptno < 0 || cmptno >= image->numcmpts_) {
  413. return -1;
  414. }
  415. cmpt = image->cmpts_[cmptno];
  416. if (x >= cmpt->width_ || y >= cmpt->height_ ||
  417. x + width > cmpt->width_ ||
  418. y + height > cmpt->height_) {
  419. return -1;
  420. }
  421. if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) {
  422. return -1;
  423. }
  424. dr = jas_matrix_getref(data, 0, 0);
  425. drs = jas_matrix_rowstep(data);
  426. for (i = 0; i < height; ++i, dr += drs) {
  427. d = dr;
  428. if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
  429. * cmpt->cps_, SEEK_SET) < 0) {
  430. return -1;
  431. }
  432. for (j = width; j > 0; --j, ++d) {
  433. v = inttobits(*d, cmpt->prec_, cmpt->sgnd_);
  434. for (k = cmpt->cps_; k > 0; --k) {
  435. c = (v >> (8 * (cmpt->cps_ - 1))) & 0xff;
  436. if (jas_stream_putc(cmpt->stream_,
  437. (unsigned char) c) == EOF) {
  438. return -1;
  439. }
  440. v <<= 8;
  441. }
  442. }
  443. }
  444. return 0;
  445. }
  446. /******************************************************************************\
  447. * File format operations.
  448. \******************************************************************************/
  449. void jas_image_clearfmts()
  450. {
  451. int i;
  452. jas_image_fmtinfo_t *fmtinfo;
  453. for (i = 0; i < jas_image_numfmts; ++i) {
  454. fmtinfo = &jas_image_fmtinfos[i];
  455. if (fmtinfo->name) {
  456. jas_free(fmtinfo->name);
  457. fmtinfo->name = 0;
  458. }
  459. if (fmtinfo->ext) {
  460. jas_free(fmtinfo->ext);
  461. fmtinfo->ext = 0;
  462. }
  463. if (fmtinfo->desc) {
  464. jas_free(fmtinfo->desc);
  465. fmtinfo->desc = 0;
  466. }
  467. }
  468. jas_image_numfmts = 0;
  469. }
  470. int jas_image_addfmt(int id, char *name, char *ext, char *desc,
  471. jas_image_fmtops_t *ops)
  472. {
  473. jas_image_fmtinfo_t *fmtinfo;
  474. assert(id >= 0 && name && ext && ops);
  475. if (jas_image_numfmts >= JAS_IMAGE_MAXFMTS) {
  476. return -1;
  477. }
  478. fmtinfo = &jas_image_fmtinfos[jas_image_numfmts];
  479. fmtinfo->id = id;
  480. if (!(fmtinfo->name = jas_strdup(name))) {
  481. return -1;
  482. }
  483. if (!(fmtinfo->ext = jas_strdup(ext))) {
  484. jas_free(fmtinfo->name);
  485. return -1;
  486. }
  487. if (!(fmtinfo->desc = jas_strdup(desc))) {
  488. jas_free(fmtinfo->name);
  489. jas_free(fmtinfo->ext);
  490. return -1;
  491. }
  492. fmtinfo->ops = *ops;
  493. ++jas_image_numfmts;
  494. return 0;
  495. }
  496. int jas_image_strtofmt(char *name)
  497. {
  498. jas_image_fmtinfo_t *fmtinfo;
  499. if (!(fmtinfo = jas_image_lookupfmtbyname(name))) {
  500. return -1;
  501. }
  502. return fmtinfo->id;
  503. }
  504. char *jas_image_fmttostr(int fmt)
  505. {
  506. jas_image_fmtinfo_t *fmtinfo;
  507. if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
  508. return 0;
  509. }
  510. return fmtinfo->name;
  511. }
  512. int jas_image_getfmt(jas_stream_t *in)
  513. {
  514. jas_image_fmtinfo_t *fmtinfo;
  515. int found;
  516. int i;
  517. /* Check for data in each of the supported formats. */
  518. found = 0;
  519. for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
  520. ++fmtinfo) {
  521. if (fmtinfo->ops.validate) {
  522. /* Is the input data valid for this format? */
  523. if (!(*fmtinfo->ops.validate)(in)) {
  524. found = 1;
  525. break;
  526. }
  527. }
  528. }
  529. return found ? fmtinfo->id : (-1);
  530. }
  531. int jas_image_fmtfromname(char *name)
  532. {
  533. int i;
  534. char *ext;
  535. jas_image_fmtinfo_t *fmtinfo;
  536. /* Get the file name extension. */
  537. if (!(ext = strrchr(name, '.'))) {
  538. return -1;
  539. }
  540. ++ext;
  541. /* Try to find a format that uses this extension. */
  542. for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
  543. ++fmtinfo) {
  544. /* Do we have a match? */
  545. if (!strcmp(ext, fmtinfo->ext)) {
  546. return fmtinfo->id;
  547. }
  548. }
  549. return -1;
  550. }
  551. /******************************************************************************\
  552. * Miscellaneous operations.
  553. \******************************************************************************/
  554. uint_fast32_t jas_image_rawsize(jas_image_t *image)
  555. {
  556. uint_fast32_t rawsize;
  557. int cmptno;
  558. jas_image_cmpt_t *cmpt;
  559. rawsize = 0;
  560. for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
  561. cmpt = image->cmpts_[cmptno];
  562. rawsize += (cmpt->width_ * cmpt->height_ * cmpt->prec_ +
  563. 7) / 8;
  564. }
  565. return rawsize;
  566. }
  567. void jas_image_delcmpt(jas_image_t *image, int cmptno)
  568. {
  569. if (cmptno >= image->numcmpts_) {
  570. return;
  571. }
  572. jas_image_cmpt_destroy(image->cmpts_[cmptno]);
  573. if (cmptno < image->numcmpts_) {
  574. memmove(&image->cmpts_[cmptno], &image->cmpts_[cmptno + 1],
  575. (image->numcmpts_ - 1 - cmptno) * sizeof(jas_image_cmpt_t *));
  576. }
  577. --image->numcmpts_;
  578. jas_image_setbbox(image);
  579. }
  580. int jas_image_addcmpt(jas_image_t *image, int cmptno,
  581. jas_image_cmptparm_t *cmptparm)
  582. {
  583. jas_image_cmpt_t *newcmpt;
  584. if (cmptno < 0)
  585. cmptno = image->numcmpts_;
  586. assert(cmptno >= 0 && cmptno <= image->numcmpts_);
  587. if (image->numcmpts_ >= image->maxcmpts_) {
  588. if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) {
  589. return -1;
  590. }
  591. }
  592. if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx,
  593. cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
  594. cmptparm->width, cmptparm->height, cmptparm->prec,
  595. cmptparm->sgnd, 1))) {
  596. return -1;
  597. }
  598. if (cmptno < image->numcmpts_) {
  599. memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno],
  600. (image->numcmpts_ - cmptno) * sizeof(jas_image_cmpt_t *));
  601. }
  602. image->cmpts_[cmptno] = newcmpt;
  603. ++image->numcmpts_;
  604. jas_image_setbbox(image);
  605. return 0;
  606. }
  607. jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id)
  608. {
  609. int i;
  610. jas_image_fmtinfo_t *fmtinfo;
  611. for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) {
  612. if (fmtinfo->id == id) {
  613. return fmtinfo;
  614. }
  615. }
  616. return 0;
  617. }
  618. jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name)
  619. {
  620. int i;
  621. jas_image_fmtinfo_t *fmtinfo;
  622. for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) {
  623. if (!strcmp(fmtinfo->name, name)) {
  624. return fmtinfo;
  625. }
  626. }
  627. return 0;
  628. }
  629. static uint_fast32_t inttobits(jas_seqent_t v, int prec, bool sgnd)
  630. {
  631. uint_fast32_t ret;
  632. ret = ((sgnd && v < 0) ? ((1 << prec) + v) : v) & JAS_ONES(prec);
  633. return ret;
  634. }
  635. static jas_seqent_t bitstoint(uint_fast32_t v, int prec, bool sgnd)
  636. {
  637. jas_seqent_t ret;
  638. v &= JAS_ONES(prec);
  639. ret = (sgnd && (v & (1 << (prec - 1)))) ? (v - (1 << prec)) : v;
  640. return ret;
  641. }
  642. static void jas_image_setbbox(jas_image_t *image)
  643. {
  644. jas_image_cmpt_t *cmpt;
  645. int cmptno;
  646. int_fast32_t x;
  647. int_fast32_t y;
  648. if (image->numcmpts_ > 0) {
  649. /* Determine the bounding box for all of the components on the
  650. reference grid (i.e., the image area) */
  651. cmpt = image->cmpts_[0];
  652. image->tlx_ = cmpt->tlx_;
  653. image->tly_ = cmpt->tly_;
  654. image->brx_ = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1) + 1;
  655. image->bry_ = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1) + 1;
  656. for (cmptno = 1; cmptno < image->numcmpts_; ++cmptno) {
  657. cmpt = image->cmpts_[cmptno];
  658. if (image->tlx_ > cmpt->tlx_) {
  659. image->tlx_ = cmpt->tlx_;
  660. }
  661. if (image->tly_ > cmpt->tly_) {
  662. image->tly_ = cmpt->tly_;
  663. }
  664. x = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1) + 1;
  665. if (image->brx_ < x) {
  666. image->brx_ = x;
  667. }
  668. y = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1) + 1;
  669. if (image->bry_ < y) {
  670. image->bry_ = y;
  671. }
  672. }
  673. } else {
  674. image->tlx_ = 0;
  675. image->tly_ = 0;
  676. image->brx_ = 0;
  677. image->bry_ = 0;
  678. }
  679. }
  680. static int jas_image_growcmpts(jas_image_t *image, int maxcmpts)
  681. {
  682. jas_image_cmpt_t **newcmpts;
  683. int cmptno;
  684. newcmpts = jas_realloc2(image->cmpts_, maxcmpts, sizeof(jas_image_cmpt_t *));
  685. if (!newcmpts) {
  686. return -1;
  687. }
  688. image->cmpts_ = newcmpts;
  689. image->maxcmpts_ = maxcmpts;
  690. for (cmptno = image->numcmpts_; cmptno < image->maxcmpts_; ++cmptno) {
  691. image->cmpts_[cmptno] = 0;
  692. }
  693. return 0;
  694. }
  695. int jas_image_copycmpt(jas_image_t *dstimage, int dstcmptno, jas_image_t *srcimage,
  696. int srccmptno)
  697. {
  698. jas_image_cmpt_t *newcmpt;
  699. if (dstimage->numcmpts_ >= dstimage->maxcmpts_) {
  700. if (jas_image_growcmpts(dstimage, dstimage->maxcmpts_ + 128)) {
  701. return -1;
  702. }
  703. }
  704. if (!(newcmpt = jas_image_cmpt_copy(srcimage->cmpts_[srccmptno]))) {
  705. return -1;
  706. }
  707. if (dstcmptno < dstimage->numcmpts_) {
  708. memmove(&dstimage->cmpts_[dstcmptno + 1], &dstimage->cmpts_[dstcmptno],
  709. (dstimage->numcmpts_ - dstcmptno) * sizeof(jas_image_cmpt_t *));
  710. }
  711. dstimage->cmpts_[dstcmptno] = newcmpt;
  712. ++dstimage->numcmpts_;
  713. jas_image_setbbox(dstimage);
  714. return 0;
  715. }
  716. void jas_image_dump(jas_image_t *image, FILE *out)
  717. {
  718. long buf[1024];
  719. int cmptno;
  720. int n;
  721. int i;
  722. int width;
  723. int height;
  724. jas_image_cmpt_t *cmpt;
  725. for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
  726. cmpt = image->cmpts_[cmptno];
  727. fprintf(out, "prec=%d, sgnd=%d, cmpttype=%d\n", cmpt->prec_,
  728. cmpt->sgnd_, (int)cmpt->type_);
  729. width = jas_image_cmptwidth(image, cmptno);
  730. height = jas_image_cmptheight(image, cmptno);
  731. n = JAS_MIN(16, width);
  732. if (jas_image_readcmpt2(image, cmptno, 0, 0, n, 1, buf)) {
  733. abort();
  734. }
  735. for (i = 0; i < n; ++i) {
  736. fprintf(out, " f(%d,%d)=%ld", i, 0, buf[i]);
  737. }
  738. fprintf(out, "\n");
  739. if (jas_image_readcmpt2(image, cmptno, width - n, height - 1, n, 1, buf)) {
  740. abort();
  741. }
  742. for (i = 0; i < n; ++i) {
  743. fprintf(out, " f(%d,%d)=%ld", width - n + i, height - 1, buf[i]);
  744. }
  745. fprintf(out, "\n");
  746. }
  747. }
  748. int jas_image_depalettize(jas_image_t *image, int cmptno, int numlutents,
  749. int_fast32_t *lutents, int dtype, int newcmptno)
  750. {
  751. jas_image_cmptparm_t cmptparms;
  752. int_fast32_t v;
  753. int i;
  754. int j;
  755. jas_image_cmpt_t *cmpt;
  756. cmpt = image->cmpts_[cmptno];
  757. cmptparms.tlx = cmpt->tlx_;
  758. cmptparms.tly = cmpt->tly_;
  759. cmptparms.hstep = cmpt->hstep_;
  760. cmptparms.vstep = cmpt->vstep_;
  761. cmptparms.width = cmpt->width_;
  762. cmptparms.height = cmpt->height_;
  763. cmptparms.prec = JAS_IMAGE_CDT_GETPREC(dtype);
  764. cmptparms.sgnd = JAS_IMAGE_CDT_GETSGND(dtype);
  765. if (jas_image_addcmpt(image, newcmptno, &cmptparms)) {
  766. return -1;
  767. }
  768. if (newcmptno <= cmptno) {
  769. ++cmptno;
  770. cmpt = image->cmpts_[cmptno];
  771. }
  772. for (j = 0; j < cmpt->height_; ++j) {
  773. for (i = 0; i < cmpt->width_; ++i) {
  774. v = jas_image_readcmptsample(image, cmptno, i, j);
  775. if (v < 0) {
  776. v = 0;
  777. } else if (v >= numlutents) {
  778. v = numlutents - 1;
  779. }
  780. jas_image_writecmptsample(image, newcmptno, i, j,
  781. lutents[v]);
  782. }
  783. }
  784. return 0;
  785. }
  786. int jas_image_readcmptsample(jas_image_t *image, int cmptno, int x, int y)
  787. {
  788. jas_image_cmpt_t *cmpt;
  789. uint_fast32_t v;
  790. int k;
  791. int c;
  792. cmpt = image->cmpts_[cmptno];
  793. if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_,
  794. SEEK_SET) < 0) {
  795. return -1;
  796. }
  797. v = 0;
  798. for (k = cmpt->cps_; k > 0; --k) {
  799. if ((c = jas_stream_getc(cmpt->stream_)) == EOF) {
  800. return -1;
  801. }
  802. v = (v << 8) | (c & 0xff);
  803. }
  804. return bitstoint(v, cmpt->prec_, cmpt->sgnd_);
  805. }
  806. void jas_image_writecmptsample(jas_image_t *image, int cmptno, int x, int y,
  807. int_fast32_t v)
  808. {
  809. jas_image_cmpt_t *cmpt;
  810. uint_fast32_t t;
  811. int k;
  812. int c;
  813. cmpt = image->cmpts_[cmptno];
  814. if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_,
  815. SEEK_SET) < 0) {
  816. return;
  817. }
  818. t = inttobits(v, cmpt->prec_, cmpt->sgnd_);
  819. for (k = cmpt->cps_; k > 0; --k) {
  820. c = (t >> (8 * (cmpt->cps_ - 1))) & 0xff;
  821. if (jas_stream_putc(cmpt->stream_, (unsigned char) c) == EOF) {
  822. return;
  823. }
  824. t <<= 8;
  825. }
  826. }
  827. int jas_image_getcmptbytype(jas_image_t *image, int ctype)
  828. {
  829. int cmptno;
  830. for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
  831. if (image->cmpts_[cmptno]->type_ == ctype) {
  832. return cmptno;
  833. }
  834. }
  835. return -1;
  836. }
  837. /***********************************************/
  838. /***********************************************/
  839. /***********************************************/
  840. /***********************************************/
  841. int jas_image_readcmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x,
  842. jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
  843. long *buf)
  844. {
  845. jas_image_cmpt_t *cmpt;
  846. jas_image_coord_t i;
  847. jas_image_coord_t j;
  848. long v;
  849. long *bufptr;
  850. if (cmptno < 0 || cmptno >= image->numcmpts_)
  851. goto error;
  852. cmpt = image->cmpts_[cmptno];
  853. if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
  854. width < 0 || height < 0 || x + width > cmpt->width_ ||
  855. y + height > cmpt->height_)
  856. goto error;
  857. bufptr = buf;
  858. for (i = 0; i < height; ++i) {
  859. if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
  860. * cmpt->cps_, SEEK_SET) < 0)
  861. goto error;
  862. for (j = 0; j < width; ++j) {
  863. if (getint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, &v))
  864. goto error;
  865. *bufptr++ = v;
  866. }
  867. }
  868. return 0;
  869. error:
  870. return -1;
  871. }
  872. int jas_image_writecmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x,
  873. jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
  874. long *buf)
  875. {
  876. jas_image_cmpt_t *cmpt;
  877. jas_image_coord_t i;
  878. jas_image_coord_t j;
  879. long v;
  880. long *bufptr;
  881. if (cmptno < 0 || cmptno >= image->numcmpts_)
  882. goto error;
  883. cmpt = image->cmpts_[cmptno];
  884. if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
  885. width < 0 || height < 0 || x + width > cmpt->width_ ||
  886. y + height > cmpt->height_)
  887. goto error;
  888. bufptr = buf;
  889. for (i = 0; i < height; ++i) {
  890. if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
  891. * cmpt->cps_, SEEK_SET) < 0)
  892. goto error;
  893. for (j = 0; j < width; ++j) {
  894. v = *bufptr++;
  895. if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v))
  896. goto error;
  897. }
  898. }
  899. return 0;
  900. error:
  901. return -1;
  902. }
  903. int jas_image_sampcmpt(jas_image_t *image, int cmptno, int newcmptno,
  904. jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs,
  905. jas_image_coord_t vs, int sgnd, int prec)
  906. {
  907. jas_image_cmpt_t *oldcmpt;
  908. jas_image_cmpt_t *newcmpt;
  909. int width;
  910. int height;
  911. jas_image_coord_t tlx;
  912. jas_image_coord_t tly;
  913. jas_image_coord_t brx;
  914. jas_image_coord_t bry;
  915. int i;
  916. int j;
  917. jas_image_cmptparm_t cmptparm;
  918. jas_image_coord_t ax;
  919. jas_image_coord_t ay;
  920. jas_image_coord_t bx;
  921. jas_image_coord_t by;
  922. jas_image_coord_t d0;
  923. jas_image_coord_t d1;
  924. jas_image_coord_t d2;
  925. jas_image_coord_t d3;
  926. jas_image_coord_t oldx;
  927. jas_image_coord_t oldy;
  928. jas_image_coord_t x;
  929. jas_image_coord_t y;
  930. long v;
  931. jas_image_coord_t cmptbrx;
  932. jas_image_coord_t cmptbry;
  933. assert(cmptno >= 0 && cmptno < image->numcmpts_);
  934. oldcmpt = image->cmpts_[cmptno];
  935. assert(oldcmpt->tlx_ == 0 && oldcmpt->tly_ == 0);
  936. jas_image_calcbbox2(image, &tlx, &tly, &brx, &bry);
  937. width = FLOORDIV(brx - ho + hs, hs);
  938. height = FLOORDIV(bry - vo + vs, vs);
  939. cmptparm.tlx = ho;
  940. cmptparm.tly = vo;
  941. cmptparm.hstep = hs;
  942. cmptparm.vstep = vs;
  943. cmptparm.width = width;
  944. cmptparm.height = height;
  945. cmptparm.prec = prec;
  946. cmptparm.sgnd = sgnd;
  947. if (jas_image_addcmpt(image, newcmptno, &cmptparm))
  948. goto error;
  949. cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_;
  950. cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_;
  951. newcmpt = image->cmpts_[newcmptno];
  952. jas_stream_rewind(newcmpt->stream_);
  953. for (i = 0; i < height; ++i) {
  954. y = newcmpt->tly_ + newcmpt->vstep_ * i;
  955. for (j = 0; j < width; ++j) {
  956. x = newcmpt->tlx_ + newcmpt->hstep_ * j;
  957. ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
  958. ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
  959. bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
  960. if (bx > cmptbrx)
  961. bx = cmptbrx;
  962. by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
  963. if (by > cmptbry)
  964. by = cmptbry;
  965. d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y);
  966. d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y);
  967. d2 = (bx - x) * (bx - x) + (by - y) * (by - y);
  968. d3 = (ax - x) * (ax - x) + (by - y) * (by - y);
  969. if (d0 <= d1 && d0 <= d2 && d0 <= d3) {
  970. oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_;
  971. oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_;
  972. } else if (d1 <= d0 && d1 <= d2 && d1 <= d3) {
  973. oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_;
  974. oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_;
  975. } else if (d2 <= d0 && d2 <= d1 && d1 <= d3) {
  976. oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_;
  977. oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_;
  978. } else {
  979. oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_;
  980. oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_;
  981. }
  982. assert(oldx >= 0 && oldx < oldcmpt->width_ &&
  983. oldy >= 0 && oldy < oldcmpt->height_);
  984. if (jas_stream_seek(oldcmpt->stream_, oldcmpt->cps_ *
  985. (oldy * oldcmpt->width_ + oldx), SEEK_SET) < 0)
  986. goto error;
  987. if (getint(oldcmpt->stream_, oldcmpt->sgnd_,
  988. oldcmpt->prec_, &v))
  989. goto error;
  990. if (newcmpt->prec_ != oldcmpt->prec_ ||
  991. newcmpt->sgnd_ != oldcmpt->sgnd_) {
  992. v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_,
  993. newcmpt->sgnd_, newcmpt->prec_);
  994. }
  995. if (putint(newcmpt->stream_, newcmpt->sgnd_,
  996. newcmpt->prec_, v))
  997. goto error;
  998. }
  999. }
  1000. return 0;
  1001. error:
  1002. return -1;
  1003. }
  1004. int jas_image_ishomosamp(jas_image_t *image)
  1005. {
  1006. jas_image_coord_t hstep;
  1007. jas_image_coord_t vstep;
  1008. int result;
  1009. int i;
  1010. hstep = jas_image_cmpthstep(image, 0);
  1011. vstep = jas_image_cmptvstep(image, 0);
  1012. result = 1;
  1013. for (i = 0; i < image->numcmpts_; ++i) {
  1014. if (jas_image_cmpthstep(image, i) != hstep ||
  1015. jas_image_cmptvstep(image, i) != vstep) {
  1016. result = 0;
  1017. break;
  1018. }
  1019. }
  1020. return result;
  1021. }
  1022. /* Note: This function defines a bounding box differently. */
  1023. static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
  1024. jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry)
  1025. {
  1026. jas_image_cmpt_t *cmpt;
  1027. jas_image_coord_t tmptlx;
  1028. jas_image_coord_t tmptly;
  1029. jas_image_coord_t tmpbrx;
  1030. jas_image_coord_t tmpbry;
  1031. jas_image_coord_t t;
  1032. int i;
  1033. if (image->numcmpts_ > 0) {
  1034. cmpt = image->cmpts_[0];
  1035. tmptlx = cmpt->tlx_;
  1036. tmptly = cmpt->tly_;
  1037. tmpbrx = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
  1038. tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
  1039. for (i = 0; i < image->numcmpts_; ++i) {
  1040. cmpt = image->cmpts_[i];
  1041. if (cmpt->tlx_ < tmptlx)
  1042. tmptlx = cmpt->tlx_;
  1043. if (cmpt->tly_ < tmptly)
  1044. tmptly = cmpt->tly_;
  1045. t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
  1046. if (t > tmpbrx)
  1047. tmpbrx = t;
  1048. t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
  1049. if (t > tmpbry)
  1050. tmpbry = t;
  1051. }
  1052. } else {
  1053. tmptlx = 0;
  1054. tmptly = 0;
  1055. tmpbrx = -1;
  1056. tmpbry = -1;
  1057. }
  1058. *tlx = tmptlx;
  1059. *tly = tmptly;
  1060. *brx = tmpbrx;
  1061. *bry = tmpbry;
  1062. }
  1063. static int getint(jas_stream_t *in, int sgnd, int prec, long *val)
  1064. {
  1065. long v;
  1066. int n;
  1067. int c;
  1068. n = (prec + 7) / 8;
  1069. v = 0;
  1070. while (--n >= 0) {
  1071. if ((c = jas_stream_getc(in)) == EOF)
  1072. return -1;
  1073. v = (v << 8) | c;
  1074. }
  1075. v &= ((1 << prec) - 1);
  1076. if (sgnd) {
  1077. /* XXX - Do something here. */
  1078. abort();
  1079. } else {
  1080. *val = v;
  1081. }
  1082. return 0;
  1083. }
  1084. static int putint(jas_stream_t *out, int sgnd, int prec, long val)
  1085. {
  1086. int n;
  1087. int c;
  1088. if (sgnd) {
  1089. /* XXX - Do something here. */
  1090. abort();
  1091. }
  1092. val &= (1 << prec) - 1;
  1093. n = (prec + 7) / 8;
  1094. while (--n >= 0) {
  1095. c = (val >> (n * 8)) & 0xff;
  1096. if (jas_stream_putc(out, c) != c)
  1097. return -1;
  1098. }
  1099. return 0;
  1100. }
  1101. static long convert(long val, int oldsgnd, int oldprec, int newsgnd,
  1102. int newprec)
  1103. {
  1104. if (newsgnd != oldsgnd) {
  1105. }
  1106. if (newprec != oldprec) {
  1107. if (newprec > oldprec) {
  1108. val <<= newprec - oldprec;
  1109. } else if (oldprec > newprec) {
  1110. val >>= oldprec - newprec;
  1111. }
  1112. }
  1113. return val;
  1114. }
  1115. static long downtomult(long x, long y)
  1116. {
  1117. assert(x >= 0);
  1118. return (x / y) * y;
  1119. }
  1120. static long uptomult(long x, long y)
  1121. {
  1122. assert(x >= 0);
  1123. return ((x + y - 1) / y) * y;
  1124. }
  1125. jas_image_t *jas_image_chclrspc(jas_image_t *image, jas_cmprof_t *outprof,
  1126. int intent)
  1127. {
  1128. jas_image_t *inimage;
  1129. int minhstep;
  1130. int minvstep;
  1131. int i;
  1132. int j;
  1133. int k;
  1134. int n;
  1135. int hstep;
  1136. int vstep;
  1137. int numinauxchans;
  1138. int numoutauxchans;
  1139. int numinclrchans;
  1140. int numoutclrchans;
  1141. int prec;
  1142. jas_image_t *outimage;
  1143. int cmpttype;
  1144. int numoutchans;
  1145. jas_cmprof_t *inprof;
  1146. jas_cmprof_t *tmpprof;
  1147. jas_image_cmptparm_t cmptparm;
  1148. int width;
  1149. int height;
  1150. jas_cmxform_t *xform;
  1151. jas_cmpixmap_t inpixmap;
  1152. jas_cmpixmap_t outpixmap;
  1153. jas_cmcmptfmt_t *incmptfmts;
  1154. jas_cmcmptfmt_t *outcmptfmts;
  1155. #if 0
  1156. jas_eprintf("IMAGE\n");
  1157. jas_image_dump(image, stderr);
  1158. #endif
  1159. if (!(inimage = jas_image_copy(image)))
  1160. goto error;
  1161. image = 0;
  1162. if (!jas_image_ishomosamp(inimage)) {
  1163. minhstep = jas_image_cmpthstep(inimage, 0);
  1164. minvstep = jas_image_cmptvstep(inimage, 0);
  1165. for (i = 1; i < jas_image_numcmpts(inimage); ++i) {
  1166. hstep = jas_image_cmpthstep(inimage, i);
  1167. vstep = jas_image_cmptvstep(inimage, i);
  1168. if (hstep < minhstep)
  1169. minhstep = hstep;
  1170. if (vstep < minvstep)
  1171. minvstep = vstep;
  1172. }
  1173. n = jas_image_numcmpts(inimage);
  1174. for (i = 0; i < n; ++i) {
  1175. cmpttype = jas_image_cmpttype(inimage, i);
  1176. if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, i)))
  1177. goto error;
  1178. jas_image_setcmpttype(inimage, i + 1, cmpttype);
  1179. jas_image_delcmpt(inimage, i);
  1180. }
  1181. }
  1182. width = jas_image_cmptwidth(inimage, 0);
  1183. height = jas_image_cmptheight(inimage, 0);
  1184. hstep = jas_image_cmpthstep(inimage, 0);
  1185. vstep = jas_image_cmptvstep(inimage, 0);
  1186. inprof = jas_image_cmprof(inimage);
  1187. assert(inprof);
  1188. numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof));
  1189. numinauxchans = jas_image_numcmpts(inimage) - numinclrchans;
  1190. numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof));
  1191. numoutauxchans = 0;
  1192. numoutchans = numoutclrchans + numoutauxchans;
  1193. prec = 8;
  1194. if (!(outimage = jas_image_create0()))
  1195. goto error;
  1196. /* Create a component for each of the colorants. */
  1197. for (i = 0; i < numoutclrchans; ++i) {
  1198. cmptparm.tlx = 0;
  1199. cmptparm.tly = 0;
  1200. cmptparm.hstep = hstep;
  1201. cmptparm.vstep = vstep;
  1202. cmptparm.width = width;
  1203. cmptparm.height = height;
  1204. cmptparm.prec = prec;
  1205. cmptparm.sgnd = 0;
  1206. if (jas_image_addcmpt(outimage, -1, &cmptparm))
  1207. goto error;
  1208. jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i));
  1209. }
  1210. #if 0
  1211. /* Copy the auxiliary components without modification. */
  1212. for (i = 0; i < jas_image_numcmpts(inimage); ++i) {
  1213. if (!ISCOLOR(jas_image_cmpttype(inimage, i))) {
  1214. jas_image_copycmpt(outimage, -1, inimage, i);
  1215. /* XXX - need to specify laydown of component on ref. grid */
  1216. }
  1217. }
  1218. #endif
  1219. if (!(tmpprof = jas_cmprof_copy(outprof)))
  1220. goto error;
  1221. assert(!jas_image_cmprof(outimage));
  1222. jas_image_setcmprof(outimage, tmpprof);
  1223. tmpprof = 0;
  1224. jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof));
  1225. if (!(xform = jas_cmxform_create(inprof, outprof, 0, JAS_CMXFORM_OP_FWD, intent, 0)))
  1226. goto error;
  1227. inpixmap.numcmpts = numinclrchans;
  1228. incmptfmts = malloc(numinclrchans * sizeof(jas_cmcmptfmt_t));
  1229. assert(incmptfmts);
  1230. inpixmap.cmptfmts = incmptfmts;
  1231. for (i = 0; i < numinclrchans; ++i) {
  1232. j = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(i));
  1233. assert(j >= 0);
  1234. if (!(incmptfmts[i].buf = malloc(width * sizeof(long))))
  1235. goto error;
  1236. incmptfmts[i].prec = jas_image_cmptprec(inimage, j);
  1237. incmptfmts[i].sgnd = jas_image_cmptsgnd(inimage, j);
  1238. incmptfmts[i].width = width;
  1239. incmptfmts[i].height = 1;
  1240. }
  1241. outpixmap.numcmpts = numoutclrchans;
  1242. outcmptfmts = malloc(numoutclrchans * sizeof(jas_cmcmptfmt_t));
  1243. assert(outcmptfmts);
  1244. outpixmap.cmptfmts = outcmptfmts;
  1245. for (i = 0; i < numoutclrchans; ++i) {
  1246. j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i));
  1247. assert(j >= 0);
  1248. if (!(outcmptfmts[i].buf = malloc(width * sizeof(long))))
  1249. goto error;
  1250. outcmptfmts[i].prec = jas_image_cmptprec(outimage, j);
  1251. outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j);
  1252. outcmptfmts[i].width = width;
  1253. outcmptfmts[i].height = 1;
  1254. }
  1255. for (i = 0; i < height; ++i) {
  1256. for (j = 0; j < numinclrchans; ++j) {
  1257. k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j));
  1258. if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, incmptfmts[j].buf))
  1259. goto error;
  1260. }
  1261. jas_cmxform_apply(xform, &inpixmap, &outpixmap);
  1262. for (j = 0; j < numoutclrchans; ++j) {
  1263. k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j));
  1264. if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, outcmptfmts[j].buf))
  1265. goto error;
  1266. }
  1267. }
  1268. for (i = 0; i < numoutclrchans; ++i)
  1269. jas_free(outcmptfmts[i].buf);
  1270. jas_free(outcmptfmts);
  1271. for (i = 0; i < numinclrchans; ++i)
  1272. jas_free(incmptfmts[i].buf);
  1273. jas_free(incmptfmts);
  1274. jas_cmxform_destroy(xform);
  1275. jas_image_destroy(inimage);
  1276. #if 0
  1277. jas_eprintf("INIMAGE\n");
  1278. jas_image_dump(inimage, stderr);
  1279. jas_eprintf("OUTIMAGE\n");
  1280. jas_image_dump(outimage, stderr);
  1281. #endif
  1282. return outimage;
  1283. error:
  1284. return 0;
  1285. }