Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308/* quirc -- QR-code recognition library * Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <stdio.h>#include <stdlib.h>#include <string.h>
#include <jpeglib.h>#include <png.h>
#include <quirc.h>
#include "dbgutil.h"
static const char *data_type_str(int dt){ switch (dt) { case QUIRC_DATA_TYPE_NUMERIC: return "NUMERIC"; case QUIRC_DATA_TYPE_ALPHA: return "ALPHA"; case QUIRC_DATA_TYPE_BYTE: return "BYTE"; case QUIRC_DATA_TYPE_KANJI: return "KANJI"; }
return "unknown";}
void dump_data(const struct quirc_data *data){ printf(" Version: %d\n", data->version); printf(" ECC level: %c\n", "MLHQ"[data->ecc_level]); printf(" Mask: %d\n", data->mask); printf(" Data type: %d (%s)\n", data->data_type, data_type_str(data->data_type)); printf(" Length: %d\n", data->payload_len); printf(" Payload: %s\n", data->payload);
if (data->eci) printf(" ECI: %d\n", data->eci);}
void dump_cells(const struct quirc_code *code){ int u, v;
printf(" %d cells, corners:", code->size); for (u = 0; u < 4; u++) printf(" (%d,%d)", code->corners[u].x, code->corners[u].y); printf("\n");
for (v = 0; v < code->size; v++) { printf(" "); for (u = 0; u < code->size; u++) { int p = v * code->size + u;
if (code->cell_bitmap[p >> 3] & (1 << (p & 7))) printf("[]"); else printf(" "); } printf("\n"); }}
struct my_jpeg_error { struct jpeg_error_mgr base; jmp_buf env;};
static void my_output_message(struct jpeg_common_struct *com){ struct my_jpeg_error *err = (struct my_jpeg_error *)com->err; char buf[JMSG_LENGTH_MAX];
err->base.format_message(com, buf); fprintf(stderr, "JPEG error: %s\n", buf);}
static void my_error_exit(struct jpeg_common_struct *com){ struct my_jpeg_error *err = (struct my_jpeg_error *)com->err;
my_output_message(com); longjmp(err->env, 0);}
static struct jpeg_error_mgr *my_error_mgr(struct my_jpeg_error *err){ jpeg_std_error(&err->base);
err->base.error_exit = my_error_exit; err->base.output_message = my_output_message;
return &err->base;}
int load_jpeg(struct quirc *q, const char *filename){ FILE *infile = fopen(filename, "rb"); struct jpeg_decompress_struct dinfo; struct my_jpeg_error err; uint8_t *image; int y;
if (!infile) { perror("can't open input file"); return -1; }
memset(&dinfo, 0, sizeof(dinfo)); dinfo.err = my_error_mgr(&err);
if (setjmp(err.env)) goto fail;
jpeg_create_decompress(&dinfo); jpeg_stdio_src(&dinfo, infile);
jpeg_read_header(&dinfo, TRUE); dinfo.output_components = 1; dinfo.out_color_space = JCS_GRAYSCALE; jpeg_start_decompress(&dinfo);
if (dinfo.output_components != 1) { fprintf(stderr, "Unexpected number of output components: %d", dinfo.output_components); goto fail; }
if (quirc_resize(q, dinfo.output_width, dinfo.output_height) < 0) goto fail;
image = quirc_begin(q, NULL, NULL);
for (y = 0; y < dinfo.output_height; y++) { JSAMPROW row_pointer = image + y * dinfo.output_width;
jpeg_read_scanlines(&dinfo, &row_pointer, 1); }
jpeg_finish_decompress(&dinfo); fclose(infile); jpeg_destroy_decompress(&dinfo); return 0;
fail: fclose(infile); jpeg_destroy_decompress(&dinfo); return -1;}
/* hacked from https://dev.w3.org/Amaya/libpng/example.c * * Check if a file is a PNG image using png_sig_cmp(). Returns 1 if the given * file is a PNG and 0 otherwise. */#define PNG_BYTES_TO_CHECK 4int 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. * png_sig_cmp() returns zero if the image is a PNG and nonzero if it * isn't a PNG. */ 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_uint_32 trns; 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; int pass;
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 ((trns = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_tRNS_to_alpha(png_ptr);
if (bit_depth == 16)#if PNG_LIBPNG_VER >= 10504 png_set_scale_16(png_ptr);#else png_set_strip_16(png_ptr);#endif
if ((trns) || color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE || 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 (pass = 0; pass < number_passes; pass++) { int y;
for (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);}