Current section

Files

Jump to
cimg src CImgEx.h
Raw

src/CImgEx.h

#ifndef cimg_plugin
#define cimg_plugin "CImgEx.h"
#include <vector>
#define STBI_NO_BMP
#define STBI_NO_PSD
#define STBI_NO_TGA
#define STBI_NO_GIF
#define STBI_NO_HDR
#define STBI_NO_PIC
#define STBI_NO_PNM
#include "stb_image.h"
#include "stb_image_write.h"
#define cimg_load_plugin(filename) \
if (!cimg::strcasecmp(ext,"jpg") \
|| !cimg::strcasecmp(ext,"jpeg") \
|| !cimg::strcasecmp(ext,"jpe") \
|| !cimg::strcasecmp(ext,"jfif") \
|| !cimg::strcasecmp(ext,"jif") \
|| !cimg::strcasecmp(ext,"png")) return load_from_file(filename);
#define cimg_save_plugin(filename) \
if (!cimg::strcasecmp(ext,"jpg") \
|| !cimg::strcasecmp(ext,"jpeg") \
|| !cimg::strcasecmp(ext,"jpe") \
|| !cimg::strcasecmp(ext,"jfif") \
|| !cimg::strcasecmp(ext,"jif") \
|| !cimg::strcasecmp(ext,"png")) return save_to_file(filename); \
#ifndef STB_IMAGE_WRITE_IMPLEMENTATION
void stbi_write_vector(void* context, void* data, int size);
#else
void stbi_write_vector(void* context, void* data, int size)
{
auto ptr = reinterpret_cast<unsigned char*>(data);
auto mem = reinterpret_cast<std::vector<unsigned char>*>(context);
for (int i = 0; i < size; i++) {
mem->push_back(*ptr++);
}
}
#endif
#include "CImg.h"
#else
/**************************************************************************}}}*/
/*** CImg Plugins: ***/
/**************************************************************************{{{*/
CImg<T>& load_from_file(const char *const filename)
{
int x, y, n;
unsigned char* data = stbi_load(filename, &x, &y, &n, 0);
if (data == NULL) {
throw CImgIOException(_cimg_instance
"load_from_file: %s.",
cimg_instance, stbi_failure_reason());
}
try { assign(x, y, 1, n); } catch (...) { throw; }
read_hwc_from(data);
stbi_image_free(data);
return *this;
}
CImg<T>& load_from_memory(unsigned char const *buffer, int len)
{
int x, y, n;
unsigned char* data = stbi_load_from_memory(buffer, len, &x, &y, &n, 0);
if (data == NULL) {
throw CImgIOException(_cimg_instance
"load_from_memory: %s.",
cimg_instance, stbi_failure_reason());
}
try { assign(x, y, 1, n); } catch (...) { throw; }
read_hwc_from(data);
stbi_image_free(data);
return *this;
}
void read_hwc_from(const unsigned char* ptrs)
{
switch (_spectrum) {
case 1: {
T *ptr_r = _data;
cimg_forXY(*this, x, y) {
*(ptr_r++) = (T)*(ptrs++);
}
}
break;
case 3: {
T *ptr_r = _data,
*ptr_g = _data + 1UL*_width*_height,
*ptr_b = _data + 2UL*_width*_height;
cimg_forXY(*this, x, y) {
*(ptr_r++) = (T)*(ptrs++);
*(ptr_g++) = (T)*(ptrs++);
*(ptr_b++) = (T)*(ptrs++);
}
}
break;
case 4: {
T *ptr_r = _data,
*ptr_g = _data + 1UL*_width*_height,
*ptr_b = _data + 2UL*_width*_height,
*ptr_a = _data + 3UL*_width*_height;
cimg_forXY(*this, x, y) {
*(ptr_r++) = (T)*(ptrs++);
*(ptr_g++) = (T)*(ptrs++);
*(ptr_b++) = (T)*(ptrs++);
*(ptr_a++) = (T)*(ptrs++);
}
}
break;
}
}
const CImg<T>& save_to_file(const char *const filename) const
{
if (is_empty()) { return *this; }
if (_depth > 1) {
cimg::warn(_cimg_instance
"save_to_file(): Instance is volumetric, only the first slice will be saved in file '%s'.",
cimg_instance,
filename);
}
unsigned char *buff = reinterpret_cast<unsigned char*>(malloc(_width*_height*_spectrum));
if (buff == NULL) {
throw CImgIOException(_cimg_instance
"save_to_file: Failed to allocate memory for work.",
cimg_instance);
}
write_hwc_to(buff);
const char *const ext = cimg::split_filename(filename);
if (cimg::strcasecmp(ext,"png") == 0) {
stbi_write_png(filename, _width, _height, _spectrum, buff, 0);
}
else {
stbi_write_jpg(filename, _width, _height, _spectrum, buff, 100);
}
return *this;
}
std::vector<unsigned char> save_to_memory(const char *const format) const
{
std::vector<unsigned char> mem;
if (is_empty()) { return mem; }
if (_depth > 1) {
cimg::warn(_cimg_instance
"save_to_file(): Instance is volumetric, only the first slice will be save to memory.",
cimg_instance);
}
unsigned char *buff = reinterpret_cast<unsigned char*>(malloc(_width*_height*_spectrum));
if (buff == NULL) {
throw CImgIOException(_cimg_instance
"save_to_memory: Failed to allocate memory for work.",
cimg_instance);
}
write_hwc_to(buff);
if (cimg::strcasecmp(format, "png") == 0) {
stbi_write_png_to_func(stbi_write_vector, &mem, _width, _height, _spectrum, buff, 0);
}
else if (cimg::strcasecmp(format, "jpeg") == 0) {
stbi_write_jpg_to_func(stbi_write_vector, &mem, _width, _height, _spectrum, buff, 100);
}
return mem;
}
void write_hwc_to(unsigned char* ptrd) const
{
switch (_spectrum) {
case 1: {
const T *ptr_g = data(0, 0, 0, 0);
cimg_forXY(*this, x, y) {
*(ptrd++) = (unsigned char)*(ptr_g++);
}
}
break;
case 3: {
const T *ptr_r = data(0, 0, 0, 0),
*ptr_g = data(0, 0, 0, 1),
*ptr_b = data(0, 0, 0, 2);
cimg_forXY(*this, x, y) {
*(ptrd++) = (unsigned char)*(ptr_r++);
*(ptrd++) = (unsigned char)*(ptr_g++);
*(ptrd++) = (unsigned char)*(ptr_b++);
}
}
break;
case 4: {
const T *ptr_r = data(0, 0, 0, 0),
*ptr_g = data(0, 0, 0, 1),
*ptr_b = data(0, 0, 0, 2),
*ptr_a = data(0, 0, 0, 3);
cimg_forXY(*this, x, y) {
*(ptrd++) = (unsigned char)*(ptr_r++);
*(ptrd++) = (unsigned char)*(ptr_g++);
*(ptrd++) = (unsigned char)*(ptr_b++);
*(ptrd++) = (unsigned char)*(ptr_a++);
}
}
break;
}
}
// option: image convert POSI/NEGA
enum {
cPOSI = 0,
cNEGA
};
// create the GRAY image
CImg<T> getRGBtoGRAY(int optPN=cPOSI)
{
if (_spectrum != 3) {
throw CImgInstanceException(_cimg_instance
"makeGRAY(): Instance is not a RGB image.",
cimg_instance);
}
CImg<T> res(width(), height(), depth(), 1);
T *R = data(0,0,0,0), *G = data(0,0,0,1), *B = data(0,0,0,2), *Y = res.data(0,0,0,0);
const longT whd = (longT)width()*height()*depth();
cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256))
for (longT i = 0; i < whd; i++) {
Y[i] = (T)(0.299f*R[i] + 0.587f*G[i] + 0.114f*B[i]);
if (optPN == cNEGA) {
Y[i] = cimg::type<T>::max() - Y[i];
}
}
return res;
}
CImg<T> RGBtoGRAY(int optPN=cPOSI)
{
return assign(getRGBtoGRAY(cPOSI));
}
#endif