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