OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
ojph_img_io.cpp
Go to the documentation of this file.
1//***************************************************************************/
2// This software is released under the 2-Clause BSD license, included
3// below.
4//
5// Copyright (c) 2019, Aous Naman
6// Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
7// Copyright (c) 2019, The University of New South Wales, Australia
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// 1. Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//
16// 2. Redistributions in binary form must reproduce the above copyright
17// notice, this list of conditions and the following disclaimer in the
18// documentation and/or other materials provided with the distribution.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31//***************************************************************************/
32// This file is part of the OpenJPH software implementation.
33// File: ojph_img_io.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38
39#include <cstdlib>
40#include <cstring>
41
42#include "ojph_file.h"
43#include "ojph_img_io.h"
44#include "ojph_mem.h"
45#include "ojph_message.h"
46
47namespace ojph {
48
50 // Static functions
52
54 static
55 ui16 be2le(const ui16 v)
56 {
57 return (ui16)((v<<8) | (v>>8));
58 }
59
61 static inline
62 ui32 be2le(const ui32 t)
63 {
64 ui32 u = be2le((ui16)(t & 0xFFFFu));
65 u <<= 16;
66 u |= be2le((ui16)(t >> 16));
67 return u;
68 }
69
71 static
72 void eat_white_spaces(FILE *fh)
73 {
74 int c = fgetc(fh);
75 while(1)
76 {
77 if (c == ' ' || c == '\r' || c == '\n' || c == '\t')
78 c = fgetc(fh);
79 else if (c == '#')
80 {
81 while (c != '\n') c = fgetc(fh);
82 }
83 else
84 {
85 ungetc(c, fh);
86 break;
87 }
88 }
89 }
90
92 //
93 //
94 // Accelerators -- non-accelerating
95 //
96 //
98
99 void gen_cvrt_32b1c_to_8ub1c(const line_buf *ln0, const line_buf *ln1,
100 const line_buf *ln2, void *dp,
101 ui32 bit_depth, ui32 count)
102 {
103 ojph_unused(ln1);
104 ojph_unused(ln2);
105
106 int max_val = (1 << bit_depth) - 1;
107 const si32 *sp = ln0->i32;
108 ui8* p = (ui8 *)dp;
109 for ( ; count > 0; --count)
110 {
111 int val = *sp++;
112 val = val >= 0 ? val : 0;
113 val = val <= max_val ? val : max_val;
114 *p++ = (ui8)val;
115 }
116 }
117
118 void gen_cvrt_32b3c_to_8ub3c(const line_buf *ln0, const line_buf *ln1,
119 const line_buf *ln2, void *dp,
120 ui32 bit_depth, ui32 count)
121 {
122 int max_val = (1<<bit_depth) - 1;
123 const si32 *sp0 = ln0->i32;
124 const si32 *sp1 = ln1->i32;
125 const si32 *sp2 = ln2->i32;
126 ui8* p = (ui8 *)dp;
127 for (; count > 0; --count)
128 {
129 int val;
130 val = *sp0++;
131 val = val >= 0 ? val : 0;
132 val = val <= max_val ? val : max_val;
133 *p++ = (ui8) val;
134 val = *sp1++;
135 val = val >= 0 ? val : 0;
136 val = val <= max_val ? val : max_val;
137 *p++ = (ui8) val;
138 val = *sp2++;
139 val = val >= 0 ? val : 0;
140 val = val <= max_val ? val : max_val;
141 *p++ = (ui8) val;
142 }
143 }
144
145 void gen_cvrt_32b1c_to_16ub1c_le(const line_buf *ln0, const line_buf *ln1,
146 const line_buf *ln2, void *dp,
147 ui32 bit_depth, ui32 count)
148 {
149 ojph_unused(ln1);
150 ojph_unused(ln2);
151 int max_val = (1<<bit_depth) - 1;
152 const si32 *sp = ln0->i32;
153 ui16* p = (ui16*)dp;
154 for (; count > 0; --count)
155 {
156 int val = *sp++;
157 val = val >= 0 ? val : 0;
158 val = val <= max_val ? val : max_val;
159 *p++ = (ui16) val;
160 }
161 }
162
163 void gen_cvrt_32b3c_to_16ub3c_le(const line_buf *ln0, const line_buf *ln1,
164 const line_buf *ln2, void *dp,
165 ui32 bit_depth, ui32 count)
166 {
167 int max_val = (1<<bit_depth) - 1;
168 const si32 *sp0 = ln0->i32;
169 const si32 *sp1 = ln1->i32;
170 const si32 *sp2 = ln2->i32;
171 ui16* p = (ui16*)dp;
172 for (; count > 0; --count)
173 {
174 int val;
175 val = *sp0++;
176 val = val >= 0 ? val : 0;
177 val = val <= max_val ? val : max_val;
178 *p++ = (ui16) val;
179 val = *sp1++;
180 val = val >= 0 ? val : 0;
181 val = val <= max_val ? val : max_val;
182 *p++ = (ui16) val;
183 val = *sp2++;
184 val = val >= 0 ? val : 0;
185 val = val <= max_val ? val : max_val;
186 *p++ = (ui16) val;
187 }
188 }
189
190 void gen_cvrt_32b1c_to_16ub1c_be(const line_buf *ln0, const line_buf *ln1,
191 const line_buf *ln2, void *dp,
192 ui32 bit_depth, ui32 count)
193 {
194 ojph_unused(ln1);
195 ojph_unused(ln2);
196 int max_val = (1<<bit_depth) - 1;
197 const si32 *sp = ln0->i32;
198 ui16* p = (ui16*)dp;
199 for (; count > 0; --count)
200 {
201 int val = *sp++;
202 val = val >= 0 ? val : 0;
203 val = val <= max_val ? val : max_val;
204 *p++ = be2le((ui16) val);
205 }
206 }
207
208 void gen_cvrt_32b3c_to_16ub3c_be(const line_buf *ln0, const line_buf *ln1,
209 const line_buf *ln2, void *dp,
210 ui32 bit_depth, ui32 count)
211 {
212 int max_val = (1<<bit_depth) - 1;
213 const si32 *sp0 = ln0->i32;
214 const si32 *sp1 = ln1->i32;
215 const si32 *sp2 = ln2->i32;
216 ui16* p = (ui16*)dp;
217 for (; count > 0; --count)
218 {
219 int val;
220 val = *sp0++;
221 val = val >= 0 ? val : 0;
222 val = val <= max_val ? val : max_val;
223 *p++ = be2le((ui16) val);
224 val = *sp1++;
225 val = val >= 0 ? val : 0;
226 val = val <= max_val ? val : max_val;
227 *p++ = be2le((ui16) val);
228 val = *sp2++;
229 val = val >= 0 ? val : 0;
230 val = val <= max_val ? val : max_val;
231 *p++ = be2le((ui16) val);
232 }
233 }
234
235
237 //
238 //
239 //
240 //
241 //
243
245 void ppm_in::open(const char *filename)
246 {
247 assert(fh == 0);
248 fh = fopen(filename, "rb");
249 if (fh == 0)
250 OJPH_ERROR(0x03000001, "Unable to open file %s", filename);
251 fname = filename;
252
253 // read magic number
254 char t[2];
255 if (fread(t, 1, 2, fh) != 2)
256 {
257 close();
258 OJPH_ERROR(0x03000002, "Error reading file %s", filename);
259 }
260
261 // check magic number
262 if (t[0] != 'P' || (t[1] != '5' && t[1] != '6'))
263 {
264 close();
265 OJPH_ERROR(0x03000003, "unknown file type for file %s", filename);
266 }
267
268 size_t len = strlen(filename);
269 if (t[1] == '5' && strncmp(filename + len - 4, ".pgm", 4) != 0)
270 {
271 close();
272 OJPH_ERROR(0x03000004, "wrong file extension, a file with "
273 "keyword P5 must have a .pgm extension for file %s", filename);
274 }
275 if (t[1] == '6' && strncmp(filename + len - 4, ".ppm", 4) != 0)
276 {
277 close();
278 OJPH_ERROR(0x03000005, "wrong file extension, a file with keyword P6 "
279 "must have a .ppm extension for file %s", filename);
280 }
281
282 // set number of components based on file-type
283 num_comps = t[1] == '5' ? 1 : 3;
285
286 // read width, height and max value in header
287 if (fscanf(fh, "%d %d %d", &width, &height, &max_val) != 3)
288 {
289 close();
290 OJPH_ERROR(0x03000006, "error in file format for file %s", filename);
291 }
293 bytes_per_sample = max_val > 255 ? 2 : 1;
296 fgetc(fh);
298
299 // allocate linebuffer to hold a line of image data
301 {
302 if (alloc_p == NULL)
303 {
305 void* t = temp_buf;
306 if (temp_buf)
308 else
310 if (temp_buf == NULL) { // failed to allocate memory
311 if (t) free(t); // the original buffer is still valid
312 OJPH_ERROR(0x03000007, "error allocating memory");
313 }
314 }
315 else
316 {
317 assert(temp_buf_byte_size == 0); //cannot reallocate the buffer
320 }
321 }
322 cur_line = 0;
323 }
324
327 {
328 if (alloc_p == NULL)
329 return;
330
331 if (bytes_per_sample == 1)
333 else
335 }
336
338 ui32 ppm_in::read(const line_buf* line, ui32 comp_num)
339 {
340 assert(temp_buf_byte_size != 0 && fh != 0 && comp_num < num_comps);
341 assert(line->size >= width);
342
343 if (planar || comp_num == 0)
344 {
345 size_t result = fread(
347 if (result != num_ele_per_line)
348 {
349 close();
350 OJPH_ERROR(0x03000011, "not enough data in file %s", fname);
351 }
352 if (++cur_line >= height)
353 {
354 cur_line = 0;
355 ojph_fseek(fh, start_of_data, SEEK_SET); //handles plannar reading
356 }
357 }
358
359 if (bytes_per_sample == 1)
360 {
361 const ui8* sp = (ui8*)temp_buf + comp_num;
362 si32* dp = line->i32;
363 for (ui32 i = width; i > 0; --i, sp+=num_comps)
364 *dp++ = (si32)*sp;
365 }
366 else
367 {
368 const ui16* sp = (ui16*)temp_buf + comp_num;
369 si32* dp = line->i32;
370 for (ui32 i = width; i > 0; --i, sp+=num_comps)
371 *dp++ = (si32)be2le(*sp);
372 }
373
374 return width;
375 }
376
378 //
379 //
380 //
381 //
382 //
384
386 void ppm_out::open(char* filename)
387 {
388 assert(fh == NULL && buffer == NULL);
389 if (num_components == 1)
390 {
391 size_t len = strlen(filename);
392 if (len >= 4)
393 {
394 if (strncmp(".ppm", filename + len - 4, 4) == 0)
395 {
396 filename[len - 2] = 'g';
397 OJPH_WARN(0x03000021, "file was renamed %s\n", filename);
398 }
399 if (strncmp(".PPM", filename + len - 4, 4) == 0)
400 {
401 filename[len - 2] = 'G';
402 OJPH_WARN(0x03000022, "file was renamed %s\n", filename);
403 }
404 }
405 fh = fopen(filename, "wb");
406 if (fh == NULL)
407 OJPH_ERROR(0x03000023,
408 "unable to open file %s for writing", filename);
409
410 fprintf(fh, "P5\n%d %d\n%d\n", width, height, (1 << bit_depth) - 1);
412 buffer = (ui8*)malloc(buffer_size);
413 }
414 else
415 {
416 size_t len = strlen(filename);
417 if (len >= 4)
418 {
419 if (strncmp(".pgm", filename + len - 4, 4) == 0)
420 {
421 filename[len - 2] = 'p';
422 OJPH_WARN(0x03000024, "file was renamed %s\n", filename);
423 }
424 if (strncmp(".PGM", filename + len - 4, 4) == 0)
425 {
426 filename[len - 2] = 'P';
427 OJPH_WARN(0x03000025, "file was renamed %s\n", filename);
428 }
429 }
430 fh = fopen(filename, "wb");
431 if (fh == NULL)
432 OJPH_ERROR(0x03000026,
433 "unable to open file %s for writing", filename);
434 int result = //the number of written characters
435 fprintf(fh, "P6\n%d %d\n%d\n", width, height, (1 << bit_depth) - 1);
436 if (result == 0)
437 OJPH_ERROR(0x03000027, "error writing to file %s", filename);
438 buffer_size = (size_t)width * num_components * (size_t)bytes_per_sample;
439 buffer = (ui8*)malloc(buffer_size);
440 }
441 fname = filename;
442 cur_line = 0;
443 }
444
446 void ppm_out::configure(ui32 width, ui32 height, ui32 num_components,
447 ui32 bit_depth)
448 {
449 assert(fh == NULL); //configure before opening
450 if (num_components != 1 && num_components != 3)
451 OJPH_ERROR(0x03000031,
452 "ppm supports 3 colour components, while pgm supports 1");
453 this->width = width;
454 this->height = height;
455 this->num_components = num_components;
456 this->bit_depth = bit_depth;
457 bytes_per_sample = 1 + (bit_depth > 8 ? 1 : 0);
460
461#if !defined(OJPH_ENABLE_WASM_SIMD) || !defined(OJPH_EMSCRIPTEN)
462
463 if (bytes_per_sample == 1) {
464 if (num_components == 1)
466 else
468 }
469 else {
470 if (num_components == 1)
472 else
474 }
475
476 #ifndef OJPH_DISABLE_SIMD
477
478 #if (defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
479
480 #ifndef OJPH_DISABLE_SSE4
482 if (bytes_per_sample == 1) {
483 if (num_components == 1)
485 else
487 }
488 else {
489 if (num_components == 1)
491 else
493 }
494 }
495 #endif // !OJPH_DISABLE_SSE4
496
497 #ifndef OJPH_DISABLE_AVX2
499 if (bytes_per_sample == 1) {
500 if (num_components == 1)
502 else
504 }
505 else {
506 if (num_components == 1)
508 else
509 { } // did not find an implementation better than sse41
510 }
511 }
512 #endif // !OJPH_DISABLE_AVX2
513
514 #elif defined(OJPH_ARCH_ARM)
515
516 #endif // !(defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
517
518 #endif // !OJPH_DISABLE_SIMD
519
520#else // OJPH_ENABLE_WASM_SIMD
521
522 if (bytes_per_sample == 1) {
523 if (num_components == 1)
525 else
527 }
528 else {
529 if (num_components == 1)
531 else
533 }
534
535#endif // !OJPH_ENABLE_WASM_SIMD
536 }
537
539 ui32 ppm_out::write(const line_buf* line, ui32 comp_num)
540 {
541 assert(fh);
542
543 lptr[comp_num] = line;
544 if (comp_num == num_components - 1)
545 {
546 assert(lptr[0] != lptr[1]);
547 assert((lptr[1]!=lptr[2] && num_components==3) || num_components==1);
549 size_t result = fwrite(buffer,
551 if (result != samples_per_line)
552 OJPH_ERROR(0x03000041, "error writing to file %s", fname);
553 }
554 return 0;
555 }
556
558 //
559 //
560 //
561 //
562 //
564
566 void pfm_in::open(const char *filename)
567 {
568 assert(fh == 0);
569 fh = fopen(filename, "rb");
570 if (fh == 0)
571 OJPH_ERROR(0x03000051, "Unable to open file %s", filename);
572 fname = filename;
573
574 // read magic number
575 char t[2];
576 if (fread(t, 1, 2, fh) != 2)
577 {
578 close();
579 OJPH_ERROR(0x03000052, "Error reading file %s", filename);
580 }
581
582 // check magic number
583 if (t[0] != 'P' || (t[1] != 'F' && t[1] != 'f'))
584 {
585 close();
586 OJPH_ERROR(0x03000053, "Unknown file type for file %s", filename);
587 }
588
589 // set number of components based on file-type
590 num_comps = t[1] == 'f' ? 1 : 3;
592
593 // read width, height and max value in header
594 if (fscanf(fh, "%d %d", &width, &height) != 2)
595 {
596 close();
597 OJPH_ERROR(0x03000054,
598 "Error reading width and height in file %s", filename);
599 }
601
602 // little or big-endian
603 if (fscanf(fh, "%f", &scale) != 1)
604 {
605 close();
606 OJPH_ERROR(0x03000055, "Error reading scale in file %s", filename);
607 }
608 little_endian = scale < 0.0f;
609 scale = std::abs(scale);
610
611 fgetc(fh);
613
614 // alloc. linebuffer to hold a line of image data, if more than 1 comp.
615 if (temp_buf_byte_size < num_comps * (size_t)width * sizeof(float))
616 {
617 if (alloc_p == NULL)
618 {
619 temp_buf_byte_size = num_comps * (size_t)width * sizeof(float);
620 void* t = temp_buf;
621 if (temp_buf)
622 temp_buf = (float*)realloc(temp_buf, temp_buf_byte_size);
623 else
624 temp_buf = (float*)malloc(temp_buf_byte_size);
625 if (temp_buf == NULL) { // failed to allocate memory
626 if (t) free(t); // the original buffer is still valid
627 OJPH_ERROR(0x03000056, "Error allocating memory");
628 }
629 }
630 else
631 {
632 assert(temp_buf_byte_size == 0); //cannot reallocate the buffer
633 temp_buf_byte_size = num_comps * (size_t)width * sizeof(float);
635 }
636 }
637 cur_line = 0;
638 }
639
642 {
643 if (alloc_p == NULL)
644 return;
645 temp_buf = alloc_p->post_alloc_data<float>(num_comps * (size_t)width, 0);
646 }
647
649 ui32 pfm_in::read(const line_buf* line, ui32 comp_num)
650 {
651 assert(temp_buf_byte_size != 0 );
652 assert(fh != 0 && comp_num < num_comps);
653 assert(line->size >= width);
654
655 if (comp_num == 0)
656 {
657 si64 loc = start_of_data;
658 loc += (size_t)(height-1 - cur_line) * (size_t)num_comps
659 * (size_t)width * sizeof(float);
660 if (ojph_fseek(fh, loc, SEEK_SET) != 0)
661 {
662 close();
663 OJPH_ERROR(0x03000061, "Error seeking in file %s", fname);
664 }
665 size_t result =
666 fread(temp_buf, sizeof(float), (size_t)num_comps * (size_t)width, fh);
667 if (result != (size_t)num_comps * (size_t)width)
668 {
669 close();
670 OJPH_ERROR(0x03000062, "Not enough data in file %s", fname);
671 }
672 if (++cur_line >= height)
673 cur_line = 0;
674 }
675
676 union {
677 si32* s;
678 ui32* u;
679 float* f;
680 } sp, dp;
681
682 if (little_endian)
683 {
684 ui32 shift = 32 - bit_depth[comp_num];
685 sp.f = temp_buf + comp_num;
686 dp.f = line->f32;
687 if (shift)
688 for (ui32 i = width; i > 0; --i, sp.f += num_comps)
689 {
690 si32 s = *sp.s;
691 s >>= shift;
692 *dp.s++ = s;
693 }
694 else
695 for (ui32 i = width; i > 0; --i, sp.f += num_comps)
696 *dp.f++ = *sp.f;
697 }
698 else {
699 ui32 shift = 32 - bit_depth[comp_num];
700 sp.f = temp_buf + comp_num;
701 dp.f = line->f32;
702 if (shift)
703 for (ui32 i = width; i > 0; --i, sp.f += num_comps) {
704 ui32 u = be2le(*sp.u);
705 si32 s = *(si32*)&u;
706 s >>= shift;
707 *dp.s++ = s;
708 }
709 else
710 for (ui32 i = width; i > 0; --i, sp.f += num_comps)
711 *dp.u++ = be2le(*sp.u);
712 }
713
714 return width;
715 }
716
718 //
719 //
720 //
721 //
722 //
724
726 void pfm_out::open(char* filename)
727 {
728 assert(fh == NULL && buffer == NULL);
729 fh = fopen(filename, "wb");
730 if (fh == NULL)
731 OJPH_ERROR(0x03000071,
732 "Unable to open file %s for writing", filename);
733 int result = //the number of written characters
734 fprintf(fh, "P%c\n%d %d\n%f\n",
735 num_components > 1 ? 'F' : 'f', width, height, scale);
736 if (result == 0)
737 OJPH_ERROR(0x03000072, "error writing to file %s", filename);
738 buffer_size = (size_t)width * num_components * sizeof(float);
739 buffer = (float*)malloc(buffer_size);
740 fname = filename;
741 cur_line = 0;
743 }
744
746 void pfm_out::configure(ui32 width, ui32 height, ui32 num_components,
747 float scale, ui32* bit_depth)
748 {
749 assert(fh == NULL); //configure before opening
750 if (num_components != 1 && num_components != 3)
751 OJPH_ERROR(0x03000081,
752 "pfm supports 1 or 3 colour components, not %d", num_components);
753 this->width = width;
754 this->height = height;
755 this->num_components = num_components;
756 this->scale = scale < 0.0f ? scale : -scale;
757 for (ui32 c = 0; c < num_components; ++c)
758 this->bit_depth[c] = bit_depth[c];
759 }
760
762 ui32 pfm_out::write(const line_buf* line, ui32 comp_num)
763 {
764 assert(fh);
765
766 ui32 shift = 32 - bit_depth[comp_num];
767 union {
768 ui32* u;
769 float* f;
770 } sp, dp;
771
772 dp.f = buffer + comp_num;
773 sp.f = line->f32;
774
775 if (shift)
776 for (ui32 i = width; i > 0; --i, dp.f += num_components, ++sp.f)
777 {
778 ui32 u = *sp.u;
779 u <<= shift;
780 *dp.u = u;
781 }
782 else
783 for (ui32 i = width; i > 0; --i, dp.f += num_components)
784 *dp.f = *sp.f++;
785
786 if (comp_num == num_components - 1)
787 {
788 size_t samples_per_line = num_components * (size_t)width;
789 si64 loc = start_of_data;
790 loc += (height - 1 - cur_line)* samples_per_line * sizeof(float);
791 if (ojph_fseek(fh, loc, SEEK_SET) != 0)
792 OJPH_ERROR(0x03000082, "Error seeking in file %s", fname);
793 size_t result = fwrite(buffer, sizeof(float), samples_per_line, fh);
794 if (result != samples_per_line)
795 OJPH_ERROR(0x03000083, "error writing to file %s", fname);
796 ++cur_line;
797 }
798
799 return 0;
800 }
801
803 //
804 //
805 //
806 //
807 //
809#ifdef OJPH_ENABLE_TIFF_SUPPORT
811 void tif_in::open(const char* filename)
812 {
813 tiff_handle = NULL;
814 if ((tiff_handle = TIFFOpen(filename, "r")) == NULL)
815 OJPH_ERROR(0x03000091, "Unable to open file %s", filename);
816 fname = filename;
817
818 ui32 tiff_width = 0;
819 ui32 tiff_height = 0;
820 TIFFGetField(tiff_handle, TIFFTAG_IMAGEWIDTH, &tiff_width);
821 TIFFGetField(tiff_handle, TIFFTAG_IMAGELENGTH, &tiff_height);
822
823 ui16 tiff_bits_per_sample = 0;
824 ui16 tiff_samples_per_pixel = 0;
825 TIFFGetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, &tiff_bits_per_sample);
826 TIFFGetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, &tiff_samples_per_pixel);
827 // some TIFs have tiff_samples_per_pixel=0 when it is a single channel
828 // image - set to 1
829 tiff_samples_per_pixel =
830 (tiff_samples_per_pixel < 1) ? 1 : tiff_samples_per_pixel;
831
832 ui16 tiff_planar_configuration = 0;
833 ui16 tiff_photometric = 0;
834 TIFFGetField(tiff_handle, TIFFTAG_PLANARCONFIG, &tiff_planar_configuration);
835 TIFFGetField(tiff_handle, TIFFTAG_PHOTOMETRIC, &tiff_photometric);
836
837 planar_configuration = tiff_planar_configuration;
838
839 ui16 tiff_compression = 0;
840 ui32 tiff_rows_per_strip = 0;
841 TIFFGetField(tiff_handle, TIFFTAG_COMPRESSION, &tiff_compression);
842 TIFFGetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, &tiff_rows_per_strip);
843
844 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE)
845 {
846 bytes_per_line = tiff_samples_per_pixel * TIFFScanlineSize64(tiff_handle);
847 }
848 else
849 {
850 bytes_per_line = TIFFScanlineSize64(tiff_handle);
851 }
852 // allocate linebuffer to hold a line of image data
853 line_buffer = malloc(bytes_per_line);
854 if (NULL == line_buffer)
855 OJPH_ERROR(0x03000092, "Unable to allocate %d bytes for line_buffer[] "
856 "for file %s", bytes_per_line, filename);
857
858 cur_line = 0;
859
860 // Error on known incompatilbe input formats
861 if( tiff_bits_per_sample != 8 && tiff_bits_per_sample != 16 )
862 {
863 OJPH_ERROR(0x03000093, "\nTIFF IO is currently limited"
864 " to files with TIFFTAG_BITSPERSAMPLE=8 and TIFFTAG_BITSPERSAMPLE=16 \n"
865 "input file = %s has TIFFTAG_BITSPERSAMPLE=%d",
866 filename, tiff_bits_per_sample);
867 }
868
869 if( TIFFIsTiled( tiff_handle ) )
870 {
871 OJPH_ERROR(0x03000094, "\nTIFF IO is currently limited to TIF files "
872 "without tiles. \nInput file %s has been detected as tiled", filename);
873 }
874
875 if(PHOTOMETRIC_RGB != tiff_photometric &&
876 PHOTOMETRIC_MINISBLACK != tiff_photometric )
877 {
878 OJPH_ERROR(0x03000095, "\nTIFF IO is currently limited to "
879 "TIFFTAG_PHOTOMETRIC=PHOTOMETRIC_MINISBLACK=%d and "
880 "PHOTOMETRIC_RGB=%d. \nInput file %s has been detected "
881 "TIFFTAG_PHOTOMETRIC=%d",
882 PHOTOMETRIC_MINISBLACK, PHOTOMETRIC_RGB, filename, tiff_photometric);
883 }
884
885 if( tiff_samples_per_pixel > 4 )
886 {
887 OJPH_ERROR(0x03000096, "\nTIFF IO is currently limited to "
888 "TIFFTAG_SAMPLESPERPIXEL=4 \nInput file %s has been detected with "
889 "TIFFTAG_SAMPLESPERPIXEL=%d",
890 filename, tiff_samples_per_pixel);
891 }
892
893 // set number of components based on tiff_samples_per_pixel
894 width = tiff_width;
895 height = tiff_height;
896 num_comps = tiff_samples_per_pixel;
897 bytes_per_sample = (tiff_bits_per_sample + 7) / 8;
898 for (ui32 comp_num = 0; comp_num < num_comps; comp_num++)
899 bit_depth[comp_num] = tiff_bits_per_sample;
900
901 // allocate intermediate linebuffers to hold a line of a single component
902 // of image data
903 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
904 bytes_per_sample == 1)
905 {
906 line_buffer_for_planar_support_uint8 =
907 (uint8_t*)calloc(width, sizeof(uint8_t));
908 if (NULL == line_buffer_for_planar_support_uint8)
909 OJPH_ERROR(0x03000097, "Unable to allocate %d bytes for "
910 "line_buffer_for_planar_support_uint8[] for file %s",
911 width * sizeof(uint8_t), filename);
912 }
913 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
914 bytes_per_sample == 2)
915 {
916 line_buffer_for_planar_support_uint16 =
917 (uint16_t*)calloc(width, sizeof(uint16_t));
918 if (NULL == line_buffer_for_planar_support_uint16)
919 OJPH_ERROR(0x03000098, "Unable to allocate %d bytes for "
920 "line_buffer_for_planar_support_uint16[] for file %s",
921 width * sizeof(uint16_t), filename);
922 }
923 }
924
926
928 void tif_in::set_bit_depth(ui32 num_bit_depths, ui32* bit_depth)
929 {
930 if (num_bit_depths < 1)
931 OJPH_ERROR(0x030000A1, "one or more bit_depths must be provided");
932 ui32 last_bd_idx = 0;
933 for (ui32 i = 0; i < 4; ++i)
934 {
935 ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
936 last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
937
938 if (bd > 32 || bd < 1)
939 {
940 OJPH_ERROR(0x030000A2,
941 "bit_depth = %d, this must be an integer from 1-32", bd);
942 }
943 this->bit_depth[i] = bd;
944 }
945 }
946
948 ui32 tif_in::read(const line_buf* line, ui32 comp_num)
949 {
950 assert(bytes_per_line != 0 && tiff_handle != 0 && comp_num < num_comps);
951 assert((ui32)line->size >= width);
952
953 // do a read from the file if this is the first component and therefore
954 // the first time trying to access this line
955 if (PLANARCONFIG_SEPARATE == planar_configuration && 0 == comp_num )
956 {
957 for (ui32 color = 0; color < num_comps; color++)
958 {
959 if (bytes_per_sample == 1)
960 {
961 TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint8,
962 cur_line, (ui16)color);
963 ui32 x = color;
964 uint8_t* line_buffer_of_interleaved_components =
965 (uint8_t*)line_buffer;
966 for (ui32 i = 0; i < width; i++, x += num_comps)
967 {
968 line_buffer_of_interleaved_components[x] =
969 line_buffer_for_planar_support_uint8[i];
970 }
971 }
972 else if (bytes_per_sample == 2)
973 {
974 TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint16,
975 cur_line, (ui16)color);
976 ui32 x = color;
977 ui16* line_buffer_of_interleaved_components = (ui16*)line_buffer;
978 for (ui32 i = 0; i < width; i++, x += num_comps)
979 {
980 line_buffer_of_interleaved_components[x] =
981 line_buffer_for_planar_support_uint16[i];
982 }
983 }
984 }
985 cur_line++;
986
987 }
988 else if (planar_configuration == PLANARCONFIG_CONTIG && 0 == comp_num)
989 {
990 TIFFReadScanline(tiff_handle, line_buffer, cur_line++);
991 }
992 if (cur_line >= height)
993 {
994 cur_line = 0;
995 }
996
997 if (bytes_per_sample == 1)
998 {
999 const ui8* sp = (ui8*)line_buffer + comp_num;
1000 si32* dp = line->i32;
1001 if (bit_depth[comp_num] == 8)
1002 {
1003 for (ui32 i = width; i > 0; --i, sp += num_comps)
1004 *dp++ = (si32)*sp;
1005 }
1006 else if (bit_depth[comp_num] < 8)
1007 {
1008 // read the desired precision from the MSBs
1009 const int bits_to_shift = 8 - (int)bit_depth[comp_num];
1010 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1011 for (ui32 i = width; i > 0; --i, sp += num_comps)
1012 *dp++ = (si32) (((*sp) >> bits_to_shift) & bit_mask);
1013 }
1014 else if (bit_depth[comp_num] > 8)
1015 {
1016 const int bits_to_shift = (int)bit_depth[comp_num] - 8;
1017 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1018 for (ui32 i = width; i > 0; --i, sp += num_comps)
1019 *dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
1020 }
1021 }
1022 else if(bytes_per_sample == 2)
1023 {
1024 if (bit_depth[comp_num] == 16)
1025 {
1026 const ui16* sp = (ui16*)line_buffer + comp_num;
1027 si32* dp = line->i32;
1028 for (ui32 i = width; i > 0; --i, sp += num_comps)
1029 *dp++ = (si32)*sp;
1030 }
1031 else if (bit_depth[comp_num] < 16)
1032 {
1033 // read the desired precision from the MSBs
1034 const int bits_to_shift = 16 - (int)bit_depth[comp_num];
1035 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1036 const ui16* sp = (ui16*)line_buffer + comp_num;
1037 si32* dp = line->i32;
1038 for (ui32 i = width; i > 0; --i, sp += num_comps)
1039 *dp++ = (si32)(((*sp) >> bits_to_shift) & bit_mask);
1040 }
1041 else if (bit_depth[comp_num] > 16)
1042 {
1043 const int bits_to_shift = (int)bit_depth[comp_num] - 16;
1044 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1045 const ui16* sp = (ui16*)line_buffer + comp_num;
1046 si32* dp = line->i32;
1047 for (ui32 i = width; i > 0; --i, sp += num_comps)
1048 *dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
1049 }
1050
1051 }
1052
1053 return width;
1054 }
1055
1057 //
1058 //
1059 //
1060 //
1061 //
1063
1065 void tif_out::open(char* filename)
1066 {
1067 // Error on known incompatilbe output formats
1068 ui32 max_bitdepth = 0;
1069 for (ui32 c = 0; c < num_components; c++)
1070 {
1071 if (bit_depth_of_data[c] > max_bitdepth)
1072 max_bitdepth = bit_depth_of_data[c];
1073 }
1074 if (max_bitdepth > 16)
1075 {
1076 OJPH_WARN(0x030000B1, "TIFF output is currently limited to files "
1077 "with max_bitdepth = 16, the source codestream has max_bitdepth=%d"
1078 ", the decoded data will be truncated to 16 bits", max_bitdepth);
1079 }
1080 if (num_components > 4)
1081 {
1082 OJPH_ERROR(0x030000B2, "TIFF IO is currently limited to files with "
1083 "num_components=1 to 4");
1084 }
1085
1086 assert(tiff_handle == NULL && buffer == NULL);
1087 if ((tiff_handle = TIFFOpen(filename, "w")) == NULL)
1088 {
1089 OJPH_ERROR(0x030000B3, "unable to open file %s for writing", filename);
1090 }
1091
1092 buffer_size = width * (size_t)num_components * (size_t)bytes_per_sample;
1093 buffer = (ui8*)malloc(buffer_size);
1094 fname = filename;
1095 cur_line = 0;
1096
1097 // set tiff fields
1098
1099 // Write the tiff tags to the file
1100 TIFFSetField(tiff_handle, TIFFTAG_IMAGEWIDTH, width);
1101 TIFFSetField(tiff_handle, TIFFTAG_IMAGELENGTH, height);
1102
1103 TIFFSetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, bytes_per_sample * 8);
1104 TIFFSetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, num_components);
1105
1106 planar_configuration = PLANARCONFIG_CONTIG;
1107 TIFFSetField(tiff_handle, TIFFTAG_PLANARCONFIG, planar_configuration);
1108
1109 if (num_components == 1)
1110 {
1111 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1112 }
1113 else if (num_components == 2)
1114 {
1115 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1116 // possible values are EXTRASAMPLE_UNSPECIFIED = 0;
1117 // EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
1118 const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
1119 TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
1120 &extra_samples_description);
1121 }
1122 else if (num_components == 3)
1123 {
1124 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1125 }
1126 else if (num_components == 4)
1127 {
1128 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1129 // possible values are EXTRASAMPLE_UNSPECIFIED = 0;
1130 // EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
1131 const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
1132 TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
1133 &extra_samples_description);
1134 }
1135
1136 TIFFSetField(tiff_handle, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1137 TIFFSetField(tiff_handle, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1138 //TIFFSetField(tiff_handle, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1139 TIFFSetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, height);
1140
1141 }
1142
1144 void tif_out::configure(ui32 width, ui32 height, ui32 num_components,
1145 ui32 *bit_depth)
1146 {
1147 assert(tiff_handle == NULL); //configure before opening
1148
1149 this->width = width;
1150 this->height = height;
1151 this->num_components = num_components;
1152 ui32 max_bitdepth = 0;
1153 for (ui32 c = 0; c < num_components; c++)
1154 {
1155 this->bit_depth_of_data[c] = bit_depth[c];
1156 if (bit_depth[c] > max_bitdepth)
1157 max_bitdepth = bit_depth[c];
1158 }
1159
1160 bytes_per_sample = (max_bitdepth + 7) / 8; // round up
1161 if (bytes_per_sample > 2)
1162 {
1163 // TIFF output is currently limited to files with max_bitdepth = 16,
1164 // the decoded data will be truncated to 16 bits
1165 bytes_per_sample = 2;
1166 }
1167 samples_per_line = num_components * width;
1168 bytes_per_line = bytes_per_sample * (size_t)samples_per_line;
1169
1170 }
1171
1173 ui32 tif_out::write(const line_buf* line, ui32 comp_num)
1174 {
1175 assert(tiff_handle);
1176
1177 if (bytes_per_sample == 1)
1178 {
1179 int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
1180 const si32* sp = line->i32;
1181 ui8* dp = buffer + comp_num;
1182 if (bit_depth_of_data[comp_num] == 8)
1183 {
1184 for (ui32 i = width; i > 0; --i, dp += num_components)
1185 {
1186 // clamp the decoded sample to the allowed range
1187 int val = *sp++;
1188 val = val >= 0 ? val : 0;
1189 val = val <= max_val ? val : max_val;
1190 *dp = (ui8)val;
1191 }
1192 }
1193 else if (bit_depth_of_data[comp_num] < 8)
1194 {
1195 const int bits_to_shift = 8 - (int)bit_depth_of_data[comp_num];
1196 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1197 for (ui32 i = width; i > 0; --i, dp += num_components)
1198 {
1199 // clamp the decoded sample to the allowed range
1200 int val = *sp++;
1201 val = val >= 0 ? val : 0;
1202 val = val <= max_val ? val : max_val;
1203 // shift the decoded data so the data's MSB is aligned with the
1204 // 8 bit MSB
1205 *dp = (ui8)((val & bit_mask) << bits_to_shift);
1206 }
1207 }
1208 else if (bit_depth_of_data[comp_num] > 8)
1209 {
1210 const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 8;
1211 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1212 for (ui32 i = width; i > 0; --i, dp += num_components)
1213 {
1214 // clamp the decoded sample to the allowed range
1215 int val = *sp++;
1216 val = val >= 0 ? val : 0;
1217 val = val <= max_val ? val : max_val;
1218 // shift the decoded data so the data's MSB is aligned with the
1219 // 8 bit MSB
1220 *dp = (ui8)((val >> bits_to_shift) & bit_mask);
1221 }
1222 }
1223
1224 }
1225 else if(bytes_per_sample == 2)
1226 {
1227 int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
1228 const si32* sp = line->i32;
1229 ui16* dp = (ui16*)buffer + comp_num;
1230
1231 if (bit_depth_of_data[comp_num] == 16)
1232 {
1233 for (ui32 i = width; i > 0; --i, dp += num_components)
1234 {
1235 // clamp the decoded sample to the allowed range
1236 int val = *sp++;
1237 val = val >= 0 ? val : 0;
1238 val = val <= max_val ? val : max_val;
1239 *dp = (ui16)val;
1240 }
1241 }
1242 else if (bit_depth_of_data[comp_num] < 16)
1243 {
1244 const int bits_to_shift = 16 - (int)bit_depth_of_data[comp_num];
1245 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1246 for (ui32 i = width; i > 0; --i, dp += num_components)
1247 {
1248 // clamp the decoded sample to the allowed range
1249 int val = *sp++;
1250 val = val >= 0 ? val : 0;
1251 val = val <= max_val ? val : max_val;
1252
1253 // shift the decoded data so the data's MSB is aligned with the
1254 // 16 bit MSB
1255 *dp = (ui16)((val & bit_mask) << bits_to_shift);
1256 }
1257 }
1258 else if (bit_depth_of_data[comp_num] > 16)
1259 {
1260 const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 16;
1261 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1262 for (ui32 i = width; i > 0; --i, dp += num_components)
1263 {
1264 // clamp the decoded sample to the allowed range
1265 int val = *sp++;
1266 val = val >= 0 ? val : 0;
1267 val = val <= max_val ? val : max_val;
1268
1269 // shift the decoded data so the data's MSB is aligned with the
1270 // 16 bit MSB
1271 *dp = (ui16)((val >> bits_to_shift) & bit_mask);
1272 }
1273 }
1274
1275 }
1276 // write scanline when the last component is reached
1277 if (comp_num == num_components-1)
1278 {
1279 int result = TIFFWriteScanline(tiff_handle, buffer, cur_line++);
1280 if (result != 1)
1281 OJPH_ERROR(0x030000C1, "error writing to file %s", fname);
1282 }
1283 return 0;
1284 }
1285 #endif /* OJPH_ENABLE_TIFF_SUPPORT */
1286
1288 //
1289 //
1290 //
1291 //
1292 //
1294
1296 void yuv_in::open(const char* filename)
1297 {
1298 assert(fh == NULL);
1299 fh = fopen(filename, "rb");
1300 if (fh == 0)
1301 OJPH_ERROR(0x030000D1, "Unable to open file %s", filename);
1302
1303 //need to extract info from filename
1304
1305 assert(num_com == 1 || num_com == 3);
1306 for (ui32 i = 0; i < num_com; ++i)
1307 bytes_per_sample[i] = bit_depth[i] > 8 ? 2 : 1;
1308 ui32 max_byte_width = width[0] * bytes_per_sample[0];
1309 comp_address[0] = 0;
1310 for (ui32 i = 1; i < num_com; ++i)
1311 {
1312 comp_address[i] = comp_address[i - 1];
1313 comp_address[i] += width[i-1] * height[i-1] * bytes_per_sample[i-1];
1314 max_byte_width = ojph_max(max_byte_width, width[i]*bytes_per_sample[i]);
1315 }
1316 temp_buf = malloc(max_byte_width);
1317 fname = filename;
1318 }
1319
1321 ui32 yuv_in::read(const line_buf* line, ui32 comp_num)
1322 {
1323 assert(comp_num < num_com);
1324 size_t result = fread(temp_buf, bytes_per_sample[comp_num],
1325 width[comp_num], fh);
1326 if (result != width[comp_num])
1327 {
1328 close();
1329 OJPH_ERROR(0x030000E1, "not enough data in file %s", fname);
1330 }
1331
1332 if (bytes_per_sample[comp_num] == 1)
1333 {
1334 const ui8* sp = (ui8*)temp_buf;
1335 si32* dp = line->i32;
1336 for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
1337 *dp++ = (si32)*sp;
1338 }
1339 else
1340 {
1341 const ui16* sp = (ui16*)temp_buf;
1342 si32* dp = line->i32;
1343 for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
1344 *dp++ = (si32)*sp;
1345 }
1346
1347 return width[comp_num];
1348 }
1349
1351 void yuv_in::set_img_props(const size& s, ui32 num_components,
1352 ui32 num_downsamplings, const point *subsampling)
1353 {
1354 if (num_components != 1 && num_components !=3)
1355 OJPH_ERROR(0x030000F1, "yuv_in support 1 or 3 components");
1356 this->num_com = num_components;
1357
1358 if (num_downsamplings < 1)
1359 OJPH_ERROR(0x030000F2, "one or more downsampling must be provided");
1360
1361 ui32 last_downsamp_idx = 0;
1362 for (ui32 i = 0; i < num_components; ++i)
1363 {
1364 point cp_ds = subsampling[i<num_downsamplings ? i : last_downsamp_idx];
1365 last_downsamp_idx += last_downsamp_idx + 1 < num_downsamplings ? 1 : 0;
1366
1367 this->subsampling[i] = cp_ds;
1368 }
1369
1370 for (ui32 i = 0; i < num_components; ++i)
1371 {
1372 width[i] = ojph_div_ceil(s.w, this->subsampling[i].x);
1373 height[i] = ojph_div_ceil(s.h, this->subsampling[i].y);
1374 }
1375 }
1376
1378 void yuv_in::set_bit_depth(ui32 num_bit_depths, ui32* bit_depth)
1379 {
1380 if (num_bit_depths < 1)
1381 OJPH_ERROR(0x03000101, "one or more bit_depths must be provided");
1382 ui32 last_bd_idx = 0;
1383 for (ui32 i = 0; i < 3; ++i)
1384 {
1385 ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
1386 last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
1387
1388 this->bit_depth[i] = bd;
1389 }
1390 }
1391
1393 //
1394 //
1395 //
1396 //
1397 //
1399
1402 {
1403 close();
1404 if (buffer)
1405 {
1406 free(buffer);
1407 buffer = NULL;
1408 buffer_size = 0;
1409 }
1410 if (comp_width)
1411 {
1412 delete [] comp_width;
1413 comp_width = NULL;
1414 }
1415 }
1416
1418 void yuv_out::open(char *filename)
1419 {
1420 assert(fh == NULL); //configure before open
1421 fh = fopen(filename, "wb");
1422 if (fh == 0)
1423 OJPH_ERROR(0x03000111, "Unable to open file %s", filename);
1424 fname = filename;
1425 }
1426
1428 void yuv_out::configure(ui32 bit_depth, ui32 num_components,
1429 ui32* comp_width)
1430 {
1431 assert(fh == NULL);
1432 this->num_components = num_components;
1433 this->bit_depth = bit_depth;
1434 this->comp_width = new ui32[num_components];
1435 ui32 tw = 0;
1436 for (ui32 i = 0; i < num_components; ++i)
1437 {
1438 this->comp_width[i] = comp_width[i];
1439 tw = ojph_max(tw, this->comp_width[i]);
1440 }
1441 this->width = tw;
1442 buffer_size = tw * (bit_depth > 8 ? 2 : 1);
1443 buffer = (ui8*)malloc(buffer_size);
1444 }
1445
1447 ui32 yuv_out::write(const line_buf* line, ui32 comp_num)
1448 {
1449 assert(fh);
1450 assert(comp_num < num_components);
1451
1452 int max_val = (1<<bit_depth) - 1;
1453 ui32 w = comp_width[comp_num];
1454 if (bit_depth > 8)
1455 {
1456 const si32 *sp = line->i32;
1457 ui16 *dp = (ui16 *)buffer;
1458 for (ui32 i = w; i > 0; --i)
1459 {
1460 int val = *sp++;
1461 val = val >= 0 ? val : 0;
1462 val = val <= max_val ? val : max_val;
1463 *dp++ = (ui16)val;
1464 }
1465 if (fwrite(buffer, 2, w, fh) != w)
1466 OJPH_ERROR(0x03000121, "unable to write to file %s", fname);
1467 }
1468 else
1469 {
1470 const si32 *sp = line->i32;
1471 ui8 *dp = (ui8 *)buffer;
1472 for (ui32 i = w; i > 0; --i)
1473 {
1474 int val = *sp++;
1475 val = val >= 0 ? val : 0;
1476 val = val <= max_val ? val : max_val;
1477 *dp++ = (ui8)val;
1478 }
1479 if (fwrite(buffer, 1, w, fh) != w)
1480 OJPH_ERROR(0x03000122, "unable to write to file %s", fname);
1481 }
1482
1483 return w;
1484 }
1485
1487 //
1488 //
1489 //
1490 //
1491 //
1493
1495 void raw_in::open(const char* filename)
1496 {
1497 assert(fh == NULL);
1498 fh = fopen(filename, "rb");
1499 if (fh == NULL)
1500 OJPH_ERROR(0x03000131, "Unable to open file %s", filename);
1501
1502 cur_line = 0;
1503 bytes_per_sample = (bit_depth + 7) >> 3;
1505 buffer = (ui8*)malloc(buffer_size);
1506 fname = filename;
1507 }
1508
1510 ui32 raw_in::read(const line_buf* line, ui32 comp_num)
1511 {
1512 ojph_unused(comp_num);
1513 assert(comp_num == 0);
1514 size_t result = fread(buffer, bytes_per_sample, width, fh);
1515 if (result != width)
1516 {
1517 close();
1518 OJPH_ERROR(0x03000132, "not enough data in file %s", fname);
1519 }
1520
1521 if (bytes_per_sample > 3)
1522 {
1523 si32* dp = line->i32;
1524 if (is_signed) {
1525 const si32* sp = (si32*)buffer;
1526 for (ui32 i = width; i > 0; --i, ++sp)
1527 *dp++ = *sp;
1528 }
1529 else {
1530 si32* dp = line->i32;
1531 const ui32* sp = (ui32*)buffer;
1532 for (ui32 i = width; i > 0; --i, ++sp)
1533 *dp++ = (si32)*sp;
1534 }
1535 }
1536 else if (bytes_per_sample > 2)
1537 {
1538 si32* dp = line->i32;
1539 if (is_signed) {
1540 const si32* sp = (si32*)buffer;
1541 for (ui32 i = width; i > 0; --i) {
1542 si32 val = *sp & 0xFFFFFF;
1543 val |= (val & 0x800000) ? 0xFF000000 : 0;
1544 *dp++ = val;
1545 // this only works for little endian architecture
1546 sp = (si32*)((si8*)sp + 3);
1547 }
1548 }
1549 else {
1550 const ui32* sp = (ui32*)buffer;
1551 for (ui32 i = width; i > 0; --i) {
1552 *dp++ = (si32)(*sp & 0xFFFFFFu);
1553 // this only works for little endian architecture
1554 sp = (ui32*)((ui8*)sp + 3);
1555 }
1556 }
1557 }
1558 else if (bytes_per_sample > 1)
1559 {
1560 si32* dp = line->i32;
1561 if (is_signed) {
1562 const si16* sp = (si16*)buffer;
1563 for (ui32 i = width; i > 0; --i, ++sp)
1564 *dp++ = *sp;
1565 }
1566 else {
1567 const ui16* sp = (ui16*)buffer;
1568 for (ui32 i = width; i > 0; --i, ++sp)
1569 *dp++ = (si32)*sp;
1570 }
1571 }
1572 else
1573 {
1574 si32* dp = line->i32;
1575 if (is_signed) {
1576 const si8* sp = (si8*)buffer;
1577 for (ui32 i = width; i > 0; --i, ++sp)
1578 *dp++ = *sp;
1579 }
1580 else {
1581 const ui8* sp = (ui8*)buffer;
1582 for (ui32 i = width; i > 0; --i, ++sp)
1583 *dp++ = (si32)*sp;
1584 }
1585 }
1586
1587 return width;
1588 }
1589
1591 void raw_in::set_img_props(const size& s, ui32 bit_depth, bool is_signed)
1592 {
1593 assert(fh == NULL);
1594 //need to extract this info from filename
1595 this->width = s.w;
1596 this->height = s.h;
1597 this->bit_depth = bit_depth;
1598 this->is_signed = is_signed;
1599 }
1600
1602 //
1603 //
1604 //
1605 //
1606 //
1608
1611 {
1612 close();
1613 if (buffer)
1614 {
1615 free(buffer);
1616 buffer = NULL;
1617 buffer_size = 0;
1618 }
1619 }
1620
1622 void raw_out::open(char *filename)
1623 {
1624 assert(fh == NULL); //configure before open
1625 fh = fopen(filename, "wb");
1626 if (fh == 0)
1627 OJPH_ERROR(0x03000141, "Unable to open file %s", filename);
1628 fname = filename;
1629 }
1630
1632 void raw_out::configure(bool is_signed, ui32 bit_depth, ui32 width)
1633 {
1634 assert(fh == NULL);
1635 this->is_signed = is_signed;
1636 this->bit_depth = bit_depth;
1637 this->width = width;
1638
1639 if (is_signed) {
1640 upper_val = ((si64)1 << (bit_depth - 1));
1641 lower_val = -((si64)1 << (bit_depth - 1));
1642 } else {
1643 upper_val = (si64)1 << bit_depth;
1644 lower_val = (si64)0;
1645 }
1646
1647 bytes_per_sample = (bit_depth + 7) >> 3;
1649 buffer = (ui8*)malloc(buffer_size);
1650 }
1651
1653 ui32 raw_out::write(const line_buf* line, ui32 comp_num)
1654 {
1655 ojph_unused(comp_num);
1656 assert(fh);
1657 assert(comp_num == 0);
1658
1659 if (is_signed)
1660 {
1661 if (bytes_per_sample > 3)
1662 {
1663 const si32* sp = line->i32;
1664 si32* dp = (si32*)buffer;
1665 for (ui32 i = width; i > 0; --i)
1666 {
1667 si64 val = *sp++;
1668 val = val < upper_val ? val : upper_val;
1669 val = val >= lower_val ? val : lower_val;
1670 *dp++ = (si32)val;
1671 }
1672 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1673 OJPH_ERROR(0x03000151, "unable to write to file %s", fname);
1674 }
1675 else if (bytes_per_sample > 2)
1676 {
1677 const si32* sp = line->i32;
1678 si32* dp = (si32*)buffer;
1679 for (ui32 i = width; i > 0; --i)
1680 {
1681 si64 val = *sp++;
1682 val = val < upper_val ? val : upper_val;
1683 val = val >= lower_val ? val : lower_val;
1684 *dp = (si32)val;
1685 // this only works for little endian architecture
1686 dp = (si32*)((ui8*)dp + 3);
1687 }
1688 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1689 OJPH_ERROR(0x03000152, "unable to write to file %s", fname);
1690 }
1691 else if (bytes_per_sample > 1)
1692 {
1693 const si32* sp = line->i32;
1694 si16* dp = (si16*)buffer;
1695 for (ui32 i = width; i > 0; --i)
1696 {
1697 si64 val = *sp++;
1698 val = val < upper_val ? val : upper_val;
1699 val = val >= lower_val ? val : lower_val;
1700 *dp++ = (si16)val;
1701 }
1702 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1703 OJPH_ERROR(0x03000153, "unable to write to file %s", fname);
1704 }
1705 else
1706 {
1707 const si32* sp = line->i32;
1708 si8* dp = (si8*)buffer;
1709 for (ui32 i = width; i > 0; --i)
1710 {
1711 si64 val = *sp++;
1712 val = val < upper_val ? val : upper_val;
1713 val = val >= lower_val ? val : lower_val;
1714 *dp++ = (si8)val;
1715 }
1716 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1717 OJPH_ERROR(0x03000154, "unable to write to file %s", fname);
1718 }
1719 }
1720 else
1721 {
1722 if (bytes_per_sample > 3)
1723 {
1724 const ui32* sp = (ui32*)line->i32;
1725 ui32* dp = (ui32*)buffer;
1726 for (ui32 i = width; i > 0; --i)
1727 {
1728 si64 val = *sp++;
1729 val = val < upper_val ? val : upper_val;
1730 val = val >= lower_val ? val : lower_val;
1731 *dp++ = (ui32)val;
1732 }
1733 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1734 OJPH_ERROR(0x03000155, "unable to write to file %s", fname);
1735 }
1736 else if (bytes_per_sample > 2)
1737 {
1738 const ui32* sp = (ui32*)line->i32;
1739 ui32* dp = (ui32*)buffer;
1740 for (ui32 i = width; i > 0; --i)
1741 {
1742 si64 val = *sp++;
1743 val = val < upper_val ? val : upper_val;
1744 val = val >= lower_val ? val : lower_val;
1745 *dp = (ui32)val;
1746 // this only works for little endian architecture
1747 dp = (ui32*)((ui8*)dp + 3);
1748 }
1749 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1750 OJPH_ERROR(0x03000156, "unable to write to file %s", fname);
1751 }
1752 else if (bytes_per_sample > 1)
1753 {
1754 const ui32* sp = (ui32*)line->i32;
1755 ui16* dp = (ui16*)buffer;
1756 for (ui32 i = width; i > 0; --i)
1757 {
1758 si64 val = *sp++;
1759 val = val < upper_val ? val : upper_val;
1760 val = val >= lower_val ? val : lower_val;
1761 *dp++ = (ui16)val;
1762 }
1763 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1764 OJPH_ERROR(0x03000157, "unable to write to file %s", fname);
1765 }
1766 else
1767 {
1768 const ui32* sp = (ui32*)line->i32;
1769 ui8* dp = (ui8*)buffer;
1770 for (ui32 i = width; i > 0; --i)
1771 {
1772 si64 val = *sp++;
1773 val = val < upper_val ? val : upper_val;
1774 val = val >= lower_val ? val : lower_val;
1775 *dp++ = (ui8)val;
1776 }
1777 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1778 OJPH_ERROR(0x03000158, "unable to write to file %s", fname);
1779 }
1780 }
1781
1782 return width;
1783 }
1784
1785
1787 //
1788 //
1789 //
1790 //
1791 //
1793
1795
1796 void dpx_in::open(const char* filename)
1797 {
1798 assert(file_handle == 0);
1799 file_handle = fopen(filename, "rb");
1800 if (0 == file_handle)
1801 OJPH_ERROR(0x03000161, "Unable to open file %s", filename);
1802 fname = filename;
1803
1804 // read magic number
1805 ui32 magic_number;
1806 if (fread(&magic_number, sizeof(ui32), 1, file_handle) != 1)
1807 {
1808 close();
1809 OJPH_ERROR(0x03000162, "Error reading file %s", filename);
1810 }
1811
1812 // check magic number
1813 const ui32 dpx_magic_number = 0x53445058;
1814 if (dpx_magic_number == magic_number)
1815 {
1816 // magic number is a match - no byte swapping necessary
1818 }
1819 else if (dpx_magic_number == be2le(magic_number))
1820 {
1821 // magic number is a match after bytes swapping -
1822 // the data read from this file needs byte swapping
1824 }
1825 else
1826 {
1827 close();
1828 OJPH_ERROR(0x03000163, "Error reading file %s - this does not appear "
1829 "to be a valid DPX file. It has magic number = 0x%08X. The magic "
1830 "number of a DPX file is 0x%08X.", filename, magic_number,
1831 dpx_magic_number);
1832 }
1833
1834 // read offset to data
1835 if (fread(&offset_to_image_data_in_bytes, sizeof(ui32), 1, file_handle)
1836 != 1)
1837 {
1838 close();
1839 OJPH_ERROR(0x03000164, "Error reading file %s", filename);
1840 }
1843 // read version
1844 if (fread(version, sizeof(uint8_t), 8, file_handle) != 8)
1845 {
1846 close();
1847 OJPH_ERROR(0x03000165, "Error reading file %s", filename);
1848 }
1849 // read image file size in bytes
1850 if (fread(&total_image_file_size_in_bytes, sizeof(ui32), 1, file_handle)
1851 != 1)
1852 {
1853 close();
1854 OJPH_ERROR(0x03000166, "Error reading file %s", filename);
1855 }
1858
1859 // seek to image info header
1860 if (fseek(file_handle,768, SEEK_SET) != 0)
1861 {
1862 close();
1863 OJPH_ERROR(0x03000167, "Error reading file %s", filename);
1864 }
1865
1866 // read image_orientation
1867 if (fread(&image_orientation, sizeof(uint16_t), 1, file_handle) != 1)
1868 {
1869 close();
1870 OJPH_ERROR(0x03000168, "Error reading file %s", filename);
1871 }
1874
1875 // read number of image elements
1876 if (fread(&number_of_image_elements, sizeof(uint16_t), 1, file_handle)
1877 != 1)
1878 {
1879 close();
1880 OJPH_ERROR(0x03000169, "Error reading file %s", filename);
1881 }
1884
1885 // read pixels per line
1886 if (fread(&pixels_per_line, sizeof(ui32), 1, file_handle) != 1)
1887 {
1888 close();
1889 OJPH_ERROR(0x0300016A, "Error reading file %s", filename);
1890 }
1893
1894 // read lines per image element
1895 if (fread(&lines_per_image_element, sizeof(ui32), 1, file_handle) != 1)
1896 {
1897 close();
1898 OJPH_ERROR(0x0300016B, "Error reading file %s", filename);
1899 }
1902
1903 // seek to data structure for image element 1
1904 if (fseek(file_handle, 780, SEEK_SET) != 0)
1905 {
1906 close();
1907 OJPH_ERROR(0x0300016C, "Error reading file %s", filename);
1908 }
1909
1910 // read data sign for image element
1911 if (fread(&data_sign_for_image_element_1, sizeof(ui32), 1, file_handle)
1912 != 1)
1913 {
1914 close();
1915 OJPH_ERROR(0x0300016E, "Error reading file %s", filename);
1916 }
1919
1920 // seek to core data elements in image element 1
1921 if (fseek(file_handle, 800, SEEK_SET) != 0)
1922 {
1923 close();
1924 OJPH_ERROR(0x0300016F, "Error reading file %s", filename);
1925 }
1926
1927 // read descriptor
1928 if (fread(&descriptor_for_image_element_1, sizeof(uint8_t), 1, file_handle)
1929 != 1)
1930 {
1931 close();
1932 OJPH_ERROR(0x03000170, "Error reading file %s", filename);
1933 }
1934
1935 // read transfer characteristic
1936 if (fread(&transfer_characteristic_for_image_element_1, sizeof(uint8_t),
1937 1, file_handle) != 1)
1938 {
1939 close();
1940 OJPH_ERROR(0x03000171, "Error reading file %s", filename);
1941 }
1942
1943 // read colorimetric specification
1944 if (fread(&colormetric_specification_for_image_element_1, sizeof(uint8_t),
1945 1, file_handle) != 1)
1946 {
1947 close();
1948 OJPH_ERROR(0x03000172, "Error reading file %s", filename);
1949 }
1950
1951 // read bit depth
1952 if (fread(&bitdepth_for_image_element_1, sizeof(uint8_t), 1, file_handle)
1953 != 1)
1954 {
1955 close();
1956 OJPH_ERROR(0x03000173, "Error reading file %s", filename);
1957 }
1958
1959 // read packing
1960 if (fread(&packing_for_image_element_1, sizeof(uint16_t), 1, file_handle)
1961 != 1)
1962 {
1963 close();
1964 OJPH_ERROR(0x03000174, "Error reading file %s", filename);
1965 }
1968
1969 // read encoding
1970 if (fread(&encoding_for_image_element_1, sizeof(uint16_t), 1, file_handle)
1971 != 1)
1972 {
1973 close();
1974 OJPH_ERROR(0x03000175, "Error reading file %s", filename);
1975 }
1978
1979 // read offset to data
1980 if (fread(&offset_to_data_for_image_element_1, sizeof(ui32), 1,
1981 file_handle) != 1)
1982 {
1983 close();
1984 OJPH_ERROR(0x03000176, "Error reading file %s", filename);
1985 }
1989
1990 // set to starting point of image data
1991 if (fseek(file_handle, (long)offset_to_image_data_in_bytes, SEEK_SET) != 0)
1992 {
1993 close();
1994 OJPH_ERROR(0x03000177, "Error reading file %s", filename);
1995 }
1996
1997 // set ojph properties
2000 num_comps = 3; // descriptor field can indicate 1, 3, or 4 comps
2001 for ( ojph::ui32 c = 0; c < get_num_components(); c++)
2002 {
2004 is_signed[c] = false;
2005 subsampling[c] = point(1,1);
2006 }
2007
2008 // handle DPX image data packing in file
2009 ui32 number_of_samples_per_32_bit_word = 32 / bitdepth_for_image_element_1;
2012 (number_of_samples_per_line + (number_of_samples_per_32_bit_word - 1))
2013 / number_of_samples_per_32_bit_word;
2014
2015 cur_line = 0;
2016
2017 // allocate linebuffer to hold a line of image data from the file
2019 if (NULL == line_buffer)
2020 OJPH_ERROR(0x03000178, "Unable to allocate %d bytes for line_buffer[] "
2021 "for file %s",
2022 number_of_32_bit_words_per_line * sizeof(ui32), filename);
2023
2024 // allocate line_buffer_16bit_samples to hold a line of image data in memory
2026 (ui16*) malloc((size_t)width * num_comps * sizeof(ui16));
2027 if (NULL == line_buffer_16bit_samples)
2028 OJPH_ERROR(0x03000179, "Unable to allocate %d bytes for "
2029 "line_buffer_16bit_samples[] for file %s",
2030 (size_t)width * num_comps * sizeof(ui16), filename);
2031
2032 cur_line = 0;
2033
2034 return;
2035 }
2036
2038 ui32 dpx_in::read(const line_buf* line, ui32 comp_num)
2039 {
2040 assert(file_handle != 0 && comp_num < num_comps);
2041 assert((ui32)line->size >= width);
2042
2043 // read from file if trying to read the first component
2044 if (0 == comp_num)
2045 {
2048 {
2049 close();
2050 OJPH_ERROR(0x03000181, "Error reading file %s", fname);
2051 }
2052
2053 if (true == is_byte_swapping_necessary)
2054 {
2056 {
2057 ui16* line_buffer_ptr = (ui16*)line_buffer;
2058 for (size_t i = 0; i < 2*number_of_32_bit_words_per_line; i++)
2059 {
2060 line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
2061 }
2062 }
2063 else
2064 {
2065 ui32* line_buffer_ptr = (ui32*)line_buffer;
2066 for (size_t i = 0; i < number_of_32_bit_words_per_line; i++)
2067 {
2068 line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
2069 }
2070 }
2071 }
2072
2073 // extract samples from 32bit words from file read into
2074 // RGB ordered buffer
2075 ui32 word_index = 0;
2076 if (10 == bitdepth_for_image_element_1 && 3 == num_comps
2078 {
2079 ui32* line_buffer_ptr = (ui32*)line_buffer;
2080 for (ui32 i = 0; i < number_of_samples_per_line; i += 3)
2081 {
2082 // R
2084 (ui16) ((line_buffer_ptr[word_index] & 0xFFC00000) >> 22);
2085 // G
2087 (ui16) ((line_buffer_ptr[word_index] & 0x003FF000) >> 12);
2088 // B
2090 (ui16) ((line_buffer_ptr[word_index] & 0x00000FFC) >> 2);
2091 word_index++;
2092 }
2093 }
2094 else if (16 == bitdepth_for_image_element_1 && 3 == num_comps)
2095 {
2096 ui16* line_buffer_ptr = (ui16*)line_buffer;
2097 for (ui32 i = 0; i < number_of_samples_per_line; i++)
2098 {
2099 line_buffer_16bit_samples[i] = line_buffer_ptr[i];
2100 }
2101 }
2102 else
2103 {
2104 OJPH_ERROR(0x03000182, "file %s uses DPX image formats that are not "
2105 "yet supported by this software\n bitdepth_for_image_element_1 = "
2106 "%d\n num_comps=%d\npacking_for_image_element_1=%d\n "
2107 "descriptor_for_image_element_1=%d", fname,
2110 }
2111
2112 cur_line++;
2113 }
2114
2115 // copy sample data from the unpacked line buffer into a
2116 // single-component buffer to be used by the openjph core
2117 const ui16* sp = (ui16*)line_buffer_16bit_samples + comp_num;
2118 si32* dp = line->i32;
2119 for (ui32 i = width; i > 0; --i, sp += num_comps)
2120 *dp++ = (si32)*sp;
2121
2122 return width;
2123 }
2124
2125}
ui32 get_num_components()
void * line_buffer
size_t number_of_32_bit_words_per_line
void open(const char *filename)
ui16 packing_for_image_element_1
ui8 descriptor_for_image_element_1
ui32 offset_to_data_for_image_element_1
ui32 total_image_file_size_in_bytes
FILE * file_handle
ui32 pixels_per_line
point subsampling[4]
ui16 number_of_image_elements
ui8 bitdepth_for_image_element_1
virtual ui32 read(const line_buf *line, ui32 comp_num)
ui16 * line_buffer_16bit_samples
char version[8]
ui32 offset_to_image_data_in_bytes
ui16 encoding_for_image_element_1
ui32 number_of_samples_per_line
ui8 transfer_characteristic_for_image_element_1
ui8 colormetric_specification_for_image_element_1
ui32 lines_per_image_element
ui16 image_orientation
bool is_signed[4]
const char * fname
ui32 bit_depth[4]
bool is_byte_swapping_necessary
ui32 data_sign_for_image_element_1
float * f32
Definition ojph_mem.h:162
void pre_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:66
T * post_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:89
virtual ui32 read(const line_buf *line, ui32 comp_num)
ui32 bit_depth[3]
mem_fixed_allocator * alloc_p
void finalize_alloc()
const char * fname
void open(const char *filename)
size_t temp_buf_byte_size
float * temp_buf
const char * fname
void open(char *filename)
size_t buffer_size
void configure(ui32 width, ui32 height, ui32 num_components, float scale, ui32 *bit_depth)
virtual ui32 write(const line_buf *line, ui32 comp_num)
ui32 bit_depth[3]
void open(const char *filename)
ui32 num_ele_per_line
ui32 bytes_per_sample
ui32 max_val_num_bits
const char * fname
void finalize_alloc()
ui32 temp_buf_byte_size
void * temp_buf
mem_fixed_allocator * alloc_p
ui32 bit_depth[3]
virtual ui32 read(const line_buf *line, ui32 comp_num)
const char * fname
void open(char *filename)
virtual ui32 write(const line_buf *line, ui32 comp_num)
ui32 bytes_per_sample
const line_buf * lptr[3]
conversion_fun converter
void configure(ui32 width, ui32 height, ui32 num_components, ui32 bit_depth)
ui32 samples_per_line
size_t buffer_size
ui32 bytes_per_sample
void set_img_props(const size &s, ui32 bit_depth, bool is_signed)
size_t buffer_size
const char * fname
void open(const char *filename)
virtual ui32 read(const line_buf *line, ui32 comp_num=0)
void open(char *filename)
void configure(bool is_signed, ui32 bit_depth, ui32 width)
virtual void close()
virtual ~raw_out()
const char * fname
virtual ui32 write(const line_buf *line, ui32 comp_num=0)
ui32 bytes_per_sample
ui32 width[3]
virtual ui32 read(const line_buf *line, ui32 comp_num)
ui32 height[3]
void open(const char *filename)
void * temp_buf
const char * fname
void set_img_props(const size &s, ui32 num_components, ui32 num_downsampling, const point *downsampling)
void set_bit_depth(ui32 num_bit_depths, ui32 *bit_depth)
ui32 bytes_per_sample[3]
point subsampling[3]
ui32 bit_depth[3]
ui32 comp_address[3]
const char * fname
void open(char *filename)
ui32 * comp_width
void configure(ui32 bit_depth, ui32 num_components, ui32 *comp_width)
virtual void close()
virtual ~yuv_out()
virtual ui32 write(const line_buf *line, ui32 comp_num)
@ X86_CPU_EXT_LEVEL_AVX2
Definition ojph_arch.h:138
@ X86_CPU_EXT_LEVEL_SSE41
Definition ojph_arch.h:135
void sse41_cvrt_32b3c_to_8ub3c(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
int ojph_fseek(FILE *stream, si64 offset, int origin)
Definition ojph_file.h:61
static void eat_white_spaces(FILE *fh)
si64 ojph_ftell(FILE *stream)
Definition ojph_file.h:66
int64_t si64
Definition ojph_defs.h:57
void gen_cvrt_32b3c_to_16ub3c_le(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void avx2_cvrt_32b3c_to_8ub3c(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
int8_t si8
Definition ojph_defs.h:51
uint16_t ui16
Definition ojph_defs.h:52
void gen_cvrt_32b1c_to_16ub1c_le(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void sse41_cvrt_32b1c_to_16ub1c_be(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void avx2_cvrt_32b1c_to_16ub1c_be(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void sse41_cvrt_32b1c_to_8ub1c(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void avx2_cvrt_32b1c_to_8ub1c(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void gen_cvrt_32b3c_to_16ub3c_be(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
static ui16 be2le(const ui16 v)
OJPH_EXPORT int get_cpu_ext_level()
static ui32 count_leading_zeros(ui32 val)
Definition ojph_arch.h:199
void gen_cvrt_32b1c_to_8ub1c(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
int32_t si32
Definition ojph_defs.h:55
void sse41_cvrt_32b3c_to_16ub3c_be(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
int16_t si16
Definition ojph_defs.h:53
uint32_t ui32
Definition ojph_defs.h:54
uint8_t ui8
Definition ojph_defs.h:50
void gen_cvrt_32b1c_to_16ub1c_be(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
void gen_cvrt_32b3c_to_8ub3c(const line_buf *ln0, const line_buf *ln1, const line_buf *ln2, void *dp, ui32 bit_depth, ui32 count)
#define ojph_max(a, b)
Definition ojph_defs.h:73
#define ojph_div_ceil(a, b)
Definition ojph_defs.h:70
#define ojph_unused(x)
Definition ojph_defs.h:78
#define OJPH_ERROR(t,...)
#define OJPH_WARN(t,...)