Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 dev.myyc.aks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ modules:
- "*.yaml"
- "*.yml"
- "*.flatpak"
- lib
- test
- android
- ios
Expand All @@ -90,6 +89,9 @@ modules:
# Verify the app was pre-built
- test -f build/linux/x64/release/bundle/aks || (echo "Error: Please run 'flutter build linux --release' first" && exit 1)

# Copy raw_processor_common.h to linux directory for Flatpak build
- cp lib/ffi/raw/raw_processor_common.h linux/raw_processor/

# Build raw_processor library with statically linked LibRaw
- echo "Building raw_processor with static LibRaw..."
- |
Expand Down
85 changes: 79 additions & 6 deletions lib/ffi/raw/libraw_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ class LibRawBindings {
late final _raw_processor_get_rgb = _raw_processor_get_rgbPtr
.asFunction<ffi.Pointer<RawImageData> Function(ffi.Pointer<ffi.Void>)>();

ffi.Pointer<ExifData> raw_processor_get_exif(
ffi.Pointer<ffi.Void> processor,
) {
return _raw_processor_get_exif(processor);
}

late final _raw_processor_get_exifPtr =
_lookup<
ffi.NativeFunction<
ffi.Pointer<ExifData> Function(ffi.Pointer<ffi.Void>)
>
>('raw_processor_get_exif');
late final _raw_processor_get_exif = _raw_processor_get_exifPtr
.asFunction<ffi.Pointer<ExifData> Function(ffi.Pointer<ffi.Void>)>();

void raw_processor_free_image(ffi.Pointer<RawImageData> image) {
return _raw_processor_free_image(image);
}
Expand All @@ -85,6 +100,17 @@ class LibRawBindings {
late final _raw_processor_free_image = _raw_processor_free_imagePtr
.asFunction<void Function(ffi.Pointer<RawImageData>)>();

void raw_processor_free_exif(ffi.Pointer<ExifData> exif) {
return _raw_processor_free_exif(exif);
}

late final _raw_processor_free_exifPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ExifData>)>>(
'raw_processor_free_exif',
);
late final _raw_processor_free_exif = _raw_processor_free_exifPtr
.asFunction<void Function(ffi.Pointer<ExifData>)>();

void raw_processor_cleanup(ffi.Pointer<ffi.Void> processor) {
return _raw_processor_cleanup(processor);
}
Expand Down Expand Up @@ -114,26 +140,73 @@ final class __fsid_t extends ffi.Struct {
}

final class RawImageInfo extends ffi.Struct {
@ffi.Int()
@ffi.Uint32()
external int width;

@ffi.Int()
@ffi.Uint32()
external int height;

@ffi.Int()
@ffi.Uint16()
external int bits;

@ffi.Int()
@ffi.Uint16()
external int colors;
}

final class RawImageData extends ffi.Struct {
external RawImageInfo info;

external ffi.Pointer<ffi.Uint8> data;

@ffi.Int()
@ffi.Size()
external int size;
}

external RawImageInfo info;
final class ExifData extends ffi.Struct {
external ffi.Pointer<ffi.Char> make;

external ffi.Pointer<ffi.Char> model;

external ffi.Pointer<ffi.Char> lens_make;

external ffi.Pointer<ffi.Char> lens_model;

external ffi.Pointer<ffi.Char> software;

@ffi.Int()
external int iso_speed;

@ffi.Double()
external double aperture;

@ffi.Double()
external double shutter_speed;

@ffi.Double()
external double focal_length;

@ffi.Double()
external double focal_length_35mm;

external ffi.Pointer<ffi.Char> datetime;

@ffi.Int()
external int exposure_program;

@ffi.Int()
external int exposure_mode;

@ffi.Int()
external int metering_mode;

@ffi.Double()
external double exposure_compensation;

@ffi.Int()
external int flash_mode;

@ffi.Int()
external int white_balance;
}

const int _STDINT_H = 1;
Expand Down
135 changes: 135 additions & 0 deletions lib/ffi/raw/raw_processor_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <stddef.h>

// Platform-specific includes
#if PLATFORM_MACOS
Expand Down Expand Up @@ -95,6 +97,9 @@ int raw_processor_process(void* processor) {
}

RawImageData* raw_processor_get_rgb(void* processor) {
printf("DEBUG: C - raw_processor_get_rgb called\n");
fflush(stdout);

if (!processor) {
snprintf(last_error, sizeof(last_error), "Invalid processor");
return NULL;
Expand All @@ -103,41 +108,75 @@ RawImageData* raw_processor_get_rgb(void* processor) {
libraw_data_t* lr = (libraw_data_t*)processor;
int error_code = 0;

printf("DEBUG: C - calling libraw_dcraw_make_mem_image\n");
fflush(stdout);

libraw_processed_image_t* processed = libraw_dcraw_make_mem_image(lr, &error_code);
if (!processed || error_code != LIBRAW_SUCCESS) {
printf("DEBUG: C - failed to create RGB image, error_code=%d\n", error_code);
fflush(stdout);
snprintf(last_error, sizeof(last_error), "Failed to create RGB image: %s",
error_code ? libraw_strerror(error_code) : "Unknown error");
return NULL;
}

printf("DEBUG: C - RGB image created successfully\n");
fflush(stdout);

printf("DEBUG: C - allocating RawImageData structure\n");
fflush(stdout);

RawImageData* image = (RawImageData*)malloc(sizeof(RawImageData));
if (!image) {
printf("DEBUG: C - failed to allocate RawImageData\n");
fflush(stdout);
libraw_dcraw_clear_mem(processed);
snprintf(last_error, sizeof(last_error), "Memory allocation failed");
return NULL;
}

printf("DEBUG: C - RawImageData allocated successfully\n");
fflush(stdout);

// Calculate actual image data size (without header)
int data_size = processed->data_size;

printf("DEBUG: C - allocating image data buffer, size=%d\n", data_size);
fflush(stdout);

// Allocate and copy RGB data
image->data = (uint8_t*)malloc(data_size);
if (!image->data) {
printf("DEBUG: C - failed to allocate image data buffer\n");
fflush(stdout);
free(image);
libraw_dcraw_clear_mem(processed);
snprintf(last_error, sizeof(last_error), "Memory allocation failed for image data");
return NULL;
}

printf("DEBUG: C - image data buffer allocated successfully\n");
fflush(stdout);

memcpy(image->data, processed->data, data_size);
image->size = data_size;

// Fill image info
printf("DEBUG: C - filling image info: width=%u, height=%u, bits=%u, colors=%u\n",
processed->width, processed->height, processed->bits, processed->colors);
fflush(stdout);

image->info.width = processed->width;
image->info.height = processed->height;
image->info.bits = processed->bits;
image->info.colors = processed->colors;

printf("DEBUG: C - image info filled, checking sizes:\n");
printf("DEBUG: C - sizeof(RawImageInfo)=%zu\n", sizeof(RawImageInfo));
printf("DEBUG: C - sizeof(RawImageData)=%zu\n", sizeof(RawImageData));
printf("DEBUG: C - offset of data in RawImageData=%zu\n", offsetof(RawImageData, data));
fflush(stdout);

libraw_dcraw_clear_mem(processed);
return image;
}
Expand All @@ -159,4 +198,100 @@ void raw_processor_cleanup(void* processor) {

const char* raw_processor_get_error() {
return last_error;
}

// Extract EXIF metadata from the opened RAW file
ExifData* raw_processor_get_exif(void* processor) {
if (!processor) {
snprintf(last_error, sizeof(last_error), "Invalid processor");
return NULL;
}

libraw_data_t* lr = (libraw_data_t*)processor;

// Allocate EXIF structure
ExifData* exif = (ExifData*)calloc(1, sizeof(ExifData));
if (!exif) {
snprintf(last_error, sizeof(last_error), "Memory allocation failed for EXIF");
return NULL;
}

// Extract camera info
if (lr->idata.make[0] != '\0') {
exif->make = strdup(lr->idata.make);
}
if (lr->idata.model[0] != '\0') {
exif->model = strdup(lr->idata.model);
}
if (lr->idata.software[0] != '\0') {
exif->software = strdup(lr->idata.software);
}

// Extract lens info
libraw_lensinfo_t* lensinfo = &lr->lens;
// Check if lens fields exist before accessing
if (sizeof(lensinfo->LensMake) > 0 && lensinfo->LensMake[0] != '\0') {
exif->lens_make = strdup(lensinfo->LensMake);
}
if (sizeof(lensinfo->Lens) > 0 && lensinfo->Lens[0] != '\0') {
exif->lens_model = strdup(lensinfo->Lens);
}

// Extract shooting info with safe defaults
exif->iso_speed = 0;
exif->aperture = 0.0;
exif->shutter_speed = 0.0;
exif->focal_length = 0.0;
exif->focal_length_35mm = 0.0;

// Safely extract values if they exist
if (offsetof(libraw_imgother_t, iso_speed) < sizeof(libraw_imgother_t)) {
exif->iso_speed = lr->other.iso_speed;
}
if (offsetof(libraw_imgother_t, aperture) < sizeof(libraw_imgother_t)) {
exif->aperture = lr->other.aperture;
}
if (offsetof(libraw_imgother_t, shutter) < sizeof(libraw_imgother_t)) {
exif->shutter_speed = lr->other.shutter;
}
if (offsetof(libraw_imgother_t, focal_len) < sizeof(libraw_imgother_t)) {
exif->focal_length = lr->other.focal_len;
}

// Extract timestamp (convert to string)
if (lr->other.timestamp > 0) {
char* time_str = (char*)malloc(20);
if (time_str) {
time_t timestamp = lr->other.timestamp;
struct tm* timeinfo = localtime(&timestamp);
if (timeinfo) {
strftime(time_str, 20, "%Y:%m:%d %H:%M:%S", timeinfo);
exif->datetime = time_str;
} else {
free(time_str);
}
}
}

// Extract exposure info (only fields available in libraw)
exif->exposure_program = -1; // Not available in libraw_imgother_t
exif->exposure_mode = -1; // Not available in libraw_imgother_t
exif->metering_mode = -1; // Not available in libraw_imgother_t
exif->exposure_compensation = 0.0; // Not available in libraw_imgother_t
exif->flash_mode = -1; // Not available in libraw_imgother_t
exif->white_balance = -1; // Not available in libraw_imgother_t

return exif;
}

void raw_processor_free_exif(ExifData* exif) {
if (exif) {
if (exif->make) free(exif->make);
if (exif->model) free(exif->model);
if (exif->lens_make) free(exif->lens_make);
if (exif->lens_model) free(exif->lens_model);
if (exif->software) free(exif->software);
if (exif->datetime) free((void*)exif->datetime);
free(exif);
}
}
23 changes: 23 additions & 0 deletions lib/ffi/raw/raw_processor_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@ typedef struct {
size_t size;
} RawImageData;

// EXIF metadata structures
typedef struct {
char* make;
char* model;
char* lens_make;
char* lens_model;
char* software;
int iso_speed;
double aperture;
double shutter_speed;
double focal_length;
double focal_length_35mm;
const char* datetime;
int exposure_program;
int exposure_mode;
int metering_mode;
double exposure_compensation;
int flash_mode;
int white_balance;
} ExifData;

// Platform detection
#if defined(_WIN32) || defined(_WIN64)
#define PLATFORM_WINDOWS 1
Expand All @@ -39,7 +60,9 @@ void* raw_processor_init();
int raw_processor_open(void* processor, const char* filename);
int raw_processor_process(void* processor);
RawImageData* raw_processor_get_rgb(void* processor);
ExifData* raw_processor_get_exif(void* processor);
void raw_processor_free_image(RawImageData* image);
void raw_processor_free_exif(ExifData* exif);
void raw_processor_cleanup(void* processor);
const char* raw_processor_get_error();

Expand Down
Loading