Skip to content

Commit 549f5b2

Browse files
committed
png support for inspect and qrtest.
1 parent 2cb90d5 commit 549f5b2

File tree

5 files changed

+161
-9
lines changed

5 files changed

+161
-9
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ DEMO_OBJ = \
3838
all: libquirc.so qrtest inspect quirc-demo quirc-scanner
3939

4040
qrtest: tests/dbgutil.o tests/qrtest.o libquirc.a
41-
$(CC) -o $@ $^ -lm -ljpeg
41+
$(CC) -o $@ $^ -lm -ljpeg -lpng
4242

4343
inspect: tests/dbgutil.o tests/inspect.o libquirc.a
44-
$(CC) -o $@ $^ -lm -ljpeg $(SDL_LIBS) -lSDL_gfx
44+
$(CC) -o $@ $^ -lm -ljpeg -lpng $(SDL_LIBS) -lSDL_gfx
4545

4646
quirc-demo: $(DEMO_OBJ) demo/demo.o libquirc.a
4747
$(CC) -o $@ $^ -lm -ljpeg $(SDL_LIBS) -lSDL_gfx

tests/dbgutil.c

Lines changed: 133 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515
*/
1616

17-
#include <string.h>
1817
#include <stdio.h>
19-
#include <setjmp.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
2021
#include <jpeglib.h>
22+
#include <png.h>
23+
2124
#include "dbgutil.h"
2225

2326
void dump_data(const struct quirc_data *data)
@@ -140,3 +143,131 @@ int load_jpeg(struct quirc *q, const char *filename)
140143
jpeg_destroy_decompress(&dinfo);
141144
return -1;
142145
}
146+
147+
/* hacked from https://dev.w3.org/Amaya/libpng/example.c
148+
*
149+
* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp()
150+
* returns zero if the image is a PNG and nonzero if it isn't a PNG.
151+
*/
152+
#define PNG_BYTES_TO_CHECK 4
153+
int check_if_png(const char *filename)
154+
{
155+
int ret = 0;
156+
FILE *infile = NULL;
157+
unsigned char buf[PNG_BYTES_TO_CHECK];
158+
159+
/* Open the prospective PNG file. */
160+
if ((infile = fopen(filename, "rb")) == NULL)
161+
goto out;
162+
163+
/* Read in some of the signature bytes */
164+
if (fread(buf, 1, PNG_BYTES_TO_CHECK, infile) != PNG_BYTES_TO_CHECK)
165+
goto out;
166+
167+
/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */
168+
if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0)
169+
ret = 1;
170+
171+
/* FALLTHROUGH */
172+
out:
173+
if (infile)
174+
fclose(infile);
175+
return (ret);
176+
}
177+
178+
int load_png(struct quirc *q, const char *filename)
179+
{
180+
int width, height, rowbytes, interlace_type, number_passes = 1;
181+
png_byte color_type, bit_depth;
182+
png_structp png_ptr = NULL;
183+
png_infop info_ptr = NULL;
184+
FILE *infile = NULL;
185+
uint8_t *image;
186+
int ret = -1;
187+
188+
if ((infile = fopen(filename, "rb")) == NULL)
189+
goto out;
190+
191+
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
192+
if (!png_ptr)
193+
goto out;
194+
195+
info_ptr = png_create_info_struct(png_ptr);
196+
if (!info_ptr)
197+
goto out;
198+
199+
if (setjmp(png_jmpbuf(png_ptr)))
200+
goto out;
201+
202+
png_init_io(png_ptr, infile);
203+
204+
png_read_info(png_ptr, info_ptr);
205+
206+
color_type = png_get_color_type(png_ptr, info_ptr);
207+
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
208+
interlace_type = png_get_interlace_type(png_ptr, info_ptr);
209+
210+
// Read any color_type into 8bit depth, Grayscale format.
211+
// See http://www.libpng.org/pub/png/libpng-manual.txt
212+
213+
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
214+
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
215+
png_set_expand_gray_1_2_4_to_8(png_ptr);
216+
217+
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
218+
png_set_tRNS_to_alpha(png_ptr);
219+
220+
if (bit_depth == 16)
221+
png_set_strip_16(png_ptr);
222+
223+
if (color_type & PNG_COLOR_MASK_ALPHA)
224+
png_set_strip_alpha(png_ptr);
225+
226+
if (color_type == PNG_COLOR_TYPE_RGB ||
227+
color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
228+
png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);
229+
}
230+
231+
if (interlace_type != PNG_INTERLACE_NONE)
232+
number_passes = png_set_interlace_handling(png_ptr);
233+
234+
png_read_update_info(png_ptr, info_ptr);
235+
236+
width = png_get_image_width(png_ptr, info_ptr);
237+
height = png_get_image_height(png_ptr, info_ptr);
238+
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
239+
if (rowbytes != width) {
240+
fprintf(stderr,
241+
"load_png: expected rowbytes to be %u but got %u\n",
242+
width, rowbytes);
243+
goto out;
244+
}
245+
246+
if (quirc_resize(q, width, height) < 0)
247+
goto out;
248+
249+
image = quirc_begin(q, NULL, NULL);
250+
251+
for (int pass = 0; pass < number_passes; pass++) {
252+
for (int y = 0; y < height; y++) {
253+
png_bytep row_pointer = image + y * width;
254+
png_read_rows(png_ptr, &row_pointer, NULL, 1);
255+
}
256+
}
257+
258+
png_read_end(png_ptr, info_ptr);
259+
260+
ret = 0;
261+
/* FALLTHROUGH */
262+
out:
263+
/* cleanup */
264+
if (png_ptr) {
265+
if (info_ptr)
266+
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
267+
else
268+
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
269+
}
270+
if (infile)
271+
fclose(infile);
272+
return (ret);
273+
}

tests/dbgutil.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,14 @@ void dump_cells(const struct quirc_code *code);
3232
*/
3333
int load_jpeg(struct quirc *q, const char *filename);
3434

35+
/* check if a file is a PNG image. */
36+
int check_if_png(const char *filename);
37+
38+
/* Read a PNG image into the decoder.
39+
*
40+
* Note that you must call quirc_end() if the function returns
41+
* successfully (0).
42+
*/
43+
int load_png(struct quirc *q, const char *filename);
44+
3545
#endif

tests/inspect.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ int main(int argc, char **argv)
226226
printf("\n");
227227

228228
if (argc < 2) {
229-
fprintf(stderr, "Usage: %s <testfile.jpg>\n", argv[0]);
229+
fprintf(stderr, "Usage: %s <testfile.jpg|testfile.png>\n", argv[0]);
230230
return -1;
231231
}
232232

@@ -236,7 +236,13 @@ int main(int argc, char **argv)
236236
return -1;
237237
}
238238

239-
if (load_jpeg(q, argv[1]) < 0) {
239+
int status = -1;
240+
if (check_if_png(argv[1])) {
241+
status = load_png(q, argv[1]);
242+
} else {
243+
status = load_jpeg(q, argv[1]);
244+
}
245+
if (status < 0) {
240246
quirc_destroy(q);
241247
return -1;
242248
}

tests/qrtest.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static void add_result(struct result_info *sum, struct result_info *inf)
8282
static int scan_file(const char *path, const char *filename,
8383
struct result_info *info)
8484
{
85+
int (*loader)(struct quirc *, const char *);
8586
int len = strlen(filename);
8687
const char *ext;
8788
clock_t start;
@@ -92,15 +93,19 @@ static int scan_file(const char *path, const char *filename,
9293
while (len >= 0 && filename[len] != '.')
9394
len--;
9495
ext = filename + len + 1;
95-
if (!(strcasecmp(ext, "jpg") || strcasecmp(ext, "jpeg")))
96+
if (strcasecmp(ext, "jpg") == 0 || strcasecmp(ext, "jpeg") == 0)
97+
loader = load_jpeg;
98+
else if (strcasecmp(ext, "png") == 0)
99+
loader = load_png;
100+
else
96101
return 0;
97102

98103
total_start = start = clock();
99-
ret = load_jpeg(decoder, path);
104+
ret = loader(decoder, path);
100105
info->load_time = clock() - start;
101106

102107
if (ret < 0) {
103-
fprintf(stderr, "%s: load_jpeg failed\n", filename);
108+
fprintf(stderr, "%s: load failed\n", filename);
104109
return -1;
105110
}
106111

0 commit comments

Comments
 (0)