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' &&
270 (len < 4 || filename[len - 4] != '.' ||
271 (filename[len - 3] != 'p' && filename[len - 3] != 'P') ||
272 (filename[len - 2] != 'g' && filename[len - 2] != 'G') ||
273 (filename[len - 1] != 'm' && filename[len - 1] != 'M')))
274 {
275 close();
276 OJPH_ERROR(0x03000004, "wrong file extension, a file with "
277 "keyword P5 must have a .pgm extension for file %s", filename);
278 }
279 if (t[1] == '6' &&
280 (len < 4 || filename[len - 4] != '.' ||
281 (filename[len - 3] != 'p' && filename[len - 3] != 'P') ||
282 (filename[len - 2] != 'p' && filename[len - 2] != 'P') ||
283 (filename[len - 1] != 'm' && filename[len - 1] != 'M')))
284 {
285 close();
286 OJPH_ERROR(0x03000005, "wrong file extension, a file with keyword P6 "
287 "must have a .ppm extension for file %s", filename);
288 }
289
290 // set number of components based on file-type
291 num_comps = t[1] == '5' ? 1 : 3;
293
294 // read width, height and max value in header
295 if (fscanf(fh, "%d %d %d", &width, &height, &max_val) != 3)
296 {
297 close();
298 OJPH_ERROR(0x03000006, "error in file format for file %s", filename);
299 }
301 bytes_per_sample = max_val > 255 ? 2 : 1;
302 max_val_num_bits = 32u - count_leading_zeros(max_val);
304 fgetc(fh);
306
307 // allocate linebuffer to hold a line of image data
309 {
310 if (alloc_p == NULL)
311 {
313 void* t = temp_buf;
314 if (temp_buf)
316 else
318 if (temp_buf == NULL) { // failed to allocate memory
319 if (t) free(t); // the original buffer is still valid
320 OJPH_ERROR(0x03000007, "error allocating memory");
321 }
322 }
323 else
324 {
325 assert(temp_buf_byte_size == 0); //cannot reallocate the buffer
328 }
329 }
330 cur_line = 0;
331 }
332
335 {
336 if (alloc_p == NULL)
337 return;
338
339 if (bytes_per_sample == 1)
341 else
343 }
344
346 ui32 ppm_in::read(const line_buf* line, ui32 comp_num)
347 {
348 assert(temp_buf_byte_size != 0 && fh != 0 && comp_num < num_comps);
349 assert(line->size >= width);
350
351 if (planar || comp_num == 0)
352 {
353 size_t result = fread(
355 if (result != num_ele_per_line)
356 {
357 close();
358 OJPH_ERROR(0x03000011, "not enough data in file %s", fname);
359 }
360 if (++cur_line >= height)
361 {
362 cur_line = 0;
363 ojph_fseek(fh, start_of_data, SEEK_SET); //handles plannar reading
364 }
365 }
366
367 if (bytes_per_sample == 1)
368 {
369 const ui8* sp = (ui8*)temp_buf + comp_num;
370 si32* dp = line->i32;
371 for (ui32 i = width; i > 0; --i, sp+=num_comps)
372 *dp++ = (si32)*sp;
373 }
374 else
375 {
376 const ui16* sp = (ui16*)temp_buf + comp_num;
377 si32* dp = line->i32;
378 for (ui32 i = width; i > 0; --i, sp+=num_comps)
379 *dp++ = (si32) swap_bytes_if_le((ui16) *sp);
380 }
381
382 return width;
383 }
384
386 //
387 //
388 //
389 //
390 //
392
394 void ppm_out::open(char* filename)
395 {
396 assert(fh == NULL && buffer == NULL);
397 if (num_components == 1)
398 {
399 size_t len = strlen(filename);
400 if (len >= 4)
401 {
402 if (strncmp(".ppm", filename + len - 4, 4) == 0)
403 {
404 filename[len - 2] = 'g';
405 OJPH_WARN(0x03000021, "file was renamed %s\n", filename);
406 }
407 if (strncmp(".PPM", filename + len - 4, 4) == 0)
408 {
409 filename[len - 2] = 'G';
410 OJPH_WARN(0x03000022, "file was renamed %s\n", filename);
411 }
412 }
413 fh = fopen(filename, "wb");
414 if (fh == NULL)
415 OJPH_ERROR(0x03000023,
416 "unable to open file %s for writing", filename);
417
418 fprintf(fh, "P5\n%d %d\n%d\n", width, height, (1 << bit_depth) - 1);
420 buffer = (ui8*)malloc(buffer_size);
421 }
422 else
423 {
424 size_t len = strlen(filename);
425 if (len >= 4)
426 {
427 if (strncmp(".pgm", filename + len - 4, 4) == 0)
428 {
429 filename[len - 2] = 'p';
430 OJPH_WARN(0x03000024, "file was renamed %s\n", filename);
431 }
432 if (strncmp(".PGM", filename + len - 4, 4) == 0)
433 {
434 filename[len - 2] = 'P';
435 OJPH_WARN(0x03000025, "file was renamed %s\n", filename);
436 }
437 }
438 fh = fopen(filename, "wb");
439 if (fh == NULL)
440 OJPH_ERROR(0x03000026,
441 "unable to open file %s for writing", filename);
442 int result = //the number of written characters
443 fprintf(fh, "P6\n%d %d\n%d\n", width, height, (1 << bit_depth) - 1);
444 if (result == 0)
445 OJPH_ERROR(0x03000027, "error writing to file %s", filename);
446 buffer_size = (size_t)width * num_components * (size_t)bytes_per_sample;
447 buffer = (ui8*)malloc(buffer_size);
448 }
449 fname = filename;
450 cur_line = 0;
451 }
452
456 {
457 assert(fh == NULL); //configure before opening
458 if (num_components != 1 && num_components != 3)
459 OJPH_ERROR(0x03000031,
460 "ppm supports 3 colour components, while pgm supports 1");
461 this->width = width;
462 this->height = height;
463 this->num_components = num_components;
464 this->bit_depth = bit_depth;
465 bytes_per_sample = 1 + (bit_depth > 8 ? 1 : 0);
468
469#if !defined(OJPH_ENABLE_WASM_SIMD) || !defined(OJPH_EMSCRIPTEN)
470
471 if (bytes_per_sample == 1) {
472 if (num_components == 1)
474 else
476 }
477 else {
478 if (num_components == 1)
480 else
482 }
483
484 #ifndef OJPH_DISABLE_SIMD
485
486 #if (defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
487
488 #ifndef OJPH_DISABLE_SSE4
490 if (bytes_per_sample == 1) {
491 if (num_components == 1)
493 else
495 }
496 else {
497 if (num_components == 1)
499 else
501 }
502 }
503 #endif // !OJPH_DISABLE_SSE4
504
505 #ifndef OJPH_DISABLE_AVX2
507 if (bytes_per_sample == 1) {
508 if (num_components == 1)
510 else
512 }
513 else {
514 if (num_components == 1)
516 else
517 { } // did not find an implementation better than sse41
518 }
519 }
520 #endif // !OJPH_DISABLE_AVX2
521
522 #elif defined(OJPH_ARCH_ARM)
523
524 #endif // !(defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
525
526 #endif // !OJPH_DISABLE_SIMD
527
528#else // OJPH_ENABLE_WASM_SIMD
529
530 if (bytes_per_sample == 1) {
531 if (num_components == 1)
533 else
535 }
536 else {
537 if (num_components == 1)
539 else
541 }
542
543#endif // !OJPH_ENABLE_WASM_SIMD
544 }
545
547 ui32 ppm_out::write(const line_buf* line, ui32 comp_num)
548 {
549 assert(fh);
550
551 lptr[comp_num] = line;
552 if (comp_num == num_components - 1)
553 {
554 assert(lptr[0] != lptr[1]);
555 assert((lptr[1]!=lptr[2] && num_components==3) || num_components==1);
557 size_t result = fwrite(buffer,
559 if (result != samples_per_line)
560 OJPH_ERROR(0x03000041, "error writing to file %s", fname);
561 }
562 return 0;
563 }
564
566 //
567 //
568 //
569 //
570 //
572
574 void pfm_in::open(const char *filename)
575 {
576 assert(fh == 0);
577 fh = fopen(filename, "rb");
578 if (fh == 0)
579 OJPH_ERROR(0x03000051, "Unable to open file %s", filename);
580 fname = filename;
581
582 // read magic number
583 char t[2];
584 if (fread(t, 1, 2, fh) != 2)
585 {
586 close();
587 OJPH_ERROR(0x03000052, "Error reading file %s", filename);
588 }
589
590 // check magic number
591 if (t[0] != 'P' || (t[1] != 'F' && t[1] != 'f'))
592 {
593 close();
594 OJPH_ERROR(0x03000053, "Unknown file type for file %s", filename);
595 }
596
597 // set number of components based on file-type
598 num_comps = t[1] == 'f' ? 1 : 3;
600
601 // read width, height and max value in header
602 if (fscanf(fh, "%d %d", &width, &height) != 2)
603 {
604 close();
605 OJPH_ERROR(0x03000054,
606 "Error reading width and height in file %s", filename);
607 }
609
610 // little or big-endian
611 if (fscanf(fh, "%f", &scale) != 1)
612 {
613 close();
614 OJPH_ERROR(0x03000055, "Error reading scale in file %s", filename);
615 }
616 little_endian = scale < 0.0f;
617 scale = std::abs(scale);
618
619 fgetc(fh);
621
622 // alloc. linebuffer to hold a line of image data, if more than 1 comp.
623 if (temp_buf_byte_size < num_comps * (size_t)width * sizeof(float))
624 {
625 if (alloc_p == NULL)
626 {
627 temp_buf_byte_size = num_comps * (size_t)width * sizeof(float);
628 void* t = temp_buf;
629 if (temp_buf)
630 temp_buf = (float*)realloc(temp_buf, temp_buf_byte_size);
631 else
632 temp_buf = (float*)malloc(temp_buf_byte_size);
633 if (temp_buf == NULL) { // failed to allocate memory
634 if (t) free(t); // the original buffer is still valid
635 OJPH_ERROR(0x03000056, "Error allocating memory");
636 }
637 }
638 else
639 {
640 assert(temp_buf_byte_size == 0); //cannot reallocate the buffer
641 temp_buf_byte_size = num_comps * (size_t)width * sizeof(float);
643 }
644 }
645 cur_line = 0;
646 }
647
650 {
651 if (alloc_p == NULL)
652 return;
653 temp_buf = alloc_p->post_alloc_data<float>(num_comps * (size_t)width, 0);
654 }
655
657 ui32 pfm_in::read(const line_buf* line, ui32 comp_num)
658 {
659 assert(temp_buf_byte_size != 0 );
660 assert(fh != 0 && comp_num < num_comps);
661 assert(line->size >= width);
662
663 if (comp_num == 0)
664 {
665 si64 loc = start_of_data;
666 loc += (size_t)(height-1 - cur_line) * (size_t)num_comps
667 * (size_t)width * sizeof(float);
668 if (ojph_fseek(fh, loc, SEEK_SET) != 0)
669 {
670 close();
671 OJPH_ERROR(0x03000061, "Error seeking in file %s", fname);
672 }
673 size_t result =
674 fread(temp_buf, sizeof(float), (size_t)num_comps * (size_t)width, fh);
675 if (result != (size_t)num_comps * (size_t)width)
676 {
677 close();
678 OJPH_ERROR(0x03000062, "Not enough data in file %s", fname);
679 }
680 if (++cur_line >= height)
681 cur_line = 0;
682 }
683
684 float* sp = temp_buf + comp_num;
685 float* dp = line->f32;
686
688 {
689 ui32 shift = 32 - bit_depth[comp_num];
690 if (shift)
691 for (ui32 i = width; i > 0; --i, sp += num_comps)
692 {
693 si32 s;
694 memcpy(&s, sp, sizeof(si32));
695 s >>= shift;
696 memcpy(dp, &s, sizeof(si32));
697 ++dp;
698 }
699 else
700 for (ui32 i = width; i > 0; --i, sp += num_comps)
701 *dp++ = *sp;
702 }
703 else {
704 ui32 shift = 32 - bit_depth[comp_num];
705 if (shift)
706 for (ui32 i = width; i > 0; --i, sp += num_comps) {
707 si32 s;
708 memcpy(&s, sp, sizeof(si32));
709 s = (si32)be2le((ui32)s);
710 s >>= shift;
711 memcpy(dp, &s, sizeof(si32));
712 ++dp;
713 }
714 else
715 for (ui32 i = width; i > 0; --i, sp += num_comps) {
716 ui32 u;
717 memcpy(&u, sp, sizeof(ui32));
718 u = be2le(u);
719 memcpy(dp, &u, sizeof(ui32));
720 ++dp;
721 }
722 }
723
724 return width;
725 }
726
728 //
729 //
730 //
731 //
732 //
734 // When is_force_pfm_write_as_little_endian_on_disk is true, pfm_out writes
735 // little-endian files on both big and little endian machines.
736 // When is_force_pfm_write_as_little_endian_on_disk is false, pfm_out writes
737 // in the machine's native byte order and sets the scale sign accordingly.
740 void pfm_out::open(char* filename)
741 {
742 assert(fh == NULL && buffer == NULL);
743 fh = fopen(filename, "wb");
744 if (fh == NULL)
745 OJPH_ERROR(0x03000071,
746 "Unable to open file %s for writing", filename);
747 int result = //the number of written characters
748 fprintf(fh, "P%c\n%d %d\n%f\n",
749 num_components > 1 ? 'F' : 'f', width, height, scale);
750 if (result == 0)
751 OJPH_ERROR(0x03000072, "error writing to file %s", filename);
752 buffer_size = (size_t)width * num_components * sizeof(float);
753 buffer = (float*)malloc(buffer_size);
754 fname = filename;
755 cur_line = 0;
757 }
758
761 float scale, ui32* bit_depth)
762 {
763 assert(fh == NULL); //configure before opening
764 if (num_components != 1 && num_components != 3)
765 OJPH_ERROR(0x03000081,
766 "pfm supports 1 or 3 colour components, not %d", num_components);
767 this->width = width;
768 this->height = height;
769 this->num_components = num_components;
770 bool is_write_little_endian_on_disk =
772 scale = scale < 0.0f ? -scale : scale;
773 this->scale = is_write_little_endian_on_disk ? -scale : scale;
774 for (ui32 c = 0; c < num_components; ++c)
775 this->bit_depth[c] = bit_depth[c];
776 }
777
779 ui32 pfm_out::write(const line_buf* line, ui32 comp_num)
780 {
781 assert(fh);
782
783 ui32 shift = 32 - bit_depth[comp_num];
784 float* sp = line->f32;
785 float* dp = buffer + comp_num;
786
787 // swap bytes when the samples are forced to little endian on disk
788 // but the machine is big endian
791 if (shift) {
792 if (needs_swap)
793 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
794 {
795 ui32 u;
796 memcpy(&u, sp, sizeof(ui32));
797 u <<= shift;
798 u = be2le(u);
799 memcpy(dp, &u, sizeof(ui32));
800 }
801 else
802 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
803 {
804 ui32 u;
805 memcpy(&u, sp, sizeof(ui32));
806 u <<= shift;
807 memcpy(dp, &u, sizeof(ui32));
808 }
809 }
810 else
811 if (needs_swap)
812 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
813 {
814 ui32 u;
815 memcpy(&u, sp, sizeof(ui32));
816 u = be2le(u);
817 memcpy(dp, &u, sizeof(ui32));
818 }
819 else
820 for (ui32 i = width; i > 0; --i, dp += num_components, ++sp)
821 *dp = *sp;
822
823 if (comp_num == num_components - 1)
824 {
825 size_t samples_per_line = num_components * (size_t)width;
826 si64 loc = start_of_data;
827 loc += (height - 1 - cur_line)* samples_per_line * sizeof(float);
828 if (ojph_fseek(fh, loc, SEEK_SET) != 0)
829 OJPH_ERROR(0x03000082, "Error seeking in file %s", fname);
830 size_t result = fwrite(buffer, sizeof(float), samples_per_line, fh);
831 if (result != samples_per_line)
832 OJPH_ERROR(0x03000083, "error writing to file %s", fname);
833 ++cur_line;
834 }
835
836 return 0;
837 }
838
840 //
841 //
842 //
843 //
844 //
846#ifdef OJPH_ENABLE_TIFF_SUPPORT
848 void tif_in::open(const char* filename)
849 {
850 tiff_handle = NULL;
851 if ((tiff_handle = TIFFOpen(filename, "r")) == NULL)
852 OJPH_ERROR(0x03000091, "Unable to open file %s", filename);
853 fname = filename;
854
855 ui32 tiff_width = 0;
856 ui32 tiff_height = 0;
857 TIFFGetField(tiff_handle, TIFFTAG_IMAGEWIDTH, &tiff_width);
858 TIFFGetField(tiff_handle, TIFFTAG_IMAGELENGTH, &tiff_height);
859
860 ui16 tiff_bits_per_sample = 0;
861 ui16 tiff_samples_per_pixel = 0;
862 TIFFGetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, &tiff_bits_per_sample);
863 TIFFGetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, &tiff_samples_per_pixel);
864 // some TIFs have tiff_samples_per_pixel=0 when it is a single channel
865 // image - set to 1
866 tiff_samples_per_pixel =
867 (tiff_samples_per_pixel < 1) ? 1 : tiff_samples_per_pixel;
868
869 ui16 tiff_planar_configuration = 0;
870 ui16 tiff_photometric = 0;
871 TIFFGetField(tiff_handle, TIFFTAG_PLANARCONFIG, &tiff_planar_configuration);
872 TIFFGetField(tiff_handle, TIFFTAG_PHOTOMETRIC, &tiff_photometric);
873
874 planar_configuration = tiff_planar_configuration;
875
876 ui16 tiff_compression = 0;
877 ui32 tiff_rows_per_strip = 0;
878 TIFFGetField(tiff_handle, TIFFTAG_COMPRESSION, &tiff_compression);
879 TIFFGetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, &tiff_rows_per_strip);
880
881 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE)
882 {
883 bytes_per_line = tiff_samples_per_pixel * TIFFScanlineSize64(tiff_handle);
884 }
885 else
886 {
887 bytes_per_line = TIFFScanlineSize64(tiff_handle);
888 }
889 // allocate linebuffer to hold a line of image data
890 line_buffer = malloc(bytes_per_line);
891 if (NULL == line_buffer)
892 OJPH_ERROR(0x03000092, "Unable to allocate %d bytes for line_buffer[] "
893 "for file %s", bytes_per_line, filename);
894
895 cur_line = 0;
896
897 // Error on known incompatilbe input formats
898 if( tiff_bits_per_sample != 8 && tiff_bits_per_sample != 16 )
899 {
900 OJPH_ERROR(0x03000093, "\nTIFF IO is currently limited"
901 " to files with TIFFTAG_BITSPERSAMPLE=8 and TIFFTAG_BITSPERSAMPLE=16 \n"
902 "input file = %s has TIFFTAG_BITSPERSAMPLE=%d",
903 filename, tiff_bits_per_sample);
904 }
905
906 if( TIFFIsTiled( tiff_handle ) )
907 {
908 OJPH_ERROR(0x03000094, "\nTIFF IO is currently limited to TIF files "
909 "without tiles. \nInput file %s has been detected as tiled", filename);
910 }
911
912 if(PHOTOMETRIC_RGB != tiff_photometric &&
913 PHOTOMETRIC_MINISBLACK != tiff_photometric )
914 {
915 OJPH_ERROR(0x03000095, "\nTIFF IO is currently limited to "
916 "TIFFTAG_PHOTOMETRIC=PHOTOMETRIC_MINISBLACK=%d and "
917 "PHOTOMETRIC_RGB=%d. \nInput file %s has been detected "
918 "TIFFTAG_PHOTOMETRIC=%d",
919 PHOTOMETRIC_MINISBLACK, PHOTOMETRIC_RGB, filename, tiff_photometric);
920 }
921
922 if( tiff_samples_per_pixel > 4 )
923 {
924 OJPH_ERROR(0x03000096, "\nTIFF IO is currently limited to "
925 "TIFFTAG_SAMPLESPERPIXEL=4 \nInput file %s has been detected with "
926 "TIFFTAG_SAMPLESPERPIXEL=%d",
927 filename, tiff_samples_per_pixel);
928 }
929
930 // set number of components based on tiff_samples_per_pixel
931 width = tiff_width;
932 height = tiff_height;
933 num_comps = tiff_samples_per_pixel;
934 bytes_per_sample = (tiff_bits_per_sample + 7) / 8;
935 for (ui32 comp_num = 0; comp_num < num_comps; comp_num++)
936 bit_depth[comp_num] = tiff_bits_per_sample;
937
938 // allocate intermediate linebuffers to hold a line of a single component
939 // of image data
940 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
941 bytes_per_sample == 1)
942 {
943 line_buffer_for_planar_support_uint8 =
944 (uint8_t*)calloc(width, sizeof(uint8_t));
945 if (NULL == line_buffer_for_planar_support_uint8)
946 OJPH_ERROR(0x03000097, "Unable to allocate %d bytes for "
947 "line_buffer_for_planar_support_uint8[] for file %s",
948 width * sizeof(uint8_t), filename);
949 }
950 if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
951 bytes_per_sample == 2)
952 {
953 line_buffer_for_planar_support_uint16 =
954 (uint16_t*)calloc(width, sizeof(uint16_t));
955 if (NULL == line_buffer_for_planar_support_uint16)
956 OJPH_ERROR(0x03000098, "Unable to allocate %d bytes for "
957 "line_buffer_for_planar_support_uint16[] for file %s",
958 width * sizeof(uint16_t), filename);
959 }
960 }
961
963
965 void tif_in::set_bit_depth(ui32 num_bit_depths, ui32* bit_depth)
966 {
967 if (num_bit_depths < 1)
968 OJPH_ERROR(0x030000A1, "one or more bit_depths must be provided");
969 ui32 last_bd_idx = 0;
970 for (ui32 i = 0; i < 4; ++i)
971 {
972 ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
973 last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
974
975 if (bd > 32 || bd < 1)
976 {
977 OJPH_ERROR(0x030000A2,
978 "bit_depth = %d, this must be an integer from 1-32", bd);
979 }
980 this->bit_depth[i] = bd;
981 }
982 }
983
985 ui32 tif_in::read(const line_buf* line, ui32 comp_num)
986 {
987 assert(bytes_per_line != 0 && tiff_handle != 0 && comp_num < num_comps);
988 assert((ui32)line->size >= width);
989
990 // do a read from the file if this is the first component and therefore
991 // the first time trying to access this line
992 if (PLANARCONFIG_SEPARATE == planar_configuration && 0 == comp_num )
993 {
994 for (ui32 color = 0; color < num_comps; color++)
995 {
996 if (bytes_per_sample == 1)
997 {
998 TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint8,
999 cur_line, (ui16)color);
1000 ui32 x = color;
1001 uint8_t* line_buffer_of_interleaved_components =
1002 (uint8_t*)line_buffer;
1003 for (ui32 i = 0; i < width; i++, x += num_comps)
1004 {
1005 line_buffer_of_interleaved_components[x] =
1006 line_buffer_for_planar_support_uint8[i];
1007 }
1008 }
1009 else if (bytes_per_sample == 2)
1010 {
1011 TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint16,
1012 cur_line, (ui16)color);
1013 ui32 x = color;
1014 ui16* line_buffer_of_interleaved_components = (ui16*)line_buffer;
1015 for (ui32 i = 0; i < width; i++, x += num_comps)
1016 {
1017 line_buffer_of_interleaved_components[x] =
1018 line_buffer_for_planar_support_uint16[i];
1019 }
1020 }
1021 }
1022 cur_line++;
1023
1024 }
1025 else if (planar_configuration == PLANARCONFIG_CONTIG && 0 == comp_num)
1026 {
1027 TIFFReadScanline(tiff_handle, line_buffer, cur_line++);
1028 }
1029 if (cur_line >= height)
1030 {
1031 cur_line = 0;
1032 }
1033
1034 if (bytes_per_sample == 1)
1035 {
1036 const ui8* sp = (ui8*)line_buffer + comp_num;
1037 si32* dp = line->i32;
1038 if (bit_depth[comp_num] == 8)
1039 {
1040 for (ui32 i = width; i > 0; --i, sp += num_comps)
1041 *dp++ = (si32)*sp;
1042 }
1043 else if (bit_depth[comp_num] < 8)
1044 {
1045 // read the desired precision from the MSBs
1046 const int bits_to_shift = 8 - (int)bit_depth[comp_num];
1047 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1048 for (ui32 i = width; i > 0; --i, sp += num_comps)
1049 *dp++ = (si32) (((*sp) >> bits_to_shift) & bit_mask);
1050 }
1051 else if (bit_depth[comp_num] > 8)
1052 {
1053 const int bits_to_shift = (int)bit_depth[comp_num] - 8;
1054 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1055 for (ui32 i = width; i > 0; --i, sp += num_comps)
1056 *dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
1057 }
1058 }
1059 else if(bytes_per_sample == 2)
1060 {
1061 if (bit_depth[comp_num] == 16)
1062 {
1063 const ui16* sp = (ui16*)line_buffer + comp_num;
1064 si32* dp = line->i32;
1065 for (ui32 i = width; i > 0; --i, sp += num_comps)
1066 *dp++ = (si32)*sp;
1067 }
1068 else if (bit_depth[comp_num] < 16)
1069 {
1070 // read the desired precision from the MSBs
1071 const int bits_to_shift = 16 - (int)bit_depth[comp_num];
1072 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1073 const ui16* sp = (ui16*)line_buffer + comp_num;
1074 si32* dp = line->i32;
1075 for (ui32 i = width; i > 0; --i, sp += num_comps)
1076 *dp++ = (si32)(((*sp) >> bits_to_shift) & bit_mask);
1077 }
1078 else if (bit_depth[comp_num] > 16)
1079 {
1080 const int bits_to_shift = (int)bit_depth[comp_num] - 16;
1081 const int bit_mask = (1 << bit_depth[comp_num]) - 1;
1082 const ui16* sp = (ui16*)line_buffer + comp_num;
1083 si32* dp = line->i32;
1084 for (ui32 i = width; i > 0; --i, sp += num_comps)
1085 *dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
1086 }
1087
1088 }
1089
1090 return width;
1091 }
1092
1094 //
1095 //
1096 //
1097 //
1098 //
1100
1102 void tif_out::open(char* filename)
1103 {
1104 // Error on known incompatilbe output formats
1105 ui32 max_bitdepth = 0;
1106 for (ui32 c = 0; c < num_components; c++)
1107 {
1108 if (bit_depth_of_data[c] > max_bitdepth)
1109 max_bitdepth = bit_depth_of_data[c];
1110 }
1111 if (max_bitdepth > 16)
1112 {
1113 OJPH_WARN(0x030000B1, "TIFF output is currently limited to files "
1114 "with max_bitdepth = 16, the source codestream has max_bitdepth=%d"
1115 ", the decoded data will be truncated to 16 bits", max_bitdepth);
1116 }
1117 if (num_components > 4)
1118 {
1119 OJPH_ERROR(0x030000B2, "TIFF IO is currently limited to files with "
1120 "num_components=1 to 4");
1121 }
1122
1123 assert(tiff_handle == NULL && buffer == NULL);
1124 if ((tiff_handle = TIFFOpen(filename, "w")) == NULL)
1125 {
1126 OJPH_ERROR(0x030000B3, "unable to open file %s for writing", filename);
1127 }
1128
1129 buffer_size = width * (size_t)num_components * (size_t)bytes_per_sample;
1130 buffer = (ui8*)malloc(buffer_size);
1131 fname = filename;
1132 cur_line = 0;
1133
1134 // set tiff fields
1135
1136 // Write the tiff tags to the file
1137 TIFFSetField(tiff_handle, TIFFTAG_IMAGEWIDTH, width);
1138 TIFFSetField(tiff_handle, TIFFTAG_IMAGELENGTH, height);
1139
1140 TIFFSetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, bytes_per_sample * 8);
1141 TIFFSetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, num_components);
1142
1143 planar_configuration = PLANARCONFIG_CONTIG;
1144 TIFFSetField(tiff_handle, TIFFTAG_PLANARCONFIG, planar_configuration);
1145
1146 if (num_components == 1)
1147 {
1148 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1149 }
1150 else if (num_components == 2)
1151 {
1152 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1153 // possible values are EXTRASAMPLE_UNSPECIFIED = 0;
1154 // EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
1155 const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
1156 TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
1157 &extra_samples_description);
1158 }
1159 else if (num_components == 3)
1160 {
1161 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1162 }
1163 else if (num_components == 4)
1164 {
1165 TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1166 // possible values are EXTRASAMPLE_UNSPECIFIED = 0;
1167 // EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
1168 const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
1169 TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
1170 &extra_samples_description);
1171 }
1172
1173 TIFFSetField(tiff_handle, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1174 TIFFSetField(tiff_handle, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1175 //TIFFSetField(tiff_handle, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1176 TIFFSetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, height);
1177
1178 }
1179
1181 void tif_out::configure(ui32 width, ui32 height, ui32 num_components,
1182 ui32 *bit_depth)
1183 {
1184 assert(tiff_handle == NULL); //configure before opening
1185
1186 this->width = width;
1187 this->height = height;
1188 this->num_components = num_components;
1189 ui32 max_bitdepth = 0;
1190 for (ui32 c = 0; c < num_components; c++)
1191 {
1192 this->bit_depth_of_data[c] = bit_depth[c];
1193 if (bit_depth[c] > max_bitdepth)
1194 max_bitdepth = bit_depth[c];
1195 }
1196
1197 bytes_per_sample = (max_bitdepth + 7) / 8; // round up
1198 if (bytes_per_sample > 2)
1199 {
1200 // TIFF output is currently limited to files with max_bitdepth = 16,
1201 // the decoded data will be truncated to 16 bits
1202 bytes_per_sample = 2;
1203 }
1204 samples_per_line = num_components * width;
1205 bytes_per_line = bytes_per_sample * (size_t)samples_per_line;
1206
1207 }
1208
1210 ui32 tif_out::write(const line_buf* line, ui32 comp_num)
1211 {
1212 assert(tiff_handle);
1213
1214 if (bytes_per_sample == 1)
1215 {
1216 int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
1217 const si32* sp = line->i32;
1218 ui8* dp = buffer + comp_num;
1219 if (bit_depth_of_data[comp_num] == 8)
1220 {
1221 for (ui32 i = width; i > 0; --i, dp += num_components)
1222 {
1223 // clamp the decoded sample to the allowed range
1224 int val = *sp++;
1225 val = val >= 0 ? val : 0;
1226 val = val <= max_val ? val : max_val;
1227 *dp = (ui8)val;
1228 }
1229 }
1230 else if (bit_depth_of_data[comp_num] < 8)
1231 {
1232 const int bits_to_shift = 8 - (int)bit_depth_of_data[comp_num];
1233 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1234 for (ui32 i = width; i > 0; --i, dp += num_components)
1235 {
1236 // clamp the decoded sample to the allowed range
1237 int val = *sp++;
1238 val = val >= 0 ? val : 0;
1239 val = val <= max_val ? val : max_val;
1240 // shift the decoded data so the data's MSB is aligned with the
1241 // 8 bit MSB
1242 *dp = (ui8)((val & bit_mask) << bits_to_shift);
1243 }
1244 }
1245 else if (bit_depth_of_data[comp_num] > 8)
1246 {
1247 const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 8;
1248 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1249 for (ui32 i = width; i > 0; --i, dp += num_components)
1250 {
1251 // clamp the decoded sample to the allowed range
1252 int val = *sp++;
1253 val = val >= 0 ? val : 0;
1254 val = val <= max_val ? val : max_val;
1255 // shift the decoded data so the data's MSB is aligned with the
1256 // 8 bit MSB
1257 *dp = (ui8)((val >> bits_to_shift) & bit_mask);
1258 }
1259 }
1260
1261 }
1262 else if(bytes_per_sample == 2)
1263 {
1264 int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
1265 const si32* sp = line->i32;
1266 ui16* dp = (ui16*)buffer + comp_num;
1267
1268 if (bit_depth_of_data[comp_num] == 16)
1269 {
1270 for (ui32 i = width; i > 0; --i, dp += num_components)
1271 {
1272 // clamp the decoded sample to the allowed range
1273 int val = *sp++;
1274 val = val >= 0 ? val : 0;
1275 val = val <= max_val ? val : max_val;
1276 *dp = (ui16)val;
1277 }
1278 }
1279 else if (bit_depth_of_data[comp_num] < 16)
1280 {
1281 const int bits_to_shift = 16 - (int)bit_depth_of_data[comp_num];
1282 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1283 for (ui32 i = width; i > 0; --i, dp += num_components)
1284 {
1285 // clamp the decoded sample to the allowed range
1286 int val = *sp++;
1287 val = val >= 0 ? val : 0;
1288 val = val <= max_val ? val : max_val;
1289
1290 // shift the decoded data so the data's MSB is aligned with the
1291 // 16 bit MSB
1292 *dp = (ui16)((val & bit_mask) << bits_to_shift);
1293 }
1294 }
1295 else if (bit_depth_of_data[comp_num] > 16)
1296 {
1297 const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 16;
1298 const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
1299 for (ui32 i = width; i > 0; --i, dp += num_components)
1300 {
1301 // clamp the decoded sample to the allowed range
1302 int val = *sp++;
1303 val = val >= 0 ? val : 0;
1304 val = val <= max_val ? val : max_val;
1305
1306 // shift the decoded data so the data's MSB is aligned with the
1307 // 16 bit MSB
1308 *dp = (ui16)((val >> bits_to_shift) & bit_mask);
1309 }
1310 }
1311
1312 }
1313 // write scanline when the last component is reached
1314 if (comp_num == num_components-1)
1315 {
1316 int result = TIFFWriteScanline(tiff_handle, buffer, cur_line++);
1317 if (result != 1)
1318 OJPH_ERROR(0x030000C1, "error writing to file %s", fname);
1319 }
1320 return 0;
1321 }
1322 #endif /* OJPH_ENABLE_TIFF_SUPPORT */
1323
1325 //
1326 //
1327 //
1328 //
1329 //
1331
1333 void yuv_in::open(const char* filename)
1334 {
1335 assert(fh == NULL);
1336 fh = fopen(filename, "rb");
1337 if (fh == 0)
1338 OJPH_ERROR(0x030000D1, "Unable to open file %s", filename);
1339
1340 //need to extract info from filename
1341
1342 assert(num_com == 1 || num_com == 3);
1343 for (ui32 i = 0; i < num_com; ++i)
1344 bytes_per_sample[i] = bit_depth[i] > 8 ? 2 : 1;
1345 ui32 max_byte_width = width[0] * bytes_per_sample[0];
1346 comp_address[0] = 0;
1347 for (ui32 i = 1; i < num_com; ++i)
1348 {
1349 comp_address[i] = comp_address[i - 1];
1350 comp_address[i] += width[i-1] * height[i-1] * bytes_per_sample[i-1];
1351 max_byte_width = ojph_max(max_byte_width, width[i]*bytes_per_sample[i]);
1352 }
1353 temp_buf = malloc(max_byte_width);
1354 fname = filename;
1355 }
1356
1358 ui32 yuv_in::read(const line_buf* line, ui32 comp_num)
1359 {
1360 assert(comp_num < num_com);
1361 size_t result = fread(temp_buf, bytes_per_sample[comp_num],
1362 width[comp_num], fh);
1363 if (result != width[comp_num])
1364 {
1365 close();
1366 OJPH_ERROR(0x030000E1, "not enough data in file %s", fname);
1367 }
1368
1369 if (bytes_per_sample[comp_num] == 1)
1370 {
1371 const ui8* sp = (ui8*)temp_buf;
1372 si32* dp = line->i32;
1373 for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
1374 *dp++ = (si32)*sp;
1375 }
1376 else
1377 {
1378 // yuv samples wider than one byte are little-endian on disk
1379 const ui16* sp = (ui16*)temp_buf;
1380 si32* dp = line->i32;
1381 for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
1382 *dp++ = (si32)swap_bytes_if_be(*sp);
1383 }
1384
1385 return width[comp_num];
1386 }
1387
1389 void yuv_in::set_img_props(const size& s, ui32 num_components,
1390 ui32 num_downsamplings, const point *subsampling)
1391 {
1392 if (num_components != 1 && num_components !=3)
1393 OJPH_ERROR(0x030000F1, "yuv_in support 1 or 3 components");
1394 this->num_com = num_components;
1395
1396 if (num_downsamplings < 1)
1397 OJPH_ERROR(0x030000F2, "one or more downsampling must be provided");
1398
1399 ui32 last_downsamp_idx = 0;
1400 for (ui32 i = 0; i < num_components; ++i)
1401 {
1402 point cp_ds = subsampling[i<num_downsamplings ? i : last_downsamp_idx];
1403 last_downsamp_idx += last_downsamp_idx + 1 < num_downsamplings ? 1 : 0;
1404
1405 this->subsampling[i] = cp_ds;
1406 }
1407
1408 for (ui32 i = 0; i < num_components; ++i)
1409 {
1410 width[i] = ojph_div_ceil(s.w, this->subsampling[i].x);
1411 height[i] = ojph_div_ceil(s.h, this->subsampling[i].y);
1412 }
1413 }
1414
1417 {
1418 if (num_bit_depths < 1)
1419 OJPH_ERROR(0x03000101, "one or more bit_depths must be provided");
1420 ui32 last_bd_idx = 0;
1421 for (ui32 i = 0; i < 3; ++i)
1422 {
1423 ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
1424 last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
1425
1426 this->bit_depth[i] = bd;
1427 }
1428 }
1429
1431 //
1432 //
1433 //
1434 //
1435 //
1437
1440 {
1441 close();
1442 if (buffer)
1443 {
1444 free(buffer);
1445 buffer = NULL;
1446 buffer_size = 0;
1447 }
1448 if (comp_width)
1449 {
1450 delete [] comp_width;
1451 comp_width = NULL;
1452 }
1453 }
1454
1456 void yuv_out::open(char *filename)
1457 {
1458 assert(fh == NULL); //configure before open
1459 fh = fopen(filename, "wb");
1460 if (fh == 0)
1461 OJPH_ERROR(0x03000111, "Unable to open file %s", filename);
1462 fname = filename;
1463 }
1464
1468 {
1469 assert(fh == NULL);
1470 this->num_components = num_components;
1471 this->bit_depth = bit_depth;
1472 this->comp_width = new ui32[num_components];
1473 ui32 tw = 0;
1474 for (ui32 i = 0; i < num_components; ++i)
1475 {
1476 this->comp_width[i] = comp_width[i];
1477 tw = ojph_max(tw, this->comp_width[i]);
1478 }
1479 this->width = tw;
1480 buffer_size = tw * (bit_depth > 8 ? 2 : 1);
1481 buffer = (ui8*)malloc(buffer_size);
1482 }
1483
1485 ui32 yuv_out::write(const line_buf* line, ui32 comp_num)
1486 {
1487 assert(fh);
1488 assert(comp_num < num_components);
1489
1490 int max_val = (1<<bit_depth) - 1;
1491 ui32 w = comp_width[comp_num];
1492 if (bit_depth > 8)
1493 {
1494 const si32 *sp = line->i32;
1495 ui16 *dp = (ui16 *)buffer;
1496 for (ui32 i = w; i > 0; --i)
1497 {
1498 int val = *sp++;
1499 val = val >= 0 ? val : 0;
1500 val = val <= max_val ? val : max_val;
1501 *dp++ = swap_bytes_if_be((ui16)val);
1502 }
1503 if (fwrite(buffer, 2, w, fh) != w)
1504 OJPH_ERROR(0x03000121, "unable to write to file %s", fname);
1505 }
1506 else
1507 {
1508 const si32 *sp = line->i32;
1509 ui8 *dp = (ui8 *)buffer;
1510 for (ui32 i = w; i > 0; --i)
1511 {
1512 int val = *sp++;
1513 val = val >= 0 ? val : 0;
1514 val = val <= max_val ? val : max_val;
1515 *dp++ = (ui8)val;
1516 }
1517 if (fwrite(buffer, 1, w, fh) != w)
1518 OJPH_ERROR(0x03000122, "unable to write to file %s", fname);
1519 }
1520
1521 return w;
1522 }
1523
1525 //
1526 //
1527 //
1528 //
1529 //
1531
1533 void raw_in::open(const char* filename)
1534 {
1535 assert(fh == NULL);
1536 fh = fopen(filename, "rb");
1537 if (fh == NULL)
1538 OJPH_ERROR(0x03000131, "Unable to open file %s", filename);
1539
1540 cur_line = 0;
1541 bytes_per_sample = (bit_depth + 7) >> 3;
1543 buffer = (ui8*)malloc(buffer_size);
1544 fname = filename;
1545 }
1546
1548 ui32 raw_in::read(const line_buf* line, ui32 comp_num)
1549 {
1550 ojph_unused(comp_num);
1551 assert(comp_num == 0);
1552 size_t result = fread(buffer, bytes_per_sample, width, fh);
1553 if (result != width)
1554 {
1555 close();
1556 OJPH_ERROR(0x03000132, "not enough data in file %s", fname);
1557 }
1558
1559 if (bytes_per_sample > 3)
1560 {
1561 si32* dp = line->i32;
1562 if (is_signed) {
1563 const si32* sp = (si32*)buffer;
1564 for (ui32 i = width; i > 0; --i, ++sp)
1565 *dp++ = (si32)swap_bytes_if_be((ui32)*sp);
1566 }
1567 else {
1568 const ui32* sp = (ui32*)buffer;
1569 for (ui32 i = width; i > 0; --i, ++sp)
1570 *dp++ = (si32)swap_bytes_if_be(*sp);
1571 }
1572 }
1573 else if (bytes_per_sample > 2)
1574 {
1575 si32* dp = line->i32;
1576 const ui8* sp = (const ui8*)buffer;
1577 if (is_signed) {
1578 for (ui32 i = width; i > 0; --i, sp += 3) {
1579 si32 val =
1580 (si32)((ui32)sp[0] | ((ui32)sp[1] << 8) | ((ui32)sp[2] << 16));
1581 val |= (val & 0x800000) ? (si32)0xFF000000 : 0;
1582 *dp++ = val;
1583 }
1584 }
1585 else {
1586 for (ui32 i = width; i > 0; --i, sp += 3)
1587 *dp++ =
1588 (si32)((ui32)sp[0] | ((ui32)sp[1] << 8) | ((ui32)sp[2] << 16));
1589 }
1590 }
1591 else if (bytes_per_sample > 1)
1592 {
1593 si32* dp = line->i32;
1594 if (is_signed) {
1595 const si16* sp = (si16*)buffer;
1596 for (ui32 i = width; i > 0; --i, ++sp)
1597 *dp++ = (si32)(si16)swap_bytes_if_be((ui16)*sp);
1598 }
1599 else {
1600 const ui16* sp = (ui16*)buffer;
1601 for (ui32 i = width; i > 0; --i, ++sp)
1602 *dp++ = (si32)swap_bytes_if_be(*sp);
1603 }
1604 }
1605 else
1606 {
1607 si32* dp = line->i32;
1608 if (is_signed) {
1609 const si8* sp = (si8*)buffer;
1610 for (ui32 i = width; i > 0; --i, ++sp)
1611 *dp++ = *sp;
1612 }
1613 else {
1614 const ui8* sp = (ui8*)buffer;
1615 for (ui32 i = width; i > 0; --i, ++sp)
1616 *dp++ = (si32)*sp;
1617 }
1618 }
1619
1620 return width;
1621 }
1622
1625 {
1626 assert(fh == NULL);
1627 //need to extract this info from filename
1628 this->width = s.w;
1629 this->height = s.h;
1630 this->bit_depth = bit_depth;
1631 this->is_signed = is_signed;
1632 }
1633
1635 //
1636 //
1637 //
1638 //
1639 //
1641
1644 {
1645 close();
1646 if (buffer)
1647 {
1648 free(buffer);
1649 buffer = NULL;
1650 buffer_size = 0;
1651 }
1652 }
1653
1655 void raw_out::open(char *filename)
1656 {
1657 assert(fh == NULL); //configure before open
1658 fh = fopen(filename, "wb");
1659 if (fh == 0)
1660 OJPH_ERROR(0x03000141, "Unable to open file %s", filename);
1661 fname = filename;
1662 }
1663
1666 {
1667 assert(fh == NULL);
1668 this->is_signed = is_signed;
1669 this->bit_depth = bit_depth;
1670 this->width = width;
1671
1672 if (is_signed) {
1673 upper_val = ((si64)1 << (bit_depth - 1));
1674 lower_val = -((si64)1 << (bit_depth - 1));
1675 } else {
1676 upper_val = (si64)1 << bit_depth;
1677 lower_val = (si64)0;
1678 }
1679
1680 bytes_per_sample = (bit_depth + 7) >> 3;
1682 buffer = (ui8*)malloc(buffer_size);
1683 }
1684
1686 ui32 raw_out::write(const line_buf* line, ui32 comp_num)
1687 {
1688 ojph_unused(comp_num);
1689 assert(fh);
1690 assert(comp_num == 0);
1691
1692 if (is_signed)
1693 {
1694 if (bytes_per_sample > 3)
1695 {
1696 const si32* sp = line->i32;
1697 si32* dp = (si32*)buffer;
1698 for (ui32 i = width; i > 0; --i)
1699 {
1700 si64 val = *sp++;
1701 val = val < upper_val ? val : upper_val;
1702 val = val >= lower_val ? val : lower_val;
1703 *dp++ = (si32)swap_bytes_if_be((ui32)(si32)val);
1704 }
1705 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1706 OJPH_ERROR(0x03000151, "unable to write to file %s", fname);
1707 }
1708 else if (bytes_per_sample > 2)
1709 {
1710 const si32* sp = line->i32;
1711 ui8* dp = buffer;
1712 for (ui32 i = width; i > 0; --i)
1713 {
1714 si64 val = *sp++;
1715 val = val < upper_val ? val : upper_val;
1716 val = val >= lower_val ? val : lower_val;
1717 *dp++ = (ui8)val;
1718 *dp++ = (ui8)(val >> 8);
1719 *dp++ = (ui8)(val >> 16);
1720 }
1721 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1722 OJPH_ERROR(0x03000152, "unable to write to file %s", fname);
1723 }
1724 else if (bytes_per_sample > 1)
1725 {
1726 const si32* sp = line->i32;
1727 si16* dp = (si16*)buffer;
1728 for (ui32 i = width; i > 0; --i)
1729 {
1730 si64 val = *sp++;
1731 val = val < upper_val ? val : upper_val;
1732 val = val >= lower_val ? val : lower_val;
1733 *dp++ = (si16)swap_bytes_if_be((ui16)(si16)val);
1734 }
1735 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1736 OJPH_ERROR(0x03000153, "unable to write to file %s", fname);
1737 }
1738 else
1739 {
1740 const si32* sp = line->i32;
1741 si8* dp = (si8*)buffer;
1742 for (ui32 i = width; i > 0; --i)
1743 {
1744 si64 val = *sp++;
1745 val = val < upper_val ? val : upper_val;
1746 val = val >= lower_val ? val : lower_val;
1747 *dp++ = (si8)val;
1748 }
1749 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1750 OJPH_ERROR(0x03000154, "unable to write to file %s", fname);
1751 }
1752 }
1753 else
1754 {
1755 if (bytes_per_sample > 3)
1756 {
1757 const ui32* sp = (ui32*)line->i32;
1758 ui32* dp = (ui32*)buffer;
1759 for (ui32 i = width; i > 0; --i)
1760 {
1761 si64 val = *sp++;
1762 val = val < upper_val ? val : upper_val;
1763 val = val >= lower_val ? val : lower_val;
1764 *dp++ = swap_bytes_if_be((ui32)val);
1765 }
1766 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1767 OJPH_ERROR(0x03000155, "unable to write to file %s", fname);
1768 }
1769 else if (bytes_per_sample > 2)
1770 {
1771 const ui32* sp = (ui32*)line->i32;
1772 ui8* dp = buffer;
1773 for (ui32 i = width; i > 0; --i)
1774 {
1775 si64 val = *sp++;
1776 val = val < upper_val ? val : upper_val;
1777 val = val >= lower_val ? val : lower_val;
1778 *dp++ = (ui8)val;
1779 // this only works for little endian architecture
1780 *dp++ = (ui8)(val >> 8);
1781 *dp++ = (ui8)(val >> 16);
1782 }
1783 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1784 OJPH_ERROR(0x03000156, "unable to write to file %s", fname);
1785 }
1786 else if (bytes_per_sample > 1)
1787 {
1788 const ui32* sp = (ui32*)line->i32;
1789 ui16* dp = (ui16*)buffer;
1790 for (ui32 i = width; i > 0; --i)
1791 {
1792 si64 val = *sp++;
1793 val = val < upper_val ? val : upper_val;
1794 val = val >= lower_val ? val : lower_val;
1795 *dp++ = swap_bytes_if_be((ui16)val);
1796 }
1797 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1798 OJPH_ERROR(0x03000157, "unable to write to file %s", fname);
1799 }
1800 else
1801 {
1802 const ui32* sp = (ui32*)line->i32;
1803 ui8* dp = (ui8*)buffer;
1804 for (ui32 i = width; i > 0; --i)
1805 {
1806 si64 val = *sp++;
1807 val = val < upper_val ? val : upper_val;
1808 val = val >= lower_val ? val : lower_val;
1809 *dp++ = (ui8)val;
1810 }
1811 if (fwrite(buffer, bytes_per_sample, width, fh) != width)
1812 OJPH_ERROR(0x03000158, "unable to write to file %s", fname);
1813 }
1814 }
1815
1816 return width;
1817 }
1818
1819
1821 //
1822 //
1823 //
1824 //
1825 //
1827
1829
1830 void dpx_in::open(const char* filename)
1831 {
1832 assert(file_handle == 0);
1833 file_handle = fopen(filename, "rb");
1834 if (0 == file_handle)
1835 OJPH_ERROR(0x03000161, "Unable to open file %s", filename);
1836 fname = filename;
1837
1838 // read magic number
1839 ui32 magic_number;
1840 if (fread(&magic_number, sizeof(ui32), 1, file_handle) != 1)
1841 {
1842 close();
1843 OJPH_ERROR(0x03000162, "Error reading file %s", filename);
1844 }
1845
1846 // check magic number
1847 const ui32 dpx_magic_number = 0x53445058;
1848 if (dpx_magic_number == magic_number)
1849 {
1850 // magic number is a match - no byte swapping necessary
1852 }
1853 else if (dpx_magic_number == be2le(magic_number))
1854 {
1855 // magic number is a match after bytes swapping -
1856 // the data read from this file needs byte swapping
1858 }
1859 else
1860 {
1861 close();
1862 OJPH_ERROR(0x03000163, "Error reading file %s - this does not appear "
1863 "to be a valid DPX file. It has magic number = 0x%08X. The magic "
1864 "number of a DPX file is 0x%08X.", filename, magic_number,
1865 dpx_magic_number);
1866 }
1867
1868 // read offset to data
1869 if (fread(&offset_to_image_data_in_bytes, sizeof(ui32), 1, file_handle)
1870 != 1)
1871 {
1872 close();
1873 OJPH_ERROR(0x03000164, "Error reading file %s", filename);
1874 }
1877 // read version
1878 if (fread(version, sizeof(uint8_t), 8, file_handle) != 8)
1879 {
1880 close();
1881 OJPH_ERROR(0x03000165, "Error reading file %s", filename);
1882 }
1883 // read image file size in bytes
1884 if (fread(&total_image_file_size_in_bytes, sizeof(ui32), 1, file_handle)
1885 != 1)
1886 {
1887 close();
1888 OJPH_ERROR(0x03000166, "Error reading file %s", filename);
1889 }
1892
1893 // seek to image info header
1894 if (fseek(file_handle,768, SEEK_SET) != 0)
1895 {
1896 close();
1897 OJPH_ERROR(0x03000167, "Error reading file %s", filename);
1898 }
1899
1900 // read image_orientation
1901 if (fread(&image_orientation, sizeof(uint16_t), 1, file_handle) != 1)
1902 {
1903 close();
1904 OJPH_ERROR(0x03000168, "Error reading file %s", filename);
1905 }
1908
1909 // read number of image elements
1910 if (fread(&number_of_image_elements, sizeof(uint16_t), 1, file_handle)
1911 != 1)
1912 {
1913 close();
1914 OJPH_ERROR(0x03000169, "Error reading file %s", filename);
1915 }
1918
1919 // read pixels per line
1920 if (fread(&pixels_per_line, sizeof(ui32), 1, file_handle) != 1)
1921 {
1922 close();
1923 OJPH_ERROR(0x0300016A, "Error reading file %s", filename);
1924 }
1927
1928 // read lines per image element
1929 if (fread(&lines_per_image_element, sizeof(ui32), 1, file_handle) != 1)
1930 {
1931 close();
1932 OJPH_ERROR(0x0300016B, "Error reading file %s", filename);
1933 }
1936
1937 // seek to data structure for image element 1
1938 if (fseek(file_handle, 780, SEEK_SET) != 0)
1939 {
1940 close();
1941 OJPH_ERROR(0x0300016C, "Error reading file %s", filename);
1942 }
1943
1944 // read data sign for image element
1945 if (fread(&data_sign_for_image_element_1, sizeof(ui32), 1, file_handle)
1946 != 1)
1947 {
1948 close();
1949 OJPH_ERROR(0x0300016E, "Error reading file %s", filename);
1950 }
1953
1954 // seek to core data elements in image element 1
1955 if (fseek(file_handle, 800, SEEK_SET) != 0)
1956 {
1957 close();
1958 OJPH_ERROR(0x0300016F, "Error reading file %s", filename);
1959 }
1960
1961 // read descriptor
1962 if (fread(&descriptor_for_image_element_1, sizeof(uint8_t), 1, file_handle)
1963 != 1)
1964 {
1965 close();
1966 OJPH_ERROR(0x03000170, "Error reading file %s", filename);
1967 }
1968
1969 // read transfer characteristic
1970 if (fread(&transfer_characteristic_for_image_element_1, sizeof(uint8_t),
1971 1, file_handle) != 1)
1972 {
1973 close();
1974 OJPH_ERROR(0x03000171, "Error reading file %s", filename);
1975 }
1976
1977 // read colorimetric specification
1978 if (fread(&colormetric_specification_for_image_element_1, sizeof(uint8_t),
1979 1, file_handle) != 1)
1980 {
1981 close();
1982 OJPH_ERROR(0x03000172, "Error reading file %s", filename);
1983 }
1984
1985 // read bit depth
1986 if (fread(&bitdepth_for_image_element_1, sizeof(uint8_t), 1, file_handle)
1987 != 1)
1988 {
1989 close();
1990 OJPH_ERROR(0x03000173, "Error reading file %s", filename);
1991 }
1992
1993 // read packing
1994 if (fread(&packing_for_image_element_1, sizeof(uint16_t), 1, file_handle)
1995 != 1)
1996 {
1997 close();
1998 OJPH_ERROR(0x03000174, "Error reading file %s", filename);
1999 }
2002
2003 // read encoding
2004 if (fread(&encoding_for_image_element_1, sizeof(uint16_t), 1, file_handle)
2005 != 1)
2006 {
2007 close();
2008 OJPH_ERROR(0x03000175, "Error reading file %s", filename);
2009 }
2012
2013 // read offset to data
2014 if (fread(&offset_to_data_for_image_element_1, sizeof(ui32), 1,
2015 file_handle) != 1)
2016 {
2017 close();
2018 OJPH_ERROR(0x03000176, "Error reading file %s", filename);
2019 }
2023
2024 // set to starting point of image data
2025 if (fseek(file_handle, (long)offset_to_image_data_in_bytes, SEEK_SET) != 0)
2026 {
2027 close();
2028 OJPH_ERROR(0x03000177, "Error reading file %s", filename);
2029 }
2030
2031 // set ojph properties
2034 num_comps = 3; // descriptor field can indicate 1, 3, or 4 comps
2035 for ( ojph::ui32 c = 0; c < get_num_components(); c++)
2036 {
2038 is_signed[c] = false;
2039 subsampling[c] = point(1,1);
2040 }
2041
2042 // handle DPX image data packing in file
2043 ui32 number_of_samples_per_32_bit_word = 32 / bitdepth_for_image_element_1;
2046 (number_of_samples_per_line + (number_of_samples_per_32_bit_word - 1))
2047 / number_of_samples_per_32_bit_word;
2048
2049 cur_line = 0;
2050
2051 // allocate linebuffer to hold a line of image data from the file
2053 if (NULL == line_buffer)
2054 OJPH_ERROR(0x03000178, "Unable to allocate %d bytes for line_buffer[] "
2055 "for file %s",
2056 number_of_32_bit_words_per_line * sizeof(ui32), filename);
2057
2058 // allocate line_buffer_16bit_samples to hold a line of image data in memory
2060 (ui16*) malloc((size_t)width * num_comps * sizeof(ui16));
2061 if (NULL == line_buffer_16bit_samples)
2062 OJPH_ERROR(0x03000179, "Unable to allocate %d bytes for "
2063 "line_buffer_16bit_samples[] for file %s",
2064 (size_t)width * num_comps * sizeof(ui16), filename);
2065
2066 cur_line = 0;
2067
2068 return;
2069 }
2070
2072 ui32 dpx_in::read(const line_buf* line, ui32 comp_num)
2073 {
2074 assert(file_handle != 0 && comp_num < num_comps);
2075 assert((ui32)line->size >= width);
2076
2077 // read from file if trying to read the first component
2078 if (0 == comp_num)
2079 {
2082 {
2083 close();
2084 OJPH_ERROR(0x03000181, "Error reading file %s", fname);
2085 }
2086
2087 if (true == is_byte_swapping_necessary)
2088 {
2090 {
2091 ui16* line_buffer_ptr = (ui16*)line_buffer;
2092 for (size_t i = 0; i < 2*number_of_32_bit_words_per_line; i++)
2093 {
2094 line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
2095 }
2096 }
2097 else
2098 {
2099 ui32* line_buffer_ptr = (ui32*)line_buffer;
2100 for (size_t i = 0; i < number_of_32_bit_words_per_line; i++)
2101 {
2102 line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
2103 }
2104 }
2105 }
2106
2107 // extract samples from 32bit words from file read into
2108 // RGB ordered buffer
2109 ui32 word_index = 0;
2110 if (10 == bitdepth_for_image_element_1 && 3 == num_comps
2112 {
2113 ui32* line_buffer_ptr = (ui32*)line_buffer;
2114 for (ui32 i = 0; i < number_of_samples_per_line; i += 3)
2115 {
2116 // R
2118 (ui16) ((line_buffer_ptr[word_index] & 0xFFC00000) >> 22);
2119 // G
2121 (ui16) ((line_buffer_ptr[word_index] & 0x003FF000) >> 12);
2122 // B
2124 (ui16) ((line_buffer_ptr[word_index] & 0x00000FFC) >> 2);
2125 word_index++;
2126 }
2127 }
2128 else if (16 == bitdepth_for_image_element_1 && 3 == num_comps)
2129 {
2130 ui16* line_buffer_ptr = (ui16*)line_buffer;
2131 for (ui32 i = 0; i < number_of_samples_per_line; i++)
2132 {
2133 line_buffer_16bit_samples[i] = line_buffer_ptr[i];
2134 }
2135 }
2136 else
2137 {
2138 OJPH_ERROR(0x03000182, "file %s uses DPX image formats that are not "
2139 "yet supported by this software\n bitdepth_for_image_element_1 = "
2140 "%d\n num_comps=%d\npacking_for_image_element_1=%d\n "
2141 "descriptor_for_image_element_1=%d", fname,
2144 }
2145
2146 cur_line++;
2147 }
2148
2149 // copy sample data from the unpacked line buffer into a
2150 // single-component buffer to be used by the openjph core
2151 const ui16* sp = (ui16*)line_buffer_16bit_samples + comp_num;
2152 si32* dp = line->i32;
2153 for (ui32 i = width; i > 0; --i, sp += num_comps)
2154 *dp++ = (si32)*sp;
2155
2156 return width;
2157 }
2158
2159}
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
void pre_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:72
T * post_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:112
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)
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:401
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)
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()
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,...)
point(ui32 x=0, ui32 y=0)
Definition ojph_base.h:59