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