add export layers, export png, import brush padding
This commit is contained in:
@@ -835,23 +835,23 @@ Here's a list of what's available in this release.
|
||||
<!--popup menu-->
|
||||
<layout id="popup-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="camera" width="20"/>
|
||||
<text text="Snapshot" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="layers" width="20"/>
|
||||
<text text="Layers" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_white" width="20"/>
|
||||
<text text="New Layer" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_white_paste" width="20"/>
|
||||
<text text="Paste" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_white_stack" width="20"/>
|
||||
<text text="Copy" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
@@ -875,7 +875,7 @@ Here's a list of what's available in this release.
|
||||
</node>
|
||||
</button-custom>
|
||||
-->
|
||||
<button-custom id="file-newdoc" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-newdoc" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_add" width="20"/>
|
||||
<text text="New Pano" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
<text text="Ctrl-N" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||
@@ -885,80 +885,97 @@ Here's a list of what's available in this release.
|
||||
<text text="Import" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<!--
|
||||
<button-custom id="file-open" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-open" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_add" width="20"/>
|
||||
<text text="Open" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
-->
|
||||
<button-custom id="file-browse" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-browse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="images" width="20"/>
|
||||
<text text="Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
<text text="Ctrl-Shift-O" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-open" os="osx,win" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-open" os="osx,win" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="image" width="20"/>
|
||||
<text text="Open Path" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
<text text="Ctrl-O" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-save" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-save" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="disk" width="20"/>
|
||||
<text text="Save" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
<text text="Ctrl-S" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-save-as" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-save-as" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="disk_multiple" width="20"/>
|
||||
<text text="Save As.." grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-save-ver" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-save-ver" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="disk_multiple" width="20"/>
|
||||
<text text="Save Version" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
<text text="Ctrl-Shift-S" color=".4" justify="flex-end" margin="0 10 0 10" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-export" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<node dir="row">
|
||||
<button-custom id="file-export" height="40" align="center" color=".2" pad="0 0 0 10" dir="row" grow="1">
|
||||
<icon icon="picture_go" width="20"/>
|
||||
<text text="Export JPG" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-share" os="osx,ios" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-export-tick" height="40" width="40" align="center" justify="center" color=".2" dir="row">
|
||||
<icon icon="resultset_next" width="20"/>
|
||||
</button-custom>
|
||||
</node>
|
||||
<button-custom id="file-share" os="osx,ios" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="picture_go" width="20"/>
|
||||
<text text="Share" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-resize" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-resize" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="arrow_out" width="20"/>
|
||||
<text text="Resize Document" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<!--
|
||||
<button-custom id="file-export-cubes" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-export-cubes" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_white_stack" width="20"/>
|
||||
<text text="Export Cubes" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
-->
|
||||
<button-custom id="file-cloud-upload" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-cloud-upload" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="weather_clouds" width="20"/>
|
||||
<text text="Cloud Publish" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-cloud-browse" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom id="file-cloud-browse" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="weather_clouds" width="20"/>
|
||||
<text text="Cloud Browse" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<!--<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<!--<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon width="20"/>
|
||||
<text text="Quit" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>-->
|
||||
</popup-menu>
|
||||
</layout>
|
||||
|
||||
<!--file submenu - export-->
|
||||
<layout id="file-submenu-export">
|
||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<button-custom id="file-submenu-export-png" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<text text="PNG" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-submenu-export-layers" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<text text="Separate Layers" grow="1" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
</popup-menu>
|
||||
</layout>
|
||||
|
||||
<!--edit menu-->
|
||||
<layout id="edit-menu">
|
||||
<popup-menu positioning="absolute" position="100 100" width="150" thickness="1" border-color=".1" color=".4 .4 .4 .8" dir="col">
|
||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_add" width="20"/>
|
||||
<text text="New Panodoc" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="disk" width="20"/>
|
||||
<text text="Save" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<button-custom height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="disk_multiple" width="20"/>
|
||||
<text text="Save as.." margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
NodeMessageBox* msgbox;
|
||||
NodeSettings* settings;
|
||||
NodePopupMenu* popup = nullptr;
|
||||
NodePopupMenu* subpopup = nullptr;
|
||||
NodePopupMenu* menu_file = nullptr;
|
||||
NodePopupMenu* menu_edit = nullptr;
|
||||
NodePopupMenu* menu_layers = nullptr;
|
||||
@@ -178,7 +179,8 @@ public:
|
||||
void dialog_save_ver();
|
||||
void dialog_open();
|
||||
void dialog_browse();
|
||||
void dialog_export();
|
||||
void dialog_export(std::string ext);
|
||||
void dialog_export_layers();
|
||||
void dialog_export_cubes();
|
||||
void dialog_layer_rename();
|
||||
void dialog_resize();
|
||||
|
||||
@@ -412,7 +412,7 @@ void App::dialog_save()
|
||||
}
|
||||
}
|
||||
|
||||
void App::dialog_export()
|
||||
void App::dialog_export(std::string ext)
|
||||
{
|
||||
if (!check_license())
|
||||
{
|
||||
@@ -423,7 +423,30 @@ void App::dialog_export()
|
||||
if (canvas)
|
||||
{
|
||||
// TODO: use picker
|
||||
canvas->m_canvas->export_equirectangular(work_path + "/" + doc_name + ".jpg", [this]{
|
||||
canvas->m_canvas->export_equirectangular(work_path + "/" + doc_name + ext, [this]{
|
||||
#if defined(__IOS__)
|
||||
message_box("Export JPG", "Image exported to Photos");
|
||||
#elif defined(__OSX__)
|
||||
message_box("Export JPG", "Image exported to Pictures/PanoPainter folder");
|
||||
#elif defined(_WIN32)
|
||||
message_box("Export JPG", "Image exported to " + work_path);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void App::dialog_export_layers()
|
||||
{
|
||||
if (!check_license())
|
||||
{
|
||||
message_box("License", "This function is disabled in demo mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (canvas)
|
||||
{
|
||||
// TODO: use picker
|
||||
canvas->m_canvas->export_layers(doc_name, [this] {
|
||||
#if defined(__IOS__)
|
||||
message_box("Export JPG", "Image exported to Photos");
|
||||
#elif defined(__OSX__)
|
||||
|
||||
@@ -21,7 +21,7 @@ void App::init_toolbar_main()
|
||||
button->on_click = [this, button](Node*) {
|
||||
if (canvas)
|
||||
{
|
||||
canvas->m_canvas->export_anim();
|
||||
//canvas->m_canvas->export_anim();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -463,10 +463,40 @@ void App::init_menu_file()
|
||||
};
|
||||
if (auto b = popup->find<NodeButtonCustom>("file-export"))
|
||||
b->on_click = [this](Node*) {
|
||||
dialog_export();
|
||||
dialog_export(".jpg");
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
if (auto b = popup->find<NodeButtonCustom>("file-export-tick"))
|
||||
b->on_click = [this,b](Node*) {
|
||||
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
|
||||
subpopup = (NodePopupMenu*)layout[const_hash("file-submenu-export")]->m_children[0]->clone();
|
||||
subpopup->update();
|
||||
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
|
||||
pos.x = pos.x - subpopup->m_size.x + b->m_size.x;
|
||||
subpopup->SetPositioning(YGPositionTypeAbsolute);
|
||||
subpopup->SetPosition(pos.x, pos.y);
|
||||
layout[main_id]->add_child(subpopup);
|
||||
layout[main_id]->update();
|
||||
subpopup->mouse_capture();
|
||||
subpopup->m_mouse_ignore = false;
|
||||
subpopup->m_flood_events = true;
|
||||
subpopup->m_capture_children = false;
|
||||
subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [this](Node*) {
|
||||
dialog_export(".png");
|
||||
subpopup->mouse_release();
|
||||
subpopup->destroy();
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
subpopup->find<NodeButtonCustom>("file-submenu-export-layers")->on_click = [this](Node*) {
|
||||
dialog_export_layers();
|
||||
subpopup->mouse_release();
|
||||
subpopup->destroy();
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
};
|
||||
if (auto b = popup->find<NodeButtonCustom>("file-share"))
|
||||
b->on_click = [this](Node*) {
|
||||
share_file(doc_path);
|
||||
|
||||
@@ -168,15 +168,15 @@ void App::initShaders()
|
||||
"void main() {\n"
|
||||
" mediump float stroke = 1.0 - texture(tex, uv).r;\n"
|
||||
" int zero_count = 0;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(-1, -1)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(-1, 0)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(-1, +1)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2( 0, -1)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2( 0, 0)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2( 0, +1)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(+1, -1)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(+1, 0)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(+1, +1)).r == 1.0) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(-1, -1)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(-1, 0)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(-1, +1)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2( 0, -1)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2( 0, 0)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2( 0, +1)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(+1, -1)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(+1, 0)).r > 0.99) zero_count++;\n"
|
||||
" if (textureOffset(tex, uv, ivec2(+1, +1)).r > 0.99) zero_count++;\n"
|
||||
" mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0;\n"
|
||||
" frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f));\n"
|
||||
"}\n";
|
||||
|
||||
104
src/canvas.cpp
104
src/canvas.cpp
@@ -1334,7 +1334,7 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
face.bind();
|
||||
// copy the framebuffer before clearing to white
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height);
|
||||
m_tmp[i].clear({ 1, 1, 1, 1 });
|
||||
m_tmp[i].clear({ 1, 1, 1, 0 });
|
||||
m_plane.draw_fill();
|
||||
face.unbind();
|
||||
|
||||
@@ -1402,10 +1402,10 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
}
|
||||
|
||||
LOG("writing %s", file_path.c_str());
|
||||
jpge::params params;
|
||||
params.m_quality = 100;
|
||||
bool saved = jpge::compress_image_to_jpeg_file(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), params);
|
||||
inject_xmp(file_path.c_str());
|
||||
if (file_path.substr(file_path.size() - 4) == ".jpg")
|
||||
stbi_write_jpg(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 100);
|
||||
else if (file_path.substr(file_path.size() - 4) == ".png")
|
||||
stbi_write_png(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 0);
|
||||
|
||||
{
|
||||
progress++;
|
||||
@@ -1503,10 +1503,21 @@ void Canvas::inject_xmp(std::string jpg_path)
|
||||
|
||||
}
|
||||
|
||||
void Canvas::export_anim()
|
||||
void Canvas::export_layers(std::string file_name, std::function<void()> on_complete)
|
||||
{
|
||||
if (App::I.check_license())
|
||||
{
|
||||
std::thread t([=] {
|
||||
export_layers_thread(file_name);
|
||||
if (on_complete)
|
||||
on_complete();
|
||||
});
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::export_layers_thread(std::string file_name)
|
||||
{
|
||||
if (!App::I.check_license())
|
||||
return;
|
||||
// save viewport and clear color states
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
@@ -1514,6 +1525,24 @@ void Canvas::export_anim()
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
GLboolean blend = glIsEnabled(GL_BLEND);
|
||||
|
||||
gl_state gl;
|
||||
App::I.async_start();
|
||||
std::shared_ptr<NodeProgressBar> pb;
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb = std::make_shared<NodeProgressBar>();
|
||||
pb->m_manager = &App::I.layout;
|
||||
pb->init();
|
||||
pb->create();
|
||||
pb->loaded();
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Export Pano Layers");
|
||||
App::I.layout[App::I.main_id]->add_child(pb);
|
||||
App::I.async_update();
|
||||
}
|
||||
int progress = 0;
|
||||
int total = (m_order.size() + 1) * 6;
|
||||
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
|
||||
@@ -1540,20 +1569,21 @@ void Canvas::export_anim()
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
m_tmp[i].bindFramebuffer();
|
||||
|
||||
if (seq == 0)
|
||||
{
|
||||
m_tmp[i].clear({ 1, 1, 1, 1 });
|
||||
ShaderManager::use(kShader::Checkerboard);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
m_plane.draw_fill();
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
else
|
||||
//if (seq == 0)
|
||||
//{
|
||||
// m_tmp[i].clear({ 1, 1, 1, 1 });
|
||||
// ShaderManager::use(kShader::Checkerboard);
|
||||
// ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
// m_plane.draw_fill();
|
||||
// glEnable(GL_BLEND);
|
||||
//}
|
||||
//else
|
||||
{
|
||||
m_tmp[i].clear({ 1, 1, 1, 0 });
|
||||
glDisable(GL_BLEND);
|
||||
//glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@@ -1575,6 +1605,18 @@ void Canvas::export_anim()
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
LOG("progress: %f", p);
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1596,19 +1638,37 @@ void Canvas::export_anim()
|
||||
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
||||
m_latlong.readTextureData(latlong_data.get());
|
||||
static char name[128];
|
||||
sprintf(name, "%s/latlong-frame%02d.png", App::I.work_path.c_str(), seq);
|
||||
sprintf(name, "%s/%s-layer-%02d.png", App::I.work_path.c_str(), file_name.c_str(), seq);
|
||||
seq++;
|
||||
LOG("writing %s", name);
|
||||
App::I.async_end();
|
||||
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
//jpge::params params;
|
||||
//params.m_quality = 100;
|
||||
//bool saved = jpge::compress_image_to_jpeg_file(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), params);
|
||||
App::I.async_start();
|
||||
}
|
||||
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
LOG("progress: %f", p);
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &cube_id);
|
||||
m_latlong.destroy();
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->destroy();
|
||||
App::I.async_update();
|
||||
}
|
||||
App::I.async_end();
|
||||
|
||||
// restore viewport and clear color states
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
|
||||
@@ -242,7 +242,8 @@ public:
|
||||
void import_equirectangular_thread(std::string file_path);
|
||||
void export_equirectangular(std::string file_path, std::function<void()> on_complete = nullptr);
|
||||
void export_equirectangular_thread(std::string file_path);
|
||||
void export_anim();
|
||||
void export_layers(std::string file_name, std::function<void()> on_complete = nullptr);
|
||||
void export_layers_thread(std::string file_name);
|
||||
void export_cubes();
|
||||
void project_save(std::function<void(bool)> on_complete = nullptr);
|
||||
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
|
||||
|
||||
@@ -59,6 +59,18 @@ void Image::flip()
|
||||
std::swap(m_data, flipped);
|
||||
}
|
||||
|
||||
void Image::gayscale_alpha()
|
||||
{
|
||||
int np = width * height;
|
||||
auto ptr = reinterpret_cast<glm::u8vec4*>(m_data.get());
|
||||
for (int i = 0; i < np; i++)
|
||||
{
|
||||
auto& c = ptr[i];
|
||||
c.g = c.b = c.r = 255 - c.a;
|
||||
c.a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
Image Image::resize(int w, int h) const
|
||||
{
|
||||
Image ret;
|
||||
@@ -90,3 +102,50 @@ Image Image::resize(int w, int h) const
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Image Image::resize_power2() const
|
||||
{
|
||||
int w = pow(2, ceil(log(width) / log(2)));
|
||||
int h = pow(2, ceil(log(height) / log(2)));
|
||||
if (w == width && h == height)
|
||||
{
|
||||
Image i;
|
||||
i.create(width, height);
|
||||
std::copy(m_data.get(), m_data.get() + width * height * comp, i.m_data.get());
|
||||
return i;
|
||||
}
|
||||
return resize(w, h);
|
||||
}
|
||||
|
||||
Image Image::resize_squared() const
|
||||
{
|
||||
Image ret;
|
||||
if (width == height)
|
||||
{
|
||||
ret.create(width, height);
|
||||
std::copy(m_data.get(), m_data.get() + width * height * comp, ret.m_data.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
int pad_x = 0;
|
||||
int pad_y = 0;
|
||||
int size = 0;
|
||||
if (height > width)
|
||||
{
|
||||
size = height;
|
||||
pad_x = (size - width) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = width;
|
||||
pad_y = (size - height) / 2;
|
||||
}
|
||||
ret.create(size, size);
|
||||
auto ptr_src = reinterpret_cast<glm::u8vec4*>(m_data.get());
|
||||
auto ptr_dst = reinterpret_cast<glm::u8vec4*>(ret.m_data.get());
|
||||
std::fill_n(ptr_dst, size * size, glm::u8vec4(0));
|
||||
for (int y = 0; y < height; y++)
|
||||
std::copy_n(ptr_src + y * width, width, ptr_dst + pad_x + (y + pad_y) * ret.width);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ public:
|
||||
m_data.reset();
|
||||
}
|
||||
void flip();
|
||||
// convert to grayscale and set opaque
|
||||
void gayscale_alpha();
|
||||
void create() { m_data = std::make_unique<uint8_t[]>(size()); }
|
||||
Image resize(int w, int h) const;
|
||||
Image resize_power2() const;
|
||||
Image resize_squared() const;
|
||||
};
|
||||
|
||||
@@ -65,9 +65,14 @@ void NodePanelBrush::init()
|
||||
|
||||
std::string path_high = App::I.data_path + "/brushes/" + name + ".png";
|
||||
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + name + ".png";
|
||||
|
||||
img = img.resize_squared();
|
||||
img.gayscale_alpha();
|
||||
|
||||
auto thumb = img.resize(64, 64);
|
||||
thumb.save(path_thumb);
|
||||
img.save(path_high);
|
||||
auto po2 = img.resize_power2();
|
||||
po2.save(path_high);
|
||||
|
||||
async_start();
|
||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||
@@ -75,7 +80,7 @@ void NodePanelBrush::init()
|
||||
brush->init();
|
||||
brush->create();
|
||||
brush->loaded();
|
||||
brush->set_icon(path.c_str());
|
||||
brush->set_icon(path_thumb.c_str());
|
||||
brush->thumb_path = path_thumb;
|
||||
brush->high_path = path_high;
|
||||
brush->brush_name = name;
|
||||
|
||||
Reference in New Issue
Block a user