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