2020-09-21 17:17:34 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-06-26 15:17:35 +00:00
|
|
|
//
|
2020-09-21 17:17:34 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-26 15:17:35 +00:00
|
|
|
// ImageIO.cpp
|
|
|
|
//
|
|
|
|
// Image I/O functions.
|
|
|
|
//
|
|
|
|
|
2013-05-16 19:26:19 +00:00
|
|
|
#include "ImageIO.h"
|
|
|
|
|
|
|
|
#include "Log.h"
|
2020-09-21 17:17:34 +00:00
|
|
|
|
2017-11-01 22:21:10 +00:00
|
|
|
#include <FreeImage.h>
|
|
|
|
#include <string.h>
|
2013-05-16 19:26:19 +00:00
|
|
|
|
2020-09-04 17:05:48 +00:00
|
|
|
std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char* data,
|
2021-01-15 17:47:01 +00:00
|
|
|
const size_t size, size_t& width, size_t& height)
|
2013-05-16 19:26:19 +00:00
|
|
|
{
|
2020-06-26 15:17:35 +00:00
|
|
|
std::vector<unsigned char> rawData;
|
|
|
|
width = 0;
|
|
|
|
height = 0;
|
2021-01-15 17:47:01 +00:00
|
|
|
FIMEMORY* fiMemory = FreeImage_OpenMemory(const_cast<BYTE*>(data), static_cast<DWORD>(size));
|
2020-06-26 15:17:35 +00:00
|
|
|
|
|
|
|
if (fiMemory != nullptr) {
|
|
|
|
// Detect the filetype from data.
|
|
|
|
FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromMemory(fiMemory);
|
|
|
|
if (format != FIF_UNKNOWN && FreeImage_FIFSupportsReading(format)) {
|
2021-01-15 17:47:01 +00:00
|
|
|
// File type is supported, load image.
|
|
|
|
FIBITMAP* fiBitmap = FreeImage_LoadFromMemory(format, fiMemory);
|
2020-06-26 15:17:35 +00:00
|
|
|
if (fiBitmap != nullptr) {
|
2021-01-15 17:47:01 +00:00
|
|
|
// Loaded. convert to 32-bit if necessary.
|
2020-06-26 15:17:35 +00:00
|
|
|
if (FreeImage_GetBPP(fiBitmap) != 32) {
|
2021-01-15 17:47:01 +00:00
|
|
|
FIBITMAP* fiConverted = FreeImage_ConvertTo32Bits(fiBitmap);
|
2020-06-26 15:17:35 +00:00
|
|
|
if (fiConverted != nullptr) {
|
2021-01-15 17:47:01 +00:00
|
|
|
// Free original bitmap data.
|
2020-06-26 15:17:35 +00:00
|
|
|
FreeImage_Unload(fiBitmap);
|
|
|
|
fiBitmap = fiConverted;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fiBitmap != nullptr) {
|
|
|
|
width = FreeImage_GetWidth(fiBitmap);
|
|
|
|
height = FreeImage_GetHeight(fiBitmap);
|
|
|
|
// Loop through scanlines and add all pixel data to the return vector.
|
|
|
|
// This is necessary, because width*height*bpp might not be == pitch.
|
2021-01-15 17:47:01 +00:00
|
|
|
unsigned char* tempData = new unsigned char[width * height * 4];
|
2020-06-26 15:17:35 +00:00
|
|
|
for (size_t i = 0; i < height; i++) {
|
2021-01-15 17:47:01 +00:00
|
|
|
const BYTE* scanLine =
|
|
|
|
FreeImage_GetScanLine(fiBitmap, static_cast<int>(i));
|
2020-06-26 15:17:35 +00:00
|
|
|
memcpy(tempData + (i * width * 4), scanLine, width * 4);
|
|
|
|
}
|
|
|
|
// Convert from BGRA to RGBA.
|
2021-01-15 17:47:01 +00:00
|
|
|
for (size_t i = 0; i < width * height; i++) {
|
2020-11-17 22:06:54 +00:00
|
|
|
RGBQUAD bgra = reinterpret_cast<RGBQUAD*>(tempData)[i];
|
2020-06-26 15:17:35 +00:00
|
|
|
RGBQUAD rgba;
|
|
|
|
rgba.rgbBlue = bgra.rgbRed;
|
|
|
|
rgba.rgbGreen = bgra.rgbGreen;
|
|
|
|
rgba.rgbRed = bgra.rgbBlue;
|
|
|
|
rgba.rgbReserved = bgra.rgbReserved;
|
2020-11-17 22:06:54 +00:00
|
|
|
reinterpret_cast<RGBQUAD*>(tempData)[i] = rgba;
|
2020-06-26 15:17:35 +00:00
|
|
|
}
|
|
|
|
rawData = std::vector<unsigned char>(tempData, tempData + width * height * 4);
|
|
|
|
// Free bitmap data.
|
|
|
|
FreeImage_Unload(fiBitmap);
|
|
|
|
delete[] tempData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2021-01-15 17:47:01 +00:00
|
|
|
LOG(LogError) << "Failed to load image from memory";
|
2020-06-26 15:17:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2020-07-26 21:30:45 +00:00
|
|
|
LOG(LogError) << "Couldn't load image, file is missing or the file type is " <<
|
2021-01-15 17:47:01 +00:00
|
|
|
(format == FIF_UNKNOWN ? "unknown" : "unsupported");
|
2020-06-26 15:17:35 +00:00
|
|
|
}
|
2021-01-15 17:47:01 +00:00
|
|
|
// Free fiMemory again.
|
2020-06-26 15:17:35 +00:00
|
|
|
FreeImage_CloseMemory(fiMemory);
|
|
|
|
}
|
|
|
|
return rawData;
|
2013-05-16 19:26:19 +00:00
|
|
|
}
|
2014-05-28 21:43:23 +00:00
|
|
|
|
|
|
|
void ImageIO::flipPixelsVert(unsigned char* imagePx, const size_t& width, const size_t& height)
|
|
|
|
{
|
2020-06-26 15:17:35 +00:00
|
|
|
unsigned int temp;
|
2020-11-17 22:06:54 +00:00
|
|
|
unsigned int* arr = reinterpret_cast<unsigned int*>(imagePx);
|
2020-06-26 15:17:35 +00:00
|
|
|
for (size_t y = 0; y < height / 2; y++) {
|
|
|
|
for (size_t x = 0; x < width; x++) {
|
|
|
|
temp = arr[x + (y * width)];
|
|
|
|
arr[x + (y * width)] = arr[x + (height * width) - ((y + 1) * width)];
|
|
|
|
arr[x + (height * width) - ((y + 1) * width)] = temp;
|
|
|
|
}
|
|
|
|
}
|
2014-05-28 21:43:23 +00:00
|
|
|
}
|