Loading...
Searching...
No Matches
ojph_img_io.cpp
Go to the documentation of this file.
//***************************************************************************/
// This software is released under the 2-Clause BSD license, included
// below.
//
// Copyright (c) 2019, Aous Naman
// Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
// Copyright (c) 2019, The University of New South Wales, Australia
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//***************************************************************************/
// This file is part of the OpenJPH software implementation.
// File: ojph_img_io.cpp
// Author: Aous Naman
// Date: 28 August 2019
//***************************************************************************/
#include <cstdlib>
#include <cstring>
#include "ojph_file.h"
#include "ojph_img_io.h"
#include "ojph_mem.h"
#include "ojph_message.h"
namespace ojph {
// Static functions
static
ui16 be2le(const ui16 v)
{
return (ui16)((v<<8) | (v>>8));
}
static inline
ui32 be2le(const ui32 t)
{
ui32 u = be2le((ui16)(t & 0xFFFFu));
u <<= 16;
u |= be2le((ui16)(t >> 16));
return u;
}
static
void eat_white_spaces(FILE *fh)
{
int c = fgetc(fh);
while(1)
{
if (c == ' ' || c == '\r' || c == '\n' || c == '\t')
c = fgetc(fh);
else if (c == '#')
{
while (c != '\n') c = fgetc(fh);
}
else
{
ungetc(c, fh);
break;
}
}
}
//
//
// Accelerators -- non-accelerating
//
//
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)
{
ojph_unused(ln1);
ojph_unused(ln2);
int max_val = (1 << bit_depth) - 1;
const si32 *sp = ln0->i32;
ui8* p = (ui8 *)dp;
for ( ; count > 0; --count)
{
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui8)val;
}
}
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)
{
int max_val = (1<<bit_depth) - 1;
const si32 *sp0 = ln0->i32;
const si32 *sp1 = ln1->i32;
const si32 *sp2 = ln2->i32;
ui8* p = (ui8 *)dp;
for (; count > 0; --count)
{
int val;
val = *sp0++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui8) val;
val = *sp1++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui8) val;
val = *sp2++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui8) val;
}
}
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)
{
ojph_unused(ln1);
ojph_unused(ln2);
int max_val = (1<<bit_depth) - 1;
const si32 *sp = ln0->i32;
ui16* p = (ui16*)dp;
for (; count > 0; --count)
{
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui16) val;
}
}
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)
{
int max_val = (1<<bit_depth) - 1;
const si32 *sp0 = ln0->i32;
const si32 *sp1 = ln1->i32;
const si32 *sp2 = ln2->i32;
ui16* p = (ui16*)dp;
for (; count > 0; --count)
{
int val;
val = *sp0++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui16) val;
val = *sp1++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui16) val;
val = *sp2++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = (ui16) val;
}
}
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)
{
ojph_unused(ln1);
ojph_unused(ln2);
int max_val = (1<<bit_depth) - 1;
const si32 *sp = ln0->i32;
ui16* p = (ui16*)dp;
for (; count > 0; --count)
{
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = be2le((ui16) val);
}
}
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)
{
int max_val = (1<<bit_depth) - 1;
const si32 *sp0 = ln0->i32;
const si32 *sp1 = ln1->i32;
const si32 *sp2 = ln2->i32;
ui16* p = (ui16*)dp;
for (; count > 0; --count)
{
int val;
val = *sp0++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = be2le((ui16) val);
val = *sp1++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = be2le((ui16) val);
val = *sp2++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*p++ = be2le((ui16) val);
}
}
//
//
//
//
//
void ppm_in::open(const char *filename)
{
assert(fh == 0);
fh = fopen(filename, "rb");
if (fh == 0)
OJPH_ERROR(0x03000001, "Unable to open file %s", filename);
fname = filename;
// read magic number
char t[2];
if (fread(t, 1, 2, fh) != 2)
{
close();
OJPH_ERROR(0x03000002, "Error reading file %s", filename);
}
// check magic number
if (t[0] != 'P' || (t[1] != '5' && t[1] != '6'))
{
close();
OJPH_ERROR(0x03000003, "unknown file type for file %s", filename);
}
size_t len = strlen(filename);
if (t[1] == '5' && strncmp(filename + len - 4, ".pgm", 4) != 0)
{
close();
OJPH_ERROR(0x03000004, "wrong file extension, a file with "
"keyword P5 must have a .pgm extension for file %s", filename);
}
if (t[1] == '6' && strncmp(filename + len - 4, ".ppm", 4) != 0)
{
close();
OJPH_ERROR(0x03000005, "wrong file extension, a file with keyword P6 "
"must have a .ppm extension for file %s", filename);
}
// set number of components based on file-type
num_comps = t[1] == '5' ? 1 : 3;
eat_white_spaces(fh);
// read width, height and max value in header
if (fscanf(fh, "%d %d %d", &width, &height, &max_val) != 3)
{
close();
OJPH_ERROR(0x03000006, "error in file format for file %s", filename);
}
num_ele_per_line = num_comps * width;
bytes_per_sample = max_val > 255 ? 2 : 1;
max_val_num_bits = 32u - count_leading_zeros(max_val);
bit_depth[2] = bit_depth[1] = bit_depth [0] = max_val_num_bits;
fgetc(fh);
start_of_data = ojph_ftell(fh);
// allocate linebuffer to hold a line of image data
if (temp_buf_byte_size < num_comps * width * bytes_per_sample)
{
if (alloc_p == NULL)
{
temp_buf_byte_size = num_comps * width * bytes_per_sample;
void* t = temp_buf;
if (temp_buf)
temp_buf = realloc(temp_buf, temp_buf_byte_size);
else
temp_buf = malloc(temp_buf_byte_size);
if (temp_buf == NULL) { // failed to allocate memory
if (t) free(t); // the original buffer is still valid
OJPH_ERROR(0x03000007, "error allocating memory");
}
}
else
{
assert(temp_buf_byte_size == 0); //cannot reallocate the buffer
temp_buf_byte_size = num_comps * width * bytes_per_sample;
alloc_p->pre_alloc_data<ui8>(temp_buf_byte_size, 0);
}
}
cur_line = 0;
}
void ppm_in::finalize_alloc()
{
if (alloc_p == NULL)
return;
if (bytes_per_sample == 1)
temp_buf = alloc_p->post_alloc_data<ui8>(num_comps * (size_t)width, 0);
else
temp_buf = alloc_p->post_alloc_data<ui16>(num_comps * (size_t)width, 0);
}
ui32 ppm_in::read(const line_buf* line, ui32 comp_num)
{
assert(temp_buf_byte_size != 0 && fh != 0 && comp_num < num_comps);
assert(line->size >= width);
if (planar || comp_num == 0)
{
size_t result = fread(
temp_buf, bytes_per_sample, num_ele_per_line, fh);
if (result != num_ele_per_line)
{
close();
OJPH_ERROR(0x03000011, "not enough data in file %s", fname);
}
if (++cur_line >= height)
{
cur_line = 0;
ojph_fseek(fh, start_of_data, SEEK_SET); //handles plannar reading
}
}
if (bytes_per_sample == 1)
{
const ui8* sp = (ui8*)temp_buf + comp_num;
si32* dp = line->i32;
for (ui32 i = width; i > 0; --i, sp+=num_comps)
*dp++ = (si32)*sp;
}
else
{
const ui16* sp = (ui16*)temp_buf + comp_num;
si32* dp = line->i32;
for (ui32 i = width; i > 0; --i, sp+=num_comps)
*dp++ = (si32)be2le(*sp);
}
return width;
}
//
//
//
//
//
void ppm_out::open(char* filename)
{
assert(fh == NULL && buffer == NULL);
if (num_components == 1)
{
size_t len = strlen(filename);
if (len >= 4)
{
if (strncmp(".ppm", filename + len - 4, 4) == 0)
{
filename[len - 2] = 'g';
OJPH_WARN(0x03000021, "file was renamed %s\n", filename);
}
if (strncmp(".PPM", filename + len - 4, 4) == 0)
{
filename[len - 2] = 'G';
OJPH_WARN(0x03000022, "file was renamed %s\n", filename);
}
}
fh = fopen(filename, "wb");
if (fh == NULL)
OJPH_ERROR(0x03000023,
"unable to open file %s for writing", filename);
fprintf(fh, "P5\n%d %d\n%d\n", width, height, (1 << bit_depth) - 1);
buffer_size = (size_t)width * bytes_per_sample;
buffer = (ui8*)malloc(buffer_size);
}
else
{
size_t len = strlen(filename);
if (len >= 4)
{
if (strncmp(".pgm", filename + len - 4, 4) == 0)
{
filename[len - 2] = 'p';
OJPH_WARN(0x03000024, "file was renamed %s\n", filename);
}
if (strncmp(".PGM", filename + len - 4, 4) == 0)
{
filename[len - 2] = 'P';
OJPH_WARN(0x03000025, "file was renamed %s\n", filename);
}
}
fh = fopen(filename, "wb");
if (fh == NULL)
OJPH_ERROR(0x03000026,
"unable to open file %s for writing", filename);
int result = //the number of written characters
fprintf(fh, "P6\n%d %d\n%d\n", width, height, (1 << bit_depth) - 1);
if (result == 0)
OJPH_ERROR(0x03000027, "error writing to file %s", filename);
buffer_size = (size_t)width * num_components * (size_t)bytes_per_sample;
buffer = (ui8*)malloc(buffer_size);
}
fname = filename;
cur_line = 0;
}
void ppm_out::configure(ui32 width, ui32 height, ui32 num_components,
ui32 bit_depth)
{
assert(fh == NULL); //configure before opening
if (num_components != 1 && num_components != 3)
OJPH_ERROR(0x03000031,
"ppm supports 3 colour components, while pgm supports 1");
this->width = width;
this->height = height;
this->num_components = num_components;
this->bit_depth = bit_depth;
bytes_per_sample = 1 + (bit_depth > 8 ? 1 : 0);
samples_per_line = num_components * width;
bytes_per_line = bytes_per_sample * samples_per_line;
#if !defined(OJPH_ENABLE_WASM_SIMD) || !defined(OJPH_EMSCRIPTEN)
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = gen_cvrt_32b1c_to_8ub1c;
else
converter = gen_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = gen_cvrt_32b1c_to_16ub1c_be;
else
converter = gen_cvrt_32b3c_to_16ub3c_be;
}
#ifndef OJPH_DISABLE_SIMD
#if (defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
#ifndef OJPH_DISABLE_SSE4
if (get_cpu_ext_level() >= X86_CPU_EXT_LEVEL_SSE41) {
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_8ub1c;
else
converter = sse41_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_16ub1c_be;
else
converter = sse41_cvrt_32b3c_to_16ub3c_be;
}
}
#endif // !OJPH_DISABLE_SSE4
#ifndef OJPH_DISABLE_AVX2
if (get_cpu_ext_level() >= X86_CPU_EXT_LEVEL_AVX2) {
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = avx2_cvrt_32b1c_to_8ub1c;
else
converter = avx2_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = avx2_cvrt_32b1c_to_16ub1c_be;
else
{ } // did not find an implementation better than sse41
}
}
#endif // !OJPH_DISABLE_AVX2
#elif defined(OJPH_ARCH_ARM)
#endif // !(defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
#endif // !OJPH_DISABLE_SIMD
#else // OJPH_ENABLE_WASM_SIMD
if (bytes_per_sample == 1) {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_8ub1c;
else
converter = sse41_cvrt_32b3c_to_8ub3c;
}
else {
if (num_components == 1)
converter = sse41_cvrt_32b1c_to_16ub1c_be;
else
converter = sse41_cvrt_32b3c_to_16ub3c_be;
}
#endif // !OJPH_ENABLE_WASM_SIMD
}
ui32 ppm_out::write(const line_buf* line, ui32 comp_num)
{
assert(fh);
lptr[comp_num] = line;
if (comp_num == num_components - 1)
{
assert(lptr[0] != lptr[1]);
assert((lptr[1]!=lptr[2] && num_components==3) || num_components==1);
converter(lptr[0], lptr[1], lptr[2], buffer, bit_depth, width);
size_t result = fwrite(buffer,
bytes_per_sample, samples_per_line, fh);
if (result != samples_per_line)
OJPH_ERROR(0x03000041, "error writing to file %s", fname);
}
return 0;
}
//
//
//
//
//
void pfm_in::open(const char *filename)
{
assert(fh == 0);
fh = fopen(filename, "rb");
if (fh == 0)
OJPH_ERROR(0x03000051, "Unable to open file %s", filename);
fname = filename;
// read magic number
char t[2];
if (fread(t, 1, 2, fh) != 2)
{
close();
OJPH_ERROR(0x03000052, "Error reading file %s", filename);
}
// check magic number
if (t[0] != 'P' || (t[1] != 'F' && t[1] != 'f'))
{
close();
OJPH_ERROR(0x03000053, "Unknown file type for file %s", filename);
}
// set number of components based on file-type
num_comps = t[1] == 'f' ? 1 : 3;
eat_white_spaces(fh);
// read width, height and max value in header
if (fscanf(fh, "%d %d", &width, &height) != 2)
{
close();
OJPH_ERROR(0x03000054,
"Error reading width and height in file %s", filename);
}
eat_white_spaces(fh);
// little or big-endian
if (fscanf(fh, "%f", &scale) != 1)
{
close();
OJPH_ERROR(0x03000055, "Error reading scale in file %s", filename);
}
little_endian = scale < 0.0f;
scale = std::abs(scale);
fgetc(fh);
start_of_data = ojph_ftell(fh);
// alloc. linebuffer to hold a line of image data, if more than 1 comp.
if (temp_buf_byte_size < num_comps * (size_t)width * sizeof(float))
{
if (alloc_p == NULL)
{
temp_buf_byte_size = num_comps * (size_t)width * sizeof(float);
void* t = temp_buf;
if (temp_buf)
temp_buf = (float*)realloc(temp_buf, temp_buf_byte_size);
else
temp_buf = (float*)malloc(temp_buf_byte_size);
if (temp_buf == NULL) { // failed to allocate memory
if (t) free(t); // the original buffer is still valid
OJPH_ERROR(0x03000056, "Error allocating memory");
}
}
else
{
assert(temp_buf_byte_size == 0); //cannot reallocate the buffer
temp_buf_byte_size = num_comps * (size_t)width * sizeof(float);
alloc_p->pre_alloc_data<float>(temp_buf_byte_size, 0);
}
}
cur_line = 0;
}
void pfm_in::finalize_alloc()
{
if (alloc_p == NULL)
return;
temp_buf = alloc_p->post_alloc_data<float>(num_comps * (size_t)width, 0);
}
ui32 pfm_in::read(const line_buf* line, ui32 comp_num)
{
assert(temp_buf_byte_size != 0 );
assert(fh != 0 && comp_num < num_comps);
assert(line->size >= width);
if (comp_num == 0)
{
si64 loc = start_of_data;
loc += (size_t)(height-1 - cur_line) * (size_t)num_comps
* (size_t)width * sizeof(float);
if (ojph_fseek(fh, loc, SEEK_SET) != 0)
{
close();
OJPH_ERROR(0x03000061, "Error seeking in file %s", fname);
}
size_t result =
fread(temp_buf, sizeof(float), (size_t)num_comps * (size_t)width, fh);
if (result != (size_t)num_comps * (size_t)width)
{
close();
OJPH_ERROR(0x03000062, "Not enough data in file %s", fname);
}
if (++cur_line >= height)
cur_line = 0;
}
union {
si32* s;
ui32* u;
float* f;
} sp, dp;
if (little_endian)
{
ui32 shift = 32 - bit_depth[comp_num];
sp.f = temp_buf + comp_num;
dp.f = line->f32;
if (shift)
for (ui32 i = width; i > 0; --i, sp.f += num_comps)
{
si32 s = *sp.s;
s >>= shift;
*dp.s++ = s;
}
else
for (ui32 i = width; i > 0; --i, sp.f += num_comps)
*dp.f++ = *sp.f;
}
else {
ui32 shift = 32 - bit_depth[comp_num];
sp.f = temp_buf + comp_num;
dp.f = line->f32;
if (shift)
for (ui32 i = width; i > 0; --i, sp.f += num_comps) {
ui32 u = be2le(*sp.u);
si32 s = *(si32*)&u;
s >>= shift;
*dp.s++ = s;
}
else
for (ui32 i = width; i > 0; --i, sp.f += num_comps)
*dp.u++ = be2le(*sp.u);
}
return width;
}
//
//
//
//
//
void pfm_out::open(char* filename)
{
assert(fh == NULL && buffer == NULL);
fh = fopen(filename, "wb");
if (fh == NULL)
OJPH_ERROR(0x03000071,
"Unable to open file %s for writing", filename);
int result = //the number of written characters
fprintf(fh, "P%c\n%d %d\n%f\n",
num_components > 1 ? 'F' : 'f', width, height, scale);
if (result == 0)
OJPH_ERROR(0x03000072, "error writing to file %s", filename);
buffer_size = (size_t)width * num_components * sizeof(float);
buffer = (float*)malloc(buffer_size);
fname = filename;
cur_line = 0;
start_of_data = ojph_ftell(fh);
}
void pfm_out::configure(ui32 width, ui32 height, ui32 num_components,
float scale, ui32* bit_depth)
{
assert(fh == NULL); //configure before opening
if (num_components != 1 && num_components != 3)
OJPH_ERROR(0x03000081,
"pfm supports 1 or 3 colour components, not %d", num_components);
this->width = width;
this->height = height;
this->num_components = num_components;
this->scale = scale < 0.0f ? scale : -scale;
for (ui32 c = 0; c < num_components; ++c)
this->bit_depth[c] = bit_depth[c];
}
ui32 pfm_out::write(const line_buf* line, ui32 comp_num)
{
assert(fh);
ui32 shift = 32 - bit_depth[comp_num];
union {
ui32* u;
float* f;
} sp, dp;
dp.f = buffer + comp_num;
sp.f = line->f32;
if (shift)
for (ui32 i = width; i > 0; --i, dp.f += num_components, ++sp.f)
{
ui32 u = *sp.u;
u <<= shift;
*dp.u = u;
}
else
for (ui32 i = width; i > 0; --i, dp.f += num_components)
*dp.f = *sp.f++;
if (comp_num == num_components - 1)
{
size_t samples_per_line = num_components * (size_t)width;
si64 loc = start_of_data;
loc += (height - 1 - cur_line)* samples_per_line * sizeof(float);
if (ojph_fseek(fh, loc, SEEK_SET) != 0)
OJPH_ERROR(0x03000082, "Error seeking in file %s", fname);
size_t result = fwrite(buffer, sizeof(float), samples_per_line, fh);
if (result != samples_per_line)
OJPH_ERROR(0x03000083, "error writing to file %s", fname);
++cur_line;
}
return 0;
}
//
//
//
//
//
#ifdef OJPH_ENABLE_TIFF_SUPPORT
void tif_in::open(const char* filename)
{
tiff_handle = NULL;
if ((tiff_handle = TIFFOpen(filename, "r")) == NULL)
OJPH_ERROR(0x03000091, "Unable to open file %s", filename);
fname = filename;
ui32 tiff_width = 0;
ui32 tiff_height = 0;
TIFFGetField(tiff_handle, TIFFTAG_IMAGEWIDTH, &tiff_width);
TIFFGetField(tiff_handle, TIFFTAG_IMAGELENGTH, &tiff_height);
ui16 tiff_bits_per_sample = 0;
ui16 tiff_samples_per_pixel = 0;
TIFFGetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, &tiff_bits_per_sample);
TIFFGetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, &tiff_samples_per_pixel);
// some TIFs have tiff_samples_per_pixel=0 when it is a single channel
// image - set to 1
tiff_samples_per_pixel =
(tiff_samples_per_pixel < 1) ? 1 : tiff_samples_per_pixel;
ui16 tiff_planar_configuration = 0;
ui16 tiff_photometric = 0;
TIFFGetField(tiff_handle, TIFFTAG_PLANARCONFIG, &tiff_planar_configuration);
TIFFGetField(tiff_handle, TIFFTAG_PHOTOMETRIC, &tiff_photometric);
planar_configuration = tiff_planar_configuration;
ui16 tiff_compression = 0;
ui32 tiff_rows_per_strip = 0;
TIFFGetField(tiff_handle, TIFFTAG_COMPRESSION, &tiff_compression);
TIFFGetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, &tiff_rows_per_strip);
if (tiff_planar_configuration == PLANARCONFIG_SEPARATE)
{
bytes_per_line = tiff_samples_per_pixel * TIFFScanlineSize64(tiff_handle);
}
else
{
bytes_per_line = TIFFScanlineSize64(tiff_handle);
}
// allocate linebuffer to hold a line of image data
line_buffer = malloc(bytes_per_line);
if (NULL == line_buffer)
OJPH_ERROR(0x03000092, "Unable to allocate %d bytes for line_buffer[] "
"for file %s", bytes_per_line, filename);
cur_line = 0;
// Error on known incompatilbe input formats
if( tiff_bits_per_sample != 8 && tiff_bits_per_sample != 16 )
{
OJPH_ERROR(0x03000093, "\nTIFF IO is currently limited"
" to files with TIFFTAG_BITSPERSAMPLE=8 and TIFFTAG_BITSPERSAMPLE=16 \n"
"input file = %s has TIFFTAG_BITSPERSAMPLE=%d",
filename, tiff_bits_per_sample);
}
if( TIFFIsTiled( tiff_handle ) )
{
OJPH_ERROR(0x03000094, "\nTIFF IO is currently limited to TIF files "
"without tiles. \nInput file %s has been detected as tiled", filename);
}
if(PHOTOMETRIC_RGB != tiff_photometric &&
PHOTOMETRIC_MINISBLACK != tiff_photometric )
{
OJPH_ERROR(0x03000095, "\nTIFF IO is currently limited to "
"TIFFTAG_PHOTOMETRIC=PHOTOMETRIC_MINISBLACK=%d and "
"PHOTOMETRIC_RGB=%d. \nInput file %s has been detected "
"TIFFTAG_PHOTOMETRIC=%d",
PHOTOMETRIC_MINISBLACK, PHOTOMETRIC_RGB, filename, tiff_photometric);
}
if( tiff_samples_per_pixel > 4 )
{
OJPH_ERROR(0x03000096, "\nTIFF IO is currently limited to "
"TIFFTAG_SAMPLESPERPIXEL=4 \nInput file %s has been detected with "
"TIFFTAG_SAMPLESPERPIXEL=%d",
filename, tiff_samples_per_pixel);
}
// set number of components based on tiff_samples_per_pixel
width = tiff_width;
height = tiff_height;
num_comps = tiff_samples_per_pixel;
bytes_per_sample = (tiff_bits_per_sample + 7) / 8;
for (ui32 comp_num = 0; comp_num < num_comps; comp_num++)
bit_depth[comp_num] = tiff_bits_per_sample;
// allocate intermediate linebuffers to hold a line of a single component
// of image data
if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
bytes_per_sample == 1)
{
line_buffer_for_planar_support_uint8 =
(uint8_t*)calloc(width, sizeof(uint8_t));
if (NULL == line_buffer_for_planar_support_uint8)
OJPH_ERROR(0x03000097, "Unable to allocate %d bytes for "
"line_buffer_for_planar_support_uint8[] for file %s",
width * sizeof(uint8_t), filename);
}
if (tiff_planar_configuration == PLANARCONFIG_SEPARATE &&
bytes_per_sample == 2)
{
line_buffer_for_planar_support_uint16 =
(uint16_t*)calloc(width, sizeof(uint16_t));
if (NULL == line_buffer_for_planar_support_uint16)
OJPH_ERROR(0x03000098, "Unable to allocate %d bytes for "
"line_buffer_for_planar_support_uint16[] for file %s",
width * sizeof(uint16_t), filename);
}
}
void tif_in::set_bit_depth(ui32 num_bit_depths, ui32* bit_depth)
{
if (num_bit_depths < 1)
OJPH_ERROR(0x030000A1, "one or more bit_depths must be provided");
ui32 last_bd_idx = 0;
for (ui32 i = 0; i < 4; ++i)
{
ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
if (bd > 32 || bd < 1)
{
OJPH_ERROR(0x030000A2,
"bit_depth = %d, this must be an integer from 1-32", bd);
}
this->bit_depth[i] = bd;
}
}
ui32 tif_in::read(const line_buf* line, ui32 comp_num)
{
assert(bytes_per_line != 0 && tiff_handle != 0 && comp_num < num_comps);
assert((ui32)line->size >= width);
// do a read from the file if this is the first component and therefore
// the first time trying to access this line
if (PLANARCONFIG_SEPARATE == planar_configuration && 0 == comp_num )
{
for (ui32 color = 0; color < num_comps; color++)
{
if (bytes_per_sample == 1)
{
TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint8,
cur_line, (ui16)color);
ui32 x = color;
uint8_t* line_buffer_of_interleaved_components =
(uint8_t*)line_buffer;
for (ui32 i = 0; i < width; i++, x += num_comps)
{
line_buffer_of_interleaved_components[x] =
line_buffer_for_planar_support_uint8[i];
}
}
else if (bytes_per_sample == 2)
{
TIFFReadScanline(tiff_handle, line_buffer_for_planar_support_uint16,
cur_line, (ui16)color);
ui32 x = color;
ui16* line_buffer_of_interleaved_components = (ui16*)line_buffer;
for (ui32 i = 0; i < width; i++, x += num_comps)
{
line_buffer_of_interleaved_components[x] =
line_buffer_for_planar_support_uint16[i];
}
}
}
cur_line++;
}
else if (planar_configuration == PLANARCONFIG_CONTIG && 0 == comp_num)
{
TIFFReadScanline(tiff_handle, line_buffer, cur_line++);
}
if (cur_line >= height)
{
cur_line = 0;
}
if (bytes_per_sample == 1)
{
const ui8* sp = (ui8*)line_buffer + comp_num;
si32* dp = line->i32;
if (bit_depth[comp_num] == 8)
{
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32)*sp;
}
else if (bit_depth[comp_num] < 8)
{
// read the desired precision from the MSBs
const int bits_to_shift = 8 - (int)bit_depth[comp_num];
const int bit_mask = (1 << bit_depth[comp_num]) - 1;
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32) (((*sp) >> bits_to_shift) & bit_mask);
}
else if (bit_depth[comp_num] > 8)
{
const int bits_to_shift = (int)bit_depth[comp_num] - 8;
const int bit_mask = (1 << bit_depth[comp_num]) - 1;
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
}
}
else if(bytes_per_sample == 2)
{
if (bit_depth[comp_num] == 16)
{
const ui16* sp = (ui16*)line_buffer + comp_num;
si32* dp = line->i32;
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32)*sp;
}
else if (bit_depth[comp_num] < 16)
{
// read the desired precision from the MSBs
const int bits_to_shift = 16 - (int)bit_depth[comp_num];
const int bit_mask = (1 << bit_depth[comp_num]) - 1;
const ui16* sp = (ui16*)line_buffer + comp_num;
si32* dp = line->i32;
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32)(((*sp) >> bits_to_shift) & bit_mask);
}
else if (bit_depth[comp_num] > 16)
{
const int bits_to_shift = (int)bit_depth[comp_num] - 16;
const int bit_mask = (1 << bit_depth[comp_num]) - 1;
const ui16* sp = (ui16*)line_buffer + comp_num;
si32* dp = line->i32;
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32)(((*sp) << bits_to_shift) & bit_mask);
}
}
return width;
}
//
//
//
//
//
void tif_out::open(char* filename)
{
// Error on known incompatilbe output formats
ui32 max_bitdepth = 0;
for (ui32 c = 0; c < num_components; c++)
{
if (bit_depth_of_data[c] > max_bitdepth)
max_bitdepth = bit_depth_of_data[c];
}
if (max_bitdepth > 16)
{
OJPH_WARN(0x030000B1, "TIFF output is currently limited to files "
"with max_bitdepth = 16, the source codestream has max_bitdepth=%d"
", the decoded data will be truncated to 16 bits", max_bitdepth);
}
if (num_components > 4)
{
OJPH_ERROR(0x030000B2, "TIFF IO is currently limited to files with "
"num_components=1 to 4");
}
assert(tiff_handle == NULL && buffer == NULL);
if ((tiff_handle = TIFFOpen(filename, "w")) == NULL)
{
OJPH_ERROR(0x030000B3, "unable to open file %s for writing", filename);
}
buffer_size = width * (size_t)num_components * (size_t)bytes_per_sample;
buffer = (ui8*)malloc(buffer_size);
fname = filename;
cur_line = 0;
// set tiff fields
// Write the tiff tags to the file
TIFFSetField(tiff_handle, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tiff_handle, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tiff_handle, TIFFTAG_BITSPERSAMPLE, bytes_per_sample * 8);
TIFFSetField(tiff_handle, TIFFTAG_SAMPLESPERPIXEL, num_components);
planar_configuration = PLANARCONFIG_CONTIG;
TIFFSetField(tiff_handle, TIFFTAG_PLANARCONFIG, planar_configuration);
if (num_components == 1)
{
TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
}
else if (num_components == 2)
{
TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
// possible values are EXTRASAMPLE_UNSPECIFIED = 0;
// EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
&extra_samples_description);
}
else if (num_components == 3)
{
TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
}
else if (num_components == 4)
{
TIFFSetField(tiff_handle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
// possible values are EXTRASAMPLE_UNSPECIFIED = 0;
// EXTRASAMPLE_ASSOCALPHA = 1; EXTRASAMPLE_UNASSALPHA = 2;
const ui16 extra_samples_description[1] = { EXTRASAMPLE_ASSOCALPHA };
TIFFSetField(tiff_handle, TIFFTAG_EXTRASAMPLES, (uint16_t)1,
&extra_samples_description);
}
TIFFSetField(tiff_handle, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tiff_handle, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
//TIFFSetField(tiff_handle, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField(tiff_handle, TIFFTAG_ROWSPERSTRIP, height);
}
void tif_out::configure(ui32 width, ui32 height, ui32 num_components,
ui32 *bit_depth)
{
assert(tiff_handle == NULL); //configure before opening
this->width = width;
this->height = height;
this->num_components = num_components;
ui32 max_bitdepth = 0;
for (ui32 c = 0; c < num_components; c++)
{
this->bit_depth_of_data[c] = bit_depth[c];
if (bit_depth[c] > max_bitdepth)
max_bitdepth = bit_depth[c];
}
bytes_per_sample = (max_bitdepth + 7) / 8; // round up
if (bytes_per_sample > 2)
{
// TIFF output is currently limited to files with max_bitdepth = 16,
// the decoded data will be truncated to 16 bits
bytes_per_sample = 2;
}
samples_per_line = num_components * width;
bytes_per_line = bytes_per_sample * (size_t)samples_per_line;
}
ui32 tif_out::write(const line_buf* line, ui32 comp_num)
{
assert(tiff_handle);
if (bytes_per_sample == 1)
{
int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
const si32* sp = line->i32;
ui8* dp = buffer + comp_num;
if (bit_depth_of_data[comp_num] == 8)
{
for (ui32 i = width; i > 0; --i, dp += num_components)
{
// clamp the decoded sample to the allowed range
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*dp = (ui8)val;
}
}
else if (bit_depth_of_data[comp_num] < 8)
{
const int bits_to_shift = 8 - (int)bit_depth_of_data[comp_num];
const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
for (ui32 i = width; i > 0; --i, dp += num_components)
{
// clamp the decoded sample to the allowed range
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
// shift the decoded data so the data's MSB is aligned with the
// 8 bit MSB
*dp = (ui8)((val & bit_mask) << bits_to_shift);
}
}
else if (bit_depth_of_data[comp_num] > 8)
{
const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 8;
const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
for (ui32 i = width; i > 0; --i, dp += num_components)
{
// clamp the decoded sample to the allowed range
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
// shift the decoded data so the data's MSB is aligned with the
// 8 bit MSB
*dp = (ui8)((val >> bits_to_shift) & bit_mask);
}
}
}
else if(bytes_per_sample == 2)
{
int max_val = (1 << bit_depth_of_data[comp_num]) - 1;
const si32* sp = line->i32;
ui16* dp = (ui16*)buffer + comp_num;
if (bit_depth_of_data[comp_num] == 16)
{
for (ui32 i = width; i > 0; --i, dp += num_components)
{
// clamp the decoded sample to the allowed range
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*dp = (ui16)val;
}
}
else if (bit_depth_of_data[comp_num] < 16)
{
const int bits_to_shift = 16 - (int)bit_depth_of_data[comp_num];
const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
for (ui32 i = width; i > 0; --i, dp += num_components)
{
// clamp the decoded sample to the allowed range
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
// shift the decoded data so the data's MSB is aligned with the
// 16 bit MSB
*dp = (ui16)((val & bit_mask) << bits_to_shift);
}
}
else if (bit_depth_of_data[comp_num] > 16)
{
const int bits_to_shift = (int)bit_depth_of_data[comp_num] - 16;
const int bit_mask = (1 << bit_depth_of_data[comp_num]) - 1;
for (ui32 i = width; i > 0; --i, dp += num_components)
{
// clamp the decoded sample to the allowed range
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
// shift the decoded data so the data's MSB is aligned with the
// 16 bit MSB
*dp = (ui16)((val >> bits_to_shift) & bit_mask);
}
}
}
// write scanline when the last component is reached
if (comp_num == num_components-1)
{
int result = TIFFWriteScanline(tiff_handle, buffer, cur_line++);
if (result != 1)
OJPH_ERROR(0x030000C1, "error writing to file %s", fname);
}
return 0;
}
#endif /* OJPH_ENABLE_TIFF_SUPPORT */
//
//
//
//
//
void yuv_in::open(const char* filename)
{
assert(fh == NULL);
fh = fopen(filename, "rb");
if (fh == 0)
OJPH_ERROR(0x030000D1, "Unable to open file %s", filename);
//need to extract info from filename
assert(num_com == 1 || num_com == 3);
for (ui32 i = 0; i < num_com; ++i)
bytes_per_sample[i] = bit_depth[i] > 8 ? 2 : 1;
ui32 max_byte_width = width[0] * bytes_per_sample[0];
comp_address[0] = 0;
for (ui32 i = 1; i < num_com; ++i)
{
comp_address[i] = comp_address[i - 1];
comp_address[i] += width[i-1] * height[i-1] * bytes_per_sample[i-1];
max_byte_width = ojph_max(max_byte_width, width[i]*bytes_per_sample[i]);
}
temp_buf = malloc(max_byte_width);
fname = filename;
}
ui32 yuv_in::read(const line_buf* line, ui32 comp_num)
{
assert(comp_num < num_com);
size_t result = fread(temp_buf, bytes_per_sample[comp_num],
width[comp_num], fh);
if (result != width[comp_num])
{
close();
OJPH_ERROR(0x030000E1, "not enough data in file %s", fname);
}
if (bytes_per_sample[comp_num] == 1)
{
const ui8* sp = (ui8*)temp_buf;
si32* dp = line->i32;
for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
*dp++ = (si32)*sp;
}
else
{
const ui16* sp = (ui16*)temp_buf;
si32* dp = line->i32;
for (ui32 i = width[comp_num]; i > 0; --i, ++sp)
*dp++ = (si32)*sp;
}
return width[comp_num];
}
void yuv_in::set_img_props(const size& s, ui32 num_components,
ui32 num_downsamplings, const point *subsampling)
{
if (num_components != 1 && num_components !=3)
OJPH_ERROR(0x030000F1, "yuv_in support 1 or 3 components");
this->num_com = num_components;
if (num_downsamplings < 1)
OJPH_ERROR(0x030000F2, "one or more downsampling must be provided");
ui32 last_downsamp_idx = 0;
for (ui32 i = 0; i < num_components; ++i)
{
point cp_ds = subsampling[i<num_downsamplings ? i : last_downsamp_idx];
last_downsamp_idx += last_downsamp_idx + 1 < num_downsamplings ? 1 : 0;
this->subsampling[i] = cp_ds;
}
for (ui32 i = 0; i < num_components; ++i)
{
width[i] = ojph_div_ceil(s.w, this->subsampling[i].x);
height[i] = ojph_div_ceil(s.h, this->subsampling[i].y);
}
}
void yuv_in::set_bit_depth(ui32 num_bit_depths, ui32* bit_depth)
{
if (num_bit_depths < 1)
OJPH_ERROR(0x03000101, "one or more bit_depths must be provided");
ui32 last_bd_idx = 0;
for (ui32 i = 0; i < 3; ++i)
{
ui32 bd = bit_depth[i < num_bit_depths ? i : last_bd_idx];
last_bd_idx += last_bd_idx + 1 < num_bit_depths ? 1 : 0;
this->bit_depth[i] = bd;
}
}
//
//
//
//
//
yuv_out::~yuv_out()
{
close();
if (buffer)
{
free(buffer);
buffer = NULL;
buffer_size = 0;
}
if (comp_width)
{
delete [] comp_width;
comp_width = NULL;
}
}
void yuv_out::open(char *filename)
{
assert(fh == NULL); //configure before open
fh = fopen(filename, "wb");
if (fh == 0)
OJPH_ERROR(0x03000111, "Unable to open file %s", filename);
fname = filename;
}
void yuv_out::configure(ui32 bit_depth, ui32 num_components,
ui32* comp_width)
{
assert(fh == NULL);
this->num_components = num_components;
this->bit_depth = bit_depth;
this->comp_width = new ui32[num_components];
ui32 tw = 0;
for (ui32 i = 0; i < num_components; ++i)
{
this->comp_width[i] = comp_width[i];
tw = ojph_max(tw, this->comp_width[i]);
}
this->width = tw;
buffer_size = tw * (bit_depth > 8 ? 2 : 1);
buffer = (ui8*)malloc(buffer_size);
}
ui32 yuv_out::write(const line_buf* line, ui32 comp_num)
{
assert(fh);
assert(comp_num < num_components);
int max_val = (1<<bit_depth) - 1;
ui32 w = comp_width[comp_num];
if (bit_depth > 8)
{
const si32 *sp = line->i32;
ui16 *dp = (ui16 *)buffer;
for (ui32 i = w; i > 0; --i)
{
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*dp++ = (ui16)val;
}
if (fwrite(buffer, 2, w, fh) != w)
OJPH_ERROR(0x03000121, "unable to write to file %s", fname);
}
else
{
const si32 *sp = line->i32;
ui8 *dp = (ui8 *)buffer;
for (ui32 i = w; i > 0; --i)
{
int val = *sp++;
val = val >= 0 ? val : 0;
val = val <= max_val ? val : max_val;
*dp++ = (ui8)val;
}
if (fwrite(buffer, 1, w, fh) != w)
OJPH_ERROR(0x03000122, "unable to write to file %s", fname);
}
return w;
}
//
//
//
//
//
void raw_in::open(const char* filename)
{
assert(fh == NULL);
fh = fopen(filename, "rb");
if (fh == NULL)
OJPH_ERROR(0x03000131, "Unable to open file %s", filename);
cur_line = 0;
bytes_per_sample = (bit_depth + 7) >> 3;
buffer_size = (size_t)width * bytes_per_sample;
buffer = (ui8*)malloc(buffer_size);
fname = filename;
}
ui32 raw_in::read(const line_buf* line, ui32 comp_num)
{
ojph_unused(comp_num);
assert(comp_num == 0);
size_t result = fread(buffer, bytes_per_sample, width, fh);
if (result != width)
{
close();
OJPH_ERROR(0x03000132, "not enough data in file %s", fname);
}
if (bytes_per_sample > 3)
{
si32* dp = line->i32;
if (is_signed) {
const si32* sp = (si32*)buffer;
for (ui32 i = width; i > 0; --i, ++sp)
*dp++ = *sp;
}
else {
si32* dp = line->i32;
const ui32* sp = (ui32*)buffer;
for (ui32 i = width; i > 0; --i, ++sp)
*dp++ = (si32)*sp;
}
}
else if (bytes_per_sample > 2)
{
si32* dp = line->i32;
if (is_signed) {
const si32* sp = (si32*)buffer;
for (ui32 i = width; i > 0; --i) {
si32 val = *sp & 0xFFFFFF;
val |= (val & 0x800000) ? 0xFF000000 : 0;
*dp++ = val;
// this only works for little endian architecture
sp = (si32*)((si8*)sp + 3);
}
}
else {
const ui32* sp = (ui32*)buffer;
for (ui32 i = width; i > 0; --i) {
*dp++ = (si32)(*sp & 0xFFFFFFu);
// this only works for little endian architecture
sp = (ui32*)((ui8*)sp + 3);
}
}
}
else if (bytes_per_sample > 1)
{
si32* dp = line->i32;
if (is_signed) {
const si16* sp = (si16*)buffer;
for (ui32 i = width; i > 0; --i, ++sp)
*dp++ = *sp;
}
else {
const ui16* sp = (ui16*)buffer;
for (ui32 i = width; i > 0; --i, ++sp)
*dp++ = (si32)*sp;
}
}
else
{
si32* dp = line->i32;
if (is_signed) {
const si8* sp = (si8*)buffer;
for (ui32 i = width; i > 0; --i, ++sp)
*dp++ = *sp;
}
else {
const ui8* sp = (ui8*)buffer;
for (ui32 i = width; i > 0; --i, ++sp)
*dp++ = (si32)*sp;
}
}
return width;
}
void raw_in::set_img_props(const size& s, ui32 bit_depth, bool is_signed)
{
assert(fh == NULL);
//need to extract this info from filename
this->width = s.w;
this->height = s.h;
this->bit_depth = bit_depth;
this->is_signed = is_signed;
}
//
//
//
//
//
raw_out::~raw_out()
{
close();
if (buffer)
{
free(buffer);
buffer = NULL;
buffer_size = 0;
}
}
void raw_out::open(char *filename)
{
assert(fh == NULL); //configure before open
fh = fopen(filename, "wb");
if (fh == 0)
OJPH_ERROR(0x03000141, "Unable to open file %s", filename);
fname = filename;
}
void raw_out::configure(bool is_signed, ui32 bit_depth, ui32 width)
{
assert(fh == NULL);
this->is_signed = is_signed;
this->bit_depth = bit_depth;
this->width = width;
if (is_signed) {
upper_val = ((si64)1 << (bit_depth - 1));
lower_val = -((si64)1 << (bit_depth - 1));
} else {
upper_val = (si64)1 << bit_depth;
lower_val = (si64)0;
}
bytes_per_sample = (bit_depth + 7) >> 3;
buffer_size = width * bytes_per_sample;
buffer = (ui8*)malloc(buffer_size);
}
ui32 raw_out::write(const line_buf* line, ui32 comp_num)
{
ojph_unused(comp_num);
assert(fh);
assert(comp_num == 0);
if (is_signed)
{
if (bytes_per_sample > 3)
{
const si32* sp = line->i32;
si32* dp = (si32*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp++ = (si32)val;
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000151, "unable to write to file %s", fname);
}
else if (bytes_per_sample > 2)
{
const si32* sp = line->i32;
si32* dp = (si32*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp = (si32)val;
// this only works for little endian architecture
dp = (si32*)((ui8*)dp + 3);
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000152, "unable to write to file %s", fname);
}
else if (bytes_per_sample > 1)
{
const si32* sp = line->i32;
si16* dp = (si16*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp++ = (si16)val;
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000153, "unable to write to file %s", fname);
}
else
{
const si32* sp = line->i32;
si8* dp = (si8*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp++ = (si8)val;
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000154, "unable to write to file %s", fname);
}
}
else
{
if (bytes_per_sample > 3)
{
const ui32* sp = (ui32*)line->i32;
ui32* dp = (ui32*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp++ = (ui32)val;
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000155, "unable to write to file %s", fname);
}
else if (bytes_per_sample > 2)
{
const ui32* sp = (ui32*)line->i32;
ui32* dp = (ui32*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp = (ui32)val;
// this only works for little endian architecture
dp = (ui32*)((ui8*)dp + 3);
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000156, "unable to write to file %s", fname);
}
else if (bytes_per_sample > 1)
{
const ui32* sp = (ui32*)line->i32;
ui16* dp = (ui16*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp++ = (ui16)val;
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000157, "unable to write to file %s", fname);
}
else
{
const ui32* sp = (ui32*)line->i32;
ui8* dp = (ui8*)buffer;
for (ui32 i = width; i > 0; --i)
{
si64 val = *sp++;
val = val < upper_val ? val : upper_val;
val = val >= lower_val ? val : lower_val;
*dp++ = (ui8)val;
}
if (fwrite(buffer, bytes_per_sample, width, fh) != width)
OJPH_ERROR(0x03000158, "unable to write to file %s", fname);
}
}
return width;
}
//
//
//
//
//
void dpx_in::open(const char* filename)
{
assert(file_handle == 0);
file_handle = fopen(filename, "rb");
if (0 == file_handle)
OJPH_ERROR(0x03000161, "Unable to open file %s", filename);
fname = filename;
// read magic number
ui32 magic_number;
if (fread(&magic_number, sizeof(ui32), 1, file_handle) != 1)
{
close();
OJPH_ERROR(0x03000162, "Error reading file %s", filename);
}
// check magic number
const ui32 dpx_magic_number = 0x53445058;
if (dpx_magic_number == magic_number)
{
// magic number is a match - no byte swapping necessary
is_byte_swapping_necessary = false;
}
else if (dpx_magic_number == be2le(magic_number))
{
// magic number is a match after bytes swapping -
// the data read from this file needs byte swapping
is_byte_swapping_necessary = true;
}
else
{
close();
OJPH_ERROR(0x03000163, "Error reading file %s - this does not appear "
"to be a valid DPX file. It has magic number = 0x%08X. The magic "
"number of a DPX file is 0x%08X.", filename, magic_number,
dpx_magic_number);
}
// read offset to data
if (fread(&offset_to_image_data_in_bytes, sizeof(ui32), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000164, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
offset_to_image_data_in_bytes = be2le(offset_to_image_data_in_bytes);
// read version
if (fread(version, sizeof(uint8_t), 8, file_handle) != 8)
{
close();
OJPH_ERROR(0x03000165, "Error reading file %s", filename);
}
// read image file size in bytes
if (fread(&total_image_file_size_in_bytes, sizeof(ui32), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000166, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
total_image_file_size_in_bytes = be2le(total_image_file_size_in_bytes);
// seek to image info header
if (fseek(file_handle,768, SEEK_SET) != 0)
{
close();
OJPH_ERROR(0x03000167, "Error reading file %s", filename);
}
// read image_orientation
if (fread(&image_orientation, sizeof(uint16_t), 1, file_handle) != 1)
{
close();
OJPH_ERROR(0x03000168, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
image_orientation = be2le(image_orientation);
// read number of image elements
if (fread(&number_of_image_elements, sizeof(uint16_t), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000169, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
number_of_image_elements = be2le(number_of_image_elements);
// read pixels per line
if (fread(&pixels_per_line, sizeof(ui32), 1, file_handle) != 1)
{
close();
OJPH_ERROR(0x0300016A, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
pixels_per_line = be2le(pixels_per_line);
// read lines per image element
if (fread(&lines_per_image_element, sizeof(ui32), 1, file_handle) != 1)
{
close();
OJPH_ERROR(0x0300016B, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
lines_per_image_element = be2le(lines_per_image_element);
// seek to data structure for image element 1
if (fseek(file_handle, 780, SEEK_SET) != 0)
{
close();
OJPH_ERROR(0x0300016C, "Error reading file %s", filename);
}
// read data sign for image element
if (fread(&data_sign_for_image_element_1, sizeof(ui32), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x0300016E, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
data_sign_for_image_element_1 = be2le(data_sign_for_image_element_1);
// seek to core data elements in image element 1
if (fseek(file_handle, 800, SEEK_SET) != 0)
{
close();
OJPH_ERROR(0x0300016F, "Error reading file %s", filename);
}
// read descriptor
if (fread(&descriptor_for_image_element_1, sizeof(uint8_t), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000170, "Error reading file %s", filename);
}
// read transfer characteristic
if (fread(&transfer_characteristic_for_image_element_1, sizeof(uint8_t),
1, file_handle) != 1)
{
close();
OJPH_ERROR(0x03000171, "Error reading file %s", filename);
}
// read colorimetric specification
if (fread(&colormetric_specification_for_image_element_1, sizeof(uint8_t),
1, file_handle) != 1)
{
close();
OJPH_ERROR(0x03000172, "Error reading file %s", filename);
}
// read bit depth
if (fread(&bitdepth_for_image_element_1, sizeof(uint8_t), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000173, "Error reading file %s", filename);
}
// read packing
if (fread(&packing_for_image_element_1, sizeof(uint16_t), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000174, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
packing_for_image_element_1 = be2le(packing_for_image_element_1);
// read encoding
if (fread(&encoding_for_image_element_1, sizeof(uint16_t), 1, file_handle)
!= 1)
{
close();
OJPH_ERROR(0x03000175, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
encoding_for_image_element_1 = be2le(encoding_for_image_element_1);
// read offset to data
if (fread(&offset_to_data_for_image_element_1, sizeof(ui32), 1,
file_handle) != 1)
{
close();
OJPH_ERROR(0x03000176, "Error reading file %s", filename);
}
if (is_byte_swapping_necessary)
offset_to_data_for_image_element_1 =
be2le(offset_to_data_for_image_element_1);
// set to starting point of image data
if (fseek(file_handle, (long)offset_to_image_data_in_bytes, SEEK_SET) != 0)
{
close();
OJPH_ERROR(0x03000177, "Error reading file %s", filename);
}
// set ojph properties
width = pixels_per_line;
height = lines_per_image_element;
num_comps = 3; // descriptor field can indicate 1, 3, or 4 comps
for ( ojph::ui32 c = 0; c < get_num_components(); c++)
{
bit_depth[c] = bitdepth_for_image_element_1;
is_signed[c] = false;
subsampling[c] = point(1,1);
}
// handle DPX image data packing in file
ui32 number_of_samples_per_32_bit_word = 32 / bitdepth_for_image_element_1;
number_of_samples_per_line = width * num_comps;
number_of_32_bit_words_per_line =
(number_of_samples_per_line + (number_of_samples_per_32_bit_word - 1))
/ number_of_samples_per_32_bit_word;
cur_line = 0;
// allocate linebuffer to hold a line of image data from the file
line_buffer = malloc(number_of_32_bit_words_per_line * sizeof(ui32) );
if (NULL == line_buffer)
OJPH_ERROR(0x03000178, "Unable to allocate %d bytes for line_buffer[] "
"for file %s",
number_of_32_bit_words_per_line * sizeof(ui32), filename);
// allocate line_buffer_16bit_samples to hold a line of image data in memory
line_buffer_16bit_samples =
(ui16*) malloc((size_t)width * num_comps * sizeof(ui16));
if (NULL == line_buffer_16bit_samples)
OJPH_ERROR(0x03000179, "Unable to allocate %d bytes for "
"line_buffer_16bit_samples[] for file %s",
(size_t)width * num_comps * sizeof(ui16), filename);
cur_line = 0;
return;
}
ui32 dpx_in::read(const line_buf* line, ui32 comp_num)
{
assert(file_handle != 0 && comp_num < num_comps);
assert((ui32)line->size >= width);
// read from file if trying to read the first component
if (0 == comp_num)
{
if (fread(line_buffer, sizeof(ui32), number_of_32_bit_words_per_line,
file_handle) != number_of_32_bit_words_per_line)
{
close();
OJPH_ERROR(0x03000181, "Error reading file %s", fname);
}
if (true == is_byte_swapping_necessary)
{
if (16 == bitdepth_for_image_element_1)
{
ui16* line_buffer_ptr = (ui16*)line_buffer;
for (size_t i = 0; i < 2*number_of_32_bit_words_per_line; i++)
{
line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
}
}
else
{
ui32* line_buffer_ptr = (ui32*)line_buffer;
for (size_t i = 0; i < number_of_32_bit_words_per_line; i++)
{
line_buffer_ptr[i] = be2le(line_buffer_ptr[i]);
}
}
}
// extract samples from 32bit words from file read into
// RGB ordered buffer
ui32 word_index = 0;
if (10 == bitdepth_for_image_element_1 && 3 == num_comps
&& packing_for_image_element_1 == 1)
{
ui32* line_buffer_ptr = (ui32*)line_buffer;
for (ui32 i = 0; i < number_of_samples_per_line; i += 3)
{
// R
line_buffer_16bit_samples[i + 0] =
(ui16) ((line_buffer_ptr[word_index] & 0xFFC00000) >> 22);
// G
line_buffer_16bit_samples[i + 1] =
(ui16) ((line_buffer_ptr[word_index] & 0x003FF000) >> 12);
// B
line_buffer_16bit_samples[i + 2] =
(ui16) ((line_buffer_ptr[word_index] & 0x00000FFC) >> 2);
word_index++;
}
}
else if (16 == bitdepth_for_image_element_1 && 3 == num_comps)
{
ui16* line_buffer_ptr = (ui16*)line_buffer;
for (ui32 i = 0; i < number_of_samples_per_line; i++)
{
line_buffer_16bit_samples[i] = line_buffer_ptr[i];
}
}
else
{
OJPH_ERROR(0x03000182, "file %s uses DPX image formats that are not "
"yet supported by this software\n bitdepth_for_image_element_1 = "
"%d\n num_comps=%d\npacking_for_image_element_1=%d\n "
"descriptor_for_image_element_1=%d", fname,
bitdepth_for_image_element_1, num_comps,
packing_for_image_element_1, descriptor_for_image_element_1);
}
cur_line++;
}
// copy sample data from the unpacked line buffer into a
// single-component buffer to be used by the openjph core
const ui16* sp = (ui16*)line_buffer_16bit_samples + comp_num;
si32* dp = line->i32;
for (ui32 i = width; i > 0; --i, sp += num_comps)
*dp++ = (si32)*sp;
return width;
}
}
ojph::dpx_in::get_num_components
ui32 get_num_components()
Definition ojph_img_io.h:284
ojph::dpx_in::line_buffer
void * line_buffer
Definition ojph_img_io.h:302
ojph::dpx_in::number_of_32_bit_words_per_line
size_t number_of_32_bit_words_per_line
Definition ojph_img_io.h:336
ojph::dpx_in::open
void open(const char *filename)
Definition ojph_img_io.cpp:1796
ojph::dpx_in::packing_for_image_element_1
ui16 packing_for_image_element_1
Definition ojph_img_io.h:332
ojph::dpx_in::descriptor_for_image_element_1
ui8 descriptor_for_image_element_1
Definition ojph_img_io.h:328
ojph::dpx_in::offset_to_data_for_image_element_1
ui32 offset_to_data_for_image_element_1
Definition ojph_img_io.h:334
ojph::dpx_in::height
ui32 height
Definition ojph_img_io.h:303
ojph::dpx_in::total_image_file_size_in_bytes
ui32 total_image_file_size_in_bytes
Definition ojph_img_io.h:320
ojph::dpx_in::file_handle
FILE * file_handle
Definition ojph_img_io.h:299
ojph::dpx_in::pixels_per_line
ui32 pixels_per_line
Definition ojph_img_io.h:324
ojph::dpx_in::subsampling
point subsampling[4]
Definition ojph_img_io.h:309
ojph::dpx_in::number_of_image_elements
ui16 number_of_image_elements
Definition ojph_img_io.h:323
ojph::dpx_in::bitdepth_for_image_element_1
ui8 bitdepth_for_image_element_1
Definition ojph_img_io.h:331
ojph::dpx_in::read
virtual ui32 read(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:2038
ojph::dpx_in::line_buffer_16bit_samples
ui16 * line_buffer_16bit_samples
Definition ojph_img_io.h:313
ojph::dpx_in::version
char version[8]
Definition ojph_img_io.h:319
ojph::dpx_in::offset_to_image_data_in_bytes
ui32 offset_to_image_data_in_bytes
Definition ojph_img_io.h:318
ojph::dpx_in::num_comps
ui32 num_comps
Definition ojph_img_io.h:304
ojph::dpx_in::width
ui32 width
Definition ojph_img_io.h:303
ojph::dpx_in::encoding_for_image_element_1
ui16 encoding_for_image_element_1
Definition ojph_img_io.h:333
ojph::dpx_in::number_of_samples_per_line
ui32 number_of_samples_per_line
Definition ojph_img_io.h:311
ojph::dpx_in::transfer_characteristic_for_image_element_1
ui8 transfer_characteristic_for_image_element_1
Definition ojph_img_io.h:329
ojph::dpx_in::colormetric_specification_for_image_element_1
ui8 colormetric_specification_for_image_element_1
Definition ojph_img_io.h:330
ojph::dpx_in::cur_line
ui32 cur_line
Definition ojph_img_io.h:306
ojph::dpx_in::lines_per_image_element
ui32 lines_per_image_element
Definition ojph_img_io.h:325
ojph::dpx_in::image_orientation
ui16 image_orientation
Definition ojph_img_io.h:322
ojph::dpx_in::is_signed
bool is_signed[4]
Definition ojph_img_io.h:308
ojph::dpx_in::fname
const char * fname
Definition ojph_img_io.h:301
ojph::dpx_in::close
void close()
Definition ojph_img_io.h:275
ojph::dpx_in::bit_depth
ui32 bit_depth[4]
Definition ojph_img_io.h:307
ojph::dpx_in::is_byte_swapping_necessary
bool is_byte_swapping_necessary
Definition ojph_img_io.h:316
ojph::dpx_in::data_sign_for_image_element_1
ui32 data_sign_for_image_element_1
Definition ojph_img_io.h:327
ojph::line_buf
Definition ojph_mem.h:161
ojph::line_buf::size
size_t size
Definition ojph_mem.h:181
ojph::line_buf::f32
float * f32
Definition ojph_mem.h:187
ojph::line_buf::i32
si32 * i32
Definition ojph_mem.h:185
ojph::pfm_in::fh
FILE * fh
Definition ojph_img_io.h:497
ojph::pfm_in::little_endian
bool little_endian
Definition ojph_img_io.h:504
ojph::pfm_in::read
virtual ui32 read(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:649
ojph::pfm_in::bit_depth
ui32 bit_depth[3]
Definition ojph_img_io.h:502
ojph::pfm_in::alloc_p
mem_fixed_allocator * alloc_p
Definition ojph_img_io.h:499
ojph::pfm_in::start_of_data
si64 start_of_data
Definition ojph_img_io.h:507
ojph::pfm_in::finalize_alloc
void finalize_alloc()
Definition ojph_img_io.cpp:641
ojph::pfm_in::fname
const char * fname
Definition ojph_img_io.h:498
ojph::pfm_in::height
ui32 height
Definition ojph_img_io.h:505
ojph::pfm_in::num_comps
ui32 num_comps
Definition ojph_img_io.h:505
ojph::pfm_in::cur_line
ui32 cur_line
Definition ojph_img_io.h:506
ojph::pfm_in::open
void open(const char *filename)
Definition ojph_img_io.cpp:566
ojph::pfm_in::width
ui32 width
Definition ojph_img_io.h:505
ojph::pfm_in::close
void close()
Definition ojph_img_io.h:489
ojph::pfm_in::temp_buf_byte_size
size_t temp_buf_byte_size
Definition ojph_img_io.h:501
ojph::pfm_in::temp_buf
float * temp_buf
Definition ojph_img_io.h:500
ojph::pfm_in::scale
float scale
Definition ojph_img_io.h:503
ojph::pfm_out::fname
const char * fname
Definition ojph_img_io.h:806
ojph::pfm_out::cur_line
ui32 cur_line
Definition ojph_img_io.h:812
ojph::pfm_out::fh
FILE * fh
Definition ojph_img_io.h:805
ojph::pfm_out::num_components
ui32 num_components
Definition ojph_img_io.h:809
ojph::pfm_out::open
void open(char *filename)
Definition ojph_img_io.cpp:726
ojph::pfm_out::buffer_size
size_t buffer_size
Definition ojph_img_io.h:808
ojph::pfm_out::scale
float scale
Definition ojph_img_io.h:810
ojph::pfm_out::configure
void configure(ui32 width, ui32 height, ui32 num_components, float scale, ui32 *bit_depth)
Definition ojph_img_io.cpp:746
ojph::pfm_out::write
virtual ui32 write(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:762
ojph::pfm_out::bit_depth
ui32 bit_depth[3]
Definition ojph_img_io.h:811
ojph::pfm_out::height
ui32 height
Definition ojph_img_io.h:809
ojph::pfm_out::start_of_data
si64 start_of_data
Definition ojph_img_io.h:813
ojph::pfm_out::buffer
float * buffer
Definition ojph_img_io.h:807
ojph::pfm_out::width
ui32 width
Definition ojph_img_io.h:809
ojph::ppm_in::open
void open(const char *filename)
Definition ojph_img_io.cpp:245
ojph::ppm_in::width
ui32 width
Definition ojph_img_io.h:132
ojph::ppm_in::num_ele_per_line
ui32 num_ele_per_line
Definition ojph_img_io.h:133
ojph::ppm_in::planar
bool planar
Definition ojph_img_io.h:138
ojph::ppm_in::bytes_per_sample
ui32 bytes_per_sample
Definition ojph_img_io.h:133
ojph::ppm_in::max_val_num_bits
ui32 max_val_num_bits
Definition ojph_img_io.h:132
ojph::ppm_in::fname
const char * fname
Definition ojph_img_io.h:129
ojph::ppm_in::finalize_alloc
void finalize_alloc()
Definition ojph_img_io.cpp:326
ojph::ppm_in::height
ui32 height
Definition ojph_img_io.h:132
ojph::ppm_in::num_comps
ui32 num_comps
Definition ojph_img_io.h:132
ojph::ppm_in::temp_buf_byte_size
ui32 temp_buf_byte_size
Definition ojph_img_io.h:134
ojph::ppm_in::temp_buf
void * temp_buf
Definition ojph_img_io.h:131
ojph::ppm_in::close
void close()
Definition ojph_img_io.h:112
ojph::ppm_in::fh
FILE * fh
Definition ojph_img_io.h:128
ojph::ppm_in::alloc_p
mem_fixed_allocator * alloc_p
Definition ojph_img_io.h:130
ojph::ppm_in::cur_line
ui32 cur_line
Definition ojph_img_io.h:136
ojph::ppm_in::start_of_data
si64 start_of_data
Definition ojph_img_io.h:137
ojph::ppm_in::bit_depth
ui32 bit_depth[3]
Definition ojph_img_io.h:139
ojph::ppm_in::read
virtual ui32 read(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:338
ojph::ppm_in::max_val
ui32 max_val
Definition ojph_img_io.h:132
ojph::ppm_out::num_components
ui32 num_components
Definition ojph_img_io.h:621
ojph::ppm_out::fname
const char * fname
Definition ojph_img_io.h:620
ojph::ppm_out::height
ui32 height
Definition ojph_img_io.h:621
ojph::ppm_out::width
ui32 width
Definition ojph_img_io.h:621
ojph::ppm_out::open
void open(char *filename)
Definition ojph_img_io.cpp:386
ojph::ppm_out::write
virtual ui32 write(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:539
ojph::ppm_out::cur_line
ui32 cur_line
Definition ojph_img_io.h:625
ojph::ppm_out::fh
FILE * fh
Definition ojph_img_io.h:619
ojph::ppm_out::bit_depth
ui32 bit_depth
Definition ojph_img_io.h:622
ojph::ppm_out::bytes_per_line
ui32 bytes_per_line
Definition ojph_img_io.h:625
ojph::ppm_out::bytes_per_sample
ui32 bytes_per_sample
Definition ojph_img_io.h:622
ojph::ppm_out::lptr
const line_buf * lptr[3]
Definition ojph_img_io.h:627
ojph::ppm_out::converter
conversion_fun converter
Definition ojph_img_io.h:626
ojph::ppm_out::configure
void configure(ui32 width, ui32 height, ui32 num_components, ui32 bit_depth)
Definition ojph_img_io.cpp:446
ojph::ppm_out::samples_per_line
ui32 samples_per_line
Definition ojph_img_io.h:625
ojph::ppm_out::buffer_size
size_t buffer_size
Definition ojph_img_io.h:624
ojph::ppm_out::buffer
ui8 * buffer
Definition ojph_img_io.h:623
ojph::raw_in::close
void close()
Definition ojph_img_io.h:431
ojph::raw_in::bytes_per_sample
ui32 bytes_per_sample
Definition ojph_img_io.h:442
ojph::raw_in::is_signed
bool is_signed
Definition ojph_img_io.h:443
ojph::raw_in::bit_depth
ui32 bit_depth
Definition ojph_img_io.h:441
ojph::raw_in::width
ui32 width
Definition ojph_img_io.h:441
ojph::raw_in::buffer
void * buffer
Definition ojph_img_io.h:445
ojph::raw_in::cur_line
ui32 cur_line
Definition ojph_img_io.h:444
ojph::raw_in::set_img_props
void set_img_props(const size &s, ui32 bit_depth, bool is_signed)
Definition ojph_img_io.cpp:1591
ojph::raw_in::buffer_size
size_t buffer_size
Definition ojph_img_io.h:446
ojph::raw_in::fname
const char * fname
Definition ojph_img_io.h:440
ojph::raw_in::fh
FILE * fh
Definition ojph_img_io.h:439
ojph::raw_in::open
void open(const char *filename)
Definition ojph_img_io.cpp:1495
ojph::raw_in::read
virtual ui32 read(const line_buf *line, ui32 comp_num=0)
Definition ojph_img_io.cpp:1510
ojph::raw_out::open
void open(char *filename)
Definition ojph_img_io.cpp:1622
ojph::raw_out::configure
void configure(bool is_signed, ui32 bit_depth, ui32 width)
Definition ojph_img_io.cpp:1632
ojph::raw_out::close
virtual void close()
Definition ojph_img_io.h:756
ojph::raw_out::lower_val
si64 lower_val
Definition ojph_img_io.h:763
ojph::raw_out::upper_val
si64 upper_val
Definition ojph_img_io.h:763
ojph::raw_out::fh
FILE * fh
Definition ojph_img_io.h:759
ojph::raw_out::width
ui32 width
Definition ojph_img_io.h:764
ojph::raw_out::~raw_out
virtual ~raw_out()
Definition ojph_img_io.cpp:1610
ojph::raw_out::bit_depth
ui32 bit_depth
Definition ojph_img_io.h:762
ojph::raw_out::buffer_size
ui32 buffer_size
Definition ojph_img_io.h:766
ojph::raw_out::is_signed
bool is_signed
Definition ojph_img_io.h:761
ojph::raw_out::fname
const char * fname
Definition ojph_img_io.h:760
ojph::raw_out::buffer
ui8 * buffer
Definition ojph_img_io.h:765
ojph::raw_out::write
virtual ui32 write(const line_buf *line, ui32 comp_num=0)
Definition ojph_img_io.cpp:1653
ojph::raw_out::bytes_per_sample
ui32 bytes_per_sample
Definition ojph_img_io.h:762
ojph::yuv_in::width
ui32 width[3]
Definition ojph_img_io.h:391
ojph::yuv_in::read
virtual ui32 read(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:1321
ojph::yuv_in::height
ui32 height[3]
Definition ojph_img_io.h:391
ojph::yuv_in::open
void open(const char *filename)
Definition ojph_img_io.cpp:1296
ojph::yuv_in::temp_buf
void * temp_buf
Definition ojph_img_io.h:390
ojph::yuv_in::fname
const char * fname
Definition ojph_img_io.h:389
ojph::yuv_in::set_img_props
void set_img_props(const size &s, ui32 num_components, ui32 num_downsampling, const point *downsampling)
Definition ojph_img_io.cpp:1351
ojph::yuv_in::set_bit_depth
void set_bit_depth(ui32 num_bit_depths, ui32 *bit_depth)
Definition ojph_img_io.cpp:1378
ojph::yuv_in::bytes_per_sample
ui32 bytes_per_sample[3]
Definition ojph_img_io.h:392
ojph::yuv_in::subsampling
point subsampling[3]
Definition ojph_img_io.h:398
ojph::yuv_in::close
void close()
Definition ojph_img_io.h:377
ojph::yuv_in::num_com
ui32 num_com
Definition ojph_img_io.h:391
ojph::yuv_in::fh
FILE * fh
Definition ojph_img_io.h:388
ojph::yuv_in::bit_depth
ui32 bit_depth[3]
Definition ojph_img_io.h:397
ojph::yuv_in::comp_address
ui32 comp_address[3]
Definition ojph_img_io.h:393
ojph::yuv_out::buffer
ui8 * buffer
Definition ojph_img_io.h:726
ojph::yuv_out::fname
const char * fname
Definition ojph_img_io.h:721
ojph::yuv_out::open
void open(char *filename)
Definition ojph_img_io.cpp:1418
ojph::yuv_out::comp_width
ui32 * comp_width
Definition ojph_img_io.h:725
ojph::yuv_out::num_components
ui32 num_components
Definition ojph_img_io.h:723
ojph::yuv_out::configure
void configure(ui32 bit_depth, ui32 num_components, ui32 *comp_width)
Definition ojph_img_io.cpp:1428
ojph::yuv_out::buffer_size
ui32 buffer_size
Definition ojph_img_io.h:727
ojph::yuv_out::close
virtual void close()
Definition ojph_img_io.h:717
ojph::yuv_out::~yuv_out
virtual ~yuv_out()
Definition ojph_img_io.cpp:1401
ojph::yuv_out::fh
FILE * fh
Definition ojph_img_io.h:720
ojph::yuv_out::write
virtual ui32 write(const line_buf *line, ui32 comp_num)
Definition ojph_img_io.cpp:1447
ojph::yuv_out::bit_depth
ui32 bit_depth
Definition ojph_img_io.h:724
ojph
Definition ojph_img_io.h:52
ojph::sse41_cvrt_32b3c_to_8ub3c
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)
ojph::ojph_fseek
int ojph_fseek(FILE *stream, si64 offset, int origin)
Definition ojph_file.h:61
ojph::eat_white_spaces
static void eat_white_spaces(FILE *fh)
Definition ojph_img_io.cpp:72
ojph::ojph_ftell
si64 ojph_ftell(FILE *stream)
Definition ojph_file.h:66
ojph::si64
int64_t si64
Definition ojph_defs.h:57
ojph::gen_cvrt_32b3c_to_16ub3c_le
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)
Definition ojph_img_io.cpp:163
ojph::avx2_cvrt_32b3c_to_8ub3c
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)
ojph::si8
int8_t si8
Definition ojph_defs.h:51
ojph::ui16
uint16_t ui16
Definition ojph_defs.h:52
ojph::gen_cvrt_32b1c_to_16ub1c_le
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)
Definition ojph_img_io.cpp:145
ojph::sse41_cvrt_32b1c_to_16ub1c_be
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)
ojph::avx2_cvrt_32b1c_to_16ub1c_be
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)
ojph::sse41_cvrt_32b1c_to_8ub1c
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)
ojph::avx2_cvrt_32b1c_to_8ub1c
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)
ojph::gen_cvrt_32b3c_to_16ub3c_be
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)
Definition ojph_img_io.cpp:208
ojph::be2le
static ui16 be2le(const ui16 v)
Definition ojph_img_io.cpp:55
ojph::get_cpu_ext_level
OJPH_EXPORT int get_cpu_ext_level()
Definition ojph_arch.cpp:265
ojph::count_leading_zeros
static ui32 count_leading_zeros(ui32 val)
Definition ojph_arch.h:189
ojph::gen_cvrt_32b1c_to_8ub1c
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
ojph::si32
int32_t si32
Definition ojph_defs.h:55
ojph::sse41_cvrt_32b3c_to_16ub3c_be
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)
ojph::si16
int16_t si16
Definition ojph_defs.h:53
ojph::X86_CPU_EXT_LEVEL_AVX2
@ X86_CPU_EXT_LEVEL_AVX2
Definition ojph_arch.h:154
ojph::X86_CPU_EXT_LEVEL_SSE41
@ X86_CPU_EXT_LEVEL_SSE41
Definition ojph_arch.h:151
ojph::ui32
uint32_t ui32
Definition ojph_defs.h:54
ojph::ui8
uint8_t ui8
Definition ojph_defs.h:50
ojph::gen_cvrt_32b1c_to_16ub1c_be
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)
Definition ojph_img_io.cpp:190
ojph::gen_cvrt_32b3c_to_8ub3c
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)
Definition ojph_img_io.cpp:118
ojph_max
#define ojph_max(a, b)
Definition ojph_defs.h:73
ojph_div_ceil
#define ojph_div_ceil(a, b)
Definition ojph_defs.h:70
ojph_unused
#define ojph_unused(x)
Definition ojph_defs.h:78
ojph_file.h
ojph_img_io.h
ojph_mem.h
ojph_message.h
OJPH_ERROR
#define OJPH_ERROR(t,...)
Definition ojph_message.h:288
OJPH_WARN
#define OJPH_WARN(t,...)
Definition ojph_message.h:286
ojph::point
Definition ojph_base.h:58
ojph::size
Definition ojph_base.h:48
ojph::size::w
ui32 w
Definition ojph_base.h:50
ojph::size::h
ui32 h
Definition ojph_base.h:51