39 #include <visp3/core/vpConfig.h>
41 #if defined(VISP_HAVE_STBIMAGE)
43 #include "vpImageIoBackend.h"
44 #include <visp3/core/vpImageConvert.h>
46 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
47 #define VISP_HAVE_SSE2 1
50 #ifndef VISP_HAVE_SSE2
54 #define STB_IMAGE_IMPLEMENTATION
55 #include <stb_image.h>
57 #define STB_IMAGE_WRITE_IMPLEMENTATION
58 #include <stb_image_write.h>
64 int width = 0, height = 0, channels = 0;
65 unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_grey);
66 if (image ==
nullptr) {
69 I.
init(image,
static_cast<unsigned int>(height),
static_cast<unsigned int>(width),
true);
70 stbi_image_free(image);
75 int width = 0, height = 0, channels = 0;
76 unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
77 if (image ==
nullptr) {
80 I.
init(
reinterpret_cast<vpRGBa *
>(image),
static_cast<unsigned int>(height),
static_cast<unsigned int>(width),
true);
81 stbi_image_free(image);
86 int res = stbi_write_jpg(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()), STBI_grey,
87 reinterpret_cast<void *
>(I.
bitmap), quality);
93 void writeJPEGStb(
const vpImage<vpRGBa> &I,
const std::string &filename,
int quality)
95 int res = stbi_write_jpg(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()),
96 STBI_rgb_alpha,
reinterpret_cast<void *
>(I.
bitmap), quality);
104 const int stride_in_bytes =
static_cast<int>(I.
getWidth());
105 int res = stbi_write_png(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()), STBI_grey,
106 reinterpret_cast<void *
>(I.
bitmap), stride_in_bytes);
112 void writePNGStb(
const vpImage<vpRGBa> &I,
const std::string &filename)
114 const int stride_in_bytes =
static_cast<int>(4 * I.
getWidth());
115 int res = stbi_write_png(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()),
116 STBI_rgb_alpha,
reinterpret_cast<void *
>(I.
bitmap), stride_in_bytes);
128 } custom_stbi_mem_context;
131 static void custom_stbi_write_mem(
void *context,
void *data,
int size)
133 custom_stbi_mem_context *c = (custom_stbi_mem_context *)context;
134 char *dst = (
char *)c->context;
135 char *src = (
char *)data;
136 int cur_pos = c->last_pos;
137 for (
int i = 0; i < size; ++i) {
138 dst[cur_pos++] = src[i];
140 c->last_pos = cur_pos;
152 int x = 0, y = 0, comp = 0;
153 const int req_channels = 1;
154 unsigned char *buffer_read = stbi_load_from_memory(buffer.data(),
static_cast<int>(buffer.size()), &x, &y, &comp, req_channels);
155 assert(comp == req_channels);
157 I.
init(buffer_read, y, x,
true);
158 STBI_FREE(buffer_read);
167 void readPNGfromMemStb(
const std::vector<unsigned char> &buffer,
vpImage<vpRGBa> &I_color)
169 int x = 0, y = 0, comp = 0;
170 unsigned char *buffer_read = stbi_load_from_memory(buffer.data(),
static_cast<int>(buffer.size()), &x, &y, &comp, 0);
173 const bool copyData =
true;
174 I_color.
init(
reinterpret_cast<vpRGBa *
>(buffer_read), y, x, copyData);
176 else if (comp == 3) {
178 const bool flip =
false;
182 STBI_FREE(buffer_read);
184 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
185 std::string message =
"Wrong number of channels for the input buffer: " + std::to_string(comp);
192 STBI_FREE(buffer_read);
203 const int height = I.
getRows();
205 const int channels = 1;
207 custom_stbi_mem_context context;
208 context.last_pos = 0;
210 context.context = (
void *)buffer.data();
212 const int stride_bytes = 0;
213 int result = stbi_write_png_to_func(custom_stbi_write_mem, &context, width, height, channels, I.
bitmap, stride_bytes);
216 buffer.resize(context.last_pos);
219 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
220 std::string message =
"Cannot write png to memory, result: " + std::to_string(result);
235 void writePNGtoMemStb(
const vpImage<vpRGBa> &I_color, std::vector<unsigned char> &buffer,
bool saveAlpha)
237 const int height = I_color.
getRows();
238 const int width = I_color.
getCols();
239 const int channels = saveAlpha ? 4 : 3;
241 custom_stbi_mem_context context;
242 context.last_pos = 0;
243 buffer.resize(height * width * channels);
244 context.context = (
void *)buffer.data();
246 const int stride_bytes = 0;
249 result = stbi_write_png_to_func(custom_stbi_write_mem, &context, width, height, channels,
250 reinterpret_cast<unsigned char *
>(I_color.
bitmap), stride_bytes);
253 unsigned char *bitmap =
new unsigned char[height * width * channels];
255 result = stbi_write_png_to_func(custom_stbi_write_mem, &context, width, height, channels, bitmap, stride_bytes);
260 buffer.resize(context.last_pos);
263 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
264 std::string message =
"Cannot write png to memory, result: " + std::to_string(result);
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
Error that can be emitted by the vpImage class and its derivatives.
void init(unsigned int height, unsigned int width)
Set the size of the image.
unsigned int getWidth() const
unsigned int getCols() const
Type * bitmap
points toward the bitmap
unsigned int getHeight() const
unsigned int getRows() const