3 #include "utils/PVLog.hpp" 6 #ifndef STB_IMAGE_IMPLEMENTATION 7 #define STB_IMAGE_IMPLEMENTATION 8 #include "io/stb_image.h" 10 #ifndef STB_IMAGE_WRITE_IMPLEMENTATION 11 #define STB_IMAGE_WRITE_IMPLEMENTATION 12 #include "io/stb_image_write.h" 19 Image::Image(std::string filename) { read(filename); }
21 Image::Image(
const std::vector<float> &data,
int width,
int height,
int channels) {
22 set(data, width, height, channels);
25 void Image::setPixel(
int x,
int y,
float r,
float g,
float b) {
26 if (getFeatures() > mRPos) {
29 if (getFeatures() > mGPos) {
32 if (getFeatures() > mBPos) {
37 void Image::setPixel(
int x,
int y,
float r,
float g,
float b,
float a) {
38 setPixel(x, y, r, g, b);
42 float Image::getPixelR(
int x,
int y) {
43 if (getFeatures() <= mRPos) {
46 return at(x, y, mRPos);
49 float Image::getPixelG(
int x,
int y) {
50 if (getFeatures() <= mGPos) {
53 return at(x, y, mGPos);
56 float Image::getPixelB(
int x,
int y) {
57 if (getFeatures() <= mBPos) {
60 return at(x, y, mBPos);
63 float Image::getPixelA(
int x,
int y) {
64 if (getFeatures() <= mAPos) {
67 return at(x, y, mAPos);
70 void Image::convertToGray(
bool alphaChannel) {
71 if (getFeatures() < 3) {
72 if ((getFeatures() == 1 && !alphaChannel) || (getFeatures() == 2 && alphaChannel)) {
78 Buffer<float> grayScale(getWidth(), getHeight(), alphaChannel ? 2 : 1);
79 for (
int y = 0; y < getHeight(); ++y) {
80 for (
int x = 0; x < getWidth(); ++x) {
81 grayScale.set(x, y, 0, at(x, y, 0));
83 grayScale.set(x, y, 1, 1.0f);
87 set(grayScale.asVector(), getWidth(), getHeight(), alphaChannel ? 2 : 1);
95 const float rgbWeights[3] = {mRToGray, mGToGray, mBToGray};
96 Buffer<float> grayScale(getWidth(), getHeight(), alphaChannel ? 2 : 1);
98 for (
int y = 0; y < getHeight(); ++y) {
99 for (
int x = 0; x < getWidth(); ++x) {
101 for (
int f = 0; f < 3; ++f) {
102 sum += at(x, y, f) * rgbWeights[f];
104 grayScale.set(x, y, 0, sum);
106 if (getFeatures() > 3) {
107 grayScale.set(x, y, 1, at(x, y, 3));
110 grayScale.set(x, y, 1, 1.0f);
115 set(grayScale.asVector(), getWidth(), getHeight(), alphaChannel ? 2 : 1);
119 void Image::convertToColor(
bool alphaChannel) {
121 if (getFeatures() > 2) {
122 if ((getFeatures() == 3 && !alphaChannel) || (getFeatures() == 4 && alphaChannel)) {
128 Buffer<float> color(getWidth(), getHeight(), alphaChannel ? 4 : 3);
129 for (
int y = 0; y < getHeight(); ++y) {
130 for (
int x = 0; x < getWidth(); ++x) {
131 color.set(x, y, mRPos, at(x, y, mRPos));
132 color.set(x, y, mGPos, at(x, y, mGPos));
133 color.set(x, y, mBPos, at(x, y, mBPos));
135 color.set(x, y, mAPos, 1.0f);
139 set(color.asVector(), getWidth(), getHeight(), alphaChannel ? 4 : 3);
144 Buffer<float> color(getWidth(), getHeight(), alphaChannel ? 4 : 3);
145 for (
int y = 0; y < getHeight(); ++y) {
146 for (
int x = 0; x < getWidth(); ++x) {
147 float val = at(x, y, 0);
148 color.set(x, y, mRPos, val);
149 color.set(x, y, mGPos, val);
150 color.set(x, y, mBPos, val);
152 if (getFeatures() == 2) {
153 color.set(x, y, mAPos, at(x, y, 1));
156 color.set(x, y, mAPos, 1.0f);
161 set(color.asVector(), getWidth(), getHeight(), alphaChannel ? 4 : 3);
165 void Image::read(std::string filename) {
166 int width = 0, height = 0, channels = 0;
167 uint8_t *data = stbi_load(filename.c_str(), &width, &height, &channels, 0);
168 if (data ==
nullptr) {
169 if (!std::strcmp(stbi_failure_reason(),
"unknown image type")) {
171 " File \"%s\" is an unknown image type.\n" 172 " (A list of image files must have a .txt extension;" 173 " an individual image file must be readable by the stb_image library.)\n",
177 Fatal().printf(
"Unable to load \"%s\": %s.\n", filename.c_str(), stbi_failure_reason());
180 FatalIf(data ==
nullptr,
" File not found: %s\n", filename.c_str());
181 resize(width, height, channels);
183 for (
int y = 0; y < height; ++y) {
184 for (
int x = 0; x < width; ++x) {
185 for (
int f = 0; f < channels; ++f) {
186 float value =
static_cast<float>(data[(y * width + x) * channels + f]) / 255.0f;
192 stbi_image_free(data);
195 void Image::write(std::string filename) {
196 std::vector<uint8_t> byteData(getWidth() * getHeight() * getFeatures());
198 float imageMin = 0.0f;
199 float imageMax = 1.0f;
201 for (
int y = 0; y < getHeight(); ++y) {
202 for (
int x = 0; x < getWidth(); ++x) {
203 for (
int f = 0; f < getFeatures(); ++f) {
204 imageMin = at(x, y, f) < imageMin ? at(x, y, f) : imageMin;
205 imageMax = at(x, y, f) > imageMax ? at(x, y, f) : imageMax;
210 for (
int y = 0; y < getHeight(); ++y) {
211 for (
int x = 0; x < getWidth(); ++x) {
212 for (
int f = 0; f < getFeatures(); ++f) {
213 float normVal = (at(x, y, f) - imageMin) / (imageMax - imageMin);
214 byteData.at(byteIndex++) =
static_cast<uint8_t
>(normVal * 255.0f);
225 getWidth() * getFeatures());