-
Notifications
You must be signed in to change notification settings - Fork 0
/
raw.cpp
116 lines (102 loc) · 3.09 KB
/
raw.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) Mathieu Malaterre
// SPDX-License-Identifier: BSD-3-Clause
#include "raw.h"
#include "dest.h"
#include "factory.h"
#include "image.h"
#include "source.h"
#include <cassert>
#include <charls/charls.h>
namespace jlst {
bool raw::handle_type(std::string const& type) const
{
return type == "raw";
}
static charls::frame_info compute_info(size_t const byte_count_file, image_info const& ii)
{
auto fi = ii.frame_info();
assert(fi.width != 0 && fi.height != 0);
const size_t div = byte_count_file % (fi.width * fi.height);
// be nice with user, and compute default bits_per_sample / component_count if not specified:
if (div == 0)
{
// mult is either 1, 2, 3 or 6:
const size_t mult = byte_count_file / (fi.width * fi.height);
if (fi.bits_per_sample == 0)
{
fi.bits_per_sample = mult % 2 == 0 ? 16 : 8;
}
if (fi.component_count == 0)
{
fi.component_count = mult % 3 == 0 ? 3 : 1;
}
}
return fi;
}
static size_t compute_len(charls::frame_info const& i)
{
auto const bytes_per_sample{(i.bits_per_sample + 7) / 8};
const size_t len = i.width * i.height * bytes_per_sample * i.component_count;
return len;
}
bool raw::detect(source& s, image_info const& ii) const
{
auto& fi = ii.frame_info();
if (fi.width == 0 || fi.height == 0)
return false;
const auto byte_count_file = s.size();
auto info = compute_info(byte_count_file, ii);
return byte_count_file == compute_len(info);
}
void raw::read_info(source& s, image& i) const
{
const auto byte_count_file = s.size();
auto& ii = i.get_image_info();
auto& fi = ii.frame_info();
if (fi.width == 0 || fi.height == 0)
throw std::invalid_argument("Missing size");
ii.frame_info() = compute_info(byte_count_file, ii);
if (ii.frame_info().component_count == 3)
{
ii.interleave_mode() = charls::interleave_mode::sample;
}
// now is a good time to compute stride:
auto const bytes_per_sample{(ii.frame_info().bits_per_sample + 7) / 8};
i.get_image_data().stride() = ii.frame_info().width * bytes_per_sample * ii.frame_info().component_count;
}
void raw::read_data(source& ifs, image& i) const
{
auto& pd = i.get_image_data().pixel_data();
ifs.read(pd.data(), pd.size());
}
void raw::write_info(dest&, const image&, const jls_options&) const
{
}
void raw::write_data(dest& fs, const image& img, const jls_options&) const
{
auto& ii = img.get_image_info();
auto& id = img.get_image_data();
auto& pd = id.pixel_data();
auto len = pd.size();
std::vector<unsigned char> buf8(pd);
if (ii.frame_info().bits_per_sample > 8)
{
for (size_t i{}; i < len - 1; i += 2)
{
std::swap(buf8[i], buf8[i + 1]);
}
}
fs.write(buf8.data(), buf8.size());
}
format* raw::clone() const
{
return new raw;
}
static const format* get()
{
static const raw raw_;
return &raw_;
}
// set priority to 0 so that `raw` is always tested last
static bool b = factory::instance().register_format(get(), 0);
} // namespace jlst