png support for inspect and qrtest.
This commit is contained in:
parent
2cb90d5dd4
commit
549f5b2c4d
5 changed files with 161 additions and 9 deletions
4
Makefile
4
Makefile
|
@ -38,10 +38,10 @@ DEMO_OBJ = \
|
|||
all: libquirc.so qrtest inspect quirc-demo quirc-scanner
|
||||
|
||||
qrtest: tests/dbgutil.o tests/qrtest.o libquirc.a
|
||||
$(CC) -o $@ $^ -lm -ljpeg
|
||||
$(CC) -o $@ $^ -lm -ljpeg -lpng
|
||||
|
||||
inspect: tests/dbgutil.o tests/inspect.o libquirc.a
|
||||
$(CC) -o $@ $^ -lm -ljpeg $(SDL_LIBS) -lSDL_gfx
|
||||
$(CC) -o $@ $^ -lm -ljpeg -lpng $(SDL_LIBS) -lSDL_gfx
|
||||
|
||||
quirc-demo: $(DEMO_OBJ) demo/demo.o libquirc.a
|
||||
$(CC) -o $@ $^ -lm -ljpeg $(SDL_LIBS) -lSDL_gfx
|
||||
|
|
135
tests/dbgutil.c
135
tests/dbgutil.c
|
@ -14,10 +14,13 @@
|
|||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <jpeglib.h>
|
||||
#include <png.h>
|
||||
|
||||
#include "dbgutil.h"
|
||||
|
||||
void dump_data(const struct quirc_data *data)
|
||||
|
@ -140,3 +143,131 @@ fail:
|
|||
jpeg_destroy_decompress(&dinfo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* hacked from https://dev.w3.org/Amaya/libpng/example.c
|
||||
*
|
||||
* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp()
|
||||
* returns zero if the image is a PNG and nonzero if it isn't a PNG.
|
||||
*/
|
||||
#define PNG_BYTES_TO_CHECK 4
|
||||
int check_if_png(const char *filename)
|
||||
{
|
||||
int ret = 0;
|
||||
FILE *infile = NULL;
|
||||
unsigned char buf[PNG_BYTES_TO_CHECK];
|
||||
|
||||
/* Open the prospective PNG file. */
|
||||
if ((infile = fopen(filename, "rb")) == NULL)
|
||||
goto out;
|
||||
|
||||
/* Read in some of the signature bytes */
|
||||
if (fread(buf, 1, PNG_BYTES_TO_CHECK, infile) != PNG_BYTES_TO_CHECK)
|
||||
goto out;
|
||||
|
||||
/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */
|
||||
if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0)
|
||||
ret = 1;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
out:
|
||||
if (infile)
|
||||
fclose(infile);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int load_png(struct quirc *q, const char *filename)
|
||||
{
|
||||
int width, height, rowbytes, interlace_type, number_passes = 1;
|
||||
png_byte color_type, bit_depth;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
FILE *infile = NULL;
|
||||
uint8_t *image;
|
||||
int ret = -1;
|
||||
|
||||
if ((infile = fopen(filename, "rb")) == NULL)
|
||||
goto out;
|
||||
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr)
|
||||
goto out;
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr)
|
||||
goto out;
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
goto out;
|
||||
|
||||
png_init_io(png_ptr, infile);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
interlace_type = png_get_interlace_type(png_ptr, info_ptr);
|
||||
|
||||
// Read any color_type into 8bit depth, Grayscale format.
|
||||
// See http://www.libpng.org/pub/png/libpng-manual.txt
|
||||
|
||||
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_strip_alpha(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);
|
||||
}
|
||||
|
||||
if (interlace_type != PNG_INTERLACE_NONE)
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
width = png_get_image_width(png_ptr, info_ptr);
|
||||
height = png_get_image_height(png_ptr, info_ptr);
|
||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
if (rowbytes != width) {
|
||||
fprintf(stderr,
|
||||
"load_png: expected rowbytes to be %u but got %u\n",
|
||||
width, rowbytes);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (quirc_resize(q, width, height) < 0)
|
||||
goto out;
|
||||
|
||||
image = quirc_begin(q, NULL, NULL);
|
||||
|
||||
for (int pass = 0; pass < number_passes; pass++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
png_bytep row_pointer = image + y * width;
|
||||
png_read_rows(png_ptr, &row_pointer, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
ret = 0;
|
||||
/* FALLTHROUGH */
|
||||
out:
|
||||
/* cleanup */
|
||||
if (png_ptr) {
|
||||
if (info_ptr)
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||
else
|
||||
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
|
||||
}
|
||||
if (infile)
|
||||
fclose(infile);
|
||||
return (ret);
|
||||
}
|
||||
|
|
|
@ -32,4 +32,14 @@ void dump_cells(const struct quirc_code *code);
|
|||
*/
|
||||
int load_jpeg(struct quirc *q, const char *filename);
|
||||
|
||||
/* check if a file is a PNG image. */
|
||||
int check_if_png(const char *filename);
|
||||
|
||||
/* Read a PNG image into the decoder.
|
||||
*
|
||||
* Note that you must call quirc_end() if the function returns
|
||||
* successfully (0).
|
||||
*/
|
||||
int load_png(struct quirc *q, const char *filename);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -226,7 +226,7 @@ int main(int argc, char **argv)
|
|||
printf("\n");
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s <testfile.jpg>\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s <testfile.jpg|testfile.png>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,13 @@ int main(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (load_jpeg(q, argv[1]) < 0) {
|
||||
int status = -1;
|
||||
if (check_if_png(argv[1])) {
|
||||
status = load_png(q, argv[1]);
|
||||
} else {
|
||||
status = load_jpeg(q, argv[1]);
|
||||
}
|
||||
if (status < 0) {
|
||||
quirc_destroy(q);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ static void add_result(struct result_info *sum, struct result_info *inf)
|
|||
static int scan_file(const char *path, const char *filename,
|
||||
struct result_info *info)
|
||||
{
|
||||
int (*loader)(struct quirc *, const char *);
|
||||
int len = strlen(filename);
|
||||
const char *ext;
|
||||
clock_t start;
|
||||
|
@ -92,15 +93,19 @@ static int scan_file(const char *path, const char *filename,
|
|||
while (len >= 0 && filename[len] != '.')
|
||||
len--;
|
||||
ext = filename + len + 1;
|
||||
if (!(strcasecmp(ext, "jpg") || strcasecmp(ext, "jpeg")))
|
||||
if (strcasecmp(ext, "jpg") == 0 || strcasecmp(ext, "jpeg") == 0)
|
||||
loader = load_jpeg;
|
||||
else if (strcasecmp(ext, "png") == 0)
|
||||
loader = load_png;
|
||||
else
|
||||
return 0;
|
||||
|
||||
total_start = start = clock();
|
||||
ret = load_jpeg(decoder, path);
|
||||
ret = loader(decoder, path);
|
||||
info->load_time = clock() - start;
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: load_jpeg failed\n", filename);
|
||||
fprintf(stderr, "%s: load failed\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue