mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Updated the CImg functions and miximage generator for BGRA instead of RGBA pixel format.
This commit is contained in:
parent
e1d911f401
commit
126d93709e
|
@ -111,14 +111,14 @@ void MiximageGenerator::startThread(std::promise<bool>* miximagePromise)
|
||||||
bool MiximageGenerator::generateImage()
|
bool MiximageGenerator::generateImage()
|
||||||
{
|
{
|
||||||
FREE_IMAGE_FORMAT fileFormat;
|
FREE_IMAGE_FORMAT fileFormat;
|
||||||
FIBITMAP* screenshotFile = nullptr;
|
FIBITMAP* screenshotFile {nullptr};
|
||||||
FIBITMAP* marqueeFile = nullptr;
|
FIBITMAP* marqueeFile {nullptr};
|
||||||
FIBITMAP* boxFile = nullptr;
|
FIBITMAP* boxFile {nullptr};
|
||||||
FIBITMAP* physicalMediaFile = nullptr;
|
FIBITMAP* physicalMediaFile {nullptr};
|
||||||
|
|
||||||
unsigned int fileWidth = 0;
|
unsigned int fileWidth {0};
|
||||||
unsigned int fileHeight = 0;
|
unsigned int fileHeight {0};
|
||||||
unsigned int filePitch = 0;
|
unsigned int filePitch {0};
|
||||||
|
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
fileFormat = FreeImage_GetFileTypeU(Utils::String::stringToWideString(mScreenshotPath).c_str());
|
fileFormat = FreeImage_GetFileTypeU(Utils::String::stringToWideString(mScreenshotPath).c_str());
|
||||||
|
@ -336,19 +336,19 @@ bool MiximageGenerator::generateImage()
|
||||||
resolutionMultiplier = 2;
|
resolutionMultiplier = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int screenshotWidth = 530 * resolutionMultiplier;
|
const unsigned int screenshotWidth {530 * resolutionMultiplier};
|
||||||
const unsigned int screenshotOffset = 20 * resolutionMultiplier;
|
const unsigned int screenshotOffset {20 * resolutionMultiplier};
|
||||||
const unsigned int screenshotFrameWidth = 6 * resolutionMultiplier;
|
const unsigned int screenshotFrameWidth {6 * resolutionMultiplier};
|
||||||
const unsigned int screenshotHeight = 400 * resolutionMultiplier;
|
const unsigned int screenshotHeight {400 * resolutionMultiplier};
|
||||||
|
|
||||||
// These sizes are increased slightly when adding the drop shadow.
|
// These sizes are increased slightly when adding the drop shadow.
|
||||||
const unsigned int marqueeTargetWidth = 310 * resolutionMultiplier;
|
const unsigned int marqueeTargetWidth {310 * resolutionMultiplier};
|
||||||
const unsigned int marqueeTargetHeight = 230 * resolutionMultiplier;
|
const unsigned int marqueeTargetHeight {230 * resolutionMultiplier};
|
||||||
unsigned int boxTargetWidth = 0;
|
unsigned int boxTargetWidth {0};
|
||||||
unsigned int boxTargetHeight = 0;
|
unsigned int boxTargetHeight {0};
|
||||||
unsigned int coverTargetWidth = 0;
|
unsigned int coverTargetWidth {0};
|
||||||
unsigned int physicalMediaTargetWidth = 0;
|
unsigned int physicalMediaTargetWidth {0};
|
||||||
unsigned int physicalMediaTargetHeight = 0;
|
unsigned int physicalMediaTargetHeight {0};
|
||||||
|
|
||||||
if (Settings::getInstance()->getString("MiximageBoxSize") == "small") {
|
if (Settings::getInstance()->getString("MiximageBoxSize") == "small") {
|
||||||
boxTargetWidth = 264 * resolutionMultiplier;
|
boxTargetWidth = 264 * resolutionMultiplier;
|
||||||
|
@ -379,12 +379,12 @@ bool MiximageGenerator::generateImage()
|
||||||
physicalMediaTargetHeight = 120 * resolutionMultiplier;
|
physicalMediaTargetHeight = 120 * resolutionMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int marqueeShadowSize = 6 * resolutionMultiplier;
|
const unsigned int marqueeShadowSize {6 * resolutionMultiplier};
|
||||||
const unsigned int boxShadowSize = 6 * resolutionMultiplier;
|
const unsigned int boxShadowSize {6 * resolutionMultiplier};
|
||||||
const unsigned int physicalMediaShadowSize = 6 * resolutionMultiplier;
|
const unsigned int physicalMediaShadowSize {6 * resolutionMultiplier};
|
||||||
|
|
||||||
if (FreeImage_GetBPP(screenshotFile) != 32) {
|
if (FreeImage_GetBPP(screenshotFile) != 32) {
|
||||||
FIBITMAP* screenshotTemp = FreeImage_ConvertTo32Bits(screenshotFile);
|
FIBITMAP* screenshotTemp {FreeImage_ConvertTo32Bits(screenshotFile)};
|
||||||
FreeImage_Unload(screenshotFile);
|
FreeImage_Unload(screenshotFile);
|
||||||
screenshotFile = screenshotTemp;
|
screenshotFile = screenshotTemp;
|
||||||
}
|
}
|
||||||
|
@ -396,12 +396,12 @@ bool MiximageGenerator::generateImage()
|
||||||
std::vector<unsigned char> screenshotVector(fileWidth * fileHeight * 4);
|
std::vector<unsigned char> screenshotVector(fileWidth * fileHeight * 4);
|
||||||
|
|
||||||
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&screenshotVector.at(0)), screenshotFile,
|
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&screenshotVector.at(0)), screenshotFile,
|
||||||
filePitch, 32, FI_RGBA_RED, FI_RGBA_GREEN, FI_RGBA_BLUE, 1);
|
filePitch, 32, FI_RGBA_BLUE, FI_RGBA_GREEN, FI_RGBA_RED, 1);
|
||||||
|
|
||||||
CImg<unsigned char> screenshotImage(fileWidth, fileHeight, 1, 4, 0);
|
CImg<unsigned char> screenshotImage(fileWidth, fileHeight, 1, 4, 0);
|
||||||
|
|
||||||
// Convert the RGBA image to CImg internal format.
|
// Convert the RGBA image to CImg internal format.
|
||||||
Utils::CImg::convertRGBAToCImg(screenshotVector, screenshotImage);
|
Utils::CImg::convertBGRAToCImg(screenshotVector, screenshotImage);
|
||||||
screenshotVector.clear();
|
screenshotVector.clear();
|
||||||
|
|
||||||
if (Settings::getInstance()->getBool("MiximageRemoveLetterboxes"))
|
if (Settings::getInstance()->getBool("MiximageRemoveLetterboxes"))
|
||||||
|
@ -426,17 +426,17 @@ bool MiximageGenerator::generateImage()
|
||||||
// of the miximage.
|
// of the miximage.
|
||||||
screenshotImage.get_shared_channel(3).fill(255);
|
screenshotImage.get_shared_channel(3).fill(255);
|
||||||
|
|
||||||
int xPosScreenshot = 0;
|
int xPosScreenshot {0};
|
||||||
int yPosScreenshot = 0;
|
int yPosScreenshot {0};
|
||||||
|
|
||||||
int xPosMarquee = 0;
|
int xPosMarquee {0};
|
||||||
int yPosMarquee = 0;
|
int yPosMarquee {0};
|
||||||
|
|
||||||
int xPosBox = 0;
|
int xPosBox {0};
|
||||||
int yPosBox = 0;
|
int yPosBox {0};
|
||||||
|
|
||||||
int xPosPhysicalMedia = 0;
|
int xPosPhysicalMedia {0};
|
||||||
int yPosPhysicalMedia = 0;
|
int yPosPhysicalMedia {0};
|
||||||
|
|
||||||
CImg<unsigned char> canvasImage(mWidth, mHeight, 1, 4, 0);
|
CImg<unsigned char> canvasImage(mWidth, mHeight, 1, 4, 0);
|
||||||
|
|
||||||
|
@ -459,7 +459,7 @@ bool MiximageGenerator::generateImage()
|
||||||
|
|
||||||
if (mMarquee) {
|
if (mMarquee) {
|
||||||
if (FreeImage_GetBPP(marqueeFile) != 32) {
|
if (FreeImage_GetBPP(marqueeFile) != 32) {
|
||||||
FIBITMAP* marqueeTemp = FreeImage_ConvertTo32Bits(marqueeFile);
|
FIBITMAP* marqueeTemp {FreeImage_ConvertTo32Bits(marqueeFile)};
|
||||||
FreeImage_Unload(marqueeFile);
|
FreeImage_Unload(marqueeFile);
|
||||||
marqueeFile = marqueeTemp;
|
marqueeFile = marqueeTemp;
|
||||||
}
|
}
|
||||||
|
@ -471,16 +471,16 @@ bool MiximageGenerator::generateImage()
|
||||||
std::vector<unsigned char> marqueeVector(fileWidth * fileHeight * 4);
|
std::vector<unsigned char> marqueeVector(fileWidth * fileHeight * 4);
|
||||||
|
|
||||||
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&marqueeVector.at(0)), marqueeFile,
|
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&marqueeVector.at(0)), marqueeFile,
|
||||||
filePitch, 32, FI_RGBA_RED, FI_RGBA_GREEN, FI_RGBA_BLUE, 1);
|
filePitch, 32, FI_RGBA_BLUE, FI_RGBA_GREEN, FI_RGBA_RED, 1);
|
||||||
|
|
||||||
marqueeImage = CImg<unsigned char>(FreeImage_GetWidth(marqueeFile),
|
marqueeImage = CImg<unsigned char>(FreeImage_GetWidth(marqueeFile),
|
||||||
FreeImage_GetHeight(marqueeFile), 1, 4, 0);
|
FreeImage_GetHeight(marqueeFile), 1, 4, 0);
|
||||||
|
|
||||||
Utils::CImg::convertRGBAToCImg(marqueeVector, marqueeImage);
|
Utils::CImg::convertBGRAToCImg(marqueeVector, marqueeImage);
|
||||||
Utils::CImg::removeTransparentPadding(marqueeImage);
|
Utils::CImg::removeTransparentPadding(marqueeImage);
|
||||||
|
|
||||||
unsigned int marqueeWidth = static_cast<unsigned int>(marqueeImage.width());
|
unsigned int marqueeWidth {static_cast<unsigned int>(marqueeImage.width())};
|
||||||
unsigned int marqueeHeight = static_cast<unsigned int>(marqueeImage.height());
|
unsigned int marqueeHeight {static_cast<unsigned int>(marqueeImage.height())};
|
||||||
|
|
||||||
calculateMarqueeSize(marqueeTargetWidth, marqueeTargetHeight, marqueeWidth, marqueeHeight);
|
calculateMarqueeSize(marqueeTargetWidth, marqueeTargetHeight, marqueeWidth, marqueeHeight);
|
||||||
|
|
||||||
|
@ -501,7 +501,7 @@ bool MiximageGenerator::generateImage()
|
||||||
|
|
||||||
if (mBox3D || mCover) {
|
if (mBox3D || mCover) {
|
||||||
if (FreeImage_GetBPP(boxFile) != 32) {
|
if (FreeImage_GetBPP(boxFile) != 32) {
|
||||||
FIBITMAP* boxTemp = FreeImage_ConvertTo32Bits(boxFile);
|
FIBITMAP* boxTemp {FreeImage_ConvertTo32Bits(boxFile)};
|
||||||
FreeImage_Unload(boxFile);
|
FreeImage_Unload(boxFile);
|
||||||
boxFile = boxTemp;
|
boxFile = boxTemp;
|
||||||
}
|
}
|
||||||
|
@ -513,24 +513,25 @@ bool MiximageGenerator::generateImage()
|
||||||
std::vector<unsigned char> boxVector(fileWidth * fileHeight * 4);
|
std::vector<unsigned char> boxVector(fileWidth * fileHeight * 4);
|
||||||
|
|
||||||
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&boxVector.at(0)), boxFile, filePitch,
|
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&boxVector.at(0)), boxFile, filePitch,
|
||||||
32, FI_RGBA_RED, FI_RGBA_GREEN, FI_RGBA_BLUE, 1);
|
32, FI_RGBA_BLUE, FI_RGBA_GREEN, FI_RGBA_RED, 1);
|
||||||
|
|
||||||
boxImage =
|
boxImage =
|
||||||
CImg<unsigned char>(FreeImage_GetWidth(boxFile), FreeImage_GetHeight(boxFile), 1, 4);
|
CImg<unsigned char>(FreeImage_GetWidth(boxFile), FreeImage_GetHeight(boxFile), 1, 4);
|
||||||
|
|
||||||
Utils::CImg::convertRGBAToCImg(boxVector, boxImage);
|
Utils::CImg::convertBGRAToCImg(boxVector, boxImage);
|
||||||
Utils::CImg::removeTransparentPadding(boxImage);
|
Utils::CImg::removeTransparentPadding(boxImage);
|
||||||
|
|
||||||
float sizeRatio =
|
float sizeRatio {static_cast<float>(boxImage.width()) /
|
||||||
static_cast<float>(boxImage.width()) / static_cast<float>(boxImage.height());
|
static_cast<float>(boxImage.height())};
|
||||||
|
|
||||||
if (sizeRatio > 1.14f && Settings::getInstance()->getBool("MiximageRotateHorizontalBoxes"))
|
if (sizeRatio > 1.14f && Settings::getInstance()->getBool("MiximageRotateHorizontalBoxes"))
|
||||||
boxImage.rotate(90.0f);
|
boxImage.rotate(90.0f);
|
||||||
|
|
||||||
float scaleFactor =
|
float scaleFactor {static_cast<float>(boxTargetHeight) /
|
||||||
static_cast<float>(boxTargetHeight) / static_cast<float>(boxImage.height());
|
static_cast<float>(boxImage.height())};
|
||||||
unsigned int width = static_cast<int>(static_cast<float>(boxImage.width()) * scaleFactor);
|
unsigned int width {
|
||||||
unsigned int targetWidth = 0;
|
static_cast<unsigned int>(static_cast<float>(boxImage.width()) * scaleFactor)};
|
||||||
|
unsigned int targetWidth {0};
|
||||||
|
|
||||||
// We make this distinction as some cover images are in square format and would cover
|
// We make this distinction as some cover images are in square format and would cover
|
||||||
// too much surface otherwise.
|
// too much surface otherwise.
|
||||||
|
@ -541,7 +542,7 @@ bool MiximageGenerator::generateImage()
|
||||||
|
|
||||||
if (width > targetWidth) {
|
if (width > targetWidth) {
|
||||||
scaleFactor = static_cast<float>(targetWidth) / static_cast<float>(boxImage.width());
|
scaleFactor = static_cast<float>(targetWidth) / static_cast<float>(boxImage.width());
|
||||||
int height = static_cast<int>(static_cast<float>(boxImage.height()) * scaleFactor);
|
int height {static_cast<int>(static_cast<float>(boxImage.height()) * scaleFactor)};
|
||||||
// We use Lanczos3 which is the highest quality resampling method available.
|
// We use Lanczos3 which is the highest quality resampling method available.
|
||||||
boxImage.resize(targetWidth, height, 1, 4, 6);
|
boxImage.resize(targetWidth, height, 1, 4, 6);
|
||||||
}
|
}
|
||||||
|
@ -562,7 +563,7 @@ bool MiximageGenerator::generateImage()
|
||||||
|
|
||||||
if (mPhysicalMedia) {
|
if (mPhysicalMedia) {
|
||||||
if (FreeImage_GetBPP(physicalMediaFile) != 32) {
|
if (FreeImage_GetBPP(physicalMediaFile) != 32) {
|
||||||
FIBITMAP* physicalMediaTemp = FreeImage_ConvertTo32Bits(physicalMediaFile);
|
FIBITMAP* physicalMediaTemp {FreeImage_ConvertTo32Bits(physicalMediaFile)};
|
||||||
FreeImage_Unload(physicalMediaFile);
|
FreeImage_Unload(physicalMediaFile);
|
||||||
physicalMediaFile = physicalMediaTemp;
|
physicalMediaFile = physicalMediaTemp;
|
||||||
}
|
}
|
||||||
|
@ -574,26 +575,26 @@ bool MiximageGenerator::generateImage()
|
||||||
std::vector<unsigned char> physicalMediaVector(fileWidth * fileHeight * 4);
|
std::vector<unsigned char> physicalMediaVector(fileWidth * fileHeight * 4);
|
||||||
|
|
||||||
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&physicalMediaVector.at(0)),
|
FreeImage_ConvertToRawBits(reinterpret_cast<BYTE*>(&physicalMediaVector.at(0)),
|
||||||
physicalMediaFile, filePitch, 32, FI_RGBA_RED, FI_RGBA_GREEN,
|
physicalMediaFile, filePitch, 32, FI_RGBA_BLUE, FI_RGBA_GREEN,
|
||||||
FI_RGBA_BLUE, 1);
|
FI_RGBA_RED, 1);
|
||||||
|
|
||||||
physicalMediaImage = CImg<unsigned char>(FreeImage_GetWidth(physicalMediaFile),
|
physicalMediaImage = CImg<unsigned char>(FreeImage_GetWidth(physicalMediaFile),
|
||||||
FreeImage_GetHeight(physicalMediaFile), 1, 4, 0);
|
FreeImage_GetHeight(physicalMediaFile), 1, 4, 0);
|
||||||
|
|
||||||
Utils::CImg::convertRGBAToCImg(physicalMediaVector, physicalMediaImage);
|
Utils::CImg::convertBGRAToCImg(physicalMediaVector, physicalMediaImage);
|
||||||
Utils::CImg::removeTransparentPadding(physicalMediaImage);
|
Utils::CImg::removeTransparentPadding(physicalMediaImage);
|
||||||
|
|
||||||
// Make sure the image size is not exceeding either the target width or height.
|
// Make sure the image size is not exceeding either the target width or height.
|
||||||
float scaleFactorX = static_cast<float>(physicalMediaTargetWidth) /
|
float scaleFactorX {static_cast<float>(physicalMediaTargetWidth) /
|
||||||
static_cast<float>(physicalMediaImage.width());
|
static_cast<float>(physicalMediaImage.width())};
|
||||||
float scaleFactorY = static_cast<float>(physicalMediaTargetHeight) /
|
float scaleFactorY {static_cast<float>(physicalMediaTargetHeight) /
|
||||||
static_cast<float>(physicalMediaImage.height());
|
static_cast<float>(physicalMediaImage.height())};
|
||||||
float scaleFactor = std::min(scaleFactorX, scaleFactorY);
|
float scaleFactor {std::min(scaleFactorX, scaleFactorY)};
|
||||||
|
|
||||||
unsigned int width =
|
unsigned int width {static_cast<unsigned int>(
|
||||||
static_cast<int>(static_cast<float>(physicalMediaImage.width()) * scaleFactor);
|
static_cast<float>(physicalMediaImage.width()) * scaleFactor)};
|
||||||
unsigned int height =
|
unsigned int height {static_cast<unsigned int>(
|
||||||
static_cast<int>(static_cast<float>(physicalMediaImage.height()) * scaleFactor);
|
static_cast<float>(physicalMediaImage.height()) * scaleFactor)};
|
||||||
|
|
||||||
// We use Lanczos3 which is the highest quality resampling method available.
|
// We use Lanczos3 which is the highest quality resampling method available.
|
||||||
physicalMediaImage.resize(width, height, 1, 4, 6);
|
physicalMediaImage.resize(width, height, 1, 4, 6);
|
||||||
|
@ -632,8 +633,8 @@ bool MiximageGenerator::generateImage()
|
||||||
yPosScreenshot + screenshotHeight - 2, frameColor);
|
yPosScreenshot + screenshotHeight - 2, frameColor);
|
||||||
|
|
||||||
// We draw circles in order to get rounded corners for the frame.
|
// We draw circles in order to get rounded corners for the frame.
|
||||||
const unsigned int circleRadius = 8 * resolutionMultiplier;
|
const unsigned int circleRadius {8 * resolutionMultiplier};
|
||||||
const unsigned int circleOffset = 2 * resolutionMultiplier;
|
const unsigned int circleOffset {2 * resolutionMultiplier};
|
||||||
|
|
||||||
// Upper left corner.
|
// Upper left corner.
|
||||||
frameImage.draw_circle(xPosScreenshot + circleOffset, yPosScreenshot + circleOffset,
|
frameImage.draw_circle(xPosScreenshot + circleOffset, yPosScreenshot + circleOffset,
|
||||||
|
@ -668,19 +669,19 @@ bool MiximageGenerator::generateImage()
|
||||||
std::vector<unsigned char> canvasVector;
|
std::vector<unsigned char> canvasVector;
|
||||||
|
|
||||||
// Convert the image from CImg internal format.
|
// Convert the image from CImg internal format.
|
||||||
Utils::CImg::convertCImgToRGBA(canvasImage, canvasVector);
|
Utils::CImg::convertCImgToBGRA(canvasImage, canvasVector);
|
||||||
|
|
||||||
FIBITMAP* mixImage = nullptr;
|
FIBITMAP* mixImage {nullptr};
|
||||||
mixImage = FreeImage_ConvertFromRawBits(&canvasVector.at(0), canvasImage.width(),
|
mixImage = FreeImage_ConvertFromRawBits(&canvasVector.at(0), canvasImage.width(),
|
||||||
canvasImage.height(), canvasImage.width() * 4, 32,
|
canvasImage.height(), canvasImage.width() * 4, 32,
|
||||||
FI_RGBA_RED, FI_RGBA_GREEN, FI_RGBA_BLUE);
|
FI_RGBA_BLUE, FI_RGBA_GREEN, FI_RGBA_RED);
|
||||||
|
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
bool savedImage =
|
bool savedImage {FreeImage_SaveU(FIF_PNG, mixImage,
|
||||||
(FreeImage_SaveU(FIF_PNG, mixImage,
|
Utils::String::stringToWideString(getSavePath()).c_str()) !=
|
||||||
Utils::String::stringToWideString(getSavePath()).c_str()) != 0);
|
0};
|
||||||
#else
|
#else
|
||||||
bool savedImage = (FreeImage_Save(FIF_PNG, mixImage, getSavePath().c_str()) != 0);
|
bool savedImage {FreeImage_Save(FIF_PNG, mixImage, getSavePath().c_str()) != 0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!savedImage) {
|
if (!savedImage) {
|
||||||
|
@ -705,14 +706,14 @@ void MiximageGenerator::calculateMarqueeSize(const unsigned int& targetWidth,
|
||||||
unsigned int& width,
|
unsigned int& width,
|
||||||
unsigned int& height)
|
unsigned int& height)
|
||||||
{
|
{
|
||||||
unsigned int adjustedTargetWidth = 0;
|
unsigned int adjustedTargetWidth {0};
|
||||||
float widthModifier = 0.5f;
|
float widthModifier {0.5f};
|
||||||
float scaleFactor = 0.0f;
|
float scaleFactor {0.0f};
|
||||||
|
|
||||||
// The idea is to adjust the size of the marquee based on its surface area, so that
|
// The idea is to adjust the size of the marquee based on its surface area, so that
|
||||||
// wider but shorter images get a larger width than taller images in order to use
|
// wider but shorter images get a larger width than taller images in order to use
|
||||||
// an approximately equivalent amount of space on the miximage.
|
// an approximately equivalent amount of space on the miximage.
|
||||||
float widthRatio = static_cast<float>(width) / static_cast<float>(height);
|
float widthRatio {static_cast<float>(width) / static_cast<float>(height)};
|
||||||
|
|
||||||
widthModifier = glm::clamp(widthModifier + widthRatio / 6.5f, 0.0f, 1.0f);
|
widthModifier = glm::clamp(widthModifier + widthRatio / 6.5f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
@ -737,18 +738,18 @@ void MiximageGenerator::sampleFrameColor(CImg<unsigned char>& screenshotImage,
|
||||||
unsigned char (&frameColor)[4])
|
unsigned char (&frameColor)[4])
|
||||||
{
|
{
|
||||||
// Calculate the number of samples relative to the configured resolution so we get
|
// Calculate the number of samples relative to the configured resolution so we get
|
||||||
// the same result regardless of miximage target size seting.
|
// the same result regardless of miximage target size setting.
|
||||||
unsigned int samples = static_cast<int>(static_cast<float>(mWidth) * 0.03125f);
|
unsigned int samples {static_cast<unsigned int>(static_cast<float>(mWidth) * 0.03125f)};
|
||||||
|
|
||||||
unsigned int red = 0;
|
unsigned int red {0};
|
||||||
unsigned int green = 0;
|
unsigned int green {0};
|
||||||
unsigned int blue = 0;
|
unsigned int blue {0};
|
||||||
|
|
||||||
unsigned int redLine = 0;
|
unsigned int redLine {0};
|
||||||
unsigned int greenLine = 0;
|
unsigned int greenLine {0};
|
||||||
unsigned int blueLine = 0;
|
unsigned int blueLine {0};
|
||||||
|
|
||||||
unsigned int counter = 0;
|
unsigned int counter {0};
|
||||||
|
|
||||||
// This is a very simple method to get an average pixel value. It's limited in that it
|
// This is a very simple method to get an average pixel value. It's limited in that it
|
||||||
// does not consider dominant colors and such, so the result could possibly be a value
|
// does not consider dominant colors and such, so the result could possibly be a value
|
||||||
|
@ -770,16 +771,19 @@ void MiximageGenerator::sampleFrameColor(CImg<unsigned char>& screenshotImage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char redC = glm::clamp(static_cast<int>(redLine / 255), 0, 255);
|
unsigned char redC {
|
||||||
unsigned char greenC = glm::clamp(static_cast<int>(greenLine / 255), 0, 255);
|
static_cast<unsigned char>(glm::clamp(static_cast<int>(redLine / 255), 0, 255))};
|
||||||
unsigned char blueC = glm::clamp(static_cast<int>(blueLine / 255), 0, 255);
|
unsigned char greenC {
|
||||||
|
static_cast<unsigned char>(glm::clamp(static_cast<int>(greenLine / 255), 0, 255))};
|
||||||
|
unsigned char blueC {
|
||||||
|
static_cast<unsigned char>(glm::clamp(static_cast<int>(blueLine / 255), 0, 255))};
|
||||||
|
|
||||||
// Convert to the HSL color space to be able to modify saturation and lightness.
|
// Convert to the HSL color space to be able to modify saturation and lightness.
|
||||||
CImg<float> colorHSL = CImg<>(1, 1, 1, 3).fill(redC, greenC, blueC).RGBtoHSL();
|
CImg<float> colorHSL = CImg<>(1, 1, 1, 3).fill(redC, greenC, blueC).RGBtoHSL();
|
||||||
|
|
||||||
// float hue = colorHSL(0, 0, 0, 0);
|
// float hue = colorHSL(0, 0, 0, 0);
|
||||||
float saturation = colorHSL(0, 0, 0, 1);
|
float saturation {colorHSL(0, 0, 0, 1)};
|
||||||
float lightness = colorHSL(0, 0, 0, 2);
|
float lightness {colorHSL(0, 0, 0, 2)};
|
||||||
|
|
||||||
// Decrease saturation slightly and increase lightness a bit, these adjustments
|
// Decrease saturation slightly and increase lightness a bit, these adjustments
|
||||||
// makes the end result look better than the raw average pixel value. Also clamp
|
// makes the end result look better than the raw average pixel value. Also clamp
|
||||||
|
@ -798,7 +802,7 @@ void MiximageGenerator::sampleFrameColor(CImg<unsigned char>& screenshotImage,
|
||||||
|
|
||||||
std::string MiximageGenerator::getSavePath() const
|
std::string MiximageGenerator::getSavePath() const
|
||||||
{
|
{
|
||||||
const std::string name = Utils::FileSystem::getStem(mGame->getPath());
|
const std::string name {Utils::FileSystem::getStem(mGame->getPath())};
|
||||||
std::string subFolders;
|
std::string subFolders;
|
||||||
|
|
||||||
// Extract possible subfolders from the path.
|
// Extract possible subfolders from the path.
|
||||||
|
@ -806,7 +810,7 @@ std::string MiximageGenerator::getSavePath() const
|
||||||
subFolders = Utils::String::replace(Utils::FileSystem::getParent(mGame->getPath()),
|
subFolders = Utils::String::replace(Utils::FileSystem::getParent(mGame->getPath()),
|
||||||
mGame->getSystemEnvData()->mStartPath, "");
|
mGame->getSystemEnvData()->mStartPath, "");
|
||||||
|
|
||||||
std::string path = FileData::getMediaDirectory();
|
std::string path {FileData::getMediaDirectory()};
|
||||||
|
|
||||||
if (!Utils::FileSystem::exists(path))
|
if (!Utils::FileSystem::exists(path))
|
||||||
Utils::FileSystem::createDirectory(path);
|
Utils::FileSystem::createDirectory(path);
|
||||||
|
|
|
@ -187,9 +187,9 @@ void ImageComponent::cropTransparentPadding(const float maxSizeX, const float ma
|
||||||
if (mSize == glm::vec2 {0.0f, 0.0f})
|
if (mSize == glm::vec2 {0.0f, 0.0f})
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<unsigned char> imageRGBA {mTexture.get()->getRawRGBAData()};
|
std::vector<unsigned char> imageBGRA {mTexture.get()->getRawRGBAData()};
|
||||||
|
|
||||||
if (imageRGBA.size() == 0)
|
if (imageBGRA.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glm::ivec2 imageSize {mTexture.get()->getSize()};
|
glm::ivec2 imageSize {mTexture.get()->getSize()};
|
||||||
|
@ -198,8 +198,8 @@ void ImageComponent::cropTransparentPadding(const float maxSizeX, const float ma
|
||||||
int paddingCoords[4] {0, 0, 0, 0};
|
int paddingCoords[4] {0, 0, 0, 0};
|
||||||
|
|
||||||
// We need to convert our RGBA data to the CImg internal format as CImg does not interleave
|
// We need to convert our RGBA data to the CImg internal format as CImg does not interleave
|
||||||
// the pixels (as in RGBARGBARGBA).
|
// the pixels (as in BGRABGRABGRA).
|
||||||
Utils::CImg::convertRGBAToCImg(imageRGBA, imageCImg);
|
Utils::CImg::convertBGRAToCImg(imageBGRA, imageCImg);
|
||||||
|
|
||||||
// This will give us the coordinates for the fully transparent areas.
|
// This will give us the coordinates for the fully transparent areas.
|
||||||
Utils::CImg::getTransparentPaddingCoords(imageCImg, paddingCoords);
|
Utils::CImg::getTransparentPaddingCoords(imageCImg, paddingCoords);
|
||||||
|
|
|
@ -12,10 +12,39 @@ namespace Utils
|
||||||
{
|
{
|
||||||
namespace CImg
|
namespace CImg
|
||||||
{
|
{
|
||||||
|
void convertBGRAToCImg(const std::vector<unsigned char>& imageBGRA,
|
||||||
|
cimg_library::CImg<unsigned char>& image)
|
||||||
|
{
|
||||||
|
// CImg does not interleave pixels as in BGRABGRABGRA so a conversion is required.
|
||||||
|
int counter = 0;
|
||||||
|
for (int r = 0; r < image.height(); ++r) {
|
||||||
|
for (int c = 0; c < image.width(); ++c) {
|
||||||
|
image(c, r, 0, 0) = imageBGRA[counter + 0];
|
||||||
|
image(c, r, 0, 1) = imageBGRA[counter + 1];
|
||||||
|
image(c, r, 0, 2) = imageBGRA[counter + 2];
|
||||||
|
image(c, r, 0, 3) = imageBGRA[counter + 3];
|
||||||
|
counter += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void convertCImgToBGRA(const cimg_library::CImg<unsigned char>& image,
|
||||||
|
std::vector<unsigned char>& imageBGRA)
|
||||||
|
{
|
||||||
|
for (int r = image.height() - 1; r >= 0; --r) {
|
||||||
|
for (int c = 0; c < image.width(); ++c) {
|
||||||
|
imageBGRA.emplace_back((unsigned char)image(c, r, 0, 0));
|
||||||
|
imageBGRA.emplace_back((unsigned char)image(c, r, 0, 1));
|
||||||
|
imageBGRA.emplace_back((unsigned char)image(c, r, 0, 2));
|
||||||
|
imageBGRA.emplace_back((unsigned char)image(c, r, 0, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void convertRGBAToCImg(const std::vector<unsigned char>& imageRGBA,
|
void convertRGBAToCImg(const std::vector<unsigned char>& imageRGBA,
|
||||||
cimg_library::CImg<unsigned char>& image)
|
cimg_library::CImg<unsigned char>& image)
|
||||||
{
|
{
|
||||||
// CImg does not interleave the pixels as in RGBARGBARGBA so a conversion is required.
|
// CImg does not interleave pixels as in RGBARGBARGBA so a conversion is required.
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (int r = 0; r < image.height(); ++r) {
|
for (int r = 0; r < image.height(); ++r) {
|
||||||
for (int c = 0; c < image.width(); ++c) {
|
for (int c = 0; c < image.width(); ++c) {
|
||||||
|
|
|
@ -20,6 +20,10 @@ namespace Utils
|
||||||
{
|
{
|
||||||
namespace CImg
|
namespace CImg
|
||||||
{
|
{
|
||||||
|
void convertBGRAToCImg(const std::vector<unsigned char>& imageBGRA,
|
||||||
|
cimg_library::CImg<unsigned char>& image);
|
||||||
|
void convertCImgToBGRA(const cimg_library::CImg<unsigned char>& image,
|
||||||
|
std::vector<unsigned char>& imageBGRA);
|
||||||
void convertRGBAToCImg(const std::vector<unsigned char>& imageRGBA,
|
void convertRGBAToCImg(const std::vector<unsigned char>& imageRGBA,
|
||||||
cimg_library::CImg<unsigned char>& image);
|
cimg_library::CImg<unsigned char>& image);
|
||||||
void convertCImgToRGBA(const cimg_library::CImg<unsigned char>& image,
|
void convertCImgToRGBA(const cimg_library::CImg<unsigned char>& image,
|
||||||
|
|
Loading…
Reference in a new issue