Skip to content

Commit 032a894

Browse files
committed
PAM/Y4M: support for UTF-8 file names
GPUJPEG 0.27.5 refers to GH-93
1 parent 773cb61 commit 032a894

File tree

5 files changed

+64
-4
lines changed

5 files changed

+64
-4
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR)
22
# change version also in configure.ac
3-
project(gpujpeg VERSION 0.27.2 LANGUAGES C CUDA)
3+
project(gpujpeg VERSION 0.27.5 LANGUAGES C CUDA)
44

55
# options
66
set(BUILD_OPENGL OFF CACHE STRING "Build with OpenGL support, options are: AUTO ON OFF")

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
next
1+
2025-06-10 - 0.27.5
22
----------
33

44
- support for non-ASCII characters in filename (tool+_load/_save)

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
AC_PREREQ([2.65])
22
# change version also in CMakeLists.txt
3-
AC_INIT([libgpujpeg],[0.27.2],[https://github.com/CESNET/GPUJPEG/issues],[libgpujpeg],[https://github.com/CESNET/GPUJPEG])
3+
AC_INIT([libgpujpeg],[0.27.5],[https://github.com/CESNET/GPUJPEG/issues],[libgpujpeg],[https://github.com/CESNET/GPUJPEG])
44
AC_CONFIG_MACRO_DIR([m4])
55
AC_CONFIG_SRCDIR([src/main.c])
66
AC_CONFIG_AUX_DIR([.])

src/utils/pam.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,36 @@ static bool parse_pnm(FILE *file, char pnm_id, struct pam_metadata *info) {
138138
return false;
139139
}
140140

141+
#ifdef _WIN32
142+
#include <wchar.h>
143+
#include <windows.h>
144+
static wchar_t*
145+
mbs_to_wstr_helper(const char* mbstr, wchar_t* wstr_buf, size_t wstr_len)
146+
{
147+
const int size_needed = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbstr, -1, NULL, 0);
148+
if ( size_needed == 0 ) {
149+
fprintf(stderr, "[PAM] MultiByteToWideChar error: %d (0x%x)!\n", GetLastError(), GetLastError());
150+
return NULL;
151+
}
152+
if ( size_needed > (int)wstr_len ) {
153+
fprintf(stderr, "[PAM] buffer provided to %s too short - needed %d, got %zu!\n", __func__, size_needed,
154+
wstr_len);
155+
return NULL;
156+
}
157+
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbstr, -1, wstr_buf, size_needed);
158+
return wstr_buf;
159+
}
160+
#define mbs_to_wstr(tstr) mbs_to_wstr_helper(tstr, (wchar_t[1024]){0}, 1024)
161+
#endif
162+
141163
bool pam_read(const char *filename, struct pam_metadata *info, unsigned char **data, void *(*allocator)(size_t)) {
142164
char line[128];
143165
errno = 0;
166+
#ifdef _WIN32
167+
FILE *file = _wfopen(mbs_to_wstr(filename), L"rb");
168+
#else
144169
FILE *file = fopen(filename, "rb");
170+
#endif
145171
if (!file) {
146172
fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno));
147173
return false;
@@ -203,7 +229,11 @@ bool pam_read(const char *filename, struct pam_metadata *info, unsigned char **d
203229

204230
bool pam_write(const char *filename, unsigned int width, unsigned int height, int ch_count, int maxval, const unsigned char *data, bool pnm) {
205231
errno = 0;
232+
#ifdef _WIN32
233+
FILE *file = _wfopen(mbs_to_wstr(filename), L"wb");
234+
#else
206235
FILE *file = fopen(filename, "wb");
236+
#endif
207237
if (!file) {
208238
fprintf(stderr, "Failed to open %s for writing: %s\n", filename, strerror(errno));
209239
return false;

src/utils/y4m.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* This file is part of GPUJPEG.
66
*/
77
/*
8-
* Copyright (c) 2022-2024, CESNET z.s.p.o.
8+
* Copyright (c) 2022-2025, CESNET
99
*
1010
* All rights reserved.
1111
*
@@ -74,8 +74,34 @@ static size_t y4m_get_data_len(const struct y4m_metadata *info) {
7474
return ret * (info->bitdepth > 8 ? 2 : 1);
7575
}
7676

77+
#ifdef _WIN32
78+
#include <wchar.h>
79+
#include <windows.h>
80+
static wchar_t*
81+
mbs_to_wstr_helper(const char* mbstr, wchar_t* wstr_buf, size_t wstr_len)
82+
{
83+
const int size_needed = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbstr, 0 - 1, NULL, 0);
84+
if ( size_needed == 0 ) {
85+
fprintf(stderr, "[Y4M] MultiByteToWideChar error %d (0x%x)!\n", GetLastError(), GetLastError());
86+
return NULL;
87+
}
88+
if ( size_needed > (int)wstr_len ) {
89+
fprintf(stderr, "[Y4M] buffer provided to %s too short - needed %d, got %zu!\n", __func__, size_needed,
90+
wstr_len);
91+
return NULL;
92+
}
93+
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbstr, -1, wstr_buf, size_needed);
94+
return wstr_buf;
95+
}
96+
#define mbs_to_wstr(tstr) mbs_to_wstr_helper(tstr, (wchar_t[1024]){0}, 1024)
97+
#endif
98+
7799
size_t y4m_read(const char *filename, struct y4m_metadata *info, unsigned char **data, void *(*allocator)(size_t)) {
100+
#ifdef _WIN32
101+
FILE *file = _wfopen(mbs_to_wstr(filename), L"rb");
102+
#else
78103
FILE *file = fopen(filename, "rb");
104+
#endif
79105
if (!file) {
80106
fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno));
81107
return 0;
@@ -134,7 +160,11 @@ size_t y4m_read(const char *filename, struct y4m_metadata *info, unsigned char *
134160

135161
bool y4m_write(const char *filename, const struct y4m_metadata *info, const unsigned char *data) {
136162
errno = 0;
163+
#ifdef _WIN32
164+
FILE *file = _wfopen(mbs_to_wstr(filename), L"wb");
165+
#else
137166
FILE *file = fopen(filename, "wb");
167+
#endif
138168
if (!file) {
139169
fprintf(stderr, "Failed to open %s for writing: %s\n", filename, strerror(errno));
140170
return false;

0 commit comments

Comments
 (0)