allow some more stdin/stout I/O

* allow reading from stdin for dwebp / vwebp
 * allow writing to stdout for gif2webp

by introducing a new function ExUtilReadFromStdin()

Example use: cat in.webp | dwebp -o - -- - > out.png

Note that the '-- -' option must appear *last*
(as per general fashion for '--' option parsing)

Change-Id: I8df0f3a246cc325925d6b6f668ba060f7dd81d68
This commit is contained in:
skal 2014-03-12 19:32:16 +01:00
parent 84ed4b3aa5
commit 2bcad89b4c
6 changed files with 71 additions and 11 deletions

View File

@ -13,18 +13,54 @@
#include "./example_util.h" #include "./example_util.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// File I/O // File I/O
static const size_t kBlockSize = 16384; // default initial size
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
size_t max_size = 0;
size_t size = 0;
uint8_t* input = NULL;
if (data == NULL || data_size == NULL) return 0;
*data = NULL;
*data_size = 0;
while (!feof(stdin)) {
// We double the buffer size each time and read as much as possible.
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
void* const new_data = realloc(input, max_size + extra_size);
if (new_data == NULL) goto Error;
input = (uint8_t*)new_data;
max_size += extra_size;
size += fread(input + size, 1, extra_size, stdin);
if (size < max_size) break;
}
if (ferror(stdin)) goto Error;
*data = input;
*data_size = size;
return 1;
Error:
free(input);
fprintf(stderr, "Could not read from stdin\n");
return 0;
}
int ExUtilReadFile(const char* const file_name, int ExUtilReadFile(const char* const file_name,
const uint8_t** data, size_t* data_size) { const uint8_t** data, size_t* data_size) {
int ok; int ok;
void* file_data; void* file_data;
size_t file_size; size_t file_size;
FILE* in; FILE* in;
const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
if (file_name == NULL || data == NULL || data_size == NULL) return 0; if (from_stdin) return ExUtilReadFromStdin(data, data_size);
if (data == NULL || data_size == NULL) return 0;
*data = NULL; *data = NULL;
*data_size = 0; *data_size = 0;
@ -56,17 +92,18 @@ int ExUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size) { const uint8_t* data, size_t data_size) {
int ok; int ok;
FILE* out; FILE* out;
const int to_stdout = (file_name == NULL) || !strcmp(file_name, "-");
if (file_name == NULL || data == NULL) { if (data == NULL) {
return 0; return 0;
} }
out = fopen(file_name, "wb"); out = to_stdout ? stdout : fopen(file_name, "wb");
if (out == NULL) { if (out == NULL) {
fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name); fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
return 0; return 0;
} }
ok = (fwrite(data, data_size, 1, out) == 1); ok = (fwrite(data, data_size, 1, out) == 1);
fclose(out); if (out != stdout) fclose(out);
return ok; return ok;
} }

View File

@ -22,10 +22,16 @@ extern "C" {
// Allocates storage for entire file 'file_name' and returns contents and size // Allocates storage for entire file 'file_name' and returns contents and size
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should // in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
// be deleted using free(). // be deleted using free().
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
// the function ExUtilReadFromStdin().
int ExUtilReadFile(const char* const file_name, int ExUtilReadFile(const char* const file_name,
const uint8_t** data, size_t* data_size); const uint8_t** data, size_t* data_size);
// Same as ExUtilReadFile(), but reads until EOF from stdin instead.
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size);
// Write a data segment into a file named 'file_name'. Returns true if ok. // Write a data segment into a file named 'file_name'. Returns true if ok.
// If 'file_name' is NULL or equal to "-", output is written to stdout.
int ExUtilWriteFile(const char* const file_name, int ExUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size); const uint8_t* data, size_t data_size);

View File

@ -501,7 +501,7 @@ int main(int argc, const char *argv[]) {
if (data == NULL) goto End; // Loop count sub-block missing. if (data == NULL) goto End; // Loop count sub-block missing.
if (data[0] != 3 && data[1] != 1) break; // wrong size/marker if (data[0] != 3 && data[1] != 1) break; // wrong size/marker
anim.loop_count = data[2] | (data[3] << 8); anim.loop_count = data[2] | (data[3] << 8);
if (verbose) printf("Loop count: %d\n", anim.loop_count); if (verbose) fprintf(stderr, "Loop count: %d\n", anim.loop_count);
} else { // An extension containing metadata. } else { // An extension containing metadata.
// We only store the first encountered chunk of each type, and // We only store the first encountered chunk of each type, and
// only if requested by the user. // only if requested by the user.
@ -555,7 +555,8 @@ int main(int argc, const char *argv[]) {
// Add metadata chunk. // Add metadata chunk.
err = WebPMuxSetChunk(mux, fourccs[is_icc], &metadata, 1); err = WebPMuxSetChunk(mux, fourccs[is_icc], &metadata, 1);
if (verbose) { if (verbose) {
printf("%s size: %d\n", features[is_icc], (int)metadata.size); fprintf(stderr, "%s size: %d\n",
features[is_icc], (int)metadata.size);
} }
WebPDataClear(&metadata); WebPDataClear(&metadata);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
@ -621,11 +622,11 @@ int main(int argc, const char *argv[]) {
goto End; goto End;
} }
if (!quiet) { if (!quiet) {
printf("Saved output file: %s\n", out_file); fprintf(stderr, "Saved output file: %s\n", out_file);
} }
} else { } else {
if (!quiet) { if (!quiet) {
printf("Nothing written; use -o flag to save the result.\n"); fprintf(stderr, "Nothing written; use -o flag to save the result.\n");
} }
} }

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH DWEBP 1 "January 11, 2014" .TH DWEBP 1 "March 7, 2014"
.SH NAME .SH NAME
dwebp \- decompress a WebP file to an image file dwebp \- decompress a WebP file to an image file
.SH SYNOPSIS .SH SYNOPSIS
@ -25,6 +25,12 @@ Print the version number (as major.minor.revision) and exit.
Specify the name of the output file (as PNG format by default). Specify the name of the output file (as PNG format by default).
Using "-" as output name will direct output to 'stdout'. Using "-" as output name will direct output to 'stdout'.
.TP .TP
.BI \-\- " string
Explicitly specify the input file. This option is useful if the input
file starts with an '\-' for instance. This option must appear \fBlast\fP.
Any other options afterward will be ignored. If the input file is "\-",
the data will be read from \fIstdin\fP instead of a file.
.TP
.B \-bmp .B \-bmp
Change the output format to uncompressed BMP. Change the output format to uncompressed BMP.
.TP .TP
@ -104,6 +110,8 @@ dwebp picture.webp \-o output.png
dwebp picture.webp \-ppm \-o output.ppm dwebp picture.webp \-ppm \-o output.ppm
.br .br
dwebp \-o output.ppm \-\- \-\-\-picture.webp dwebp \-o output.ppm \-\- \-\-\-picture.webp
.br
cat picture.webp | dwebp \-o \- \-\- \- > output.ppm
.SH AUTHORS .SH AUTHORS
\fBdwebp\fP was written by the WebP team. \fBdwebp\fP was written by the WebP team.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "December 17, 2013" .TH GIF2WEBP 1 "March 7, 2014"
.SH NAME .SH NAME
gif2webp \- Convert a GIF image to WebP gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS .SH SYNOPSIS
@ -18,6 +18,7 @@ The basic options are:
.BI \-o " string .BI \-o " string
Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will
perform conversion but only report statistics. perform conversion but only report statistics.
Using "\-" as output name will direct output to 'stdout'.
.TP .TP
.B \-h, \-help .B \-h, \-help
Usage information. Usage information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "January 08, 2014" .TH VWEBP 1 "March 7, 2014"
.SH NAME .SH NAME
vwebp \- decompress a WebP file and display it in a window vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS .SH SYNOPSIS
@ -39,6 +39,13 @@ Use multi-threading for decoding, if possible.
.TP .TP
.B \-info .B \-info
Display image information on top of the decoded image. Display image information on top of the decoded image.
.TP
.BI \-\- " string
Explicitly specify the input file. This option is useful if the input
file starts with an '\-' for instance. This option must appear \fBlast\fP.
Any other options afterward will be ignored. If the input file is "\-",
the data will be read from \fIstdin\fP instead of a file.
.TP
.SH KEYBOARD SHORTCUTS .SH KEYBOARD SHORTCUTS
.TP .TP