OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp} Namespace Reference

Functions

bool is_image_file (const boost::filesystem::path &path)
void scan_dir (const boost::filesystem::path &dir, TextureSource source, std::vector< TextureLibraryEntry > &out)
void scan_plugin_textures (std::vector< TextureLibraryEntry > &out)
bool image_has_color (const wxImage &image)
bool encode_color_png_bytes (const wxImage &image, std::vector< unsigned char > &out, std::string &error)
bool encode_gray_png_bytes (const wxImage &image, std::vector< unsigned char > &out, std::string &error)
bool encode_png_bytes (const wxImage &image, std::vector< unsigned char > &out, std::string &error)
wxImage image_from_decoded (const DecodedHeightTexture &image, std::vector< unsigned char > &scratch)
std::vector< unsigned char > read_file_bytes (const std::string &path)
bool is_supported_height_map (const std::vector< unsigned char > &bytes)
std::optional< TextureLibraryEntry > write_user_texture (const std::vector< unsigned char > &bytes, const std::string &stem, std::string &error)
std::vector< std::string > recent_texture_names ()
void store_recent_texture_names (std::vector< std::string > names)
void sort_user_textures (std::vector< TextureLibraryEntry > &library)
bool in_user_texture_dir (const std::string &path)

Variables

std::vector< TextureLibraryEntry > g_library
bool g_library_scanned = false
uint64_t g_library_scan_generation = 0
std::atomic< uint64_t > g_library_generation { 0 }
const char *const RECENT_SECTION = "texture_displacement"
const char *const RECENT_KEY = "recent_textures"
const size_t RECENT_MAX = 200

Function Documentation

◆ encode_color_png_bytes()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::encode_color_png_bytes ( const wxImage & image,
std::vector< unsigned char > & out,
std::string & error )
126{
127 if (image.GetWidth() <= 0 || image.GetHeight() <= 0) {
128 error = _u8L("The selected image is empty.");
129 return false;
130 }
131 wxMemoryOutputStream stream;
132 // Alpha would be lost on the way into DecodedHeightTexture anyway, and a partly transparent
133 // texture reading as black relief is worse than reading as its own colour over the background.
134 wxImage opaque = image;
135 if (opaque.HasAlpha())
136 opaque.ClearAlpha();
137 if (!opaque.SaveFile(stream, wxBITMAP_TYPE_PNG)) {
138 error = _u8L("Failed to prepare the texture for use.");
139 return false;
140 }
141 const size_t size = size_t(stream.GetLength());
142 out.resize(size);
143 stream.CopyTo(out.data(), size);
144 if (out.empty()) {
145 error = _u8L("Failed to prepare the texture for use.");
146 return false;
147 }
148 return true;
149}
#define _u8L(s)
Definition I18N.hpp:11

References _u8L, and encode_color_png_bytes().

Referenced by encode_color_png_bytes(), and encode_png_bytes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ encode_gray_png_bytes()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::encode_gray_png_bytes ( const wxImage & image,
std::vector< unsigned char > & out,
std::string & error )
155{
156 const wxImage gray = image.ConvertToGreyscale();
157 const int w = gray.GetWidth();
158 const int h = gray.GetHeight();
159 if (w <= 0 || h <= 0) {
160 error = _u8L("The selected image is empty.");
161 return false;
162 }
163
164 // wxImage always stores 3 bytes per pixel; after ConvertToGreyscale the three are equal.
165 std::vector<uint8_t> pixels(size_t(w) * size_t(h));
166 const unsigned char *rgb = gray.GetData();
167 for (size_t i = 0; i < pixels.size(); ++i)
168 pixels[i] = rgb[i * 3];
169
170 const boost::filesystem::path tmp = boost::filesystem::temp_directory_path()
171 / boost::filesystem::unique_path("orca_texdisp_%%%%%%%%.png");
172 if (!Slic3r::png::write_gray_to_file(tmp.string(), size_t(w), size_t(h), pixels)) {
173 error = _u8L("Failed to prepare the texture for use.");
174 return false;
175 }
176
177 {
178 std::ifstream ifs(tmp.string(), std::ios::binary);
179 out.assign(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
180 }
181 boost::system::error_code ec;
182 boost::filesystem::remove(tmp, ec);
183
184 if (out.empty()) {
185 error = _u8L("Failed to prepare the texture for use.");
186 return false;
187 }
188 return true;
189}
bool write_gray_to_file(const char *file_name_utf8, size_t width, size_t height, const uint8_t *data_gray)
Definition PNGReadWrite.cpp:341

References _u8L, encode_gray_png_bytes(), and Slic3r::png::write_gray_to_file().

Referenced by encode_gray_png_bytes(), and encode_png_bytes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ encode_png_bytes()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::encode_png_bytes ( const wxImage & image,
std::vector< unsigned char > & out,
std::string & error )
193{
194 return image_has_color(image) ? encode_color_png_bytes(image, out, error)
195 : encode_gray_png_bytes(image, out, error);
196}
bool encode_gray_png_bytes(const wxImage &image, std::vector< unsigned char > &out, std::string &error)
Definition TextureLibrary.cpp:154
bool encode_color_png_bytes(const wxImage &image, std::vector< unsigned char > &out, std::string &error)
Definition TextureLibrary.cpp:125
bool image_has_color(const wxImage &image)
Definition TextureLibrary.cpp:109

References encode_color_png_bytes(), encode_gray_png_bytes(), encode_png_bytes(), and image_has_color().

Referenced by encode_png_bytes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ image_from_decoded()

wxImage Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::image_from_decoded ( const DecodedHeightTexture & image,
std::vector< unsigned char > & scratch )
205{
206 if (image.empty())
207 return wxImage();
208
209 const size_t n = size_t(image.width) * size_t(image.height);
210 scratch.resize(n * 3);
211 if (image.has_color())
212 scratch.assign(image.rgb.begin(), image.rgb.end());
213 else
214 for (size_t i = 0; i < n; ++i)
215 scratch[i * 3] = scratch[i * 3 + 1] = scratch[i * 3 + 2] = image.pixels[i];
216
217 return wxImage(image.width, image.height, scratch.data(), /* static_data */ true);
218}
std::vector< uint8_t > rgb
Definition TextureDisplacement.hpp:537
std::vector< uint8_t > pixels
Definition TextureDisplacement.hpp:532
bool empty() const
Definition TextureDisplacement.hpp:541
int width
Definition TextureDisplacement.hpp:538
int height
Definition TextureDisplacement.hpp:539
bool has_color() const
Definition TextureDisplacement.hpp:542

References Slic3r::DecodedHeightTexture::empty(), Slic3r::DecodedHeightTexture::has_color(), Slic3r::DecodedHeightTexture::height, image_from_decoded(), Slic3r::DecodedHeightTexture::pixels, Slic3r::DecodedHeightTexture::rgb, and Slic3r::DecodedHeightTexture::width.

Referenced by image_from_decoded().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ image_has_color()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::image_has_color ( const wxImage & image)
110{
111 const unsigned char *rgb = image.GetData();
112 if (rgb == nullptr)
113 return false;
114 const size_t n = size_t(image.GetWidth()) * size_t(image.GetHeight());
115 for (size_t i = 0; i < n; ++i)
116 if (rgb[i * 3] != rgb[i * 3 + 1] || rgb[i * 3 + 1] != rgb[i * 3 + 2])
117 return true;
118 return false;
119}

References image_has_color().

Referenced by encode_png_bytes(), and image_has_color().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ in_user_texture_dir()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::in_user_texture_dir ( const std::string & path)
339{
340 const std::string dir = user_texture_dir();
341 if (dir.empty())
342 return false;
343 boost::system::error_code ec;
344 const bool same = boost::filesystem::equivalent(boost::filesystem::path(path).parent_path(),
345 boost::filesystem::path(dir), ec);
346 return !ec && same;
347}
std::string user_texture_dir()
Definition TextureLibrary.cpp:361

References in_user_texture_dir(), and Slic3r::GUI::user_texture_dir().

Referenced by in_user_texture_dir().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_image_file()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::is_image_file ( const boost::filesystem::path & path)
52{
53 std::string ext = path.extension().string();
54 boost::algorithm::to_lower(ext);
55 return ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".bmp";
56}

References is_image_file().

Referenced by is_image_file(), and scan_dir().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_supported_height_map()

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::is_supported_height_map ( const std::vector< unsigned char > & bytes)
229{
230 return !bytes.empty() && png::is_decodable_8bit_png(png::ReadBuf{ bytes.data(), bytes.size() });
231}
bool is_decodable_8bit_png(const ReadBuf &pngbuf)
Definition PNGReadWrite.cpp:214
Definition PNGReadWrite.hpp:49

References Slic3r::png::is_decodable_8bit_png(), and is_supported_height_map().

Referenced by is_supported_height_map().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_file_bytes()

std::vector< unsigned char > Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::read_file_bytes ( const std::string & path)
221{
222 std::ifstream ifs(path, std::ios::binary);
223 return std::vector<unsigned char>(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
224}

References read_file_bytes().

Referenced by read_file_bytes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recent_texture_names()

std::vector< std::string > Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::recent_texture_names ( )
285{
286 std::vector<std::string> names;
287 if (wxTheApp == nullptr) // headless or shutting down: there is no app config to read
288 return names;
289 if (wxGetApp().app_config == nullptr)
290 return names;
291 const std::string value = wxGetApp().app_config->get(RECENT_SECTION, RECENT_KEY);
292 for (size_t begin = 0; begin <= value.size();) {
293 const size_t end = std::min(value.find('/', begin), value.size());
294 if (end > begin)
295 names.push_back(value.substr(begin, end - begin));
296 begin = end + 1;
297 }
298 return names;
299}
const char *const RECENT_SECTION
Definition TextureLibrary.cpp:280
const char *const RECENT_KEY
Definition TextureLibrary.cpp:281

References RECENT_KEY, RECENT_SECTION, and recent_texture_names().

Referenced by recent_texture_names(), and sort_user_textures().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scan_dir()

void Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::scan_dir ( const boost::filesystem::path & dir,
TextureSource source,
std::vector< TextureLibraryEntry > & out )
59{
60 boost::system::error_code ec;
61 if (!boost::filesystem::is_directory(dir, ec))
62 return;
63
64 const size_t first = out.size();
65 for (boost::filesystem::directory_iterator it(dir, ec), end; it != end && !ec; it.increment(ec)) {
66 if (!boost::filesystem::is_regular_file(it->path(), ec) || !is_image_file(it->path()))
67 continue;
68 out.push_back({ it->path().stem().string(), it->path().string(), source });
69 }
70 std::sort(out.begin() + first, out.end(),
71 [](const TextureLibraryEntry &a, const TextureLibraryEntry &b) { return a.name < b.name; });
72}
bool is_image_file(const boost::filesystem::path &path)
Definition TextureLibrary.cpp:51

References is_image_file(), and scan_dir().

Referenced by scan_dir().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scan_plugin_textures()

void Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::scan_plugin_textures ( std::vector< TextureLibraryEntry > & out)
80{
81 std::vector<TextureLibraryEntry> found;
82 for (const ResourceTextureEntry &pack : PluginResourceTextures::instance().entries()) {
83 std::string error;
84 const std::vector<std::string> files =
85 collect_resource_texture_files(pack.texture_dir, pack.plugin_root, error);
86 if (!error.empty()) {
87 BOOST_LOG_TRIVIAL(warning) << "Texture pack '" << pack.display_name << "' was skipped: " << error;
88 continue;
89 }
90 for (const std::string &file : files) {
91 const boost::filesystem::path path(file);
92 found.push_back({ path.stem().string(), file, TextureSource::Plugin, pack.display_name });
93 }
94 }
95
96 std::stable_sort(found.begin(), found.end(), [](const TextureLibraryEntry &a, const TextureLibraryEntry &b) {
97 if (a.pack_name != b.pack_name)
98 return a.pack_name < b.pack_name;
99 return a.name < b.name;
100 });
101 for (TextureLibraryEntry &entry : found)
102 out.push_back(std::move(entry));
103}
static PluginResourceTextures & instance()
Definition PluginResourceTextures.cpp:18
@ Plugin
Definition TextureLibrary.hpp:15
std::vector< std::string > collect_resource_texture_files(const std::string &dir, const std::string &plugin_root, std::string &error)
Definition PluginFsUtils.cpp:1262
Definition PluginResourceTextures.hpp:15

References Slic3r::collect_resource_texture_files(), Slic3r::PluginResourceTextures::instance(), Slic3r::GUI::Plugin, and scan_plugin_textures().

Referenced by scan_plugin_textures().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sort_user_textures()

void Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::sort_user_textures ( std::vector< TextureLibraryEntry > & library)
319{
320 const std::vector<std::string> names = recent_texture_names();
321 std::unordered_map<std::string, int> rank;
322 for (size_t i = 0; i < names.size(); ++i)
323 rank.emplace(names[i], int(i));
324 const auto rank_of = [&rank](const TextureLibraryEntry &e) {
325 const auto it = rank.find(boost::filesystem::path(e.path).filename().string());
326 return it == rank.end() ? std::numeric_limits<int>::max() : it->second;
327 };
328 const auto first_user = std::find_if(library.begin(), library.end(),
329 [](const TextureLibraryEntry &e) { return e.source == TextureSource::User; });
330 const auto user_end = std::find_if(first_user, library.end(),
331 [](const TextureLibraryEntry &e) { return e.source != TextureSource::User; });
332 std::stable_sort(first_user, user_end,
333 [&rank_of](const TextureLibraryEntry &a, const TextureLibraryEntry &b) { return rank_of(a) < rank_of(b); });
334}
std::vector< std::string > recent_texture_names()
Definition TextureLibrary.cpp:284
Definition TextureLibrary.hpp:20

References recent_texture_names(), and sort_user_textures().

Referenced by sort_user_textures().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ store_recent_texture_names()

void Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::store_recent_texture_names ( std::vector< std::string > names)
302{
303 if (wxTheApp == nullptr) // headless or shutting down: there is no app config to write
304 return;
305 if (wxGetApp().app_config == nullptr)
306 return;
307 if (names.size() > RECENT_MAX)
308 names.resize(RECENT_MAX);
309 std::string value;
310 for (const std::string &name : names)
311 value += (value.empty() ? "" : "/") + name;
312 wxGetApp().app_config->set(RECENT_SECTION, RECENT_KEY, value);
313}
const size_t RECENT_MAX
Definition TextureLibrary.cpp:282

References RECENT_KEY, RECENT_MAX, RECENT_SECTION, and store_recent_texture_names().

Referenced by store_recent_texture_names().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_user_texture()

std::optional< TextureLibraryEntry > Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::write_user_texture ( const std::vector< unsigned char > & bytes,
const std::string & stem,
std::string & error )
247{
248 const std::string user_dir = user_texture_dir();
249 if (user_dir.empty()) {
250 error = _u8L("Could not create the folder for imported textures.");
251 return std::nullopt;
252 }
253
254 boost::filesystem::path dest = boost::filesystem::path(user_dir) / (stem + ".png");
255 for (int i = 2; boost::filesystem::exists(dest); ++i)
256 dest = boost::filesystem::path(user_dir) / (stem + " (" + std::to_string(i) + ").png");
257
258 {
259 boost::nowide::ofstream ofs(dest.string(), std::ios::binary);
260 ofs.write(reinterpret_cast<const char *>(bytes.data()), std::streamsize(bytes.size()));
261 if (!ofs.good()) {
262 error = _u8L("Failed to save the imported texture.");
263 return std::nullopt;
264 }
265 }
266
267 texture_library(true); // pick the new file up
268 const std::string dest_str = dest.string();
269 for (const TextureLibraryEntry &e : g_library)
270 if (e.path == dest_str)
271 return e;
272
273 error = _u8L("Failed to save the imported texture.");
274 return std::nullopt;
275}
std::vector< TextureLibraryEntry > g_library
Definition TextureLibrary.cpp:233
const std::vector< TextureLibraryEntry > & texture_library(bool force_rescan)
Definition TextureLibrary.cpp:373

References _u8L, g_library, Slic3r::GUI::texture_library(), Slic3r::GUI::user_texture_dir(), and write_user_texture().

Referenced by write_user_texture().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ g_library

std::vector<TextureLibraryEntry> Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::g_library

Referenced by write_user_texture().

◆ g_library_generation

std::atomic<uint64_t> Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::g_library_generation { 0 }
239{ 0 };

◆ g_library_scan_generation

uint64_t Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::g_library_scan_generation = 0

◆ g_library_scanned

bool Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::g_library_scanned = false

◆ RECENT_KEY

const char* const Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::RECENT_KEY = "recent_textures"

◆ RECENT_MAX

const size_t Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::RECENT_MAX = 200

◆ RECENT_SECTION

const char* const Slic3r::GUI::anonymous_namespace{TextureLibrary.cpp}::RECENT_SECTION = "texture_displacement"