memory fixes, GTK example added
This commit is contained in:
parent
c9b33b324d
commit
e1bdccfb0d
7 changed files with 286 additions and 5 deletions
|
@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
message("-- Testing codecvt")
|
message("-- Testing codecvt")
|
||||||
try_run(CODECVT_RUN CODECVT_COMPILE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/tests/CodecvtTest.cpp)
|
try_run(CODECVT_RUN CODECVT_COMPILE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/tests/CodecvtTest.cpp)
|
||||||
if (CODECVT_COMPILE)
|
if (CODECVT_COMPILE AND CODECVT_RUN EQUAL 0)
|
||||||
list(APPEND LIBRAGEPHOTO_DEFINES
|
list(APPEND LIBRAGEPHOTO_DEFINES
|
||||||
CODECVT_COMPATIBLE
|
CODECVT_COMPATIBLE
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,7 @@ endif()
|
||||||
|
|
||||||
message("-- Testing iconv")
|
message("-- Testing iconv")
|
||||||
try_run(ICONV_RUN ICONV_COMPILE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/tests/IconvTest.cpp)
|
try_run(ICONV_RUN ICONV_COMPILE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/tests/IconvTest.cpp)
|
||||||
if (ICONV_COMPILE)
|
if (ICONV_COMPILE AND ICONV_RUN EQUAL 0)
|
||||||
list(APPEND LIBRAGEPHOTO_DEFINES
|
list(APPEND LIBRAGEPHOTO_DEFINES
|
||||||
ICONV_COMPATIBLE
|
ICONV_COMPATIBLE
|
||||||
)
|
)
|
||||||
|
@ -60,6 +60,11 @@ target_compile_definitions(ragephoto PRIVATE
|
||||||
install(TARGETS ragephoto DESTINATION lib)
|
install(TARGETS ragephoto DESTINATION lib)
|
||||||
install(FILES ${RAGEPHOTO_HEADERS} DESTINATION include)
|
install(FILES ${RAGEPHOTO_HEADERS} DESTINATION include)
|
||||||
|
|
||||||
|
option(WITH_EXAMPLES "Build ragephoto examples" OFF)
|
||||||
|
if (WITH_EXAMPLES)
|
||||||
|
add_subdirectory(examples/ragephoto-gtkviewer)
|
||||||
|
endif()
|
||||||
|
|
||||||
option(WITH_EXTRACT "Build ragephoto-extract" ON)
|
option(WITH_EXTRACT "Build ragephoto-extract" ON)
|
||||||
if (WITH_EXTRACT)
|
if (WITH_EXTRACT)
|
||||||
project(ragephoto-extract LANGUAGES CXX)
|
project(ragephoto-extract LANGUAGES CXX)
|
||||||
|
|
30
examples/ragephoto-gtkviewer/CMakeLists.txt
Normal file
30
examples/ragephoto-gtkviewer/CMakeLists.txt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(gtkmm REQUIRED gtkmm-3.0)
|
||||||
|
|
||||||
|
project(ragephoto-gtkviewer LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(GTKVIEWER_HEADERS
|
||||||
|
src/PhotoViewer.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(GTKVIEWER_SOURCES
|
||||||
|
src/main.cpp
|
||||||
|
src/PhotoViewer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if(TARGET ragephoto)
|
||||||
|
set(RAGEPHOTO_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
add_executable(ragephoto-gtkviewer ${GTKVIEWER_HEADERS} ${GTKVIEWER_SOURCES})
|
||||||
|
target_link_libraries(ragephoto-gtkviewer ${gtkmm_LIBRARIES} ragephoto)
|
||||||
|
target_link_directories(ragephoto-gtkviewer PRIVATE ${gtkmm_LIBRARY_DIRS})
|
||||||
|
target_include_directories(ragephoto-gtkviewer PRIVATE ${gtkmm_INCLUDE_DIRS} ${RAGEPHOTO_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
message("ragephoto-gtkviewer need to be build with libragephoto together")
|
||||||
|
endif()
|
102
examples/ragephoto-gtkviewer/src/PhotoViewer.cpp
Normal file
102
examples/ragephoto-gtkviewer/src/PhotoViewer.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* libragephoto RAGE Photo Parser
|
||||||
|
* Copyright (C) 2021 Syping
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* This software is provided as-is, no warranties are given to you, we are not
|
||||||
|
* responsible for anything with use of the software, you are self responsible.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "PhotoViewer.h"
|
||||||
|
#include <cairomm/context.h>
|
||||||
|
#include <gdkmm/general.h>
|
||||||
|
#include <RagePhoto.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
PhotoViewer::PhotoViewer(Gtk::Label *title_label, Gtk::Label *json_label) : p_title_label(title_label), p_json_label(json_label)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoViewer::open_file(const char *filename)
|
||||||
|
{
|
||||||
|
RagePhoto ragePhoto;
|
||||||
|
// Read file
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int fseek_end_value = fseek(file, 0, SEEK_END);
|
||||||
|
if (fseek_end_value == -1) {
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const size_t file_size = ftell(file);
|
||||||
|
if (file_size == -1) {
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int fseek_set_value = fseek(file, 0, SEEK_SET);
|
||||||
|
if (fseek_set_value == -1) {
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *data = static_cast<char*>(malloc(file_size));
|
||||||
|
const size_t file_rsize = fread(data, 1, file_size, file);
|
||||||
|
if (file_size != file_rsize) {
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
const bool loaded = ragePhoto.load(data, file_size);
|
||||||
|
free(data);
|
||||||
|
if (!loaded) {
|
||||||
|
const RagePhoto::Error error = ragePhoto.error();
|
||||||
|
if (error <= RagePhoto::Error::PhotoReadError)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
guchar *photoData = static_cast<guchar*>(malloc(ragePhoto.photoSize()));
|
||||||
|
if (!photoData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(photoData, ragePhoto.photoData(), ragePhoto.photoSize());
|
||||||
|
|
||||||
|
GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
|
||||||
|
gdk_pixbuf_loader_write(loader, photoData, static_cast<gsize>(ragePhoto.photoSize()), nullptr);
|
||||||
|
GdkPixbuf *c_pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
|
||||||
|
p_image = Glib::wrap(c_pixbuf);
|
||||||
|
|
||||||
|
p_title_label->set_text("Title: " + ragePhoto.title());
|
||||||
|
// p_title_label->show();
|
||||||
|
|
||||||
|
get_parent_window()->set_title("RagePhoto GTK Photo Viewer - " + ragePhoto.title());
|
||||||
|
|
||||||
|
free(photoData);
|
||||||
|
|
||||||
|
if (p_image)
|
||||||
|
set_size_request(p_image->get_width(), p_image->get_height());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhotoViewer::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
|
||||||
|
{
|
||||||
|
if (!p_image)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Gtk::Allocation allocation = get_allocation();
|
||||||
|
const int width = allocation.get_width();
|
||||||
|
const int height = allocation.get_height();
|
||||||
|
|
||||||
|
Gdk::Cairo::set_source_pixbuf(cr, p_image, (width - p_image->get_width()) / 2, (height - p_image->get_height()) / 2);
|
||||||
|
cr->paint();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
39
examples/ragephoto-gtkviewer/src/PhotoViewer.h
Normal file
39
examples/ragephoto-gtkviewer/src/PhotoViewer.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* libragephoto RAGE Photo Parser
|
||||||
|
* Copyright (C) 2021 Syping
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* This software is provided as-is, no warranties are given to you, we are not
|
||||||
|
* responsible for anything with use of the software, you are self responsible.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef PHOTOVIEWER_H
|
||||||
|
#define PHOTOVIEWER_H
|
||||||
|
|
||||||
|
#include <gtkmm/drawingarea.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <gdkmm/pixbuf.h>
|
||||||
|
|
||||||
|
class PhotoViewer : public Gtk::DrawingArea
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhotoViewer(Gtk::Label *title_label, Gtk::Label *json_label);
|
||||||
|
void open_file(const char *filename);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> p_image;
|
||||||
|
Gtk::Label *p_title_label;
|
||||||
|
Gtk::Label *p_json_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PHOTOVIEWER_H
|
105
examples/ragephoto-gtkviewer/src/main.cpp
Normal file
105
examples/ragephoto-gtkviewer/src/main.cpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* libragephoto RAGE Photo Parser
|
||||||
|
* Copyright (C) 2021 Syping
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* This software is provided as-is, no warranties are given to you, we are not
|
||||||
|
* responsible for anything with use of the software, you are self responsible.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "PhotoViewer.h"
|
||||||
|
#include <gtkmm/application.h>
|
||||||
|
#include <gtkmm/box.h>
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/filechooserdialog.h>
|
||||||
|
#include <gtkmm/filefilter.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <gtkmm/window.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
auto app = Gtk::Application::create(argc, argv, "de.syping.ragephoto.gtkviewer", Gio::APPLICATION_HANDLES_OPEN);
|
||||||
|
|
||||||
|
Gtk::Window win;
|
||||||
|
win.set_title("RagePhoto GTK Photo Viewer");
|
||||||
|
win.set_default_size(400, 0);
|
||||||
|
win.set_resizable(false);
|
||||||
|
|
||||||
|
Gtk::Box vertical_box(Gtk::ORIENTATION_VERTICAL);
|
||||||
|
|
||||||
|
Gtk::Label title_label;
|
||||||
|
Gtk::Label json_label;
|
||||||
|
PhotoViewer photo_viewer(&title_label, &json_label);
|
||||||
|
vertical_box.add(photo_viewer);
|
||||||
|
vertical_box.add(title_label);
|
||||||
|
vertical_box.add(json_label);
|
||||||
|
photo_viewer.show();
|
||||||
|
|
||||||
|
Gtk::Box horizontal_box(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
|
vertical_box.add(horizontal_box);
|
||||||
|
|
||||||
|
Gtk::Button open_button;
|
||||||
|
open_button.set_label("Open");
|
||||||
|
open_button.set_hexpand(true);
|
||||||
|
open_button.set_can_default(false);
|
||||||
|
open_button.signal_clicked().connect([&](){
|
||||||
|
Gtk::FileChooserDialog dialog("Open Photo", Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||||
|
dialog.set_transient_for(win);
|
||||||
|
|
||||||
|
dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL);
|
||||||
|
dialog.add_button("_Open", Gtk::RESPONSE_OK);
|
||||||
|
|
||||||
|
Glib::RefPtr<Gtk::FileFilter> filter_photo = Gtk::FileFilter::create();
|
||||||
|
filter_photo->set_name("GTA V Photo");
|
||||||
|
filter_photo->add_pattern("PGTA5*");
|
||||||
|
|
||||||
|
int result = dialog.run();
|
||||||
|
|
||||||
|
switch(result) {
|
||||||
|
case Gtk::RESPONSE_OK: {
|
||||||
|
std::string filename = dialog.get_filename();
|
||||||
|
photo_viewer.open_file(filename.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
horizontal_box.add(open_button);
|
||||||
|
open_button.show();
|
||||||
|
|
||||||
|
Gtk::Button close_button;
|
||||||
|
close_button.set_label("Close");
|
||||||
|
close_button.set_hexpand(true);
|
||||||
|
close_button.set_can_default(false);
|
||||||
|
close_button.signal_clicked().connect([&](){
|
||||||
|
win.close();
|
||||||
|
});
|
||||||
|
horizontal_box.add(close_button);
|
||||||
|
close_button.show();
|
||||||
|
|
||||||
|
app->signal_open().connect([&](const Gio::Application::type_vec_files &files, const Glib::ustring &hint){
|
||||||
|
for (const auto &file : files) {
|
||||||
|
photo_viewer.open_file(file->get_path().c_str());
|
||||||
|
}
|
||||||
|
app->add_window(win);
|
||||||
|
win.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
horizontal_box.show();
|
||||||
|
vertical_box.show();
|
||||||
|
|
||||||
|
win.add(vertical_box);
|
||||||
|
|
||||||
|
return app->run(win);
|
||||||
|
}
|
|
@ -86,7 +86,7 @@ bool RagePhoto::load(const char *data, size_t length)
|
||||||
|
|
||||||
#ifdef CODECVT_COMPATIBLE
|
#ifdef CODECVT_COMPATIBLE
|
||||||
char16_t photoHeader16[128];
|
char16_t photoHeader16[128];
|
||||||
memcpy(photoHeader16, photoHeader, sizeof(char) * 256);
|
memcpy(photoHeader16, photoHeader, 256);
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||||
p_photoString = convert.to_bytes(photoHeader16);
|
p_photoString = convert.to_bytes(photoHeader16);
|
||||||
#elif defined ICONV_COMPATIBLE
|
#elif defined ICONV_COMPATIBLE
|
||||||
|
@ -352,7 +352,7 @@ size_t RagePhoto::readBuffer(const char *input, char *output, size_t *pos, size_
|
||||||
readLen = inputLen - *pos;
|
readLen = inputLen - *pos;
|
||||||
if (readLen > len)
|
if (readLen > len)
|
||||||
readLen = len;
|
readLen = len;
|
||||||
memcpy(output, &input[*pos], sizeof(char) * readLen);
|
memcpy(output, &input[*pos], readLen);
|
||||||
*pos = *pos + readLen;
|
*pos = *pos + readLen;
|
||||||
return readLen;
|
return readLen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ int main(int argc, char *argv[])
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
char16_t photoHeader16[128];
|
char16_t photoHeader16[128];
|
||||||
memcpy(photoHeader16, photoHeader, sizeof(char) * 256);
|
memcpy(photoHeader16, photoHeader, 256);
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||||
std::string photoString = convert.to_bytes(photoHeader16);
|
std::string photoString = convert.to_bytes(photoHeader16);
|
||||||
std::cout << photoString << std::endl;
|
std::cout << photoString << std::endl;
|
||||||
|
|
Loading…
Reference in a new issue