Skip to content

Commit c6bb616

Browse files
committed
sync
1 parent fad8133 commit c6bb616

File tree

10 files changed

+156
-161
lines changed

10 files changed

+156
-161
lines changed

.github/workflows/build-wheels.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,23 @@ jobs:
6868
fetch-depth: 0
6969

7070
# Further brew packages needed to run/install vcpkg dependencies
71-
- name: Setup MacOS dependencies
71+
- name: Setup macos dependencies
7272
if: matrix.os_dist.os == 'macos-latest'
7373
run: |
7474
brew install ninja
7575
brew install autoconf
7676
brew install libtool
7777
brew install automake
7878
79+
- name: Setup Python
80+
uses: actions/setup-python@v4
81+
with:
82+
python-version: '3.12'
83+
84+
- name: Install CMake using pip
85+
run: |
86+
python -m pip install cmake
87+
7988
- name: Initialize vcpkg
8089
uses: lukka/run-vcpkg@v11
8190
with:

.github/workflows/cmake-build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ jobs:
2727
os: ubuntu-24.04
2828
compiler: gcc-13
2929
compilercxx: g++-13
30-
cflags: "-fsanitize=address,leak,undefined"
31-
cxxflags: "-fsanitize=address,leak,undefined"
30+
cflags: ""
31+
cxxflags: ""
3232
- name: Ubuntu Clang
3333
os: ubuntu-24.04
3434
compiler: clang
3535
compilercxx: clang++
36-
cflags: "-fsanitize=address,leak,undefined"
37-
cxxflags: "-fsanitize=address,leak,undefined"
36+
cflags: ""
37+
cxxflags: ""
3838
- name: Windows MSVC
3939
os: windows-latest
4040
compiler: msvc

.github/workflows/cmake-valgrind.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ jobs:
2727
os: ubuntu-24.04
2828
compiler: gcc-13
2929
compilercxx: g++-13
30-
cflags: "-fsanitize=address,leak,undefined"
31-
cxxflags: "-fsanitize=address,leak,undefined"
30+
cflags: ""
31+
cxxflags: ""
3232
- name: Ubuntu Clang
3333
os: ubuntu-24.04
3434
compiler: clang
3535
compilercxx: clang++
36-
cflags: "-fsanitize=address,leak,undefined"
37-
cxxflags: "-fsanitize=address,leak,undefined"
36+
cflags: ""
37+
cxxflags: ""
3838

3939
steps:
4040
- uses: actions/checkout@v4

PhotoshopAPI/src/LayeredFile/LayerTypes/SmartObjectLayer.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -796,12 +796,6 @@ struct SmartObjectLayer : public _ImageDataLayerType<T>
796796
void evaluate_transforms()
797797
{
798798
PSAPI_PROFILE_FUNCTION();
799-
if (m_SmartObjectWarp == _m_CachedSmartObjectWarp)
800-
{
801-
PSAPI_LOG_DEBUG("SmartObject", "No need to re-evaluate the transform data as it matches the cached values");
802-
return;
803-
}
804-
805799
_m_CachedSmartObjectWarpMesh = m_SmartObjectWarp.surface().mesh(
806800
75, // x resolution
807801
75, // y resolution
@@ -823,12 +817,6 @@ struct SmartObjectLayer : public _ImageDataLayerType<T>
823817
void evaluate_image_data()
824818
{
825819
PSAPI_PROFILE_FUNCTION();
826-
if (m_SmartObjectWarp == _m_CachedSmartObjectWarp)
827-
{
828-
PSAPI_LOG_DEBUG("SmartObject", "No need to re-evaluate the image data as it matches the cached values");
829-
return;
830-
}
831-
832820
if (!m_FilePtr)
833821
{
834822
PSAPI_LOG_ERROR("SmartObject", "Unable to evaluate the smart objects' image data without access to the original file." \

PhotoshopExamples/Tmp/main.cpp

Lines changed: 2 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -14,128 +14,15 @@ Example of loading a PhotoshopFile and extracting the image data, this can be fr
1414

1515
using namespace NAMESPACE_PSAPI;
1616

17-
// Helper function to convert Enum::ChannelIDInfo to a string
18-
std::string channel_id_to_string(Enum::ChannelIDInfo channel_id)
19-
{
20-
switch (channel_id.id) {
21-
case Enum::ChannelID::Red: return "R";
22-
case Enum::ChannelID::Green: return "G";
23-
case Enum::ChannelID::Blue: return "B";
24-
case Enum::ChannelID::Alpha: return "A";
25-
default: return "Unknown";
26-
}
27-
}
28-
29-
30-
void write_to_disk(const std::vector<uint8_t> channel,
31-
const std::string& output_filename,
32-
int width, int height)
33-
{
34-
using namespace OIIO;
35-
36-
// Open the file for writing
37-
std::unique_ptr<ImageOutput> out = ImageOutput::create(output_filename);
38-
if (!out) {
39-
throw std::runtime_error("Failed to create output file: " + output_filename);
40-
}
41-
42-
// Set up the image specification
43-
ImageSpec spec(width, height, 1, TypeDesc::UINT8);
44-
45-
// Open the file with the specification
46-
if (!out->open(output_filename, spec)) {
47-
throw std::runtime_error("Failed to open file: " + out->geterror());
48-
}
49-
// Write the image
50-
if (!out->write_image(TypeDesc::UINT8, channel.data())) {
51-
throw std::runtime_error("Failed to write image: " + out->geterror());
52-
}
53-
54-
// Close the file
55-
out->close();
56-
}
57-
58-
59-
void write_to_disk(const std::unordered_map<Enum::ChannelIDInfo, std::vector<uint8_t>, Enum::ChannelIDInfoHasher>& channel_map,
60-
const std::string& output_filename,
61-
int width, int height)
62-
{
63-
using namespace OIIO;
64-
65-
// Open the file for writing
66-
std::unique_ptr<ImageOutput> out = ImageOutput::create(output_filename);
67-
if (!out)
68-
{
69-
throw std::runtime_error("Failed to create output file: " + output_filename);
70-
}
71-
72-
// Determine the number of channels and validate dimensions
73-
int num_channels = static_cast<int>(channel_map.size());
74-
if (num_channels == 0)
75-
{
76-
throw std::runtime_error("Channel map is empty, nothing to write!");
77-
}
78-
79-
// Prepare the channel data
80-
std::vector<std::string> channel_names;
81-
if (channel_map.size() == 3)
82-
{
83-
channel_names = { "R", "G", "B" };
84-
}
85-
else if (channel_map.size() == 4)
86-
{
87-
channel_names = { "R", "G", "B", "A"};
88-
}
89-
90-
Enum::ChannelIDInfo red = { Enum::ChannelID::Red, 0 };
91-
std::span<const uint8_t> r_span = std::span<const uint8_t>(channel_map.at(red).begin(), channel_map.at(red).end());
92-
Enum::ChannelIDInfo green = { Enum::ChannelID::Green, 1 };
93-
std::span<const uint8_t> g_span = std::span<const uint8_t>(channel_map.at(green).begin(), channel_map.at(green).end());
94-
Enum::ChannelIDInfo blue = { Enum::ChannelID::Blue, 2 };
95-
std::span<const uint8_t> b_span = std::span<const uint8_t>(channel_map.at(blue).begin(), channel_map.at(blue).end());
96-
Enum::ChannelIDInfo alpha = { Enum::ChannelID::Alpha, -1 };
97-
std::span<const uint8_t> a_span = std::span<const uint8_t>(channel_map.at(alpha).begin(), channel_map.at(alpha).end());
98-
99-
std::vector<uint8_t> interleaved = NAMESPACE_PSAPI::Render::interleave_alloc(r_span, g_span, b_span, a_span);
100-
101-
// Set up the image specification
102-
ImageSpec spec(width, height, 4, TypeDesc::UINT8);
103-
spec.channelnames = channel_names;
104-
105-
// Open the file with the specification
106-
if (!out->open(output_filename, spec)) {
107-
throw std::runtime_error("Failed to open file: " + out->geterror());
108-
}
109-
// Write the image
110-
if (!out->write_image(TypeDesc::UINT8, interleaved.data())) {
111-
throw std::runtime_error("Failed to write image: " + out->geterror());
112-
}
113-
114-
// Close the file
115-
out->close();
116-
}
117-
11817

11918
int main()
12019
{
12120
using namespace NAMESPACE_PSAPI;
12221

12322
Instrumentor::Get().BeginSession("Tmp", "Tmp.json");
12423

125-
LayeredFile<bpp8_t> file = LayeredFile<bpp8_t>::read("C:/Users/emild/Desktop/linkedlayers/warp/warp_tmp.psd");
126-
auto layer_ptr = find_layer_as<bpp8_t, SmartObjectLayer>("WarpQuilt", file);
127-
layer_ptr->replace("C:/Users/emild/Desktop/uv_grid.jpg");
128-
layer_ptr->set_linkage(LinkedLayerType::external);
129-
130-
auto params = Layer<bpp8_t>::Params{};
131-
params.name = "UVGrid";
132-
auto layer_new = std::make_shared<SmartObjectLayer<bpp8_t>>(file, params, "C:/Users/emild/Desktop/linkedlayers/warp/uv_grid.jpg");
133-
layer_new->warp(layer_ptr->warp());
134-
135-
file.add_layer(layer_new);
136-
137-
LayeredFile<bpp8_t>::write(std::move(file), "C:/Users/emild/Desktop/linkedlayers/warp/warp_tmp_out1.psd");
138-
24+
LayeredFile<bpp8_t> file = LayeredFile<bpp8_t>::read("C:/repos/PhotoshopAPI/bin-int/PhotoshopAPI/x64-release/python/image_data/out.psb");
25+
auto layer_ptr = find_layer_as<bpp8_t, SmartObjectLayer>("SmartObjectLayer", file);
13926

14027
Instrumentor::Get().EndSession();
14128
}
128 KB
Loading

PhotoshopTest/src/TestSmartObjects/TestSmartObjectLayer.cpp

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "LayeredFile/LayerTypes/SmartObjectLayer.h"
66
#include "Core/Warp/SmartObjectWarp.h"
77

8+
#include "../DetectArmMac.h"
9+
810
#include "Core/Render/ImageBuffer.h"
911
#include "Core/Render/Composite.h"
1012
#include "Core/Render/Render.h"
@@ -247,4 +249,110 @@ TEST_CASE("Read all supported warps and write image files")
247249
write_smart_object_layer(file, smart_object_layer, path, ref_path);
248250
}
249251
}
250-
}
252+
}
253+
254+
255+
256+
// ---------------------------------------------------------------------------------------------------------------------
257+
// ---------------------------------------------------------------------------------------------------------------------
258+
TEST_CASE("Roundtrip layer read-write internal linkage")
259+
{
260+
using namespace NAMESPACE_PSAPI;
261+
using bpp_type = uint8_t;
262+
263+
auto file = LayeredFile<bpp_type>(Enum::ColorMode::RGB, 64, 64);
264+
265+
Layer<bpp_type>::Params lr_params{};
266+
lr_params.name = "SmartObject";
267+
lr_params.width = 64;
268+
lr_params.height = 32;
269+
270+
auto layer = std::make_shared<SmartObjectLayer<bpp_type>>(file, lr_params, "documents/image_data/ImageStackerImage.jpg");
271+
file.add_layer(layer);
272+
273+
LayeredFile<bpp_type>::write(std::move(file), "smart_object_out.psd");
274+
275+
auto read_file = LayeredFile<bpp_type>::read("smart_object_out.psd");
276+
auto read_layer = find_layer_as<bpp_type, SmartObjectLayer>("SmartObject", read_file);
277+
278+
auto image_data = read_layer->get_image_data();
279+
}
280+
281+
282+
// ---------------------------------------------------------------------------------------------------------------------
283+
// ---------------------------------------------------------------------------------------------------------------------
284+
TEST_CASE("Roundtrip layer read-write external linkage")
285+
{
286+
using namespace NAMESPACE_PSAPI;
287+
using bpp_type = uint8_t;
288+
289+
auto file = LayeredFile<bpp_type>(Enum::ColorMode::RGB, 64, 64);
290+
291+
Layer<bpp_type>::Params lr_params{};
292+
lr_params.name = "SmartObject";
293+
lr_params.width = 64;
294+
lr_params.height = 32;
295+
296+
auto layer = std::make_shared<SmartObjectLayer<bpp_type>>(file, lr_params, "documents/image_data/ImageStackerImage.jpg", LinkedLayerType::external);
297+
file.add_layer(layer);
298+
299+
LayeredFile<bpp_type>::write(std::move(file), "smart_object_out.psd");
300+
301+
auto read_file = LayeredFile<bpp_type>::read("smart_object_out.psd");
302+
auto read_layer = find_layer_as<bpp_type, SmartObjectLayer>("SmartObject", read_file);
303+
304+
auto image_data = read_layer->get_image_data();
305+
}
306+
307+
308+
309+
// ---------------------------------------------------------------------------------------------------------------------
310+
// ---------------------------------------------------------------------------------------------------------------------
311+
TEST_CASE("Roundtrip layer read-write mixed linkage")
312+
{
313+
using namespace NAMESPACE_PSAPI;
314+
using bpp_type = uint8_t;
315+
316+
auto file = LayeredFile<bpp_type>(Enum::ColorMode::RGB, 64, 64);
317+
318+
Layer<bpp_type>::Params lr_params{};
319+
lr_params.name = "SmartObject";
320+
Layer<bpp_type>::Params lr_params2{};
321+
lr_params2.name = "SmartObject2";
322+
323+
auto layer = std::make_shared<SmartObjectLayer<bpp_type>>(file, lr_params, "documents/image_data/ImageStackerImage.jpg", LinkedLayerType::external);
324+
file.add_layer(layer);
325+
auto layer_external = std::make_shared<SmartObjectLayer<bpp_type>>(file, lr_params2, "documents/image_data/uv_grid.jpg");
326+
file.add_layer(layer_external);
327+
328+
LayeredFile<bpp_type>::write(std::move(file), "smart_object_out.psd");
329+
330+
auto read_file = LayeredFile<bpp_type>::read("smart_object_out.psd");
331+
auto read_layer = find_layer_as<bpp_type, SmartObjectLayer>("SmartObject", read_file);
332+
auto read_layer2 = find_layer_as<bpp_type, SmartObjectLayer>("SmartObject2", read_file);
333+
334+
auto image_data = read_layer->get_image_data();
335+
auto image_data2 = read_layer2->get_image_data();
336+
}
337+
338+
339+
340+
// ---------------------------------------------------------------------------------------------------------------------
341+
// ---------------------------------------------------------------------------------------------------------------------
342+
#ifndef ARM_MAC_ARCH
343+
TEST_CASE("Create layer invalid filepath"
344+
* doctest::no_breaks(true)
345+
* doctest::no_output(true)
346+
* doctest::should_fail(true))
347+
{
348+
using namespace NAMESPACE_PSAPI;
349+
using bpp_type = uint8_t;
350+
351+
auto file = LayeredFile<bpp_type>(Enum::ColorMode::RGB, 64, 64);
352+
353+
Layer<bpp_type>::Params lr_params{};
354+
lr_params.name = "SmartObject";
355+
356+
auto layer = std::make_shared<SmartObjectLayer<bpp_type>>(file, lr_params, "foo/bar.jpg", LinkedLayerType::external);
357+
}
358+
#endif

python/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@ set_property(TARGET simdutf PROPERTY POSITION_INDEPENDENT_CODE ON)
99

1010
pybind11_add_module(psapi src/main.cpp)
1111
target_include_directories(psapi PUBLIC src)
12-
target_link_libraries(psapi PUBLIC PhotoshopAPI)
12+
target_link_libraries(psapi PUBLIC PhotoshopAPI)
13+
14+
# Copy the psapi-test/ folder to the build dir to run the tests
15+
add_custom_command(TARGET psapi POST_BUILD
16+
COMMAND ${CMAKE_COMMAND} -E copy_directory
17+
"${CMAKE_CURRENT_SOURCE_DIR}/psapi-test/" $<TARGET_FILE_DIR:psapi>)

0 commit comments

Comments
 (0)