satdump/src-core/common/image/image.cpp
2023-03-07 00:47:44 +01:00

231 lines
No EOL
6.4 KiB
C++

#include "image.h"
#include <cstring>
#include <limits>
#include <fstream>
namespace image
{
template <typename T>
void Image<T>::init(size_t width, size_t height, int channels)
{
// Reset image if we already had one
if (has_data)
delete[] d_data;
// Init buffer
data_size = width * height * channels;
d_data = new T[data_size];
// Set to 0
memset(d_data, 0, sizeof(T) * data_size);
// Init local variables
d_depth = sizeof(T) * 8;
d_width = width;
d_height = height;
d_channels = channels;
// We have data now if we didn't already
has_data = true;
}
template <typename T>
void Image<T>::clear()
{
// Reset image
if (has_data)
delete[] d_data;
has_data = false;
}
template <typename T>
Image<T>::Image()
{
// Do nothing
}
template <typename T>
Image<T>::Image(size_t width, size_t height, int channels)
{
init(width, height, channels);
}
template <typename T>
Image<T>::Image(const Image &img)
{
// Copy contents of the image over
init(img.d_width, img.d_height, img.d_channels);
memcpy(d_data, img.d_data, img.data_size * sizeof(T));
}
template <typename T>
Image<T>::Image(T *buffer, size_t width, size_t height, int channels)
{
// Copy contents of the image over
init(width, height, channels);
memcpy(d_data, buffer, data_size * sizeof(T));
}
template <typename T>
Image<T> &Image<T>::operator=(const Image<T> &img)
{
// Copy contents of the image over
init(img.d_width, img.d_height, img.d_channels);
memcpy(d_data, img.d_data, img.data_size * sizeof(T));
return *this;
}
template <typename T>
Image<T> &Image<T>::operator<<=(const int &shift)
{
for (size_t i = 0; i < data_size; i++)
d_data[i] <<= shift;
return *this;
}
template <typename T>
Image<T>::~Image()
{
if (has_data)
delete[] d_data;
if (has_font){
font.chars.clear();
font.bitmaps.clear();
font.wh.clear();
}
}
template <typename T>
T Image<T>::clamp(int input)
{
if (input > std::numeric_limits<T>::max())
return std::numeric_limits<T>::max();
else if (input < 0)
return 0;
else
return input;
}
template <typename T>
void Image<T>::to_rgb()
{
if (d_channels == 1)
{
Image<T> tmp = *this; // Backup image
init(d_width, d_height, 3); // Init new image as RGB
// Fill in all 3 channels
draw_image(0, tmp);
draw_image(1, tmp);
draw_image(2, tmp);
}
else if (d_channels == 4)
{
Image<T> tmp = *this; // Backup image
init(d_width, d_height, 3); // Init new image as RGB
// Copy over all 3 channels
memcpy(d_data, tmp.data(), d_width * d_height * 3 * sizeof(T));
}
}
template <typename T>
void Image<T>::to_rgba()
{
if (d_channels == 1)
{
Image<T> tmp = *this; // Backup image
init(d_width, d_height, 4); // Init new image as RGBA
// Copy over all 3 channels
memcpy(&d_data[d_width * d_height * 0], tmp.data(), d_width * d_height * sizeof(T));
memcpy(&d_data[d_width * d_height * 1], tmp.data(), d_width * d_height * sizeof(T));
memcpy(&d_data[d_width * d_height * 2], tmp.data(), d_width * d_height * sizeof(T));
for (size_t i = 0; i < d_width * d_height; i++)
channel(3)[i] = std::numeric_limits<T>::max();
}
else if (d_channels == 3)
{
Image<T> tmp = *this; // Backup image
init(d_width, d_height, 4); // Init new image as RGBA
// Copy over all 3 channels
memcpy(d_data, tmp.data(), d_width * d_height * 3 * sizeof(T));
// Fill in RGBA
for (size_t i = 0; i < d_width * d_height; i++)
channel(3)[i] = std::numeric_limits<T>::max();
}
}
template <typename T>
Image<uint8_t> Image<T>::to8bits()
{
if (d_depth == 8)
{
return *((image::Image<uint8_t> *)this);
}
else if (d_depth == 16)
{
image::Image<uint8_t> image8(d_width, d_height, d_channels);
for (size_t i = 0; i < data_size; i++)
image8[i] = d_data[i] >> 8;
return image8;
}
return Image<uint8_t>(); // This should never happen
}
template <typename T>
Image<uint16_t> Image<T>::to16bits()
{
if (d_depth == 16)
{
return *((image::Image<uint16_t> *)this);
}
else if (d_depth == 8)
{
image::Image<uint16_t> image16(d_width, d_height, d_channels);
for (size_t i = 0; i < data_size; i++)
image16[i] = d_data[i] << 8;
return image16;
}
return Image<uint16_t>(); // This should never happen
}
template <typename T>
void Image<T>::load_img(std::string file)
{
std::ifstream file_sigature_src(file, std::ios::binary);
uint8_t signature[10];
file_sigature_src.read((char *)signature, 10);
if (signature[0] == 0xFF && signature[1] == 0xD8)
load_jpeg(file);
else if (signature[0] == 0x89 && signature[1] == 0x50 && signature[2] == 0x4E && signature[3] == 0x47)
load_png(file);
}
template <typename T>
void Image<T>::load_img(uint8_t *buffer, int size)
{
if (buffer[0] == 0xFF && buffer[1] == 0xD8)
load_jpeg(buffer, size);
else if (buffer[0] == 0x89 && buffer[1] == 0x50 && buffer[2] == 0x4E && buffer[3] == 0x47)
load_png(buffer, size);
}
template <typename T>
void Image<T>::save_img(std::string file)
{
if (file.find(".png") != std::string::npos)
save_png(file);
else if (file.find(".jpeg") != std::string::npos || file.find(".jpg") != std::string::npos)
save_jpeg(file);
}
// Generate Images for uint16_t and uint8_t
template class Image<uint8_t>;
template class Image<uint16_t>;
}