aboutsummaryrefslogtreecommitdiff
path: root/examples/dwebp.c
blob: dcbde7e779eac450553e86fa2d83ddf0b1731185 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2010 Google Inc.
//
// This code is licensed under the same terms as WebM:
//  Software License Agreement:  http://www.webmproject.org/license/software/
//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
//  simple command-line example calling libwebpdecode to
//  decode a WebP image into a PPM image.
//
//  Compile with:     gcc -o dwebp dwebp.c -lwebpdecode
//
// Author: Skal (pascal.massimino@gmail.com)

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "webp/decode.h"

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

//-----------------------------------------------------------------------------

static void help(const char *s) {
  printf("Usage: dwebp "
         "[options] [in_file] [-h] [-raw] [-o ppm_file]\n\n"
         " -raw:  save the raw YUV samples as a grayscale PGM\n"
         "        file with IMC4 layout.\n"
        );
}

int main(int argc, char *argv[]) {
  const char *in_file = NULL;
  const char *out_file = NULL;
  int raw_output = 0;

  int width, height, stride, uv_stride;
  uint8_t* out = NULL, *u = NULL, *v = NULL;

  int c;
  for (c = 1; c < argc; ++c) {
    if (!strcmp(argv[c], "-h")) {
      help(argv[0]);
      return 0;
    } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
      out_file = argv[++c];
    } else if (!strcmp(argv[c], "-raw")) {
      raw_output = 1;
    } else if (argv[c][0] == '-') {
      printf("Unknown option '%s'\n", argv[c]);
      help(argv[0]);
      return -1;
    } else {
      in_file = argv[c];
    }
  }

  if (in_file == NULL) {
    printf("missing input file!!\n");
    help(argv[0]);
    return -1;
  }

  {
    uint32_t data_size = 0;
    void* data = NULL;
    FILE* const in = fopen(in_file, "rb");
    if (!in) {
      printf("cannot open input file '%s'\n", in_file);
      return 1;
    }
    fseek(in, 0, SEEK_END);
    data_size = ftell(in);
    fseek(in, 0, SEEK_SET);
    data = malloc(data_size);
    const int ok = (fread(data, data_size, 1, in) == 1);
    fclose(in);
    if (!ok) {
      free(data);
      return -1;
    }

    if (!raw_output) {
      out = WebPDecodeRGB(data, data_size, &width, &height);
    } else {
      out = WebPDecodeYUV(data, data_size, &width, &height,
                          &u, &v, &stride, &uv_stride);
    }
    free(data);
  }

  if (!out) {
    printf("Decoding of %s failed.\n", in_file);
    return -1;
  }

  if (out_file) {
    FILE* const fout = fopen(out_file, "wb");
    if (fout) {
      int ok = 1;
      if (!raw_output) {
        fprintf(fout, "P6\n%d %d\n255\n", width, height);
        ok &= (fwrite(out, width * height, 3, fout) == 3);
      } else {
        // Save a grayscale PGM file using the IMC4 layout
        // (http://www.fourcc.org/yuv.php#IMC4). This is a very
        // convenient format for viewing the samples, esp. for
        // odd dimensions.
        int y;
        const int uv_width = (width + 1) / 2;
        const int uv_height = (height + 1) / 2;
        const int out_stride = (width + 1) & ~1;
        fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height);
        for (y = 0; ok && y < height; ++y) {
          ok &= (fwrite(out + y * stride, width, 1, fout) == 1);
          if (width & 1) fputc(0, fout);    // padding byte
        }
        for (y = 0; ok && y < uv_height; ++y) {
          ok &= (fwrite(u + y * uv_stride, uv_width, 1, fout) == 1);
          ok &= (fwrite(v + y * uv_stride, uv_width, 1, fout) == 1);
        }
      }
      fclose(fout);
      if (ok) {
        printf("Saved file %s\n", out_file);
      } else {
        printf("Error writing file %s !!\n", out_file);
      }
    } else {
      printf("Error opening output file %s\n", out_file);
    }
  }
  printf("Decoded %s. Dimensions: %d x %d.\n", in_file, width, height);
  free(out);

  return 0;
}

//-----------------------------------------------------------------------------

#if defined(__cplusplus) || defined(c_plusplus)
}    // extern "C"
#endif