blob: d420a458d118626aff657705e7449d20e6a44a07 [file] [log] [blame]
/* 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 <string.h>
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include "quirc_internal.h"
#include "dbgutil.h"
static void dump_info(struct quirc *q)
{
int count = quirc_count(q);
int i;
printf("%d QR-codes found:\n\n", count);
for (i = 0; i < count; i++) {
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
quirc_extract(q, i, &code);
err = quirc_decode(&code, &data);
dump_cells(&code);
printf("\n");
if (err) {
printf(" Decoding FAILED: %s\n", quirc_strerror(err));
} else {
printf(" Decoding successful:\n");
dump_data(&data);
}
printf("\n");
}
}
static void draw_frame(SDL_Surface *screen, struct quirc *q)
{
uint8_t *pix;
uint8_t *raw = q->image;
int x, y;
SDL_LockSurface(screen);
pix = screen->pixels;
for (y = 0; y < q->h; y++) {
uint32_t *row = (uint32_t *)pix;
for (x = 0; x < q->w; x++) {
uint8_t v = *(raw++);
uint32_t color = (v << 16) | (v << 8) | v;
struct quirc_region *reg = &q->regions[v];
switch (v) {
case QUIRC_PIXEL_WHITE:
color = 0x00ffffff;
break;
case QUIRC_PIXEL_BLACK:
color = 0x00000000;
break;
default:
if (reg->capstone >= 0)
color = 0x00008000;
else
color = 0x00808080;
break;
}
*(row++) = color;
}
pix += screen->pitch;
}
SDL_UnlockSurface(screen);
}
static void draw_blob(SDL_Surface *screen, int x, int y)
{
int i, j;
for (i = -2; i <= 2; i++)
for (j = -2; j <= 2; j++)
pixelColor(screen, x + i, y + j, 0x0000ffff);
}
static void draw_mark(SDL_Surface *screen, int x, int y)
{
pixelColor(screen, x, y, 0xff0000ff);
pixelColor(screen, x + 1, y, 0xff0000ff);
pixelColor(screen, x - 1, y, 0xff0000ff);
pixelColor(screen, x, y + 1, 0xff0000ff);
pixelColor(screen, x, y - 1, 0xff0000ff);
}
static void draw_capstone(SDL_Surface *screen, struct quirc *q, int index)
{
struct quirc_capstone *cap = &q->capstones[index];
int j;
char buf[8];
for (j = 0; j < 4; j++) {
struct quirc_point *p0 = &cap->corners[j];
struct quirc_point *p1 = &cap->corners[(j + 1) % 4];
lineColor(screen, p0->x, p0->y, p1->x, p1->y,
0x800080ff);
}
draw_blob(screen, cap->corners[0].x, cap->corners[0].y);
if (cap->qr_grid < 0) {
snprintf(buf, sizeof(buf), "?%d", index);
stringColor(screen, cap->center.x, cap->center.y, buf,
0x000000ff);
}
}
static void perspective_map(const double *c,
double u, double v, struct quirc_point *ret)
{
double den = c[6]*u + c[7]*v + 1.0;
double x = (c[0]*u + c[1]*v + c[2]) / den;
double y = (c[3]*u + c[4]*v + c[5]) / den;
ret->x = rint(x);
ret->y = rint(y);
}
static void draw_grid(SDL_Surface *screen, struct quirc *q, int index)
{
struct quirc_grid *qr = &q->grids[index];
int x, y;
int i;
for (i = 0; i < 3; i++) {
struct quirc_capstone *cap = &q->capstones[qr->caps[i]];
char buf[8];
snprintf(buf, sizeof(buf), "%d.%c", index, "ABC"[i]);
stringColor(screen, cap->center.x, cap->center.y, buf,
0x000000ff);
}
lineColor(screen, qr->tpep[0].x, qr->tpep[0].y,
qr->tpep[1].x, qr->tpep[1].y, 0xff00ffff);
lineColor(screen, qr->tpep[1].x, qr->tpep[1].y,
qr->tpep[2].x, qr->tpep[2].y, 0xff00ffff);
if (qr->align_region >= 0)
draw_blob(screen, qr->align.x, qr->align.y);
for (y = 0; y < qr->grid_size; y++) {
for (x = 0; x < qr->grid_size; x++) {
double u = x + 0.5;
double v = y + 0.5;
struct quirc_point p;
perspective_map(qr->c, u, v, &p);
draw_mark(screen, p.x, p.y);
}
}
}
static int sdl_examine(struct quirc *q)
{
SDL_Surface *screen;
SDL_Event ev;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "couldn't init SDL: %s\n", SDL_GetError());
return -1;
}
screen = SDL_SetVideoMode(q->w, q->h, 32, SDL_SWSURFACE);
if (!screen) {
fprintf(stderr, "couldn't init video mode: %s\n",
SDL_GetError());
return -1;
}
while (SDL_WaitEvent(&ev) >= 0) {
int i;
if (ev.type == SDL_QUIT)
break;
if (ev.type == SDL_KEYDOWN &&
ev.key.keysym.sym == 'q')
break;
draw_frame(screen, q);
for (i = 0; i < q->num_capstones; i++)
draw_capstone(screen, q, i);
for (i = 0; i < q->num_grids; i++)
draw_grid(screen, q, i);
SDL_Flip(screen);
}
SDL_Quit();
return 0;
}
int main(int argc, char **argv)
{
struct quirc *q;
printf("quirc inspection program\n");
printf("Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>\n");
printf("Library version: %s\n", quirc_version());
printf("\n");
if (argc < 2) {
fprintf(stderr, "Usage: %s <testfile.jpg|testfile.png>\n", argv[0]);
return -1;
}
q = quirc_new();
if (!q) {
perror("can't create quirc object");
return -1;
}
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;
}
quirc_end(q);
dump_info(q);
if (sdl_examine(q) < 0) {
quirc_destroy(q);
return -1;
}
quirc_destroy(q);
return 0;
}