Skip to content

Commit 6f6690b

Browse files
committed
Fixing QOI read/write to support Wide file names on MSW
1 parent 4304aa2 commit 6f6690b

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

src/cinder/ImageSourceFileQoi.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,52 @@
2222
*/
2323

2424
#include "cinder/ImageSourceFileQoi.h"
25+
#define QOI_NO_STDIO
2526
#define QOI_IMPLEMENTATION
2627
#include "qoi/qoi.h"
2728

29+
#include <cstdio>
30+
#include <cstdlib>
31+
2832
namespace cinder {
2933

34+
namespace {
35+
36+
// Cross-platform wrapper for qoi_read that handles Unicode paths properly
37+
void* qoiReadPath( const fs::path &path, qoi_desc *desc, int channels )
38+
{
39+
#if defined( CINDER_MSW )
40+
FILE *f = _wfopen( path.wstring().c_str(), L"rb" );
41+
#else
42+
FILE *f = fopen( path.string().c_str(), "rb" );
43+
#endif
44+
45+
if( ! f )
46+
return nullptr;
47+
48+
fseek( f, 0, SEEK_END );
49+
int size = ftell( f );
50+
if( size <= 0 || fseek( f, 0, SEEK_SET ) != 0 ) {
51+
fclose( f );
52+
return nullptr;
53+
}
54+
55+
void *data = malloc( size );
56+
if( ! data ) {
57+
fclose( f );
58+
return nullptr;
59+
}
60+
61+
int bytesRead = (int)fread( data, 1, size, f );
62+
fclose( f );
63+
64+
void *pixels = ( bytesRead != size ) ? nullptr : qoi_decode( data, bytesRead, desc, channels );
65+
free( data );
66+
return pixels;
67+
}
68+
69+
} // anonymous namespace
70+
3071
///////////////////////////////////////////////////////////////////////////////
3172
// Registrar
3273
void ImageSourceFileQoi::registerSelf()
@@ -52,7 +93,7 @@ ImageSourceFileQoi::ImageSourceFileQoi( DataSourceRef dataSourceRef, ImageSource
5293
int channels = 0;
5394

5495
if( dataSourceRef->isFilePath() ) {
55-
mData = (uint8_t*)qoi_read( dataSourceRef->getFilePath().string().c_str(), &desc, 0 );
96+
mData = (uint8_t*)qoiReadPath( dataSourceRef->getFilePath(), &desc, 0 );
5697
if( ! mData )
5798
throw ImageIoExceptionFailedLoad( "Failed to load QOI image" );
5899

src/cinder/ImageTargetFileQoi.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,50 @@
2626

2727
// Note: QOI_IMPLEMENTATION is defined in ImageSourceFileQoi.cpp
2828
// to avoid multiple definition errors
29+
#define QOI_NO_STDIO
2930
#include "qoi/qoi.h"
3031

32+
#include <cstdio>
33+
#include <cstdlib>
34+
3135
namespace cinder {
3236

37+
namespace {
38+
39+
// Cross-platform wrapper for qoi_write that handles Unicode paths properly
40+
int qoiWritePath( const fs::path &path, const void *data, const qoi_desc *desc )
41+
{
42+
#if defined( CINDER_MSW )
43+
FILE *f = _wfopen( path.wstring().c_str(), L"wb" );
44+
#else
45+
FILE *f = fopen( path.string().c_str(), "wb" );
46+
#endif
47+
48+
if( ! f )
49+
return 0;
50+
51+
int size;
52+
void *encoded = qoi_encode( data, desc, &size );
53+
if( ! encoded ) {
54+
fclose( f );
55+
return 0;
56+
}
57+
58+
fwrite( encoded, 1, size, f );
59+
fflush( f );
60+
int err = ferror( f );
61+
fclose( f );
62+
63+
free( encoded );
64+
return err ? 0 : size;
65+
}
66+
67+
} // anonymous namespace
68+
3369
void ImageTargetFileQoi::registerSelf()
3470
{
3571
static bool alreadyRegistered = false;
36-
const int32_t PRIORITY = 2;
72+
const int32_t PRIORITY = 1;
3773

3874
if( alreadyRegistered )
3975
return;
@@ -92,7 +128,7 @@ void ImageTargetFileQoi::finalize()
92128
desc.colorspace = QOI_SRGB;
93129

94130
if( ! mFilePath.empty() ) {
95-
if( ! qoi_write( mFilePath.string().c_str(), mData.get(), &desc ) )
131+
if( ! qoiWritePath( mFilePath, mData.get(), &desc ) )
96132
throw ImageIoExceptionFailedWrite( "Failed to write QOI image" );
97133
}
98134
else {

0 commit comments

Comments
 (0)