Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C Bindings #1444

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ set(F3D_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/types.cxx
${CMAKE_CURRENT_SOURCE_DIR}/src/utils.cxx
${CMAKE_CURRENT_SOURCE_DIR}/src/window_impl.cxx
${CMAKE_CURRENT_SOURCE_DIR}/src/image_c_api.c # Include the C API implementation
)

# List of headers that will be installed
Expand All @@ -69,6 +70,7 @@ set(F3D_PUBLIC_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/public/types.h
${CMAKE_CURRENT_SOURCE_DIR}/public/utils.h
${CMAKE_CURRENT_SOURCE_DIR}/public/window.h
${CMAKE_CURRENT_SOURCE_DIR}/include/image_c_api.h # Include the C API header
)

set(F3D_PLUGIN_HEADERS
Expand Down Expand Up @@ -278,4 +280,4 @@ if(BUILD_SHARED_LIBS)
COMPONENT plugin_sdk
EXCLUDE_FROM_ALL)

endif()
endif()
53 changes: 53 additions & 0 deletions library/public/image_c_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#ifndef F3D_C_API_H
#define F3D_C_API_H

#include "export.h" // Ensure F3D_EXPORT is defined
Meakk marked this conversation as resolved.
Show resolved Hide resolved

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
float x;
float y;
float z;
} f3d_point3_t;

typedef struct {
float x;
float y;
float z;
} f3d_vector3_t;

typedef struct f3d_image f3d_image_t;

F3D_EXPORT f3d_image_t* f3d_image_new(void);
Meakk marked this conversation as resolved.
Show resolved Hide resolved
F3D_EXPORT void f3d_image_delete(f3d_image_t* img);
F3D_EXPORT void f3d_image_set_resolution(f3d_image_t* img, unsigned int width, unsigned int height);
F3D_EXPORT unsigned int f3d_image_get_width(f3d_image_t* img);
F3D_EXPORT unsigned int f3d_image_get_height(f3d_image_t* img);
F3D_EXPORT unsigned int f3d_image_get_channel_count(f3d_image_t* img);
F3D_EXPORT unsigned int f3d_image_get_channel_type(f3d_image_t* img);
F3D_EXPORT unsigned int f3d_image_get_channel_type_size(f3d_image_t* img);
F3D_EXPORT void f3d_image_set_content(f3d_image_t* img, void* buffer);
F3D_EXPORT void* f3d_image_get_content(f3d_image_t* img);
F3D_EXPORT int f3d_image_compare(f3d_image_t* img, f3d_image_t* reference, double threshold, f3d_image_t* diff, double* error);
F3D_EXPORT void f3d_image_save(f3d_image_t* img, const char* path, int format);
F3D_EXPORT unsigned char* f3d_image_save_buffer(f3d_image_t* img, int format, unsigned int* size);
F3D_EXPORT const char* f3d_image_to_terminal_text(f3d_image_t* img);
F3D_EXPORT void f3d_image_set_metadata(f3d_image_t* img, const char* key, const char* value);
F3D_EXPORT const char* f3d_image_get_metadata(f3d_image_t* img, const char* key);
F3D_EXPORT char** f3d_image_all_metadata(f3d_image_t* img, unsigned int* count);
F3D_EXPORT void f3d_image_free_metadata_keys(char** keys, unsigned int count);
F3D_EXPORT f3d_image_t* f3d_image_create_from_file(const char* path);
F3D_EXPORT f3d_image_t* f3d_image_create_with_params(unsigned int width, unsigned int height, unsigned int channelCount, unsigned int type);
F3D_EXPORT unsigned int f3d_image_get_supported_formats_count();
F3D_EXPORT const char** f3d_image_get_supported_formats();
F3D_EXPORT double* f3d_image_get_normalized_pixel(f3d_image_t* img, int x, int y, unsigned int* count);
F3D_EXPORT void f3d_image_free_normalized_pixel(double* pixel);

#ifdef __cplusplus
}
#endif

#endif // F3D_C_API_H
166 changes: 166 additions & 0 deletions library/src/image_c_api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "image_c_api.h"
#include "image.h"
#include <cstring>

struct f3d_image {
f3d::image img;
};

f3d_image_t* f3d_image_new(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file (which includes and uses image.h) must be a C++ file. Only image_c_api.h have to be C only (and the unit test of course).

return new f3d_image_t();
}

void f3d_image_delete(f3d_image_t* img) {
delete img;
}

void f3d_image_set_resolution(f3d_image_t* img, unsigned int width, unsigned int height) {
img->img.setResolution(width, height);
}

unsigned int f3d_image_get_width(f3d_image_t* img) {
return img->img.getWidth();
}

unsigned int f3d_image_get_height(f3d_image_t* img) {
return img->img.getHeight();
}

unsigned int f3d_image_get_channel_count(f3d_image_t* img) {
return img->img.getChannelCount();
}

unsigned int f3d_image_get_channel_type(f3d_image_t* img) {
return static_cast<unsigned int>(img->img.getChannelType());
}

unsigned int f3d_image_get_channel_type_size(f3d_image_t* img) {
return img->img.getChannelTypeSize();
}

void f3d_image_set_content(f3d_image_t* img, void* buffer) {
img->img.setContent(buffer);
}

void* f3d_image_get_content(f3d_image_t* img) {
return img->img.getContent();
}

int f3d_image_compare(f3d_image_t* img, f3d_image_t* reference, double threshold, f3d_image_t* diff, double* error) {
return img->img.compare(reference->img, threshold, diff->img, *error);
}

void f3d_image_save(f3d_image_t* img, const char* path, int format) {
f3d::image::SaveFormat save_format;
switch (format) {
case 0:
save_format = f3d::image::SaveFormat::PNG;
break;
case 1:
save_format = f3d::image::SaveFormat::JPG;
break;
case 2:
save_format = f3d::image::SaveFormat::TIF;
break;
case 3:
save_format = f3d::image::SaveFormat::BMP;
break;
default:
save_format = f3d::image::SaveFormat::PNG; // Default to PNG
break;
}
img->img.save(path, save_format);
}

unsigned char* f3d_image_save_buffer(f3d_image_t* img, int format, unsigned int* size) {
std::vector<unsigned char> buffer = img->img.saveBuffer(static_cast<f3d::image::SaveFormat>(format));
unsigned char* c_buffer = new unsigned char[buffer.size()];
std::copy(buffer.begin(), buffer.end(), c_buffer);
*size = buffer.size();
return c_buffer;
}

const char* f3d_image_to_terminal_text(f3d_image_t* img) {
static std::string result;
result = img->img.toTerminalText();
return result.c_str();
}

void f3d_image_set_metadata(f3d_image_t* img, const char* key, const char* value) {
img->img.setMetadata(key, value);
}

const char* f3d_image_get_metadata(f3d_image_t* img, const char* key) {
static std::string result;
result = img->img.getMetadata(key);
return result.c_str();
}

char** f3d_image_all_metadata(f3d_image_t* img, unsigned int* count) {
std::vector<std::string> metadata_keys = img->img.allMetadata();
*count = metadata_keys.size();
char** keys = new char*[metadata_keys.size()];
for (size_t i = 0; i < metadata_keys.size(); ++i) {
keys[i] = new char[metadata_keys[i].size() + 1];
strcpy(keys[i], metadata_keys[i].c_str());
}
return keys;
}

void f3d_image_free_metadata_keys(char** keys, unsigned int count) {
for (unsigned int i = 0; i < count; ++i) {
delete[] keys[i];
}
delete[] keys;
}

// Additional functions to match all functionalities from image.cxx
f3d_image_t* f3d_image_create_from_file(const char* path) {
return new f3d_image_t{ f3d::image(path) };
}

f3d_image_t* f3d_image_create_with_params(unsigned int width, unsigned int height, unsigned int channelCount, unsigned int type) {
f3d::image::ChannelType channel_type;
switch (type) {
case 0:
channel_type = f3d::image::ChannelType::BYTE;
break;
case 1:
channel_type = f3d::image::ChannelType::SHORT;
break;
case 2:
channel_type = f3d::image::ChannelType::FLOAT;
break;
default:
channel_type = f3d::image::ChannelType::BYTE; // Default to BYTE
break;
}
return new f3d_image_t{ f3d::image(width, height, channelCount, channel_type) };
}

unsigned int f3d_image_get_supported_formats_count() {
std::vector<std::string> formats = f3d::image::getSupportedFormats();
return formats.size();
}

const char** f3d_image_get_supported_formats() {
static std::vector<std::string> formats = f3d::image::getSupportedFormats();
static std::vector<const char*> c_formats;
c_formats.clear();
for (const auto& format : formats) {
c_formats.push_back(format.c_str());
}
return c_formats.data();
}

double* f3d_image_get_normalized_pixel(f3d_image_t* img, int x, int y, unsigned int* count) {
std::vector<double> pixel = img->img.getNormalizedPixel({x, y});
*count = pixel.size();
double* c_pixel = new double[pixel.size()];
std::copy(pixel.begin(), pixel.end(), c_pixel);
return c_pixel;
}

void f3d_image_free_normalized_pixel(double* pixel) {
delete[] pixel;
}
2 changes: 1 addition & 1 deletion library/testing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,4 @@ if(Qt5_FOUND)
endif()

# make sure the libf3d API is compatible with C++11
set_target_properties(libf3dSDKTests PROPERTIES CXX_STANDARD 11)
set_target_properties(libf3dSDKTests PROPERTIES CXX_STANDARD 11)
97 changes: 97 additions & 0 deletions library/testing/test_image_c_api.c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this file compiled ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not seem so, it needs to be added in library/testing/CMakeLists.txt

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <f3d/image.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {

f3d_image_t* img = f3d_image_new();

f3d_image_set_resolution(img, 800, 600);
printf("Image resolution set to 800x600.\n");

unsigned int width = f3d_image_get_width(img);
unsigned int height = f3d_image_get_height(img);
printf("Image width: %u, height: %u\n", width, height);

unsigned int channels = f3d_image_get_channel_count(img);
printf("Image channel count: %u\n", channels);

size_t buffer_size = width * height * channels;
unsigned char* buffer = (unsigned char*)malloc(buffer_size);
if (!buffer) {
printf("Failed to allocate buffer.\n");
f3d_image_delete(img);
return 1;
}
memset(buffer, 255, buffer_size); // Set all pixels to white
f3d_image_set_content(img, buffer);
printf("Image content set to white.\n");

f3d_image_save(img, "output.png", 0);
printf("Image saved as output.png\n");

// Save image to buffer
unsigned int size;
unsigned char* save_buffer = f3d_image_save_buffer(img, 0, &size);
if (save_buffer) {
printf("Image saved to buffer, size: %u bytes.\n", size);
free(save_buffer);
} else {
printf("Failed to save image to buffer.\n");
}

// Set metadata
f3d_image_set_metadata(img, "Author", "TestUser");
printf("Metadata 'Author' set to 'TestUser'.\n");

// Get metadata
const char* author = f3d_image_get_metadata(img, "Author");
if (author) {
printf("Metadata 'Author': %s\n", author);
} else {
printf("Failed to get metadata 'Author'.\n");
}

// List all metadata
unsigned int count;
char** metadata_keys = f3d_image_all_metadata(img, &count);
if (metadata_keys) {
printf("Metadata keys (%u):\n", count);
for (unsigned int i = 0; i < count; ++i) {
printf(" %s\n", metadata_keys[i]);
free(metadata_keys[i]);
}
free(metadata_keys);
} else {
printf("Failed to list metadata keys.\n");
}

// Create a reference image for comparison
f3d_image_t* ref_img = f3d_image_new();
if (ref_img) {
f3d_image_set_resolution(ref_img, 800, 600);
f3d_image_set_content(ref_img, buffer);

// Compare images
double error;
f3d_image_t* diff_img = f3d_image_new();
int result = f3d_image_compare(img, ref_img, 0.0, diff_img, &error);
if (result == 0) {
printf("Images are identical.\n");
} else {
printf("Images differ with error: %f\n", error);
}

f3d_image_delete(diff_img);
f3d_image_delete(ref_img);
} else {
printf("Failed to create reference image.\n");
}

// Clean up
free(buffer);
f3d_image_delete(img);

return 0;
}
Loading