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#include <cstdlib>
39#include <cstring>
40
41#include "ojph_arch.h"
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#if 0
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#endif
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++ = swap_bytes_if_le((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++ = swap_bytes_if_le((ui16) val);
224 val = *sp1++;
225 val = val >= 0 ? val : 0;
226 val = val <= max_val ? val : max_val;
227 *p++ = swap_bytes_if_le((ui16) val);
228 val = *sp2++;
229 val = val >= 0 ? val : 0;
230 val = val <= max_val ? val : max_val;
231 *p++ = swap_bytes_if_le((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
319 alloc_p->pre_alloc_data<ui8>(temp_buf_byte_size, 0);
320 }
321 }
322 cur_line = 0;
323 }
324
327 {
328 if (alloc_p == NULL)
329 return;
330
331 if (bytes_per_sample == 1)
332 temp_buf = alloc_p->post_alloc_data<ui8>(num_comps * (size_t)width, 0);
333 else
334 temp_buf = alloc_p->post_alloc_data<ui16>(num_comps * (size_t)width, 0);
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) swap_bytes_if_le((ui16) *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
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);
634 alloc_p->pre_alloc_data<float>(temp_buf_byte_size, 0);
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 float* sp = temp_buf + comp_num;
677 float* dp = line->f32;
678
680 {
681 ui32 shift = 32 - bit_depth[comp_num];
682 if (shift)
683 for (ui32 i = width; i > 0; --i, sp += num_comps)
684 {
685 si32 s;
686 memcpy(&s, sp, sizeof(si32));
687 s >>= shift;
688 memcpy(dp, &s, sizeof(si32));
689 ++dp;
690 }
691 else
692 for (ui32 i = width; i > 0; --i, sp += num_comps)
693 *dp++ = *sp;
694 }
695 else {
696 ui32 shift = 32 - bit_depth[comp_num];
697 if (shift)
698 for (ui32 i = width; i > 0; --i, sp += num_comps) {
699 si32 s;
700 memcpy(&s, sp, sizeof(si32));
701 s = (si32)be2le((ui32)s);
702 s >>= shift;
703 memcpy(dp, &s, sizeof(si32));
704 ++dp;
705 }
706 else
707 for (ui32 i = width; i > 0; --i, sp += num_comps) {
708 ui32 u;
709 memcpy(&u, sp, sizeof(ui32));
710 u = be2le(u);
711 memcpy(dp, &u, sizeof(ui32));
712 ++dp;
713 }
714 }
715
716 return width;
717 }
718
720 //
721 //
722 //
723 //
724 //
726 // When is_force_pfm_write_as_little_endian_on_disk is true, pfm_out writes
727 // little-endian files on both big and little endian machines.
728 // When is_force_pfm_write_as_little_endian_on_disk is false, pfm_out writes
729 // in the machine's native byte order and sets the scale sign accordingly.
732 void pfm_out::open(char* filename)
733 {
734 assert(fh == NULL && buffer == NULL);
735 fh = fopen(filename, "wb");
736 if (fh == NULL)
737 OJPH_ERROR(0x03000071,
738 "Unable to open file %s for writing", filename);
739 int result = //the number of written characters
740 fprintf(fh, "P%c\n%d %d\n%f\n",
741 num_components > 1 ? 'F' : 'f', width, height, scale);
742 if (result == 0)
743 OJPH_ERROR(0x03000072, "error writing to file %s", filename);
744 buffer_size = (size_t)width * num_components * sizeof(float);
745 buffer = (float*)malloc(buffer_size);
746 fname = filename;
747 cur_line = 0;
749 }
750
753 float scale, ui32* bit_depth)
754 {
755 assert(fh == NULL); //configure before opening
756 if (num_components != 1 && num_components != 3)
757 OJPH_ERROR(0x03000081,
758 "pfm supports 1 or 3 colour components, not %d", num_components);
759 this->width = width;
760 this->height = height;
761 this->num_components = num_components;
762 bool is_write_little_endian_on_disk =
764 scale = scale < 0.0f ? -scale : scale;
765 this->scale = is_write_little_endian_on_disk ? -scale : scale;
766 for (ui32 c = 0; c < num_components; ++c)
767 this->bit_depth[c] = bit_depth[c];
768 }
769
771 ui32 pfm_out::write(const line_buf* line, ui32 comp_num)
772 {
773 assert(fh);
774
775 ui32 shift = 32 - bit_depth[comp_num];
776 float* sp = line->f32;
777 float* dp = buffer + comp_num;
778
779 // swap bytes when the samples are forced to little endian on disk
780 // but the machine is big endian
783 if (shift) {
784 if (needs_swap)
785 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
786 {
787 ui32 u;
788 memcpy(&u, sp, sizeof(ui32));
789 u <<= shift;
790 u = be2le(u);
791 memcpy(dp, &u, sizeof(ui32));
792 }
793 else
794 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
795 {
796 ui32 u;
797 memcpy(&u, sp, sizeof(ui32));
798 u <<= shift;
799 memcpy(dp, &u, sizeof(ui32));
800 }
801 }
802 else
803 if (needs_swap)
804 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
805 {
806 ui32 u;
807 memcpy(&u, sp, sizeof(ui32));
808 u = be2le(u);
809 memcpy(dp, &u, sizeof(ui32));
810 }
811 else
812 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
813 *dp = *sp;
814
815 if (comp_num == num_components - 1)
816 {
817 size_t samples_per_line = num_components * (size_t)width;
818 si64 loc = start_of_data;
819 loc += (height - 1 - cur_line)* samples_per_line * sizeof(float);
820 if (ojph_fseek(fh, loc, SEEK_SET) != 0)
821 OJPH_ERROR(0x03000082, "Error seeking in file %s", fname);
822 size_t result = fwrite(buffer, sizeof(float), samples_per_line, fh);
823 if (result != samples_per_line)
824 OJPH_ERROR(0x03000083, "error writing to file %s", fname);
825 ++cur_line;
826 }
827
828 return 0;
829 }
830
832 //
833 //
834 //
835 //
836 //
838#ifdef OJPH_ENABLE_TIFF_SUPPORT
840 void tif_in::open(const char* filename)
841 {
842 tiff_handle = NULL;
843 if ((tiff_handle = TIFFOpen(filename, "r")) == NULL)
844 OJPH_ERROR(0x03000091, "Unable to open file %s", filename);
845 fname = filename;
846
847 ui32 tiff_width = 0;
848 ui32 tiff_height = 0;
849 TIFFGetField(tiff_handle, TIFFTAG_IMAGEWIDTH, &tiff_width);
850 TIFFGetField(tiff_handle, TIFFTAG_IMAGELENGTH, &tiff_height);
851
852 ui16 tiff_bits_per_sample = 0;
853 ui16 tiff_samples_per_pixel = 0;
854 TIFFGetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, &tiff_bits_per_sample);
855 TIFFGetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, &tiff_samples_per_pixel);
856 // some TIFs have tiff_samples_per_pixel=0 when it is a single channel
857 // image - set to 1
858 tiff_samples_per_pixel =
859 (tiff_samples_per_pixel < 1) ? 1 : tiff_samples_per_pixel;
860
861 ui16 tiff_planar_configuration = 0;
862 ui16 tiff_photometric = 0;
863 TIFFGetField(tiff_handle, TIFFTAG_PLANARCONFIG, &tiff_planar_configuration);
864 TIFFGetField(tiff_handle, TIFFTAG_PHOTOMETRIC, &tiff_photometric);
865
866 planar_configuration = tiff_planar_configuration;
867
868 ui16 tiff_compression = 0;
869 ui32 tiff_rows_per_strip = 0;
870 TIFFGetField(tiff_handle, TIFFTAG_COMPRESSION, &tiff_compression);
871 TIFFGetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, &tiff_rows_per_strip);
872
873 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE)
874 {
875 bytes_per_line = tiff_samples_per_pixel * TIFFScanlineSize64(tiff_handle);
876 }
877 else
878 {
879 bytes_per_line = TIFFScanlineSize64(tiff_handle);
880 }
881 // allocate linebuffer to hold a line of image data
882 line_buffer = malloc(bytes_per_line);
883 if (NULL == line_buffer)
884 OJPH_ERROR(0x03000092, "Unable to allocate %d bytes for line_buffer[] "
885 "for file %s", bytes_per_line, filename);
886
887 cur_line = 0;
888
889 // Error on known incompatilbe input formats
890 if( tiff_bits_per_sample != 8 && tiff_bits_per_sample != 16 )
891 {
892 OJPH_ERROR(0x03000093, "\nTIFF IO is currently limited"
893 " to files with TIFFTAG_BITSPERSAMPLE=8 and TIFFTAG_BITSPERSAMPLE=16 \n"
894 "input file = %s has TIFFTAG_BITSPERSAMPLE=%d",
895 filename, tiff_bits_per_sample);
896 }
897
898 if( TIFFIsTiled( tiff_handle ) )
899 {
900 OJPH_ERROR(0x03000094, "\nTIFF IO is currently limited to TIF files "
901 "without tiles. \nInput file %s has been detected as tiled", filename);
902 }
903
904 if(PHOTOMETRIC_RGB != tiff_photometric &&
905 PHOTOMETRIC_MINISBLACK != tiff_photometric )
906 {
907 OJPH_ERROR(0x03000095, "\nTIFF IO is currently limited to "
908 "TIFFTAG_PHOTOMETRIC=PHOTOMETRIC_MINISBLACK=%d and "
909 "PHOTOMETRIC_RGB=%d. \nInput file %s has been detected "
910 "TIFFTAG_PHOTOMETRIC=%d",
911 PHOTOMETRIC_MINISBLACK, PHOTOMETRIC_RGB, filename, tiff_photometric);
912 }
913
914 if( tiff_samples_per_pixel > 4 )
915 {
916 OJPH_ERROR(0x03000096, "\nTIFF IO is currently limited to "
917 "TIFFTAG_SAMPLESPERPIXEL=4 \nInput file %s has been detected with "
918 "TIFFTAG_SAMPLESPERPIXEL=%d",
919 filename, tiff_samples_per_pixel);
920 }
921
922 // set number of components based on tiff_samples_per_pixel
923 width = tiff_width;
924 height = tiff_height;
925 num_comps = tiff_samples_per_pixel;
926 bytes_per_sample = (tiff_bits_per_sample + 7) / 8;
927 for (ui32 comp_num = 0; comp_num < num_comps; comp_num++)
928 bit_depth[comp_num] = tiff_bits_per_sample;
929
930 // allocate intermediate linebuffers to hold a line of a single component
931 // of image data
932 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
933 bytes_per_sample == 1)
934 {
935 line_buffer_for_planar_support_uint8 =
936 (uint8_t*)calloc(width, sizeof(uint8_t));
937 if (NULL == line_buffer_for_planar_support_uint8)
938 OJPH_ERROR(0x03000097, "Unable to allocate %d bytes for "
939 "line_buffer_for_planar_support_uint8[] for file %s",
940 width * sizeof(uint8_t), filename);
941 }
942 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
943 bytes_per_sample == 2)
944 {
945 line_buffer_for_planar_support_uint16 =
946 (uint16_t*)calloc(width, sizeof(uint16_t));
947 if (NULL == line_buffer_for_planar_support_uint16)
948 OJPH_ERROR(0x03000098, "Unable to allocate %d bytes for "
949 "line_buffer_for_planar_support_uint16[] for file %s",
950 width * sizeof(uint16_t), filename);
951 }
952 }
953
955
957 void tif_in::set_bit_depth(ui32 num_bit_depths, ui32* bit_depth)
958 {
959 if (num_bit_depths < 1)
960 OJPH_ERROR(0x030000A1, "one or more bit_depths must be provided");
961 ui32 last_bd_idx = 0;
962 for (ui32 i = 0; i < 4; ++i)
963 {
964 ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
965 last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
966
967 if (bd > 32 || bd < 1)
968 {
969 OJPH_ERROR(0x030000A2,
970 "bit_depth = %d, this must be an integer from 1-32", bd);
971 }
972 this->bit_depth[i] = bd;
973 }
974 }
975
977 ui32 tif_in::read(const line_buf* line, ui32 comp_num)
978 {
979 assert(bytes_per_line != 0 && tiff_handle != 0 && comp_num < num_comps);
980 assert((ui32)line->size >= width);
981
982 // do a read from the file if this is the first component and therefore
983 // the first time trying to access this line
984 if (PLANARCONFIG_SEPARATE == planar_configuration && 0 == comp_num )
985 {
986 for (ui32 color = 0; color < num_comps; color++)
987 {
988 if (bytes_per_sample == 1)
989 {
990 TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint8,
991 cur_line, (ui16)color);
992 ui32 x = color;
993 uint8_t* line_buffer_of_interleaved_components =
994 (uint8_t*)line_buffer;
995 for (ui32 i = 0; i < width; i++, x += num_comps)
996 {
997 line_buffer_of_interleaved_components[x] =
998 line_buffer_for_planar_support_uint8[i];
999 }
1000 }
1001 else if (bytes_per_sample == 2)
1002 {
1003 TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint16,
1004 cur_line, (ui16)color);
1005 ui32 x = color;
1006 ui16* line_buffer_of_interleaved_components = (ui16*)line_buffer;
1007 for (ui32 i = 0; i < width; i++, x += num_comps)
1008 {
1009 line_buffer_of_interleaved_components[x] =
1010 line_buffer_for_planar_support_uint16[i];
1011 }
1012 }
1013 }
1014 cur_line++;
1015
1016 }
1017 else if (planar_configuration == PLANARCONFIG_CONTIG && 0 == comp_num)
1018 {
1019 TIFFReadScanline(tiff_handle, line_buffer, cur_line++);
1020 }
1021 if (cur_line >= height)
1022 {
1023 cur_line = 0;
1024 }
1025
1026 if (bytes_per_sample == 1)
1027 {
1028 const ui8* sp = (ui8*)line_buffer + comp_num;
1029 si32* dp = line->i32;
1030 if (bit_depth[comp_num] == 8)
1031 {
1032 for (ui32 i = width; i > 0; --i, sp += num_comps)
1033 *dp++ = (si32)*sp;
1034 }
1035 else if (bit_depth[comp_num] < 8)
1036 {
1037 // read the desired precision from the MSBs
1038 const int bits_to_shift = 8 - (int)bit_depth[comp_num];
1039 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1040 for (ui32 i = width; i > 0; --i, sp += num_comps)
1041 *dp++ = (si32) (((*sp) >> bits_to_shift) & bit_mask);
1042 }
1043 else if (bit_depth[comp_num] > 8)
1044 {
1045 const int bits_to_shift = (int)bit_depth[comp_num] - 8;
1046 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1047 for (ui32 i = width; i > 0; --i, sp += num_comps)
1048 *dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
1049 }
1050 }
1051 else if(bytes_per_sample == 2)
1052 {
1053 if (bit_depth[comp_num] == 16)
1054 {
1055 const ui16* sp = (ui16*)line_buffer + comp_num;
1056 si32* dp = line->i32;
1057 for (ui32 i = width; i > 0; --i, sp += num_comps)
1058 *dp++ = (si32)*sp;
1059 }
1060 else if (bit_depth[comp_num] < 16)
1061 {
1062 // read the desired precision from the MSBs
1063 const int bits_to_shift = 16 - (int)bit_depth[comp_num];
1064 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1065 const ui16* sp = (ui16*)line_buffer + comp_num;
1066 si32* dp = line->i32;
1067 for (ui32 i = width; i > 0; --i, sp += num_comps)
1068 *dp++ = (si32)(((*sp) >> bits_to_shift) & bit_mask);
1069 }
1070 else if (bit_depth[comp_num] > 16)
1071 {
1072 const int bits_to_shift = (int)bit_depth[comp_num] - 16;
1073 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1074 const ui16* sp = (ui16*)line_buffer + comp_num;
1075 si32* dp = line->i32;
1076 for (ui32 i = width; i > 0; --i, sp += num_comps)
1077 *dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
1078 }
1079
1080 }
1081
1082 return width;
1083 }
1084
1086 //
1087 //
1088 //
1089 //
1090 //
1092
1094 void tif_out::open(char* filename)
1095 {
1096 // Error on known incompatilbe output formats
1097 ui32 max_bitdepth = 0;
1098 for (ui32 c = 0; c < num_components; c++)
1099 {
1100 if (bit_depth_of_data[c] > max_bitdepth)
1101 max_bitdepth = bit_depth_of_data[c];
1102 }
1103 if (max_bitdepth > 16)
1104 {
1105 OJPH_WARN(0x030000B1, "TIFF output is currently limited to files "
1106 "with max_bitdepth = 16, the source codestream has max_bitdepth=%d"
1107 ", the decoded data will be truncated to 16 bits", max_bitdepth);
1108 }
1109 if (num_components > 4)
1110 {
1111 OJPH_ERROR(0x030000B2, "TIFF IO is currently limited to files with "
1112 "num_components=1 to 4");
1113 }
1114
1115 assert(tiff_handle == NULL && buffer == NULL);
1116 if ((tiff_handle = TIFFOpen(filename, "w")) == NULL)
1117 {
1118 OJPH_ERROR(0x030000B3, "unable to open file %s for writing", filename);
1119 }
1120
1121 buffer_size = width * (size_t)num_components * (size_t)bytes_per_sample;
1122 buffer = (ui8*)malloc(buffer_size);
1123 fname = filename;
1124 cur_line = 0;
1125
1126 // set tiff fields
1127
1128 // Write the tiff tags to the file
1129 TIFFSetField(tiff_handle, TIFFTAG_IMAGEWIDTH, width);
1130 TIFFSetField(tiff_handle, TIFFTAG_IMAGELENGTH, height);
1131
1132 TIFFSetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, bytes_per_sample * 8);
1133 TIFFSetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, num_components);
1134
1135 planar_configuration = PLANARCONFIG_CONTIG;
1136 TIFFSetField(tiff_handle, TIFFTAG_PLANARCONFIG, planar_configuration);
1137
1138 if (num_components == 1)
1139 {
1140 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1141 }
1142 else if (num_components == 2)
1143 {
1144 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1145 // possible values are EXTRASAMPLE_UNSPECIFIED = 0;
1146 // EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
1147 const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
1148 TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
1149 &extra_samples_description);
1150 }
1151 else if (num_components == 3)
1152 {
1153 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1154 }
1155 else if (num_components == 4)
1156 {
1157 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1158 // possible values are EXTRASAMPLE_UNSPECIFIED = 0;
1159 // EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
1160 const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
1161 TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
1162 &extra_samples_description);
1163 }
1164
1165 TIFFSetField(tiff_handle, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1166 TIFFSetField(tiff_handle, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1167 //TIFFSetField(tiff_handle, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1168 TIFFSetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, height);
1169
1170 }
1171
1173 void tif_out::configure(ui32 width, ui32 height, ui32 num_components,
1174 ui32 *bit_depth)
1175 {
1176 assert(tiff_handle == NULL); //configure before opening
1177
1178 this->width = width;
1179 this->height = height;
1180 this->num_components = num_components;
1181 ui32 max_bitdepth = 0;
1182 for (ui32 c = 0; c < num_components; c++)
1183 {
1184 this->bit_depth_of_data[c] = bit_depth[c];
1185 if (bit_depth[c] > max_bitdepth)
1186 max_bitdepth = bit_depth[c];
1187 }
1188
1189 bytes_per_sample = (max_bitdepth + 7) / 8; // round up
1190 if (bytes_per_sample > 2)
1191 {
1192 // TIFF output is currently limited to files with max_bitdepth = 16,
1193 // the decoded data will be truncated to 16 bits
1194 bytes_per_sample = 2;
1195 }
1196 samples_per_line = num_components * width;
1197 bytes_per_line = bytes_per_sample * (size_t)samples_per_line;
1198
1199 }
1200
1202 ui32 tif_out::write(const line_buf* line, ui32 comp_num)
1203 {
1204 assert(tiff_handle);
1205
1206 if (bytes_per_sample == 1)
1207 {
1208 int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
1209 const si32* sp = line->i32;
1210 ui8* dp = buffer + comp_num;
1211 if (bit_depth_of_data[comp_num] == 8)
1212 {
1213 for (ui32 i = width; i > 0; --i, dp += num_components)
1214 {
1215 // clamp the decoded sample to the allowed range
1216 int val = *sp++;
1217 val = val >= 0 ? val : 0;
1218 val = val <= max_val ? val : max_val;
1219 *dp = (ui8)val;
1220 }
1221 }
1222 else if (bit_depth_of_data[comp_num] < 8)
1223 {
1224 const int bits_to_shift = 8 - (int)bit_depth_of_data[comp_num];
1225 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1226 for (ui32 i = width; i > 0; --i, dp += num_components)
1227 {
1228 // clamp the decoded sample to the allowed range
1229 int val = *sp++;
1230 val = val >= 0 ? val : 0;
1231 val = val <= max_val ? val : max_val;
1232 // shift the decoded data so the data's MSB is aligned with the
1233 // 8 bit MSB
1234 *dp = (ui8)((val & bit_mask) << bits_to_shift);
1235 }
1236 }
1237 else if (bit_depth_of_data[comp_num] > 8)
1238 {
1239 const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 8;
1240 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1241 for (ui32 i = width; i > 0; --i, dp += num_components)
1242 {
1243 // clamp the decoded sample to the allowed range
1244 int val = *sp++;
1245 val = val >= 0 ? val : 0;
1246 val = val <= max_val ? val : max_val;
1247 // shift the decoded data so the data's MSB is aligned with the
1248 // 8 bit MSB
1249 *dp = (ui8)((val >> bits_to_shift) & bit_mask);
1250 }
1251 }
1252
1253 }
1254 else if(bytes_per_sample == 2)
1255 {
1256 int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
1257 const si32* sp = line->i32;
1258 ui16* dp = (ui16*)buffer + comp_num;
1259
1260 if (bit_depth_of_data[comp_num] == 16)
1261 {
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 *dp = (ui16)val;
1269 }
1270 }
1271 else if (bit_depth_of_data[comp_num] < 16)
1272 {
1273 const int bits_to_shift = 16 - (int)bit_depth_of_data[comp_num];
1274 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1275 for (ui32 i = width; i > 0; --i, dp += num_components)
1276 {
1277 // clamp the decoded sample to the allowed range
1278 int val = *sp++;
1279 val = val >= 0 ? val : 0;
1280 val = val <= max_val ? val : max_val;
1281
1282 // shift the decoded data so the data's MSB is aligned with the
1283 // 16 bit MSB
1284 *dp = (ui16)((val & bit_mask) << bits_to_shift);
1285 }
1286 }
1287 else if (bit_depth_of_data[comp_num] > 16)
1288 {
1289 const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 16;
1290 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1291 for (ui32 i = width; i > 0; --i, dp += num_components)
1292 {
1293 // clamp the decoded sample to the allowed range
1294 int val = *sp++;
1295 val = val >= 0 ? val : 0;
1296 val = val <= max_val ? val : max_val;
1297
1298 // shift the decoded data so the data's MSB is aligned with the
1299 // 16 bit MSB
1300 *dp = (ui16)((val >> bits_to_shift) & bit_mask);
1301 }
1302 }
1303
1304 }
1305 // write scanline when the last component is reached
1306 if (comp_num == num_components-1)
1307 {
1308 int result = TIFFWriteScanline(tiff_handle, buffer, cur_line++);
1309 if (result != 1)
1310 OJPH_ERROR(0x030000C1, "error writing to file %s", fname);
1311 }
1312 return 0;
1313 }
1314 #endif /* OJPH_ENABLE_TIFF_SUPPORT */
1315
1317 //
1318 //
1319 //
1320 //
1321 //
1323
1325 void yuv_in::open(const char* filename)
1326 {
1327 assert(fh == NULL);
1328 fh = fopen(filename, "rb");
1329 if (fh == 0)
1330 OJPH_ERROR(0x030000D1, "Unable to open file %s", filename);
1331
1332 //need to extract info from filename
1333
1334 assert(num_com == 1 || num_com == 3);
1335 for (ui32 i = 0; i < num_com; ++i)
1336 bytes_per_sample[i] = bit_depth[i] > 8 ? 2 : 1;
1337 ui32 max_byte_width = width[0] * bytes_per_sample[0];
1338 comp_address[0] = 0;
1339 for (ui32 i = 1; i < num_com; ++i)
1340 {
1341 comp_address[i] = comp_address[i - 1];
1342 comp_address[i] += width[i-1] * height[i-1] * bytes_per_sample[i-1];
1343 max_byte_width = ojph_max(max_byte_width, width[i]*bytes_per_sample[i]);
1344 }
1345 temp_buf = malloc(max_byte_width);
1346 fname = filename;
1347 }
1348
1350 ui32 yuv_in::read(const line_buf* line, ui32 comp_num)
1351 {
1352 assert(comp_num < num_com);
1353 size_t result = fread(temp_buf, bytes_per_sample[comp_num],
1354 width[comp_num], fh);
1355 if (result != width[comp_num])
1356 {
1357 close();
1358 OJPH_ERROR(0x030000E1, "not enough data in file %s", fname);
1359 }
1360
1361 if (bytes_per_sample[comp_num] == 1)
1362 {
1363 const ui8* sp = (ui8*)temp_buf;
1364 si32* dp = line->i32;
1365 for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
1366 *dp++ = (si32)*sp;
1367 }
1368 else
1369 {
1370 // yuv samples wider than one byte are little-endian on disk
1371 const ui16* sp = (ui16*)temp_buf;
1372 si32* dp = line->i32;
1373 for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
1374 *dp++ = (si32)swap_bytes_if_be(*sp);
1375 }
1376
1377 return width[comp_num];
1378 }
1379
1381 void yuv_in::set_img_props(const size& s, ui32 num_components,
1382 ui32 num_downsamplings, const point *subsampling)
1383 {
1384 if (num_components != 1 && num_components !=3)
1385 OJPH_ERROR(0x030000F1, "yuv_in support 1 or 3 components");
1386 this->num_com = num_components;
1387
1388 if (num_downsamplings < 1)
1389 OJPH_ERROR(0x030000F2, "one or more downsampling must be provided");
1390
1391 ui32 last_downsamp_idx = 0;
1392 for (ui32 i = 0; i < num_components; ++i)
1393 {
1394 point cp_ds = subsampling[i<num_downsamplings ? i : last_downsamp_idx];
1395 last_downsamp_idx += last_downsamp_idx + 1 < num_downsamplings ? 1 : 0;
1396
1397 this->subsampling[i] = cp_ds;
1398 }
1399
1400 for (ui32 i = 0; i < num_components; ++i)
1401 {
1402 width[i] = ojph_div_ceil(s.w, this->subsampling[i].x);
1403 height[i] = ojph_div_ceil(s.h, this->subsampling[i].y);
1404 }
1405 }
1406
1409 {
1410 if (num_bit_depths < 1)
1411 OJPH_ERROR(0x03000101, "one or more bit_depths must be provided");
1412 ui32 last_bd_idx = 0;
1413 for (ui32 i = 0; i < 3; ++i)
1414 {
1415 ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
1416 last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
1417
1418 this->bit_depth[i] = bd;
1419 }
1420 }
1421
1423 //
1424 //
1425 //
1426 //
1427 //
1429
1432 {
1433 close();
1434 if (buffer)
1435 {
1436 free(buffer);
1437 buffer = NULL;
1438 buffer_size = 0;
1439 }
1440 if (comp_width)
1441 {
1442 delete [] comp_width;
1443 comp_width = NULL;
1444 }
1445 }
1446
1448 void yuv_out::open(char *filename)
1449 {
1450 assert(fh == NULL); //configure before open
1451 fh = fopen(filename, "wb");
1452 if (fh == 0)
1453 OJPH_ERROR(0x03000111, "Unable to open file %s", filename);
1454 fname = filename;
1455 }
1456
1460 {
1461 assert(fh == NULL);
1462 this->num_components = num_components;
1463 this->bit_depth = bit_depth;
1464 this->comp_width = new ui32[num_components];
1465 ui32 tw = 0;
1466 for (ui32 i = 0; i < num_components; ++i)
1467 {
1468 this->comp_width[i] = comp_width[i];
1469 tw = ojph_max(tw, this->comp_width[i]);
1470 }
1471 this->width = tw;
1472 buffer_size = tw * (bit_depth > 8 ? 2 : 1);
1473 buffer = (ui8*)malloc(buffer_size);
1474 }
1475
1477 ui32 yuv_out::write(const line_buf* line, ui32 comp_num)
1478 {
1479 assert(fh);
1480 assert(comp_num < num_components);
1481
1482 int max_val = (1<<bit_depth) - 1;
1483 ui32 w = comp_width[comp_num];
1484 if (bit_depth > 8)
1485 {
1486 const si32 *sp = line->i32;
1487 ui16 *dp = (ui16 *)buffer;
1488 for (ui32 i = w; i > 0; --i)
1489 {
1490 int val = *sp++;
1491 val = val >= 0 ? val : 0;
1492 val = val <= max_val ? val : max_val;
1493 *dp++ = swap_bytes_if_be((ui16)val);
1494 }
1495 if (fwrite(buffer, 2, w, fh) != w)
1496 OJPH_ERROR(0x03000121, "unable to write to file %s", fname);
1497 }
1498 else
1499 {
1500 const si32 *sp = line->i32;
1501 ui8 *dp = (ui8 *)buffer;
1502 for (ui32 i = w; i > 0; --i)
1503 {
1504 int val = *sp++;
1505 val = val >= 0 ? val : 0;
1506 val = val <= max_val ? val : max_val;
1507 *dp++ = (ui8)val;
1508 }
1509 if (fwrite(buffer, 1, w, fh) != w)
1510 OJPH_ERROR(0x03000122, "unable to write to file %s", fname);
1511 }
1512
1513 return w;
1514 }
1515
1517 //
1518 //
1519 //
1520 //
1521 //
1523
1525 void raw_in::open(const char* filename)
1526 {
1527 assert(fh == NULL);
1528 fh = fopen(filename, "rb");
1529 if (fh == NULL)
1530 OJPH_ERROR(0x03000131, "Unable to open file %s", filename);
1531
1532 cur_line = 0;
1533 bytes_per_sample = (bit_depth + 7) >> 3;
1535 buffer = (ui8*)malloc(buffer_size);
1536 fname = filename;
1537 }
1538
1540 ui32 raw_in::read(const line_buf* line, ui32 comp_num)
1541 {
1542 ojph_unused(comp_num);
1543 assert(comp_num == 0);
1544 size_t result = fread(buffer, bytes_per_sample, width, fh);
1545 if (result != width)
1546 {
1547 close();
1548 OJPH_ERROR(0x03000132, "not enough data in file %s", fname);
1549 }
1550
1551 if (bytes_per_sample > 3)
1552 {
1553 si32* dp = line->i32;
1554 if (is_signed) {
1555 const si32* sp = (si32*)buffer;
1556 for (ui32 i = width; i > 0; --i, ++sp)
1557 *dp++ = (si32)swap_bytes_if_be((ui32)*sp);
1558 }
1559 else {
1560 const ui32* sp = (ui32*)buffer;
1561 for (ui32 i = width; i > 0; --i, ++sp)
1562 *dp++ = (si32)swap_bytes_if_be(*sp);
1563 }
1564 }
1565 else if (bytes_per_sample > 2)
1566 {
1567 si32* dp = line->i32;
1568 const ui8* sp = (const ui8*)buffer;
1569 if (is_signed) {
1570 for (ui32 i = width; i > 0; --i, sp += 3) {
1571 si32 val =
1572 (si32)((ui32)sp[0] | ((ui32)sp[1] << 8) | ((ui32)sp[2] << 16));
1573 val |= (val & 0x800000) ? (si32)0xFF000000 : 0;
1574 *dp++ = val;
1575 }
1576 }
1577 else {
1578 for (ui32 i = width; i > 0; --i, sp += 3)
1579 *dp++ =
1580 (si32)((ui32)sp[0] | ((ui32)sp[1] << 8) | ((ui32)sp[2] << 16));
1581 }
1582 }
1583 else if (bytes_per_sample > 1)
1584 {
1585 si32* dp = line->i32;
1586 if (is_signed) {
1587 const si16* sp = (si16*)buffer;
1588 for (ui32 i = width; i > 0; --i, ++sp)
1589 *dp++ = swap_bytes_if_be((ui16)*sp);
1590 }
1591 else {
1592 const ui16* sp = (ui16*)buffer;
1593 for (ui32 i = width; i > 0; --i, ++sp)
1594 *dp++ = swap_bytes_if_be(*sp);
1595 }
1596 }
1597 else
1598 {
1599 si32* dp = line->i32;
1600 if (is_signed) {
1601 const si8* sp = (si8*)buffer;
1602 for (ui32 i = width; i > 0; --i, ++sp)
1603 *dp++ = *sp;
1604 }
1605 else {
1606 const ui8* sp = (ui8*)buffer;
1607 for (ui32 i = width; i > 0; --i, ++sp)
1608 *dp++ = (si32)*sp;
1609 }
1610 }
1611
1612 return width;
1613 }
1614
1617 {
1618 assert(fh == NULL);
1619 //need to extract this info from filename
1620 this->width = s.w;
1621 this->height = s.h;
1622 this->bit_depth = bit_depth;
1623 this->is_signed = is_signed;
1624 }
1625
1627 //
1628 //
1629 //
1630 //
1631 //
1633
1636 {
1637 close();
1638 if (buffer)
1639 {
1640 free(buffer);
1641 buffer = NULL;
1642 buffer_size = 0;
1643 }
1644 }
1645
1647 void raw_out::open(char *filename)
1648 {
1649 assert(fh == NULL); //configure before open
1650 fh = fopen(filename, "wb");
1651 if (fh == 0)
1652 OJPH_ERROR(0x03000141, "Unable to open file %s", filename);
1653 fname = filename;
1654 }
1655
1658 {
1659 assert(fh == NULL);
1660 this->is_signed = is_signed;
1661 this->bit_depth = bit_depth;
1662 this->width = width;
1663
1664 if (is_signed) {
1665 upper_val = ((si64)1 << (bit_depth - 1));
1666 lower_val = -((si64)1 << (bit_depth - 1));
1667 } else {
1668 upper_val = (si64)1 << bit_depth;
1669 lower_val = (si64)0;
1670 }
1671
1672 bytes_per_sample = (bit_depth + 7) >> 3;
1674 buffer = (ui8*)malloc(buffer_size);
1675 }
1676
1678 ui32 raw_out::write(const line_buf* line, ui32 comp_num)
1679 {
1680 ojph_unused(comp_num);
1681 assert(fh);
1682 assert(comp_num == 0);
1683
1684 if (is_signed)
1685 {
1686 if (bytes_per_sample > 3)
1687 {
1688 const si32* sp = line->i32;
1689 si32* dp = (si32*)buffer;
1690 for (ui32 i = width; i > 0; --i)
1691 {
1692 si64 val = *sp++;
1693 val = val < upper_val ? val : upper_val;
1694 val = val >= lower_val ? val : lower_val;
1695 *dp++ = (si32)swap_bytes_if_be((ui32)(si32)val);
1696 }
1697 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1698 OJPH_ERROR(0x03000151, "unable to write to file %s", fname);
1699 }
1700 else if (bytes_per_sample > 2)
1701 {
1702 const si32* sp = line->i32;
1703 ui8* dp = buffer;
1704 for (ui32 i = width; i > 0; --i)
1705 {
1706 si64 val = *sp++;
1707 val = val < upper_val ? val : upper_val;
1708 val = val >= lower_val ? val : lower_val;
1709 *dp++ = (ui8)val;
1710 *dp++ = (ui8)(val >> 8);
1711 *dp++ = (ui8)(val >> 16);
1712 }
1713 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1714 OJPH_ERROR(0x03000152, "unable to write to file %s", fname);
1715 }
1716 else if (bytes_per_sample > 1)
1717 {
1718 const si32* sp = line->i32;
1719 si16* dp = (si16*)buffer;
1720 for (ui32 i = width; i > 0; --i)
1721 {
1722 si64 val = *sp++;
1723 val = val < upper_val ? val : upper_val;
1724 val = val >= lower_val ? val : lower_val;
1725 *dp++ = (si16)swap_bytes_if_be((ui16)(si16)val);
1726 }
1727 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1728 OJPH_ERROR(0x03000153, "unable to write to file %s", fname);
1729 }
1730 else
1731 {
1732 const si32* sp = line->i32;
1733 si8* dp = (si8*)buffer;
1734 for (ui32 i = width; i > 0; --i)
1735 {
1736 si64 val = *sp++;
1737 val = val < upper_val ? val : upper_val;
1738 val = val >= lower_val ? val : lower_val;
1739 *dp++ = (si8)val;
1740 }
1741 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1742 OJPH_ERROR(0x03000154, "unable to write to file %s", fname);
1743 }
1744 }
1745 else
1746 {
1747 if (bytes_per_sample > 3)
1748 {
1749 const ui32* sp = (ui32*)line->i32;
1750 ui32* dp = (ui32*)buffer;
1751 for (ui32 i = width; i > 0; --i)
1752 {
1753 si64 val = *sp++;
1754 val = val < upper_val ? val : upper_val;
1755 val = val >= lower_val ? val : lower_val;
1756 *dp++ = swap_bytes_if_be((ui32)val);
1757 }
1758 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1759 OJPH_ERROR(0x03000155, "unable to write to file %s", fname);
1760 }
1761 else if (bytes_per_sample > 2)
1762 {
1763 const ui32* sp = (ui32*)line->i32;
1764 ui8* dp = buffer;
1765 for (ui32 i = width; i > 0; --i)
1766 {
1767 si64 val = *sp++;
1768 val = val < upper_val ? val : upper_val;
1769 val = val >= lower_val ? val : lower_val;
1770 *dp++ = (ui8)val;
1771 // this only works for little endian architecture
1772 *dp++ = (ui8)(val >> 8);
1773 *dp++ = (ui8)(val >> 16);
1774 }
1775 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1776 OJPH_ERROR(0x03000156, "unable to write to file %s", fname);
1777 }
1778 else if (bytes_per_sample > 1)
1779 {
1780 const ui32* sp = (ui32*)line->i32;
1781 ui16* dp = (ui16*)buffer;
1782 for (ui32 i = width; i > 0; --i)
1783 {
1784 si64 val = *sp++;
1785 val = val < upper_val ? val : upper_val;
1786 val = val >= lower_val ? val : lower_val;
1787 *dp++ = swap_bytes_if_be((ui16)val);
1788 }
1789 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1790 OJPH_ERROR(0x03000157, "unable to write to file %s", fname);
1791 }
1792 else
1793 {
1794 const ui32* sp = (ui32*)line->i32;
1795 ui8* dp = (ui8*)buffer;
1796 for (ui32 i = width; i > 0; --i)
1797 {
1798 si64 val = *sp++;
1799 val = val < upper_val ? val : upper_val;
1800 val = val >= lower_val ? val : lower_val;
1801 *dp++ = (ui8)val;
1802 }
1803 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1804 OJPH_ERROR(0x03000158, "unable to write to file %s", fname);
1805 }
1806 }
1807
1808 return width;
1809 }
1810
1811
1813 //
1814 //
1815 //
1816 //
1817 //
1819
1821
1822 void dpx_in::open(const char* filename)
1823 {
1824 assert(file_handle == 0);
1825 file_handle = fopen(filename, "rb");
1826 if (0 == file_handle)
1827 OJPH_ERROR(0x03000161, "Unable to open file %s", filename);
1828 fname = filename;
1829
1830 // read magic number
1831 ui32 magic_number;
1832 if (fread(&magic_number, sizeof(ui32), 1, file_handle) != 1)
1833 {
1834 close();
1835 OJPH_ERROR(0x03000162, "Error reading file %s", filename);
1836 }
1837
1838 // check magic number
1839 const ui32 dpx_magic_number = 0x53445058;
1840 if (dpx_magic_number == magic_number)
1841 {
1842 // magic number is a match - no byte swapping necessary
1844 }
1845 else if (dpx_magic_number == be2le(magic_number))
1846 {
1847 // magic number is a match after bytes swapping -
1848 // the data read from this file needs byte swapping
1850 }
1851 else
1852 {
1853 close();
1854 OJPH_ERROR(0x03000163, "Error reading file %s - this does not appear "
1855 "to be a valid DPX file. It has magic number = 0x%08X. The magic "
1856 "number of a DPX file is 0x%08X.", filename, magic_number,
1857 dpx_magic_number);
1858 }
1859
1860 // read offset to data
1861 if (fread(&offset_to_image_data_in_bytes, sizeof(ui32), 1, file_handle)
1862 != 1)
1863 {
1864 close();
1865 OJPH_ERROR(0x03000164, "Error reading file %s", filename);
1866 }
1869 // read version
1870 if (fread(version, sizeof(uint8_t), 8, file_handle) != 8)
1871 {
1872 close();
1873 OJPH_ERROR(0x03000165, "Error reading file %s", filename);
1874 }
1875 // read image file size in bytes
1876 if (fread(&total_image_file_size_in_bytes, sizeof(ui32), 1, file_handle)
1877 != 1)
1878 {
1879 close();
1880 OJPH_ERROR(0x03000166, "Error reading file %s", filename);
1881 }
1884
1885 // seek to image info header
1886 if (fseek(file_handle,768, SEEK_SET) != 0)
1887 {
1888 close();
1889 OJPH_ERROR(0x03000167, "Error reading file %s", filename);
1890 }
1891
1892 // read image_orientation
1893 if (fread(&image_orientation, sizeof(uint16_t), 1, file_handle) != 1)
1894 {
1895 close();
1896 OJPH_ERROR(0x03000168, "Error reading file %s", filename);
1897 }
1900
1901 // read number of image elements
1902 if (fread(&number_of_image_elements, sizeof(uint16_t), 1, file_handle)
1903 != 1)
1904 {
1905 close();
1906 OJPH_ERROR(0x03000169, "Error reading file %s", filename);
1907 }
1910
1911 // read pixels per line
1912 if (fread(&pixels_per_line, sizeof(ui32), 1, file_handle) != 1)
1913 {
1914 close();
1915 OJPH_ERROR(0x0300016A, "Error reading file %s", filename);
1916 }
1919
1920 // read lines per image element
1921 if (fread(&lines_per_image_element, sizeof(ui32), 1, file_handle) != 1)
1922 {
1923 close();
1924 OJPH_ERROR(0x0300016B, "Error reading file %s", filename);
1925 }
1928
1929 // seek to data structure for image element 1
1930 if (fseek(file_handle, 780, SEEK_SET) != 0)
1931 {
1932 close();
1933 OJPH_ERROR(0x0300016C, "Error reading file %s", filename);
1934 }
1935
1936 // read data sign for image element
1937 if (fread(&data_sign_for_image_element_1, sizeof(ui32), 1, file_handle)
1938 != 1)
1939 {
1940 close();
1941 OJPH_ERROR(0x0300016E, "Error reading file %s", filename);
1942 }
1945
1946 // seek to core data elements in image element 1
1947 if (fseek(file_handle, 800, SEEK_SET) != 0)
1948 {
1949 close();
1950 OJPH_ERROR(0x0300016F, "Error reading file %s", filename);
1951 }
1952
1953 // read descriptor
1954 if (fread(&descriptor_for_image_element_1, sizeof(uint8_t), 1, file_handle)
1955 != 1)
1956 {
1957 close();
1958 OJPH_ERROR(0x03000170, "Error reading file %s", filename);
1959 }
1960
1961 // read transfer characteristic
1962 if (fread(&transfer_characteristic_for_image_element_1, sizeof(uint8_t),
1963 1, file_handle) != 1)
1964 {
1965 close();
1966 OJPH_ERROR(0x03000171, "Error reading file %s", filename);
1967 }
1968
1969 // read colorimetric specification
1970 if (fread(&colormetric_specification_for_image_element_1, sizeof(uint8_t),
1971 1, file_handle) != 1)
1972 {
1973 close();
1974 OJPH_ERROR(0x03000172, "Error reading file %s", filename);
1975 }
1976
1977 // read bit depth
1978 if (fread(&bitdepth_for_image_element_1, sizeof(uint8_t), 1, file_handle)
1979 != 1)
1980 {
1981 close();
1982 OJPH_ERROR(0x03000173, "Error reading file %s", filename);
1983 }
1984
1985 // read packing
1986 if (fread(&packing_for_image_element_1, sizeof(uint16_t), 1, file_handle)
1987 != 1)
1988 {
1989 close();
1990 OJPH_ERROR(0x03000174, "Error reading file %s", filename);
1991 }
1994
1995 // read encoding
1996 if (fread(&encoding_for_image_element_1, sizeof(uint16_t), 1, file_handle)
1997 != 1)
1998 {
1999 close();
2000 OJPH_ERROR(0x03000175, "Error reading file %s", filename);
2001 }
2004
2005 // read offset to data
2006 if (fread(&offset_to_data_for_image_element_1, sizeof(ui32), 1,
2007 file_handle) != 1)
2008 {
2009 close();
2010 OJPH_ERROR(0x03000176, "Error reading file %s", filename);
2011 }
2015
2016 // set to starting point of image data
2017 if (fseek(file_handle, (long)offset_to_image_data_in_bytes, SEEK_SET) != 0)
2018 {
2019 close();
2020 OJPH_ERROR(0x03000177, "Error reading file %s", filename);
2021 }
2022
2023 // set ojph properties
2026 num_comps = 3; // descriptor field can indicate 1, 3, or 4 comps
2027 for ( ojph::ui32 c = 0; c < get_num_components(); c++)
2028 {
2030 is_signed[c] = false;
2031 subsampling[c] = point(1,1);
2032 }
2033
2034 // handle DPX image data packing in file
2035 ui32 number_of_samples_per_32_bit_word = 32 / bitdepth_for_image_element_1;
2038 (number_of_samples_per_line + (number_of_samples_per_32_bit_word - 1))
2039 / number_of_samples_per_32_bit_word;
2040
2041 cur_line = 0;
2042
2043 // allocate linebuffer to hold a line of image data from the file
2045 if (NULL == line_buffer)
2046 OJPH_ERROR(0x03000178, "Unable to allocate %d bytes for line_buffer[] "
2047 "for file %s",
2048 number_of_32_bit_words_per_line * sizeof(ui32), filename);
2049
2050 // allocate line_buffer_16bit_samples to hold a line of image data in memory
2052 (ui16*) malloc((size_t)width * num_comps * sizeof(ui16));
2053 if (NULL == line_buffer_16bit_samples)
2054 OJPH_ERROR(0x03000179, "Unable to allocate %d bytes for "
2055 "line_buffer_16bit_samples[] for file %s",
2056 (size_t)width * num_comps * sizeof(ui16), filename);
2057
2058 cur_line = 0;
2059
2060 return;
2061 }
2062
2064 ui32 dpx_in::read(const line_buf* line, ui32 comp_num)
2065 {
2066 assert(file_handle != 0 && comp_num < num_comps);
2067 assert((ui32)line->size >= width);
2068
2069 // read from file if trying to read the first component
2070 if (0 == comp_num)
2071 {
2074 {
2075 close();
2076 OJPH_ERROR(0x03000181, "Error reading file %s", fname);
2077 }
2078
2079 if (true == is_byte_swapping_necessary)
2080 {
2082 {
2083 ui16* line_buffer_ptr = (ui16*)line_buffer;
2084 for (size_t i = 0; i < 2*number_of_32_bit_words_per_line; i++)
2085 {
2086 line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
2087 }
2088 }
2089 else
2090 {
2091 ui32* line_buffer_ptr = (ui32*)line_buffer;
2092 for (size_t i = 0; i < number_of_32_bit_words_per_line; i++)
2093 {
2094 line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
2095 }
2096 }
2097 }
2098
2099 // extract samples from 32bit words from file read into
2100 // RGB ordered buffer
2101 ui32 word_index = 0;
2102 if (10 == bitdepth_for_image_element_1 && 3 == num_comps
2104 {
2105 ui32* line_buffer_ptr = (ui32*)line_buffer;
2106 for (ui32 i = 0; i < number_of_samples_per_line; i += 3)
2107 {
2108 // R
2110 (ui16) ((line_buffer_ptr[word_index] & 0xFFC00000) >> 22);
2111 // G
2113 (ui16) ((line_buffer_ptr[word_index] & 0x003FF000) >> 12);
2114 // B
2116 (ui16) ((line_buffer_ptr[word_index] & 0x00000FFC) >> 2);
2117 word_index++;
2118 }
2119 }
2120 else if (16 == bitdepth_for_image_element_1 && 3 == num_comps)
2121 {
2122 ui16* line_buffer_ptr = (ui16*)line_buffer;
2123 for (ui32 i = 0; i < number_of_samples_per_line; i++)
2124 {
2125 line_buffer_16bit_samples[i] = line_buffer_ptr[i];
2126 }
2127 }
2128 else
2129 {
2130 OJPH_ERROR(0x03000182, "file %s uses DPX image formats that are not "
2131 "yet supported by this software\n bitdepth_for_image_element_1 = "
2132 "%d\n num_comps=%d\npacking_for_image_element_1=%d\n "
2133 "descriptor_for_image_element_1=%d", fname,
2136 }
2137
2138 cur_line++;
2139 }
2140
2141 // copy sample data from the unpacked line buffer into a
2142 // single-component buffer to be used by the openjph core
2143 const ui16* sp = (ui16*)line_buffer_16bit_samples + comp_num;
2144 si32* dp = line->i32;
2145 for (ui32 i = width; i > 0; --i, sp += num_comps)
2146 *dp++ = (si32)*sp;
2147
2148 return width;
2149 }
2150
2151}
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:187
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)
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)
static ui16 swap_bytes_if_le(ui16 t)
Definition ojph_arch.h:414
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
const bool is_machine_little_endian
Definition ojph_arch.h:400
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 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)
static ui16 swap_bytes_if_be(ui16 t)
Definition ojph_arch.h:405
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:206
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
const bool is_force_pfm_write_as_little_endian_on_disk
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)
@ X86_CPU_EXT_LEVEL_AVX2
Definition ojph_arch.h:163
@ X86_CPU_EXT_LEVEL_SSE41
Definition ojph_arch.h:160
#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,...)