-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrtw_stb_image.h
More file actions
122 lines (97 loc) · 4 KB
/
rtw_stb_image.h
File metadata and controls
122 lines (97 loc) · 4 KB
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
117
118
119
120
121
122
#ifndef RTW_STB_IMAGE_H
#define RTW_STB_IMAGE_H
#ifdef _MSC_VER
#pragma warning (push, 0)
#include <Windows.h>
#pragma warning (disable : 4996)
#pragma warning (disable : 4244)
#endif
#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
#include "stb_image.h"
#include <cstdlib>
#include <iostream>
#include <string>
class rtw_image {
public:
rtw_image() {}
rtw_image(const char* image_filename) {
// Loads image data from the specified file. If the RTW_IMAGES environment variable is
// defined, looks only in that directory for the image file. If the image was not found,
// searches for the specified image file first from the current directory, then in the
// images/ subdirectory, then the _parent's_ images/ subdirectory, and then _that_
// parent, on so on, for six levels up. If the image was not loaded successfully,
// width() and height() will return 0.
auto filename = std::string(image_filename);
// This call to getenv is now safe because we disabled warning 4996 above
auto imagedir = getenv("RTW_IMAGES");
// Hunt for the image file in some likely locations.
if (imagedir && load(std::string(imagedir) + "/" + image_filename)) return;
if (load(filename)) return;
if (load("images/" + filename)) return;
if (load("../images/" + filename)) return;
if (load("../../images/" + filename)) return;
if (load("../../../images/" + filename)) return;
if (load("../../../../images/" + filename)) return;
if (load("../../../../../images/" + filename)) return;
if (load("../../../../../../images/" + filename)) return;
std::cerr << "ERROR: Could not load image file '" << image_filename << "'.\n";
}
~rtw_image() {
delete[] bdata;
STBI_FREE(fdata);
}
bool load(const std::string& filename) {
// Loads the linear (gamma=1) image data from the given file name. Returns true if the
// load succeeded. The resulting data buffer contains the three [0.0, 1.0]
// floating-point values for the first pixel (red, then green, then blue). Pixels are
// contiguous, going left to right for the width of the image, followed by the next row
// below, for the full height of the image.
auto n = bytes_per_pixel;
fdata = stbi_loadf(filename.c_str(), &image_width, &image_height, &n, bytes_per_pixel);
if (fdata == nullptr) return false;
bytes_per_scanline = image_width * bytes_per_pixel;
convert_to_bytes();
return true;
}
int width() const { return (fdata == nullptr) ? 0 : image_width; }
int height() const { return (fdata == nullptr) ? 0 : image_height; }
const unsigned char* pixel_data(int x, int y) const {
static unsigned char magenta[] = { 255, 0, 255 };
if (bdata == nullptr) return magenta;
x = clamp(x, 0, image_width);
y = clamp(y, 0, image_height);
return bdata + y * bytes_per_scanline + x * bytes_per_pixel;
}
private:
const int bytes_per_pixel = 3;
float* fdata = nullptr;
unsigned char* bdata = nullptr;
int image_width = 0;
int image_height = 0;
int bytes_per_scanline = 0;
static int clamp(int x, int low, int high) {
if (x < low) return low;
if (x < high) return x;
return high - 1;
}
static unsigned char float_to_byte(float value) {
if (value <= 0.0)
return 0;
if (1.0 <= value)
return 255;
return static_cast<unsigned char>(256.0 * value);
}
void convert_to_bytes() {
int total_bytes = image_width * image_height * bytes_per_pixel;
bdata = new unsigned char[total_bytes];
auto* bptr = bdata;
auto* fptr = fdata;
for (auto i = 0; i < total_bytes; i++, fptr++, bptr++)
*bptr = float_to_byte(*fptr);
}
};
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif