Blender V4.3
iris.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstring>
10
11#include "BLI_fileops.h"
12#include "BLI_utildefines.h"
13
14#include "MEM_guardedalloc.h"
15
17#include "IMB_filetype.hh"
18#include "IMB_imbuf.hh"
19#include "IMB_imbuf_types.hh"
20
21#define IMAGIC 0732
22
37
38#define HEADER_SIZE 512
39
40BLI_STATIC_ASSERT(sizeof(IMAGE) == HEADER_SIZE, "Invalid header size");
41
42#define RINTLUM (79)
43#define GINTLUM (156)
44#define BINTLUM (21)
45
46#define ILUM(r, g, b) (int(RINTLUM * (r) + GINTLUM * (g) + BINTLUM * (b)) >> 8)
47
48#define OFFSET_R 0 /* this is byte order dependent */
49#define OFFSET_G 1
50#define OFFSET_B 2
51// #define OFFSET_A 3
52
53#define CHANOFFSET(z) (3 - (z)) /* this is byte order dependent */
54
55// #define TYPEMASK 0xff00
56#define BPPMASK 0x00ff
57// #define ITYPE_VERBATIM 0x0000 /* UNUSED */
58#define ITYPE_RLE 0x0100
59#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
60// #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
61#define BPP(type) ((type) & BPPMASK)
62#define RLE(bpp) (ITYPE_RLE | (bpp))
63// #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) /* UNUSED */
64// #define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2) /* UNUSED */
65// #define RLE_NOP 0x00
66
67/* local struct for mem access */
72
73#define MFILE_DATA(inf) ((void)0, ((inf)->_file_data + (inf)->_file_offset))
74#define MFILE_STEP(inf, step) \
75 { \
76 (inf)->_file_offset += step; \
77 } \
78 ((void)0)
79#define MFILE_SEEK(inf, pos) \
80 { \
81 (inf)->_file_offset = pos; \
82 } \
83 ((void)0)
84
85/* error flags */
86#define DIRTY_FLAG_EOF (1 << 0)
87#define DIRTY_FLAG_ENCODING (1 << 1)
88
89/* Functions. */
90static void readheader(MFileOffset *inf, IMAGE *image);
91static int writeheader(FILE *outf, const IMAGE *image);
92
93static ushort getshort(MFileOffset *inf);
94static uint getlong(MFileOffset *mofs);
95static void putshort(FILE *outf, ushort val);
96static int putlong(FILE *outf, uint val);
97static int writetab(FILE *outf, const uint *tab, int len);
98static void readtab(MFileOffset *inf, uint *tab, int len);
99
100static int expandrow(
101 uchar *optr, const uchar *optr_end, const uchar *iptr, const uchar *iptr_end, int z);
102static int expandrow2(
103 float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z);
104static void interleaverow(uchar *lptr, const uchar *cptr, int z, int n);
105static void interleaverow2(float *lptr, const uchar *cptr, int z, int n);
106static int compressrow(const uchar *lbuf, uchar *rlebuf, int z, int row_len);
107static void lumrow(const uchar *rgbptr, uchar *lumptr, int n);
108
109/*
110 * byte order independent read/write of shorts and ints.
111 */
112
114{
115 const uchar *buf;
116
117 buf = MFILE_DATA(inf);
118 MFILE_STEP(inf, 2);
119
120 return (ushort(buf[0]) << 8) + (ushort(buf[1]) << 0);
121}
122
124{
125 const uchar *buf;
126
127 buf = MFILE_DATA(mofs);
128 MFILE_STEP(mofs, 4);
129
130 return (uint(buf[0]) << 24) + (uint(buf[1]) << 16) + (uint(buf[2]) << 8) + (uint(buf[3]) << 0);
131}
132
133static void putshort(FILE *outf, ushort val)
134{
135 uchar buf[2];
136
137 buf[0] = (val >> 8);
138 buf[1] = (val >> 0);
139 fwrite(buf, 2, 1, outf);
140}
141
142static int putlong(FILE *outf, uint val)
143{
144 uchar buf[4];
145
146 buf[0] = (val >> 24);
147 buf[1] = (val >> 16);
148 buf[2] = (val >> 8);
149 buf[3] = (val >> 0);
150 return fwrite(buf, 4, 1, outf);
151}
152
153static void readheader(MFileOffset *inf, IMAGE *image)
154{
155 memset(image, 0, sizeof(IMAGE));
156 image->imagic = getshort(inf);
157 image->type = getshort(inf);
158 image->dim = getshort(inf);
159 image->xsize = getshort(inf);
160 image->ysize = getshort(inf);
161 image->zsize = getshort(inf);
162}
163
164static int writeheader(FILE *outf, const IMAGE *image)
165{
166 IMAGE t = {0};
167
168 fwrite(&t, sizeof(IMAGE), 1, outf);
169 fseek(outf, 0, SEEK_SET);
170 putshort(outf, image->imagic);
171 putshort(outf, image->type);
172 putshort(outf, image->dim);
173 putshort(outf, image->xsize);
174 putshort(outf, image->ysize);
175 putshort(outf, image->zsize);
176 putlong(outf, image->min);
177 putlong(outf, image->max);
178 putlong(outf, 0);
179 return fwrite("no name", 8, 1, outf);
180}
181
182static int writetab(FILE *outf, const uint *tab, int len)
183{
184 int r = 0;
185
186 while (len) {
187 r = putlong(outf, *tab++);
188 len -= 4;
189 }
190 return r;
191}
192
193static void readtab(MFileOffset *inf, uint *tab, int len)
194{
195 while (len) {
196 *tab++ = getlong(inf);
197 len -= 4;
198 }
199}
200
201/* From misc_util: flip the bytes from x. */
202#define GS(x) (((uchar *)(x))[0] << 8 | ((uchar *)(x))[1])
203
204/* This one is only def-ed once, strangely... */
205#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
206
207bool imb_is_a_iris(const uchar *mem, size_t size)
208{
209 if (size < 2) {
210 return false;
211 }
212 return ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC));
213}
214
215ImBuf *imb_loadiris(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
216{
217 uint *base, *lptr = nullptr;
218 float *fbase, *fptr = nullptr;
219 const uchar *rledat;
220 const uchar *mem_end = mem + size;
221 MFileOffset _inf_data = {mem, 0}, *inf = &_inf_data;
222 IMAGE image;
223 int bpp, rle, cur, badorder;
224 ImBuf *ibuf = nullptr;
225 uchar dirty_flag = 0;
226
227 if (!imb_is_a_iris(mem, size)) {
228 return nullptr;
229 }
230
231 /* Could be part of the magic check above,
232 * by convention this check only requests the size needed to read it's magic though. */
233 if (size < HEADER_SIZE) {
234 return nullptr;
235 }
236
237 /* OCIO_TODO: only tested with 1 byte per pixel, not sure how to test with other settings */
239
240 readheader(inf, &image);
241 if (image.imagic != IMAGIC) {
242 fprintf(stderr, "longimagedata: bad magic number in image file\n");
243 return nullptr;
244 }
245
246 rle = ISRLE(image.type);
247 bpp = BPP(image.type);
248 if (!ELEM(bpp, 1, 2)) {
249 fprintf(stderr, "longimagedata: image must have 1 or 2 byte per pix chan\n");
250 return nullptr;
251 }
252 if (uint(image.zsize) > 8) {
253 fprintf(stderr, "longimagedata: channels over 8 not supported\n");
254 return nullptr;
255 }
256
257 const int xsize = image.xsize;
258 const int ysize = image.ysize;
259
260 const int zsize_file = image.zsize;
261 const int zsize_read = min_ii(image.zsize, 4);
262
263 if (flags & IB_test) {
264 ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0);
265 if (ibuf) {
266 ibuf->ftype = IMB_FTYPE_IMAGIC;
267 }
268 return ibuf;
269 }
270
271 if (rle) {
272 size_t tablen = size_t(ysize) * size_t(zsize_file) * sizeof(int);
274
275 uint *starttab = static_cast<uint *>(MEM_mallocN(tablen, "iris starttab"));
276 uint *lengthtab = static_cast<uint *>(MEM_mallocN(tablen, "iris endtab"));
277
278#define MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(p) \
279 if (UNLIKELY((p) > mem_end)) { \
280 dirty_flag |= DIRTY_FLAG_EOF; \
281 goto fail_rle; \
282 } \
283 ((void)0)
284
285 MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(MFILE_DATA(inf) + ((4 * 2) * tablen));
286
287 readtab(inf, starttab, tablen);
288 readtab(inf, lengthtab, tablen);
289
290 /* check data order */
291 cur = 0;
292 badorder = 0;
293 for (size_t y = 0; y < ysize; y++) {
294 for (size_t z = 0; z < zsize_file; z++) {
295 if (starttab[y + z * ysize] < cur) {
296 badorder = 1;
297 break;
298 }
299 cur = starttab[y + z * ysize];
300 }
301 if (badorder) {
302 break;
303 }
304 }
305
306 if (bpp == 1) {
307
308 ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize_read, IB_rect);
309 if (!ibuf) {
310 goto fail_rle;
311 }
312 if (ibuf->planes > 32) {
313 ibuf->planes = 32;
314 }
315 base = (uint *)ibuf->byte_buffer.data;
316
317 if (badorder) {
318 for (size_t z = 0; z < zsize_read; z++) {
319 lptr = base;
320 for (size_t y = 0; y < ysize; y++) {
321 MFILE_SEEK(inf, starttab[y + z * ysize]);
322 rledat = MFILE_DATA(inf);
323 MFILE_STEP(inf, lengthtab[y + z * ysize]);
324 const uchar *rledat_next = MFILE_DATA(inf);
325 uint *lptr_next = lptr + xsize;
327 dirty_flag |= expandrow((uchar *)lptr, (uchar *)lptr_next, rledat, rledat_next, 3 - z);
328 lptr = lptr_next;
329 }
330 }
331 }
332 else {
333 lptr = base;
334 for (size_t y = 0; y < ysize; y++) {
335
336 uint *lptr_next = lptr + xsize;
337
338 for (size_t z = 0; z < zsize_read; z++) {
339 MFILE_SEEK(inf, starttab[y + z * ysize]);
340 rledat = MFILE_DATA(inf);
341 MFILE_STEP(inf, lengthtab[y + z * ysize]);
342 const uchar *rledat_next = MFILE_DATA(inf);
344 if (z < 4) {
345 dirty_flag |= expandrow(
346 (uchar *)lptr, (uchar *)lptr_next, rledat, rledat_next, 3 - z);
347 }
348 else {
349 break;
350 }
351 }
352 lptr = lptr_next;
353 }
354 }
355 }
356 else { /* bpp == 2 */
357
358 ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect) | IB_rectfloat);
359 if (!ibuf) {
360 goto fail_rle;
361 }
362
363 fbase = ibuf->float_buffer.data;
364
365 if (badorder) {
366 for (size_t z = 0; z < zsize_read; z++) {
367 fptr = fbase;
368 for (size_t y = 0; y < ysize; y++) {
369 MFILE_SEEK(inf, starttab[y + z * ysize]);
370 rledat = MFILE_DATA(inf);
371 MFILE_STEP(inf, lengthtab[y + z * ysize]);
372 const uchar *rledat_next = MFILE_DATA(inf);
374 float *fptr_next = fptr + (xsize * 4);
375 dirty_flag |= expandrow2(fptr, fptr_next, rledat, rledat_next, 3 - z);
376 fptr = fptr_next;
377 }
378 }
379 }
380 else {
381 fptr = fbase;
382 float *fptr_next = fptr + (xsize * 4);
383
384 for (size_t y = 0; y < ysize; y++) {
385
386 for (size_t z = 0; z < zsize_read; z++) {
387 MFILE_SEEK(inf, starttab[y + z * ysize]);
388 rledat = MFILE_DATA(inf);
389 MFILE_STEP(inf, lengthtab[y + z * ysize]);
390 const uchar *rledat_next = MFILE_DATA(inf);
392 dirty_flag |= expandrow2(fptr, fptr_next, rledat, rledat_next, 3 - z);
393 }
394 fptr = fptr_next;
395 }
396 }
397 }
398#undef MFILE_CAPACITY_AT_PTR_OK_OR_FAIL
399 fail_rle:
400 MEM_freeN(starttab);
401 MEM_freeN(lengthtab);
402
403 if (!ibuf) {
404 return nullptr;
405 }
406 }
407 else {
408
409#define MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(p) \
410 if (UNLIKELY((p) > mem_end)) { \
411 dirty_flag |= DIRTY_FLAG_EOF; \
412 goto fail_uncompressed; \
413 } \
414 ((void)0)
415
416 if (bpp == 1) {
417
418 ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize_read, IB_rect);
419 if (!ibuf) {
420 goto fail_uncompressed;
421 }
422 if (ibuf->planes > 32) {
423 ibuf->planes = 32;
424 }
425
426 base = (uint *)ibuf->byte_buffer.data;
427
429 rledat = MFILE_DATA(inf);
430
431 for (size_t z = 0; z < zsize_read; z++) {
432
433 if (z < 4) {
434 lptr = base;
435 }
436 else {
437 break;
438 }
439
440 for (size_t y = 0; y < ysize; y++) {
441 const uchar *rledat_next = rledat + xsize;
442 const int z_ofs = 3 - z;
443 MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next + z_ofs);
444 interleaverow((uchar *)lptr, rledat, z_ofs, xsize);
445 rledat = rledat_next;
446 lptr += xsize;
447 }
448 }
449 }
450 else { /* bpp == 2 */
451
452 ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect) | IB_rectfloat);
453 if (!ibuf) {
454 goto fail_uncompressed;
455 }
456
457 fbase = ibuf->float_buffer.data;
458
460 rledat = MFILE_DATA(inf);
461
462 for (size_t z = 0; z < zsize_read; z++) {
463
464 fptr = fbase;
465
466 for (size_t y = 0; y < ysize; y++) {
467 const uchar *rledat_next = rledat + xsize * 2;
468 const int z_ofs = 3 - z;
469 MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(rledat_next + z_ofs);
470 interleaverow2(fptr, rledat, z_ofs, xsize);
471 rledat = rledat_next;
472 fptr += xsize * 4;
473 }
474 }
475 }
476#undef MFILE_CAPACITY_AT_PTR_OK_OR_FAIL
477 fail_uncompressed:
478 if (!ibuf) {
479 return nullptr;
480 }
481 }
482
483 if (bpp == 1) {
484 uchar *rect;
485
486 if (image.zsize == 1) {
487 rect = ibuf->byte_buffer.data;
488 for (size_t x = size_t(ibuf->x) * size_t(ibuf->y); x > 0; x--) {
489 rect[0] = 255;
490 rect[1] = rect[2] = rect[3];
491 rect += 4;
492 }
493 }
494 else if (image.zsize == 2) {
495 /* Gray-scale with alpha. */
496 rect = ibuf->byte_buffer.data;
497 for (size_t x = size_t(ibuf->x) * size_t(ibuf->y); x > 0; x--) {
498 rect[0] = rect[2];
499 rect[1] = rect[2] = rect[3];
500 rect += 4;
501 }
502 }
503 else if (image.zsize == 3) {
504 /* add alpha */
505 rect = ibuf->byte_buffer.data;
506 for (size_t x = size_t(ibuf->x) * size_t(ibuf->y); x > 0; x--) {
507 rect[0] = 255;
508 rect += 4;
509 }
510 }
511 }
512 else { /* bpp == 2 */
513
514 if (image.zsize == 1) {
515 fbase = ibuf->float_buffer.data;
516 for (size_t x = size_t(ibuf->x) * size_t(ibuf->y); x > 0; x--) {
517 fbase[0] = 1;
518 fbase[1] = fbase[2] = fbase[3];
519 fbase += 4;
520 }
521 }
522 else if (image.zsize == 2) {
523 /* Gray-scale with alpha. */
524 fbase = ibuf->float_buffer.data;
525 for (size_t x = size_t(ibuf->x) * size_t(ibuf->y); x > 0; x--) {
526 fbase[0] = fbase[2];
527 fbase[1] = fbase[2] = fbase[3];
528 fbase += 4;
529 }
530 }
531 else if (image.zsize == 3) {
532 /* add alpha */
533 fbase = ibuf->float_buffer.data;
534 for (size_t x = size_t(ibuf->x) * size_t(ibuf->y); x > 0; x--) {
535 fbase[0] = 1;
536 fbase += 4;
537 }
538 }
539
540 if (flags & IB_rect) {
542 }
543 }
544
545 if (dirty_flag) {
546 fprintf(stderr, "longimagedata: corrupt file content (%d)\n", dirty_flag);
547 }
548 ibuf->ftype = IMB_FTYPE_IMAGIC;
549
550 if (ibuf->byte_buffer.data) {
552 }
553
554 return ibuf;
555}
556
557/* static utility functions for longimagedata */
558
559static void interleaverow(uchar *lptr, const uchar *cptr, int z, int n)
560{
561 lptr += z;
562 while (n--) {
563 *lptr = *cptr++;
564 lptr += 4;
565 }
566}
567
568static void interleaverow2(float *lptr, const uchar *cptr, int z, int n)
569{
570 lptr += z;
571 while (n--) {
572 *lptr = ((cptr[0] << 8) | (cptr[1] << 0)) / float(0xFFFF);
573 cptr += 2;
574 lptr += 4;
575 }
576}
577
578static int expandrow2(
579 float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z)
580{
581 ushort pixel, count;
582 float pixel_f;
583
584#define EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next) \
585 if (UNLIKELY(iptr_next > iptr_end)) { \
586 goto fail; \
587 } \
588 ((void)0)
589
590#define EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next) \
591 if (UNLIKELY(optr_next > optr_end)) { \
592 goto fail; \
593 } \
594 ((void)0)
595
596 optr += z;
597 optr_end += z;
598 while (true) {
599 const uchar *iptr_next = iptr + 2;
601 pixel = (iptr[0] << 8) | (iptr[1] << 0);
602 iptr = iptr_next;
603
604 if (!(count = (pixel & 0x7f))) {
605 return false;
606 }
607 const float *optr_next = optr + count;
609 if (pixel & 0x80) {
610 iptr_next = iptr + (count * 2);
612 while (count >= 8) {
613 optr[0 * 4] = ((iptr[0] << 8) | (iptr[1] << 0)) / float(0xFFFF);
614 optr[1 * 4] = ((iptr[2] << 8) | (iptr[3] << 0)) / float(0xFFFF);
615 optr[2 * 4] = ((iptr[4] << 8) | (iptr[5] << 0)) / float(0xFFFF);
616 optr[3 * 4] = ((iptr[6] << 8) | (iptr[7] << 0)) / float(0xFFFF);
617 optr[4 * 4] = ((iptr[8] << 8) | (iptr[9] << 0)) / float(0xFFFF);
618 optr[5 * 4] = ((iptr[10] << 8) | (iptr[11] << 0)) / float(0xFFFF);
619 optr[6 * 4] = ((iptr[12] << 8) | (iptr[13] << 0)) / float(0xFFFF);
620 optr[7 * 4] = ((iptr[14] << 8) | (iptr[15] << 0)) / float(0xFFFF);
621 optr += 8 * 4;
622 iptr += 8 * 2;
623 count -= 8;
624 }
625 while (count--) {
626 *optr = ((iptr[0] << 8) | (iptr[1] << 0)) / float(0xFFFF);
627 iptr += 2;
628 optr += 4;
629 }
630 BLI_assert(iptr == iptr_next);
631 }
632 else {
633 iptr_next = iptr + 2;
635 pixel_f = ((iptr[0] << 8) | (iptr[1] << 0)) / float(0xFFFF);
636 iptr = iptr_next;
637
638 while (count >= 8) {
639 optr[0 * 4] = pixel_f;
640 optr[1 * 4] = pixel_f;
641 optr[2 * 4] = pixel_f;
642 optr[3 * 4] = pixel_f;
643 optr[4 * 4] = pixel_f;
644 optr[5 * 4] = pixel_f;
645 optr[6 * 4] = pixel_f;
646 optr[7 * 4] = pixel_f;
647 optr += 8 * 4;
648 count -= 8;
649 }
650 while (count--) {
651 *optr = pixel_f;
652 optr += 4;
653 }
654 BLI_assert(iptr == iptr_next);
655 }
656 BLI_assert(optr == optr_next);
657 }
658 return false;
659
660#undef EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL
661#undef EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL
662fail:
663 return DIRTY_FLAG_ENCODING;
664}
665
666static int expandrow(
667 uchar *optr, const uchar *optr_end, const uchar *iptr, const uchar *iptr_end, int z)
668{
669 uchar pixel, count;
670
671#define EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next) \
672 if (UNLIKELY(iptr_next > iptr_end)) { \
673 goto fail; \
674 } \
675 ((void)0)
676
677#define EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next) \
678 if (UNLIKELY(optr_next > optr_end)) { \
679 goto fail; \
680 } \
681 ((void)0)
682
683 optr += z;
684 optr_end += z;
685 while (true) {
686 const uchar *iptr_next = iptr + 1;
688 pixel = *iptr;
689 iptr = iptr_next;
690 if (!(count = (pixel & 0x7f))) {
691 return false;
692 }
693 const uchar *optr_next = optr + (int(count) * 4);
695
696 if (pixel & 0x80) {
697 iptr_next = iptr + count;
699 while (count >= 8) {
700 optr[0 * 4] = iptr[0];
701 optr[1 * 4] = iptr[1];
702 optr[2 * 4] = iptr[2];
703 optr[3 * 4] = iptr[3];
704 optr[4 * 4] = iptr[4];
705 optr[5 * 4] = iptr[5];
706 optr[6 * 4] = iptr[6];
707 optr[7 * 4] = iptr[7];
708 optr += 8 * 4;
709 iptr += 8;
710 count -= 8;
711 }
712 while (count--) {
713 *optr = *iptr++;
714 optr += 4;
715 }
716 BLI_assert(iptr == iptr_next);
717 }
718 else {
719 iptr_next = iptr + 1;
721 pixel = *iptr++;
722 while (count >= 8) {
723 optr[0 * 4] = pixel;
724 optr[1 * 4] = pixel;
725 optr[2 * 4] = pixel;
726 optr[3 * 4] = pixel;
727 optr[4 * 4] = pixel;
728 optr[5 * 4] = pixel;
729 optr[6 * 4] = pixel;
730 optr[7 * 4] = pixel;
731 optr += 8 * 4;
732 count -= 8;
733 }
734 while (count--) {
735 *optr = pixel;
736 optr += 4;
737 }
738 BLI_assert(iptr == iptr_next);
739 }
740 BLI_assert(optr == optr_next);
741 }
742
743 return false;
744
745#undef EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL
746#undef EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL
747fail:
748 return DIRTY_FLAG_ENCODING;
749}
750
764static bool output_iris(const char *filepath,
765 const uint *lptr,
766 const int *zptr,
767 const int xsize,
768 const int ysize,
769 const int zsize)
770{
771 FILE *outf;
772 IMAGE *image;
773 int tablen, y, z, pos, len = 0;
774 uint *starttab, *lengthtab;
775 uchar *rlebuf;
776 uint *lumbuf;
777 int rlebuflen, goodwrite;
778
779 goodwrite = 1;
780 outf = BLI_fopen(filepath, "wb");
781 if (!outf) {
782 return false;
783 }
784
785 tablen = ysize * zsize * sizeof(int);
786
787 image = (IMAGE *)MEM_mallocN(sizeof(IMAGE), "iris image");
788 starttab = (uint *)MEM_mallocN(tablen, "iris starttab");
789 lengthtab = (uint *)MEM_mallocN(tablen, "iris lengthtab");
790 rlebuflen = 1.05 * xsize + 10;
791 rlebuf = (uchar *)MEM_mallocN(rlebuflen, "iris rlebuf");
792 lumbuf = (uint *)MEM_mallocN(xsize * sizeof(int), "iris lumbuf");
793
794 memset(image, 0, sizeof(IMAGE));
795 image->imagic = IMAGIC;
796 image->type = RLE(1);
797 if (zsize > 1) {
798 image->dim = 3;
799 }
800 else {
801 image->dim = 2;
802 }
803 image->xsize = xsize;
804 image->ysize = ysize;
805 image->zsize = zsize;
806 image->min = 0;
807 image->max = 255;
808 goodwrite *= writeheader(outf, image);
809 fseek(outf, HEADER_SIZE + (2 * tablen), SEEK_SET);
810 pos = HEADER_SIZE + (2 * tablen);
811
812 for (y = 0; y < ysize; y++) {
813 for (z = 0; z < zsize; z++) {
814
815 if (zsize == 1) {
816 lumrow((const uchar *)lptr, (uchar *)lumbuf, xsize);
817 len = compressrow((const uchar *)lumbuf, rlebuf, CHANOFFSET(z), xsize);
818 }
819 else {
820 if (z < 4) {
821 len = compressrow((const uchar *)lptr, rlebuf, CHANOFFSET(z), xsize);
822 }
823 else if (z < 8 && zptr) {
824 len = compressrow((const uchar *)zptr, rlebuf, CHANOFFSET(z - 4), xsize);
825 }
826 }
827
828 BLI_assert_msg(len <= rlebuflen, "The length calculated for 'rlebuflen' was too small!");
829
830 goodwrite *= fwrite(rlebuf, len, 1, outf);
831 starttab[y + z * ysize] = pos;
832 lengthtab[y + z * ysize] = len;
833 pos += len;
834 }
835 lptr += xsize;
836 if (zptr) {
837 zptr += xsize;
838 }
839 }
840
841 fseek(outf, HEADER_SIZE, SEEK_SET);
842 goodwrite *= writetab(outf, starttab, tablen);
843 goodwrite *= writetab(outf, lengthtab, tablen);
844 MEM_freeN(image);
845 MEM_freeN(starttab);
846 MEM_freeN(lengthtab);
847 MEM_freeN(rlebuf);
848 MEM_freeN(lumbuf);
849 fclose(outf);
850 if (goodwrite) {
851 return true;
852 }
853
854 fprintf(stderr, "output_iris: not enough space for image!!\n");
855 return false;
856}
857
858/* static utility functions for output_iris */
859
860static void lumrow(const uchar *rgbptr, uchar *lumptr, int n)
861{
862 lumptr += CHANOFFSET(0);
863 while (n--) {
864 *lumptr = ILUM(rgbptr[OFFSET_R], rgbptr[OFFSET_G], rgbptr[OFFSET_B]);
865 lumptr += 4;
866 rgbptr += 4;
867 }
868}
869
870static int compressrow(const uchar *lbuf, uchar *rlebuf, const int z, const int row_len)
871{
872 const uchar *iptr, *ibufend, *sptr;
873 uchar *optr;
874 short todo, cc;
875 int count;
876
877 lbuf += z;
878 iptr = lbuf;
879 ibufend = iptr + row_len * 4;
880 optr = rlebuf;
881
882 while (iptr < ibufend) {
883 sptr = iptr;
884 iptr += 8;
885 while ((iptr < ibufend) && ((iptr[-8] != iptr[-4]) || (iptr[-4] != iptr[0]))) {
886 iptr += 4;
887 }
888 iptr -= 8;
889 count = (iptr - sptr) / 4;
890 while (count) {
891 todo = count > 126 ? 126 : count;
892 count -= todo;
893 *optr++ = 0x80 | todo;
894 while (todo > 8) {
895 optr[0] = sptr[0 * 4];
896 optr[1] = sptr[1 * 4];
897 optr[2] = sptr[2 * 4];
898 optr[3] = sptr[3 * 4];
899 optr[4] = sptr[4 * 4];
900 optr[5] = sptr[5 * 4];
901 optr[6] = sptr[6 * 4];
902 optr[7] = sptr[7 * 4];
903
904 optr += 8;
905 sptr += 8 * 4;
906 todo -= 8;
907 }
908 while (todo--) {
909 *optr++ = *sptr;
910 sptr += 4;
911 }
912 }
913 sptr = iptr;
914 cc = *iptr;
915 iptr += 4;
916 while ((iptr < ibufend) && (*iptr == cc)) {
917 iptr += 4;
918 }
919 count = (iptr - sptr) / 4;
920 while (count) {
921 todo = count > 126 ? 126 : count;
922 count -= todo;
923 *optr++ = todo;
924 *optr++ = cc;
925 }
926 }
927 *optr++ = 0;
928 return optr - (uchar *)rlebuf;
929}
930
931bool imb_saveiris(ImBuf *ibuf, const char *filepath, int /*flags*/)
932{
933 const short zsize = (ibuf->planes + 7) >> 3;
934
936
937 const bool ok = output_iris(
938 filepath, (uint *)ibuf->byte_buffer.data, nullptr, ibuf->x, ibuf->y, zsize);
939
940 /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */
942
943 return ok;
944}
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:87
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
MINLINE int min_ii(int a, int b)
unsigned char uchar
unsigned short ushort
unsigned int uint
#define ELEM(...)
@ COLOR_ROLE_DEFAULT_BYTE
void IMB_rect_from_float(ImBuf *ibuf)
Definition divers.cc:694
#define IM_MAX_SPACE
Definition IMB_imbuf.hh:49
void IMB_convert_rgba_to_abgr(ImBuf *ibuf)
@ IMB_FTYPE_IMAGIC
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
@ IB_test
@ IB_rect
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
void colorspace_set_default_role(char *colorspace, int size, int role)
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
int count
static bool output_iris(const char *filepath, const uint *lptr, const int *zptr, const int xsize, const int ysize, const int zsize)
Definition iris.cc:764
#define ILUM(r, g, b)
Definition iris.cc:46
#define OFFSET_R
Definition iris.cc:48
#define DIRTY_FLAG_ENCODING
Definition iris.cc:87
bool imb_saveiris(ImBuf *ibuf, const char *filepath, int)
Definition iris.cc:931
static void interleaverow(uchar *lptr, const uchar *cptr, int z, int n)
Definition iris.cc:559
ImBuf * imb_loadiris(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition iris.cc:215
bool imb_is_a_iris(const uchar *mem, size_t size)
Definition iris.cc:207
#define BPP(type)
Definition iris.cc:61
static int expandrow2(float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z)
Definition iris.cc:578
static void putshort(FILE *outf, ushort val)
Definition iris.cc:133
static int writeheader(FILE *outf, const IMAGE *image)
Definition iris.cc:164
static uint getlong(MFileOffset *mofs)
Definition iris.cc:123
#define EXPAND_CAPACITY_AT_OUTPUT_OK_OR_FAIL(optr_next)
#define HEADER_SIZE
Definition iris.cc:38
static void lumrow(const uchar *rgbptr, uchar *lumptr, int n)
Definition iris.cc:860
#define ISRLE(type)
Definition iris.cc:59
static int expandrow(uchar *optr, const uchar *optr_end, const uchar *iptr, const uchar *iptr_end, int z)
Definition iris.cc:666
#define OFFSET_B
Definition iris.cc:50
#define GSS(x)
Definition iris.cc:205
#define CHANOFFSET(z)
Definition iris.cc:53
#define OFFSET_G
Definition iris.cc:49
static ushort getshort(MFileOffset *inf)
Definition iris.cc:113
static int compressrow(const uchar *lbuf, uchar *rlebuf, int z, int row_len)
Definition iris.cc:870
#define MFILE_STEP(inf, step)
Definition iris.cc:74
static void readtab(MFileOffset *inf, uint *tab, int len)
Definition iris.cc:193
static void interleaverow2(float *lptr, const uchar *cptr, int z, int n)
Definition iris.cc:568
#define GS(x)
Definition iris.cc:202
static int writetab(FILE *outf, const uint *tab, int len)
Definition iris.cc:182
#define MFILE_DATA(inf)
Definition iris.cc:73
#define MFILE_CAPACITY_AT_PTR_OK_OR_FAIL(p)
static int putlong(FILE *outf, uint val)
Definition iris.cc:142
#define EXPAND_CAPACITY_AT_INPUT_OK_OR_FAIL(iptr_next)
#define IMAGIC
Definition iris.cc:21
#define MFILE_SEEK(inf, pos)
Definition iris.cc:79
#define RLE(bpp)
Definition iris.cc:62
static void readheader(MFileOffset *inf, IMAGE *image)
Definition iris.cc:153
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
Definition iris.cc:23
uint colormap
Definition iris.cc:34
ushort ysize
Definition iris.cc:28
uchar _pad2[404]
Definition iris.cc:35
ushort xsize
Definition iris.cc:27
uint max
Definition iris.cc:31
ushort imagic
Definition iris.cc:24
ushort type
Definition iris.cc:25
uint min
Definition iris.cc:30
uchar _pad1[4]
Definition iris.cc:32
ushort dim
Definition iris.cc:26
ushort zsize
Definition iris.cc:29
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
enum eImbFileType ftype
uint _file_offset
Definition iris.cc:70
const uchar * _file_data
Definition iris.cc:69