Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/WolfireGames/overgrowth.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Images/image_export.cpp')
-rw-r--r--Source/Images/image_export.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/Source/Images/image_export.cpp b/Source/Images/image_export.cpp
new file mode 100644
index 00000000..b136549f
--- /dev/null
+++ b/Source/Images/image_export.cpp
@@ -0,0 +1,208 @@
+//-----------------------------------------------------------------------------
+// Name: image_export.cpp
+// Developer: Wolfire Games LLC
+// Author: Phillip Isola
+// Description: Wraps up FreeImage library
+// License: Read below
+//-----------------------------------------------------------------------------
+//
+//
+// Copyright 2022 Wolfire Games LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-----------------------------------------------------------------------------
+#include "image_export.hpp"
+
+#include <Images/image_export.hpp>
+#include <Images/freeimage_wrapper.h>
+
+#include <Internal/error.h>
+#include <Internal/filesystem.h>
+#include <Internal/common.h>
+
+#include <Compat/fileio.h>
+#include <Compat/compat.h>
+
+#include <Memory/allocation.h>
+#include <Logging/logdata.h>
+
+#include <FreeImage.h>
+#include <crnlib.h>
+
+#include <vector>
+#include <cstring>
+#include <algorithm>
+#include <cstdio>
+
+using std::min;
+using std::max;
+
+namespace {
+ void RGBAtoYCOCG(unsigned char *data, unsigned long width, unsigned long height) {
+ int index = 0;
+ for(unsigned i=0; i<width*height; i++){
+ const int r = data[index+2];
+ const int g = data[index+1];
+ const int b = data[index+0];
+
+ const int Co = r - b;
+ const int t = b + Co/2;
+ const int Cg = g - t;
+ const int Y = t + Cg/2;
+
+ data[index+2] = min(max(Co + 128, 0), 255);
+ data[index+1] = min(max(Cg + 128, 0), 255);
+ data[index+0] = 0;
+ data[index+3] = Y;
+ index+=4;
+ }
+ }
+}
+
+std::string ImageExport::FindEmptySequentialFile(const char* filename, const char* suffix) {
+ char abs_path[kPathSize];
+ for(int i=1; i<99999; i++){
+ FormatString(abs_path, kPathSize,"%s%s%05d%s", GetWritePath(CoreGameModID).c_str(), filename, i, suffix);
+ if(!CheckFileAccess(abs_path)) {
+ return abs_path;
+ }
+ }
+ return filename;
+}
+
+
+void ImageExport::ScaleImageUp(const unsigned char *data,
+ int levels,
+ unsigned long *width_ptr,
+ unsigned long *height_ptr,
+ std::vector<unsigned char> *new_data_ptr)
+{
+ unsigned long& width = *width_ptr;
+ unsigned long& height = *height_ptr;
+ std::vector<unsigned char> &new_data = *new_data_ptr;
+
+ const int bytes_per_pixel = 4;
+ size_t image_size = width*height*bytes_per_pixel;
+ new_data.resize(image_size);
+ memcpy(&(new_data[0]), data, image_size);
+
+ for(int i=0; i<levels; i++){
+ width *= 2;
+ height *= 2;
+ image_size = width*height*bytes_per_pixel;
+ std::vector<unsigned char> new_new_data(image_size);
+ for(unsigned i=0; i<width; i++){
+ for(unsigned j=0; j<height; j++){
+ for(int k=0; k<bytes_per_pixel; k++){
+ new_new_data[(i+j*width)*bytes_per_pixel+k] = new_data[((i/2)+(j/2)*width/2)*bytes_per_pixel+k];
+ }
+ }
+ }
+ new_data = new_new_data;
+ }
+}
+
+void ImageExport::SavePNG(const char *file_path, unsigned char *data, unsigned long width, unsigned long height, unsigned short levels) {
+ std::vector<unsigned char> scaled_data;
+ ImageExport::ScaleImageUp(data, levels, &width, &height, &scaled_data);
+ FREE_IMAGE_FORMAT format = FIF_PNG;
+ FIBITMAP *image = FreeImage_ConvertFromRawBits(&scaled_data[0], width, height, 4*width, 32, 0xC0, 0x38, 0x7);
+ CreateParentDirs(file_path);
+#ifdef _WIN32
+ createfile(file_path);
+ std::string short_path(file_path);
+ ShortenWindowsPath(short_path);
+ if(!FreeImage_Save(format, image, short_path.c_str())) {
+ DisplayError("Error","Problem exporting .png file");
+ }
+#else
+ if(!FreeImage_Save(format, image, file_path)) {
+ DisplayError("Error","Problem exporting .png file");
+ }
+#endif
+ FreeImage_Unload(image);
+}
+
+void ImageExport::SavePNGTransparent(const char *file_path, unsigned char *data, unsigned long width, unsigned long height, unsigned short levels) {
+ std::vector<unsigned char> scaled_data;
+ ImageExport::ScaleImageUp(data, levels, &width, &height, &scaled_data);
+ FREE_IMAGE_FORMAT format = FIF_PNG;
+ FIBITMAP *image = FreeImage_ConvertFromRawBits(&scaled_data[0], width, height, 4*width, 32, 0xC0, 0x38, 0x7);
+ LOGI << "BPP: " << (int)FreeImage_GetBPP(image) << std::endl;
+ LOGI << "IsTransparent: " << (int)FreeImage_IsTransparent(image) << std::endl;
+ FreeImage_SetTransparent(image, true);
+ LOGI << "IsTransparent: " << (int)FreeImage_IsTransparent(image) << std::endl;
+
+ int bytespp = FreeImage_GetLine(image) / FreeImage_GetWidth(image);
+ for(unsigned y = 0; y < FreeImage_GetHeight(image); y++) {
+ BYTE *bits = FreeImage_GetScanLine(image, y);
+ for(unsigned x = 0; x < FreeImage_GetWidth(image); x++) {
+ // Set pixel color to green with a transparency of 128
+ bits[FI_RGBA_RED] = min(255,(int)((bits[FI_RGBA_RED]/255.0f / (scaled_data[y*width*4+x*4+3]/255.0f))*255));
+ bits[FI_RGBA_GREEN] = min(255,(int)((bits[FI_RGBA_GREEN]/255.0f / (scaled_data[y*width*4+x*4+3]/255.0f))*255));
+ bits[FI_RGBA_BLUE] = min(255,(int)((bits[FI_RGBA_BLUE]/255.0f / (scaled_data[y*width*4+x*4+3]/255.0f))*255));
+ bits[FI_RGBA_ALPHA] = scaled_data[y*width*4+x*4+3];
+ // jump to next pixel
+ bits += bytespp;
+ }
+ }
+
+ CreateParentDirs(file_path);
+#ifdef _WIN32
+ createfile(file_path);
+ std::string short_path(file_path);
+ ShortenWindowsPath(short_path);
+ if(!FreeImage_Save(format, image, short_path.c_str())) {
+ DisplayError("Error","Problem exporting .png file");
+ }
+#else
+ if(!FreeImage_Save(format, image, file_path)) {
+ DisplayError("Error","Problem exporting .png file");
+ }
+#endif
+ FreeImage_Unload(image);
+}
+
+void ImageExport::SaveJPEG(const char* abs_path, unsigned char *data, unsigned long width, unsigned long height) {
+ FREE_IMAGE_FORMAT format = FIF_JPEG;
+ FIBITMAP *image = FreeImage_ConvertFromRawBits(data, width, height, 3*width, 24, 0xC0, 0x38, 0x7);
+ CreateParentDirs(abs_path);
+#ifdef _WIN32
+ createfile(abs_path);
+ std::string short_path(abs_path);
+ ShortenWindowsPath(short_path);
+ if(!FreeImage_Save(format, image, short_path.c_str(), JPEG_QUALITYSUPERB)) {
+ DisplayError("Error","Problem exporting .jpeg file");
+ }
+#else
+ if(!FreeImage_Save(format, image, abs_path, JPEG_QUALITYSUPERB)) {
+ DisplayError("Error","Problem exporting .jpeg file");
+ }
+#endif
+ FreeImage_Unload(image);
+}
+
+void ImageExport::SavePNGofGrayscaleFloats(const char *file_path, std::vector<float>& data, unsigned long width, unsigned long height) {
+ if (data.size() != width*height) return;
+ unsigned char* byte_data = (unsigned char*)(OG_MALLOC(sizeof(*byte_data)*data.size()*4));
+ for (unsigned i = 0; i < data.size(); i++) {
+ unsigned char data_i = (unsigned char)(data[i]*255);
+ byte_data[4*i] = data_i;
+ byte_data[4*i+1] = data_i;
+ byte_data[4*i+2] = data_i;
+ byte_data[4*i+3] = 255;
+ }
+ SavePNG(file_path, byte_data, width, height);
+ OG_FREE(byte_data);
+}