/src/libwebp/imageio/imageio_util.c
Line | Count | Source |
1 | | // Copyright 2016 Google Inc. All Rights Reserved. |
2 | | // |
3 | | // Use of this source code is governed by a BSD-style license |
4 | | // that can be found in the COPYING file in the root of the source |
5 | | // tree. An additional intellectual property rights grant can be found |
6 | | // in the file PATENTS. All contributing project authors may |
7 | | // be found in the AUTHORS file in the root of the source tree. |
8 | | // ----------------------------------------------------------------------------- |
9 | | // |
10 | | // Utility functions used by the image decoders. |
11 | | // |
12 | | |
13 | | #include "./imageio_util.h" |
14 | | |
15 | | #if defined(_WIN32) |
16 | | #include <fcntl.h> // for _O_BINARY |
17 | | #include <io.h> // for _setmode() |
18 | | #endif |
19 | | #include <stdio.h> |
20 | | #include <stdlib.h> |
21 | | #include <string.h> |
22 | | |
23 | | #include "../examples/unicode.h" |
24 | | #include "webp/types.h" |
25 | | |
26 | | // ----------------------------------------------------------------------------- |
27 | | // File I/O |
28 | | |
29 | 0 | FILE* ImgIoUtilSetBinaryMode(FILE* file) { |
30 | | #if defined(_WIN32) |
31 | | if (_setmode(_fileno(file), _O_BINARY) == -1) { |
32 | | fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n"); |
33 | | return NULL; |
34 | | } |
35 | | #endif |
36 | 0 | return file; |
37 | 0 | } |
38 | | |
39 | 0 | int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) { |
40 | 0 | static const size_t kBlockSize = 16384; // default initial size |
41 | 0 | size_t max_size = 0; |
42 | 0 | size_t size = 0; |
43 | 0 | uint8_t* input = NULL; |
44 | |
|
45 | 0 | if (data == NULL || data_size == NULL) return 0; |
46 | 0 | *data = NULL; |
47 | 0 | *data_size = 0; |
48 | |
|
49 | 0 | if (!ImgIoUtilSetBinaryMode(stdin)) return 0; |
50 | | |
51 | 0 | while (!feof(stdin)) { |
52 | | // We double the buffer size each time and read as much as possible. |
53 | 0 | const size_t extra_size = (max_size == 0) ? kBlockSize : max_size; |
54 | | // we allocate one extra byte for the \0 terminator |
55 | 0 | void* const new_data = realloc(input, max_size + extra_size + 1); |
56 | 0 | if (new_data == NULL) goto Error; |
57 | 0 | input = (uint8_t*)new_data; |
58 | 0 | max_size += extra_size; |
59 | 0 | size += fread(input + size, 1, extra_size, stdin); |
60 | 0 | if (size < max_size) break; |
61 | 0 | } |
62 | 0 | if (ferror(stdin)) goto Error; |
63 | 0 | if (input != NULL) input[size] = '\0'; // convenient 0-terminator |
64 | 0 | *data = input; |
65 | 0 | *data_size = size; |
66 | 0 | return 1; |
67 | | |
68 | 0 | Error: |
69 | 0 | free(input); |
70 | 0 | fprintf(stderr, "Could not read from stdin\n"); |
71 | 0 | return 0; |
72 | 0 | } |
73 | | |
74 | | int ImgIoUtilReadFile(const char* const file_name, const uint8_t** data, |
75 | 0 | size_t* data_size) { |
76 | 0 | int ok; |
77 | 0 | uint8_t* file_data; |
78 | 0 | size_t file_size; |
79 | 0 | FILE* in; |
80 | 0 | const int from_stdin = (file_name == NULL) || !WSTRCMP(file_name, "-"); |
81 | |
|
82 | 0 | if (from_stdin) return ImgIoUtilReadFromStdin(data, data_size); |
83 | | |
84 | 0 | if (data == NULL || data_size == NULL) return 0; |
85 | 0 | *data = NULL; |
86 | 0 | *data_size = 0; |
87 | |
|
88 | 0 | in = WFOPEN(file_name, "rb"); |
89 | 0 | if (in == NULL) { |
90 | 0 | WFPRINTF(stderr, "cannot open input file '%s'\n", (const W_CHAR*)file_name); |
91 | 0 | return 0; |
92 | 0 | } |
93 | 0 | fseek(in, 0, SEEK_END); |
94 | 0 | file_size = ftell(in); |
95 | 0 | if (file_size == (size_t)-1) { |
96 | 0 | fclose(in); |
97 | 0 | WFPRINTF(stderr, "error getting size of '%s'\n", (const W_CHAR*)file_name); |
98 | 0 | return 0; |
99 | 0 | } |
100 | 0 | fseek(in, 0, SEEK_SET); |
101 | | // we allocate one extra byte for the \0 terminator |
102 | 0 | file_data = (uint8_t*)WebPMalloc(file_size + 1); |
103 | 0 | if (file_data == NULL) { |
104 | 0 | fclose(in); |
105 | 0 | WFPRINTF(stderr, "memory allocation failure when reading file %s\n", |
106 | 0 | (const W_CHAR*)file_name); |
107 | 0 | return 0; |
108 | 0 | } |
109 | 0 | ok = (fread(file_data, file_size, 1, in) == 1); |
110 | 0 | fclose(in); |
111 | |
|
112 | 0 | if (!ok) { |
113 | 0 | WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n", |
114 | 0 | (int)file_size, (const W_CHAR*)file_name); |
115 | 0 | WebPFree(file_data); |
116 | 0 | return 0; |
117 | 0 | } |
118 | 0 | file_data[file_size] = '\0'; // convenient 0-terminator |
119 | 0 | *data = file_data; |
120 | 0 | *data_size = file_size; |
121 | 0 | return 1; |
122 | 0 | } |
123 | | |
124 | | // ----------------------------------------------------------------------------- |
125 | | |
126 | | int ImgIoUtilWriteFile(const char* const file_name, const uint8_t* data, |
127 | 0 | size_t data_size) { |
128 | 0 | int ok; |
129 | 0 | FILE* out; |
130 | 0 | const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-"); |
131 | |
|
132 | 0 | if (data == NULL) { |
133 | 0 | return 0; |
134 | 0 | } |
135 | 0 | out = to_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(file_name, "wb"); |
136 | 0 | if (out == NULL) { |
137 | 0 | WFPRINTF(stderr, "Error! Cannot open output file '%s'\n", |
138 | 0 | (const W_CHAR*)file_name); |
139 | 0 | return 0; |
140 | 0 | } |
141 | 0 | ok = (fwrite(data, data_size, 1, out) == 1); |
142 | 0 | if (out != stdout) fclose(out); |
143 | 0 | return ok; |
144 | 0 | } |
145 | | |
146 | | // ----------------------------------------------------------------------------- |
147 | | |
148 | | void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, uint8_t* dst, |
149 | 0 | int dst_stride, int width, int height) { |
150 | 0 | while (height-- > 0) { |
151 | 0 | memcpy(dst, src, width * sizeof(*dst)); |
152 | 0 | src += src_stride; |
153 | 0 | dst += dst_stride; |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | // ----------------------------------------------------------------------------- |
158 | | |
159 | 21.2k | int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height) { |
160 | 21.2k | const uint64_t total_size = stride * height; |
161 | 21.2k | int ok = (total_size == (size_t)total_size); |
162 | | // check that 'stride' is representable as int: |
163 | 21.2k | ok = ok && ((uint64_t)(int)stride == stride); |
164 | 21.2k | #if defined(WEBP_MAX_IMAGE_SIZE) |
165 | 21.2k | ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE); |
166 | 21.2k | #endif |
167 | 21.2k | return ok; |
168 | 21.2k | } |
169 | | |
170 | | // ----------------------------------------------------------------------------- |