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>
62 int width = 0, height = 0, channels = 0;
63 unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_grey);
64 if (image ==
nullptr) {
67 I.
init(image,
static_cast<unsigned int>(height),
static_cast<unsigned int>(width),
true);
68 stbi_image_free(image);
73 int width = 0, height = 0, channels = 0;
74 unsigned char *image = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
75 if (image ==
nullptr) {
78 I.
init(
reinterpret_cast<vpRGBa *
>(image),
static_cast<unsigned int>(height),
static_cast<unsigned int>(width),
true);
79 stbi_image_free(image);
84 int res = stbi_write_jpg(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()), STBI_grey,
85 reinterpret_cast<void *
>(I.
bitmap), quality);
91 void writeJPEGStb(
const vpImage<vpRGBa> &I,
const std::string &filename,
int quality)
93 int res = stbi_write_jpg(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()),
94 STBI_rgb_alpha,
reinterpret_cast<void *
>(I.
bitmap), quality);
102 const int stride_in_bytes =
static_cast<int>(I.
getWidth());
103 int res = stbi_write_png(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()), STBI_grey,
104 reinterpret_cast<void *
>(I.
bitmap), stride_in_bytes);
110 void writePNGStb(
const vpImage<vpRGBa> &I,
const std::string &filename)
112 const int stride_in_bytes =
static_cast<int>(4 * I.
getWidth());
113 int res = stbi_write_png(filename.c_str(),
static_cast<int>(I.
getWidth()),
static_cast<int>(I.
getHeight()),
114 STBI_rgb_alpha,
reinterpret_cast<void *
>(I.
bitmap), stride_in_bytes);
126 } custom_stbi_mem_context;
129 static void custom_stbi_write_mem(
void *context,
void *data,
int size)
131 custom_stbi_mem_context *c = (custom_stbi_mem_context *)context;
132 char *dst = (
char *)c->context;
133 char *src = (
char *)data;
134 int cur_pos = c->last_pos;
135 for (
int i = 0; i < size; ++i) {
136 dst[cur_pos++] = src[i];
138 c->last_pos = cur_pos;
150 int x = 0, y = 0, comp = 0;
151 const int req_channels = 1;
152 unsigned char *buffer_read = stbi_load_from_memory(buffer.data(),
static_cast<int>(buffer.size()), &x, &y, &comp, req_channels);
153 assert(comp == req_channels);
155 I.
init(buffer_read, y, x,
true);
156 STBI_FREE(buffer_read);
165 void readPNGfromMemStb(
const std::vector<unsigned char> &buffer,
vpImage<vpRGBa> &I_color)
167 int x = 0, y = 0, comp = 0;
168 unsigned char *buffer_read = stbi_load_from_memory(buffer.data(),
static_cast<int>(buffer.size()), &x, &y, &comp, 0);
171 const bool copyData =
true;
172 I_color.
init(
reinterpret_cast<vpRGBa *
>(buffer_read), y, x, copyData);
174 else if (comp == 3) {
176 const bool flip =
false;
180 STBI_FREE(buffer_read);
182 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
183 std::string message =
"Wrong number of channels for the input buffer: " + std::to_string(comp);
190 STBI_FREE(buffer_read);
201 const int height = I.
getRows();
203 const int channels = 1;
205 custom_stbi_mem_context context;
206 context.last_pos = 0;
208 context.context = (
void *)buffer.data();
210 const int stride_bytes = 0;
211 int result = stbi_write_png_to_func(custom_stbi_write_mem, &context, width, height, channels, I.
bitmap, stride_bytes);
214 buffer.resize(context.last_pos);
217 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
218 std::string message =
"Cannot write png to memory, result: " + std::to_string(result);
233 void writePNGtoMemStb(
const vpImage<vpRGBa> &I_color, std::vector<unsigned char> &buffer,
bool saveAlpha)
235 const int height = I_color.
getRows();
236 const int width = I_color.
getCols();
237 const int channels = saveAlpha ? 4 : 3;
239 custom_stbi_mem_context context;
240 context.last_pos = 0;
241 buffer.resize(height * width * channels);
242 context.context = (
void *)buffer.data();
244 const int stride_bytes = 0;
247 result = stbi_write_png_to_func(custom_stbi_write_mem, &context, width, height, channels,
248 reinterpret_cast<unsigned char *
>(I_color.
bitmap), stride_bytes);
251 unsigned char *bitmap =
new unsigned char[height * width * channels];
253 result = stbi_write_png_to_func(custom_stbi_write_mem, &context, width, height, channels, bitmap, stride_bytes);
258 buffer.resize(context.last_pos);
261 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
262 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