mirror of
https://github.com/Pixinn/Rgb2Hires.git
synced 2024-06-10 14:29:32 +00:00
SDL2 port: Picture with live preview
This commit is contained in:
parent
20f85a2dc5
commit
ed03b6a48f
|
@ -30,12 +30,6 @@ add_library(${PROJECT_NAME} src/Common.h
|
||||||
src/HiRes.h
|
src/HiRes.h
|
||||||
src/ImageQuantized.cpp
|
src/ImageQuantized.cpp
|
||||||
src/ImageQuantized.h
|
src/ImageQuantized.h
|
||||||
# src/Picture.h
|
|
||||||
# src/Picture.cpp
|
|
||||||
# src/Tile.h
|
|
||||||
# src/Tile.cpp
|
|
||||||
#src/Display.h
|
|
||||||
#src/Display.cpp
|
|
||||||
)
|
)
|
||||||
## dependencies
|
## dependencies
|
||||||
conan_set_find_library_paths(${PROJECT_NAME})
|
conan_set_find_library_paths(${PROJECT_NAME})
|
||||||
|
@ -43,7 +37,10 @@ conan_target_link_libraries(${PROJECT_NAME})
|
||||||
|
|
||||||
|
|
||||||
# Application Picture
|
# Application Picture
|
||||||
add_executable( Picture src/App_Picture.cpp)
|
add_executable( Picture src/App_Picture.cpp
|
||||||
|
src/Display.h
|
||||||
|
src/Display.cpp
|
||||||
|
)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
set_target_properties(Picture PROPERTIES COMPILE_FLAGS -pthread LINK_FLAGS -pthread)
|
set_target_properties(Picture PROPERTIES COMPILE_FLAGS -pthread LINK_FLAGS -pthread)
|
||||||
endif()
|
endif()
|
||||||
|
@ -58,23 +55,24 @@ target_link_libraries(Picture ${PROJECT_NAME})
|
||||||
set_property(TARGET Picture PROPERTY
|
set_property(TARGET Picture PROPERTY
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG})
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG})
|
||||||
|
|
||||||
|
|
||||||
## Application Tile
|
## Application Tile
|
||||||
#add_executable(Tile src/App_Tile.cpp)
|
#add_executable(Tile src/App_Tile.cpp
|
||||||
|
# src/Tile.h
|
||||||
|
# src/Tile.cpp
|
||||||
|
# )
|
||||||
### custom definitions
|
### custom definitions
|
||||||
#target_compile_definitions(Tile PRIVATE cimg_use_png)
|
#target_compile_definitions(Tile PRIVATE cimg_use_png)
|
||||||
### dependencies
|
### dependencies
|
||||||
#if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "9")
|
#if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "9")
|
||||||
# target_link_libraries(Tile stdc++fs) # filesystem lib not included in stdc++ for gcc < 9
|
# target_link_libraries(Tile stdc++fs) # filesystem lib not included in stdc++ for gcc < 9
|
||||||
#endif()
|
#endif()
|
||||||
|
#conan_set_find_library_paths(Tile)
|
||||||
|
#conan_target_link_libraries(Tile)
|
||||||
|
#target_link_libraries(Picture ${PROJECT_NAME})
|
||||||
|
### output
|
||||||
#set_property(TARGET Tile PROPERTY
|
#set_property(TARGET Tile PROPERTY
|
||||||
# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG})
|
# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}
|
||||||
#target_include_directories(Tile PRIVATE
|
|
||||||
# ${CONAN_INCLUDE_DIRS_SDL}
|
|
||||||
# ${CONAN_INCLUDE_DIRS_TCLAP})
|
|
||||||
#target_link_libraries(Tile PRIVATE
|
|
||||||
# CONAN_PKG::sdl
|
|
||||||
# ${PROJECT_NAME}
|
|
||||||
#)
|
#)
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define SDL_MAIN_HANDLED
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -27,9 +28,7 @@
|
||||||
#include <tclap/CmdLine.h>
|
#include <tclap/CmdLine.h>
|
||||||
|
|
||||||
#include "ImageQuantized.h"
|
#include "ImageQuantized.h"
|
||||||
//#include "Picture.h"
|
#include "Display.h"
|
||||||
//#include "Tile.h"
|
|
||||||
//#include "Display.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace RgbToHires;
|
using namespace RgbToHires;
|
||||||
|
@ -108,21 +107,23 @@ int main( int argc, char *argv[] )
|
||||||
}
|
}
|
||||||
const ImageQuantized imageHiRes{ surfaceRgb };
|
const ImageQuantized imageHiRes{ surfaceRgb };
|
||||||
|
|
||||||
if (assembly.getValue() == true) { //Ouput in ASM
|
if (preview.getValue()) {
|
||||||
ofstream output(outputPath.getValue());
|
const auto bytes = imageHiRes.getHiresBuffer();
|
||||||
output << imageHiRes.getAsm();
|
Display::Window::GetInstance()->display(filepath, bytes->data());
|
||||||
}
|
}
|
||||||
else { //Binary output
|
else
|
||||||
ofstream output(outputPath.getValue(), ios::binary);
|
{
|
||||||
const auto bytes = imageHiRes.getBlob();
|
if (assembly.getValue() == true) { //Ouput in ASM
|
||||||
output.write(reinterpret_cast<const char*>(bytes.get()), bytes->size());
|
ofstream output(outputPath.getValue());
|
||||||
|
output << imageHiRes.getHiresAsm();
|
||||||
|
}
|
||||||
|
else { //Binary output
|
||||||
|
ofstream output(outputPath.getValue(), ios::binary);
|
||||||
|
const auto bytes = imageHiRes.getHiresBuffer();
|
||||||
|
output.write(reinterpret_cast<const char*>(bytes.get()), bytes->size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (preview.getValue()) {
|
|
||||||
// const auto bytes = imageHiRes.getBlob();
|
|
||||||
// Display::Window::GetInstance()->display(filepath, bytes->data());
|
|
||||||
//}
|
|
||||||
|
|
||||||
for (auto surface : surfaces)
|
for (auto surface : surfaces)
|
||||||
{
|
{
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
|
|
|
@ -82,7 +82,7 @@ int main( int argc, char *argv[] )
|
||||||
|
|
||||||
// Always output in asm
|
// Always output in asm
|
||||||
ofstream output(outputPath.getValue());
|
ofstream output(outputPath.getValue());
|
||||||
output << tileHiRes.getAsm();
|
output << tileHiRes.getHiresAsm();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#define SDL_MAIN_HANDLED
|
#define SDL_MAIN_HANDLED
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <SDL_image.h>
|
||||||
|
|
||||||
#include "Picture.h"
|
#include "Picture.h"
|
||||||
#include "Display.h"
|
#include "Display.h"
|
||||||
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace RgbToHires
|
|
||||||
{
|
|
||||||
namespace Display
|
namespace Display
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -118,24 +116,29 @@ namespace RgbToHires
|
||||||
{
|
{
|
||||||
bool isDone = false;
|
bool isDone = false;
|
||||||
int nbErrors = 0;
|
int nbErrors = 0;
|
||||||
|
std::vector<SDL_Surface*> surfaces;
|
||||||
while (!isDone) // several attempts as the file may be marked modified before being written
|
while (!isDone) // several attempts as the file may be marked modified before being written
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this_thread::sleep_for(std::chrono::milliseconds(500)); // 500ms between each attempt
|
this_thread::sleep_for(std::chrono::milliseconds(500)); // 500ms between each attempt
|
||||||
// update hires image
|
// update hires image
|
||||||
const auto imageRgb = Magick::Image{ path };
|
SDL_Surface* surfaceRgb = IMG_Load(path.c_str());
|
||||||
auto imageQuantized = ImageQuantized{ imageRgb };
|
surfaces.push_back(surfaceRgb);
|
||||||
const auto imageHiRes = Picture{ imageQuantized };
|
if (surfaceRgb == nullptr)
|
||||||
|
{
|
||||||
|
throw("Cannot decode " + path);
|
||||||
|
}
|
||||||
|
const RgbToHires::ImageQuantized imageHiRes{ surfaceRgb };
|
||||||
|
|
||||||
// rgb conversion from hires data
|
// rgb conversion from hires data
|
||||||
std::lock_guard<std::mutex> lock{ this->_mutex }; // protecting pViewport
|
std::lock_guard<std::mutex> lock{ this->_mutex }; // protecting pViewport
|
||||||
pViewport = ComputeRgbBuffer(imageHiRes.getBlob()->data());
|
pViewport = ComputeRgbBuffer(imageHiRes.getHiresBuffer()->data());
|
||||||
isDone = true;
|
isDone = true;
|
||||||
timeModified = std::filesystem::last_write_time(path);
|
timeModified = std::filesystem::last_write_time(path);
|
||||||
this->_isFileModified.store(isImgModified);
|
this->_isFileModified.store(isImgModified);
|
||||||
}
|
}
|
||||||
catch (Magick::Error& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
++nbErrors;
|
++nbErrors;
|
||||||
if (nbErrors >= 5) { // 5 atttemps
|
if (nbErrors >= 5) { // 5 atttemps
|
||||||
|
@ -146,6 +149,7 @@ namespace RgbToHires
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(auto surface : surfaces) { SDL_FreeSurface(surface); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}); // thread
|
}); // thread
|
||||||
|
@ -179,24 +183,6 @@ namespace RgbToHires
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdlError(const std::string& error,
|
|
||||||
SDL_Window* const pWindow = nullptr,
|
|
||||||
SDL_Renderer* const pRenderer = nullptr
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::cout << "Error: " << error << '\n';
|
|
||||||
|
|
||||||
if (pRenderer != nullptr) {
|
|
||||||
SDL_DestroyRenderer(pRenderer);
|
|
||||||
}
|
|
||||||
if (pWindow != nullptr) {
|
|
||||||
SDL_DestroyWindow(pWindow);
|
|
||||||
}
|
|
||||||
SDL_Quit();
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
constexpr std::array<rgba8Bits_t, 7> Palette = {
|
constexpr std::array<rgba8Bits_t, 7> Palette = {
|
||||||
rgba8Bits_t{0x00,0x00,0x00, 0xFF}, // black
|
rgba8Bits_t{0x00,0x00,0x00, 0xFF}, // black
|
||||||
|
@ -299,9 +285,9 @@ namespace RgbToHires
|
||||||
// Converting line per line, pixel-block per pixel-block
|
// Converting line per line, pixel-block per pixel-block
|
||||||
auto pViewport = make_unique<Screen>();
|
auto pViewport = make_unique<Screen>();
|
||||||
auto itLine = std::begin(*pViewport);
|
auto itLine = std::begin(*pViewport);
|
||||||
for (const auto lineBlockOffset : LineAdresses)
|
for (const auto lineBlockOffset : RgbToHires::LineAdresses)
|
||||||
{
|
{
|
||||||
for (const auto lineOffset : LineOffsets)
|
for (const auto lineOffset : RgbToHires::LineOffsets)
|
||||||
{
|
{
|
||||||
const uint8_t* pHires = hires + lineBlockOffset + lineOffset; // interleaved HIRES source line
|
const uint8_t* pHires = hires + lineBlockOffset + lineOffset; // interleaved HIRES source line
|
||||||
for (std::size_t x = 0; x < itLine->size(); ++x)
|
for (std::size_t x = 0; x < itLine->size(); ++x)
|
||||||
|
@ -317,6 +303,4 @@ namespace RgbToHires
|
||||||
return pViewport;
|
return pViewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,51 +29,48 @@ struct SDL_Window;
|
||||||
struct SDL_Renderer;
|
struct SDL_Renderer;
|
||||||
struct SDL_Texture;
|
struct SDL_Texture;
|
||||||
|
|
||||||
namespace RgbToHires
|
namespace Display
|
||||||
{
|
{
|
||||||
namespace Display
|
|
||||||
{
|
|
||||||
|
|
||||||
struct rgba8Bits_t
|
struct rgba8Bits_t
|
||||||
{
|
{
|
||||||
uint8_t r = 0;
|
uint8_t r = 0;
|
||||||
uint8_t g = 0;
|
uint8_t g = 0;
|
||||||
uint8_t b = 0;
|
uint8_t b = 0;
|
||||||
uint8_t a = 0xff;
|
uint8_t a = 0xff;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Block = std::array<rgba8Bits_t, 14>;
|
using Block = std::array<rgba8Bits_t, 14>;
|
||||||
using Line = std::array<Block, 40>;
|
using Line = std::array<Block, 40>;
|
||||||
using Screen = std::array<Line, 192 * 2>;
|
using Screen = std::array<Line, 192 * 2>;
|
||||||
|
|
||||||
class Window
|
class Window
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Window() = default;
|
Window() = default;
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
static Window* GetInstance();
|
static Window* GetInstance();
|
||||||
|
|
||||||
void display(const std::string& path, const uint8_t* hiresblob);
|
void display(const std::string& path, const uint8_t* hiresblob);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init();
|
bool init();
|
||||||
void sdlError(const std::string& msg);
|
void sdlError(const std::string& msg);
|
||||||
|
|
||||||
std::thread* _pThread = nullptr; //< to survey filechange
|
std::thread* _pThread = nullptr; //< to survey filechange
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
std::atomic_bool _isFileModified = false;
|
std::atomic_bool _isFileModified = false;
|
||||||
std::atomic_bool _stopFileSurvey = false;
|
std::atomic_bool _stopFileSurvey = false;
|
||||||
|
|
||||||
static Window* S_pInstance;
|
static Window* S_pInstance;
|
||||||
static const int SCALE = 2;
|
static const int SCALE = 2;
|
||||||
|
|
||||||
SDL_Window* _pWindow = nullptr;
|
SDL_Window* _pWindow = nullptr;
|
||||||
SDL_Renderer* _pRenderer = nullptr;
|
SDL_Renderer* _pRenderer = nullptr;
|
||||||
SDL_Texture* _pTexture = nullptr;
|
SDL_Texture* _pTexture = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace RgbToHires {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unique_ptr<array<uint8_t, ImageQuantized::FRAME_SIZE>> ImageQuantized::getBlob() const
|
unique_ptr<array<uint8_t, ImageQuantized::FRAME_SIZE>> ImageQuantized::getHiresBuffer() const
|
||||||
{
|
{
|
||||||
auto blob = unique_ptr<array<uint8_t, FRAME_SIZE>>{ new array<uint8_t, FRAME_SIZE> };
|
auto blob = unique_ptr<array<uint8_t, FRAME_SIZE>>{ new array<uint8_t, FRAME_SIZE> };
|
||||||
auto byte_blob = begin(*blob);
|
auto byte_blob = begin(*blob);
|
||||||
|
@ -97,7 +97,7 @@ namespace RgbToHires {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string ImageQuantized::getAsm() const
|
string ImageQuantized::getHiresAsm() const
|
||||||
{
|
{
|
||||||
string assembly{ "Picture:\n" };
|
string assembly{ "Picture:\n" };
|
||||||
for (const auto& line : _hrOrderedLines)
|
for (const auto& line : _hrOrderedLines)
|
||||||
|
@ -155,6 +155,7 @@ namespace RgbToHires {
|
||||||
const auto distOrange = Distance(ORANGE, color);
|
const auto distOrange = Distance(ORANGE, color);
|
||||||
if (distMin > distOrange) { distMin = distOrange; }
|
if (distMin > distOrange) { distMin = distOrange; }
|
||||||
const auto distViolet = Distance(VIOLET, color);
|
const auto distViolet = Distance(VIOLET, color);
|
||||||
|
if (distMin > distViolet) { distMin = distViolet; }
|
||||||
|
|
||||||
if (distMin == distBlack) {
|
if (distMin == distBlack) {
|
||||||
return BLACK;
|
return BLACK;
|
||||||
|
|
|
@ -49,11 +49,11 @@ namespace RgbToHires {
|
||||||
ImageQuantized(SDL_Surface* const source);
|
ImageQuantized(SDL_Surface* const source);
|
||||||
~ImageQuantized() = default;
|
~ImageQuantized() = default;
|
||||||
|
|
||||||
|
|
||||||
/// @brief Returns the binary hires picture
|
/// @brief Returns the binary hires picture
|
||||||
std::unique_ptr <std::array<uint8_t, FRAME_SIZE>> getBlob() const;
|
std::unique_ptr <std::array<uint8_t, FRAME_SIZE>> getHiresBuffer() const;
|
||||||
/// @brief Returns asm code corresponding to the image in memory (CA65 format)
|
/// @brief Returns asm code corresponding to the image in memory (CA65 format)
|
||||||
std::string getAsm() const;
|
std::string getHiresAsm() const;
|
||||||
|
/// @brief Returns an HIRES block
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Color Quantize(const Color& color);
|
Color Quantize(const Color& color);
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace RgbToHires
|
||||||
/// @brief Returns the binary hires picture
|
/// @brief Returns the binary hires picture
|
||||||
std::unique_ptr <std::array<uint8_t, FRAME_SIZE>> getBlob() const;
|
std::unique_ptr <std::array<uint8_t, FRAME_SIZE>> getBlob() const;
|
||||||
/// @brief Returns asm code corresponding to the image in memory (CA65 format)
|
/// @brief Returns asm code corresponding to the image in memory (CA65 format)
|
||||||
std::string getAsm() const;
|
std::string getHiresAsm() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ RgbToHires::Tile::Tile(const ImageQuantized& source, const unsigned col, const u
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RgbToHires::Tile::getAsm() const
|
std::string RgbToHires::Tile::getHiresAsm() const
|
||||||
{
|
{
|
||||||
std::string assembly;
|
std::string assembly;
|
||||||
for (const auto& line : _blob)
|
for (const auto& line : _blob)
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace RgbToHires
|
||||||
~Tile() = default;
|
~Tile() = default;
|
||||||
|
|
||||||
/// @brief Returns asm code corresponding to the tile: the lines are not interleaved!
|
/// @brief Returns asm code corresponding to the tile: the lines are not interleaved!
|
||||||
std::string getAsm() const;
|
std::string getHiresAsm() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using LineHr = std::vector<BlockHr>;
|
using LineHr = std::vector<BlockHr>;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user