Skip to content
Permalink
Browse files

libwebp: Unicode command tools on Windows

Define macros in examples/unicode.h to use Unicode argv
on Windows. Keep char everywhere on Unix since it handles
UTF-8 without any change.

Impact:
 - All fopen () and SHCreateStreamOnFile(),
 - All fprintf() printing file paths,
 - All strcmp() used with "-",
 - File path parsing,
 - Gif reading.

Concerned executables from examples/ and extras/:
  anim_diff, anim_dump, vwebp, vwebp_sdl,
  cwebp, dwebp, gif2webp, img2webp,
  webpmux, webpinfo, webp_quality, get_disto

When compiled on Windows with Unicode enabled, webpmux and
img2webp will not work when used with an argument file and
will print "Reading arguments from a file is a feature
unavailable with Unicode binaries."

BUG=webp:398

Change-Id: Ic55d222a3ce1a715f9c4cce57ecbe2705d5ce317
  • Loading branch information...
Yannis Guyon
Yannis Guyon committed Oct 16, 2018
1 parent 5030e90 commit 9cf9841b5e1669cc6678991419cdcb7b5e879237
@@ -18,6 +18,11 @@ option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
OFF)

# Option needed for handling Unicode file names on Windows.
if(WIN32)
option(WEBP_UNICODE "Build Unicode executables." ON)
endif()

if(WEBP_BUILD_WEBP_JS)
set(WEBP_ENABLE_SIMD OFF)
endif()
@@ -41,6 +46,11 @@ if(WEBP_ENABLE_SWAP_16BIT_CSP)
add_definitions(-DWEBP_SWAP_16BIT_CSP=1)
endif()

if(WEBP_UNICODE)
# Windows recommends setting both UNICODE and _UNICODE.
add_definitions(-DUNICODE -D_UNICODE)
endif()

set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\$\{prefix\}")
set(libdir "\$\{prefix\}/lib")
@@ -134,12 +134,16 @@ LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
CFGSET = TRUE
!ENDIF

!IF "$(UNICODE)" == "1"
CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
!ENDIF

#######################
# Usage
#
!IF "$(CFGSET)" == "FALSE"
!MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>]
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [UNICODE=1] [<target>]
!MESSAGE
!MESSAGE where <config> is one of:
!MESSAGE - release-static - release static library
@@ -492,15 +496,18 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
{src\utils}.c{$(DIROBJ)\utils}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<

LNKLIBS = ole32.lib windowscodecs.lib shlwapi.lib
!IF "$(UNICODE)" == "1"
LNKLIBS = $(LNKLIBS) Shell32.lib
!ENDIF

{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest

{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest

2 README
@@ -136,6 +136,8 @@ cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../

or through your favorite interface (like ccmake or cmake-qt-gui).

Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001).

Finally, once installed, you can also use WebP in your CMake project by doing:

find_package(WebP)
@@ -21,6 +21,7 @@

#include "./anim_util.h"
#include "./example_util.h"
#include "./unicode.h"

#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
@@ -218,12 +219,14 @@ int main(int argc, const char* argv[]) {
const char* files[2] = { NULL, NULL };
AnimatedImage images[2];

INIT_WARGV(argc, argv);

for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-dump_frames")) {
if (c < argc - 1) {
dump_frames = 1;
dump_folder = argv[++c];
dump_folder = (const char*)GET_WARGV(argv, ++c);
} else {
parse_error = 1;
}
@@ -243,7 +246,7 @@ int main(int argc, const char* argv[]) {
}
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
@@ -252,43 +255,44 @@ int main(int argc, const char* argv[]) {
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
return 0;
FREE_WARGV_AND_RETURN(0);
} else {
if (!got_input1) {
files[0] = argv[c];
files[0] = (const char*)GET_WARGV(argv, c);
got_input1 = 1;
} else if (!got_input2) {
files[1] = argv[c];
files[1] = (const char*)GET_WARGV(argv, c);
got_input2 = 1;
} else {
parse_error = 1;
}
}
if (parse_error) {
Help();
return -1;
FREE_WARGV_AND_RETURN(-1);
}
}
if (argc < 3) {
Help();
return -1;
FREE_WARGV_AND_RETURN(-1);
}


if (!got_input2) {
Help();
return -1;
FREE_WARGV_AND_RETURN(-1);
}

if (dump_frames) {
printf("Dumping decoded frames in: %s\n", dump_folder);
WPRINTF("Dumping decoded frames in: %s\n", (const W_CHAR*)dump_folder);
}

memset(images, 0, sizeof(images));
for (i = 0; i < 2; ++i) {
printf("Decoding file: %s\n", files[i]);
WPRINTF("Decoding file: %s\n", (const W_CHAR*)files[i]);
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
fprintf(stderr, "Error decoding file: %s\n Aborting.\n", files[i]);
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n",
(const W_CHAR*)files[i]);
return_code = -2;
goto End;
} else {
@@ -298,14 +302,16 @@ int main(int argc, const char* argv[]) {

if (!CompareAnimatedImagePair(&images[0], &images[1],
premultiply, min_psnr)) {
fprintf(stderr, "\nFiles %s and %s differ.\n", files[0], files[1]);
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]);
return_code = -3;
} else {
printf("\nFiles %s and %s are identical.\n", files[0], files[1]);
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]);
return_code = 0;
}
End:
ClearAnimatedImage(&images[0]);
ClearAnimatedImage(&images[1]);
return return_code;
FREE_WARGV_AND_RETURN(return_code);
}
@@ -17,6 +17,7 @@
#include "./anim_util.h"
#include "webp/decode.h"
#include "../imageio/image_enc.h"
#include "./unicode.h"

#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
@@ -36,15 +37,17 @@ static void Help(void) {

int main(int argc, const char* argv[]) {
int error = 0;
const char* dump_folder = ".";
const char* prefix = "dump_";
const char* suffix = "png";
const W_CHAR* dump_folder = TO_W_CHAR(".");
const W_CHAR* prefix = TO_W_CHAR("dump_");
const W_CHAR* suffix = TO_W_CHAR("png");
WebPOutputFileFormat format = PNG;
int c;

INIT_WARGV(argc, argv);

if (argc < 2) {
Help();
return -1;
FREE_WARGV_AND_RETURN(-1);
}

for (c = 1; !error && c < argc; ++c) {
@@ -54,23 +57,23 @@ int main(int argc, const char* argv[]) {
error = 1;
break;
}
dump_folder = argv[++c];
dump_folder = GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-prefix")) {
if (c + 1 == argc) {
fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
error = 1;
break;
}
prefix = argv[++c];
prefix = GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-tiff")) {
format = TIFF;
suffix = "tiff";
suffix = TO_W_CHAR("tiff");
} else if (!strcmp(argv[c], "-pam")) {
format = PAM;
suffix = "pam";
suffix = TO_W_CHAR("pam");
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
@@ -79,21 +82,21 @@ int main(int argc, const char* argv[]) {
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
return 0;
FREE_WARGV_AND_RETURN(0);
} else {
uint32_t i;
AnimatedImage image;
const char* const file = argv[c];
const W_CHAR* const file = GET_WARGV(argv, c);
memset(&image, 0, sizeof(image));
printf("Decoding file: %s as %s/%sxxxx.%s\n",
file, dump_folder, prefix, suffix);
if (!ReadAnimatedImage(file, &image, 0, NULL)) {
fprintf(stderr, "Error decoding file: %s\n Aborting.\n", file);
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n",
file, dump_folder, prefix, suffix);
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
error = 1;
break;
}
for (i = 0; !error && i < image.num_frames; ++i) {
char out_file[1024];
W_CHAR out_file[1024];
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_RGBA;
@@ -103,16 +106,16 @@ int main(int argc, const char* argv[]) {
buffer.u.RGBA.rgba = image.frames[i].rgba;
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
snprintf(out_file, sizeof(out_file), "%s/%s%.4d.%s",
dump_folder, prefix, i, suffix);
if (!WebPSaveImage(&buffer, format, out_file)) {
fprintf(stderr, "Error while saving image '%s'\n", out_file);
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s",
dump_folder, prefix, i, suffix);
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
error = 1;
}
WebPFreeDecBuffer(&buffer);
}
ClearAnimatedImage(&image);
}
}
return error ? 1 : 0;
FREE_WARGV_AND_RETURN(error ? 1 : 0);
}
Oops, something went wrong.

0 comments on commit 9cf9841

Please sign in to comment.
You can’t perform that action at this time.