|
|
@@ -1,15 +1,10 @@
|
|
1
|
1
|
#include <stdio.h>
|
|
2
|
2
|
|
|
3
|
|
-// for error recovery
|
|
4
|
|
-#include <setjmp.h>
|
|
5
|
|
-
|
|
6
|
3
|
#include <iostream>
|
|
7
|
4
|
#include <fstream>
|
|
8
|
5
|
#include <sstream>
|
|
9
|
6
|
#include <vector>
|
|
10
|
7
|
|
|
11
|
|
-#include "jpeglib.h"
|
|
12
|
|
-
|
|
13
|
8
|
#define STB_IMAGE_IMPLEMENTATION
|
|
14
|
9
|
#include "stb_image.h"
|
|
15
|
10
|
|
|
|
@@ -71,168 +66,6 @@ bool Image::read_from_file(const char *file_path) {
|
|
71
|
66
|
stbi_image_free(data);
|
|
72
|
67
|
}
|
|
73
|
68
|
|
|
74
|
|
-struct my_error_mgr {
|
|
75
|
|
- struct jpeg_error_mgr pub; /* "public" fields */
|
|
76
|
|
-
|
|
77
|
|
- jmp_buf setjmp_buffer; /* for return to caller */
|
|
78
|
|
-};
|
|
79
|
|
-
|
|
80
|
|
-typedef struct my_error_mgr * my_error_ptr;
|
|
81
|
|
-
|
|
82
|
|
-/*
|
|
83
|
|
- * Here's the routine that will replace the standard error_exit method:
|
|
84
|
|
- */
|
|
85
|
|
-
|
|
86
|
|
-METHODDEF(void)
|
|
87
|
|
-my_error_exit (j_common_ptr cinfo)
|
|
88
|
|
-{
|
|
89
|
|
- /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
|
90
|
|
- my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
|
91
|
|
-
|
|
92
|
|
- /* Always display the message. */
|
|
93
|
|
- /* We could postpone this until after returning, if we chose. */
|
|
94
|
|
- (*cinfo->err->output_message) (cinfo);
|
|
95
|
|
-
|
|
96
|
|
- /* Return control to the setjmp point */
|
|
97
|
|
- longjmp(myerr->setjmp_buffer, 1);
|
|
98
|
|
-}
|
|
99
|
|
-
|
|
100
|
|
-bool Image::read_from_jpeg_file(const char *file_path) {
|
|
101
|
|
- /* This struct contains the JPEG decompression parameters and pointers to
|
|
102
|
|
- * working space (which is allocated as needed by the JPEG library).
|
|
103
|
|
- */
|
|
104
|
|
- struct jpeg_decompress_struct cinfo;
|
|
105
|
|
-
|
|
106
|
|
- /* We use our private extension JPEG error handler.
|
|
107
|
|
- * Note that this struct must live as long as the main JPEG parameter
|
|
108
|
|
- * struct, to avoid dangling-pointer problems.
|
|
109
|
|
- */
|
|
110
|
|
- struct my_error_mgr jerr;
|
|
111
|
|
-
|
|
112
|
|
- /* More stuff */
|
|
113
|
|
- FILE * infile; /* source file */
|
|
114
|
|
- JSAMPARRAY buffer; /* Output row buffer */
|
|
115
|
|
- int row_stride; /* physical row width in output buffer */
|
|
116
|
|
-
|
|
117
|
|
- /* In this example we want to open the input file before doing anything else,
|
|
118
|
|
- * so that the setjmp() error recovery below can assume the file is open.
|
|
119
|
|
- * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
|
120
|
|
- * requires it in order to read binary files.
|
|
121
|
|
- */
|
|
122
|
|
-
|
|
123
|
|
- if ((infile = fopen(file_path, "rb")) == NULL) {
|
|
124
|
|
- cerr << "Can not open \"" << file_path << "\"" << endl;
|
|
125
|
|
- return false;
|
|
126
|
|
- }
|
|
127
|
|
-
|
|
128
|
|
- /* Step 1: allocate and initialize JPEG decompression object */
|
|
129
|
|
-
|
|
130
|
|
- /* We set up the normal JPEG error routines, then override error_exit. */
|
|
131
|
|
- cinfo.err = jpeg_std_error(&jerr.pub);
|
|
132
|
|
- jerr.pub.error_exit = my_error_exit;
|
|
133
|
|
- /* Establish the setjmp return context for my_error_exit to use. */
|
|
134
|
|
- if (setjmp(jerr.setjmp_buffer)) {
|
|
135
|
|
- /* If we get here, the JPEG code has signaled an error.
|
|
136
|
|
- * We need to clean up the JPEG object, close the input file, and return.
|
|
137
|
|
- */
|
|
138
|
|
- jpeg_destroy_decompress(&cinfo);
|
|
139
|
|
- fclose(infile);
|
|
140
|
|
- return false;
|
|
141
|
|
- }
|
|
142
|
|
- /* Now we can initialize the JPEG decompression object. */
|
|
143
|
|
- jpeg_create_decompress(&cinfo);
|
|
144
|
|
-
|
|
145
|
|
- /* Step 2: specify data source (eg, a file) */
|
|
146
|
|
-
|
|
147
|
|
- jpeg_stdio_src(&cinfo, infile);
|
|
148
|
|
-
|
|
149
|
|
- /* Step 3: read file parameters with jpeg_read_header() */
|
|
150
|
|
-
|
|
151
|
|
- (void) jpeg_read_header(&cinfo, TRUE);
|
|
152
|
|
- /* We can ignore the return value from jpeg_read_header since
|
|
153
|
|
- * (a) suspension is not possible with the stdio data source, and
|
|
154
|
|
- * (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
|
155
|
|
- * See libjpeg.txt for more info.
|
|
156
|
|
- */
|
|
157
|
|
-
|
|
158
|
|
- /* Step 4: set parameters for decompression */
|
|
159
|
|
-
|
|
160
|
|
- /* In this example, we don't need to change any of the defaults set by
|
|
161
|
|
- * jpeg_read_header(), so we do nothing here.
|
|
162
|
|
- */
|
|
163
|
|
-
|
|
164
|
|
- /* Step 5: Start decompressor */
|
|
165
|
|
-
|
|
166
|
|
- (void) jpeg_start_decompress(&cinfo);
|
|
167
|
|
- /* We can ignore the return value since suspension is not possible
|
|
168
|
|
- * with the stdio data source.
|
|
169
|
|
- */
|
|
170
|
|
-
|
|
171
|
|
- m_image_data.reserve(cinfo.output_width * cinfo.output_height * cinfo.output_components);
|
|
172
|
|
-
|
|
173
|
|
- m_width = cinfo.output_width;
|
|
174
|
|
- m_height = cinfo.output_height;
|
|
175
|
|
- m_components = cinfo.output_components;
|
|
176
|
|
-
|
|
177
|
|
- /* We may need to do some setup of our own at this point before reading
|
|
178
|
|
- * the data. After jpeg_start_decompress() we have the correct scaled
|
|
179
|
|
- * output image dimensions available, as well as the output colormap
|
|
180
|
|
- * if we asked for color quantization.
|
|
181
|
|
- * In this example, we need to make an output work buffer of the right size.
|
|
182
|
|
- */
|
|
183
|
|
- /* JSAMPLEs per row in output buffer */
|
|
184
|
|
- row_stride = cinfo.output_width * cinfo.output_components;
|
|
185
|
|
- /* Make a one-row-high sample array that will go away when done with image */
|
|
186
|
|
- buffer = (*cinfo.mem->alloc_sarray)
|
|
187
|
|
- ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
|
188
|
|
-
|
|
189
|
|
- /* Step 6: while (scan lines remain to be read) */
|
|
190
|
|
- /* jpeg_read_scanlines(...); */
|
|
191
|
|
-
|
|
192
|
|
- /* Here we use the library's state variable cinfo.output_scanline as the
|
|
193
|
|
- * loop counter, so that we don't have to keep track ourselves.
|
|
194
|
|
- */
|
|
195
|
|
- while (cinfo.output_scanline < cinfo.output_height) {
|
|
196
|
|
- /* jpeg_read_scanlines expects an array of pointers to scanlines.
|
|
197
|
|
- * Here the array is only one element long, but you could ask for
|
|
198
|
|
- * more than one scanline at a time if that's more convenient.
|
|
199
|
|
- */
|
|
200
|
|
- (void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
|
201
|
|
- /* Assume put_scanline_someplace wants a pointer and sample count. */
|
|
202
|
|
- //put_scanline_someplace(buffer[0], row_stride);
|
|
203
|
|
-
|
|
204
|
|
- for (int i = 0; i < row_stride; i++) {
|
|
205
|
|
- m_image_data.push_back(buffer[0][i]);
|
|
206
|
|
- }
|
|
207
|
|
- }
|
|
208
|
|
-
|
|
209
|
|
- /* Step 7: Finish decompression */
|
|
210
|
|
-
|
|
211
|
|
- (void) jpeg_finish_decompress(&cinfo);
|
|
212
|
|
- /* We can ignore the return value since suspension is not possible
|
|
213
|
|
- * with the stdio data source.
|
|
214
|
|
- */
|
|
215
|
|
-
|
|
216
|
|
- /* Step 8: Release JPEG decompression object */
|
|
217
|
|
-
|
|
218
|
|
- /* This is an important step since it will release a good deal of memory. */
|
|
219
|
|
- jpeg_destroy_decompress(&cinfo);
|
|
220
|
|
-
|
|
221
|
|
- /* After finish_decompress, we can close the input file.
|
|
222
|
|
- * Here we postpone it until after no more JPEG errors are possible,
|
|
223
|
|
- * so as to simplify the setjmp error logic above. (Actually, I don't
|
|
224
|
|
- * think that jpeg_destroy can do an error exit, but why assume anything...)
|
|
225
|
|
- */
|
|
226
|
|
- fclose(infile);
|
|
227
|
|
-
|
|
228
|
|
- if (jerr.pub.num_warnings != 0) {
|
|
229
|
|
- cout << jerr.pub.num_warnings << " errors occured." << endl;
|
|
230
|
|
- return false;
|
|
231
|
|
- } else {
|
|
232
|
|
- return true;
|
|
233
|
|
- }
|
|
234
|
|
-}
|
|
235
|
|
-
|
|
236
|
69
|
bool Image::save_as_ppm_file(const char *file_path, bool ascii) const {
|
|
237
|
70
|
if (ascii) {
|
|
238
|
71
|
// ASCII
|