ZBar bar code reader . http://zbar.sourceforge.net/ ZBar is licensed under the GNU LGPL 2.1 to enable development of both open source and commercial projects.

Dependents:   GR-PEACH_Camera_in_barcode levkov_ov7670

LICENSE

The ZBar Bar Code Reader is Copyright (C) 2007-2009 Jeff Brown <spadix@users.sourceforge.net> The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry <tterribe@xiph.org>

You can redistribute this library and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

ISAAC is based on the public domain implementation by Robert J. Jenkins Jr., and is itself public domain.

Portions of the bit stream reader are copyright (C) The Xiph.Org Foundation 1994-2008, and are licensed under a BSD-style license.

The Reed-Solomon decoder is derived from an implementation (C) 1991-1995 Henry Minsky (hqm@ua.com, hqm@ai.mit.edu), and is licensed under the LGPL with permission.

Committer:
RyoheiHagimoto
Date:
Tue Apr 19 02:19:39 2016 +0000
Revision:
1:500d42699c34
Parent:
0:56c5742b9e2b
Add copying.txt and license.txt

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RyoheiHagimoto 0:56c5742b9e2b 1 /*Copyright (C) 2008-2009 Timothy B. Terriberry (tterribe@xiph.org)
RyoheiHagimoto 0:56c5742b9e2b 2 You can redistribute this library and/or modify it under the terms of the
RyoheiHagimoto 0:56c5742b9e2b 3 GNU Lesser General Public License as published by the Free Software
RyoheiHagimoto 0:56c5742b9e2b 4 Foundation; either version 2.1 of the License, or (at your option) any later
RyoheiHagimoto 0:56c5742b9e2b 5 version.*/
RyoheiHagimoto 0:56c5742b9e2b 6 #include <stdlib.h>
RyoheiHagimoto 0:56c5742b9e2b 7 #include <limits.h>
RyoheiHagimoto 0:56c5742b9e2b 8 #include <string.h>
RyoheiHagimoto 0:56c5742b9e2b 9 #include <time.h>
RyoheiHagimoto 0:56c5742b9e2b 10 #include "qrcode.h"
RyoheiHagimoto 0:56c5742b9e2b 11 #include "qrdec.h"
RyoheiHagimoto 0:56c5742b9e2b 12 #include "bch15_5.h"
RyoheiHagimoto 0:56c5742b9e2b 13 #include "rs.h"
RyoheiHagimoto 0:56c5742b9e2b 14 #include "isaac.h"
RyoheiHagimoto 0:56c5742b9e2b 15 #include "util.h"
RyoheiHagimoto 0:56c5742b9e2b 16 #include "binarize.h"
RyoheiHagimoto 0:56c5742b9e2b 17 #include "image.h"
RyoheiHagimoto 0:56c5742b9e2b 18 #include "error.h"
RyoheiHagimoto 0:56c5742b9e2b 19 #include "svg.h"
RyoheiHagimoto 0:56c5742b9e2b 20
RyoheiHagimoto 0:56c5742b9e2b 21 typedef int qr_line[3];
RyoheiHagimoto 0:56c5742b9e2b 22
RyoheiHagimoto 0:56c5742b9e2b 23 typedef struct qr_finder_cluster qr_finder_cluster;
RyoheiHagimoto 0:56c5742b9e2b 24 typedef struct qr_finder_edge_pt qr_finder_edge_pt;
RyoheiHagimoto 0:56c5742b9e2b 25 typedef struct qr_finder_center qr_finder_center;
RyoheiHagimoto 0:56c5742b9e2b 26
RyoheiHagimoto 0:56c5742b9e2b 27 typedef struct qr_aff qr_aff;
RyoheiHagimoto 0:56c5742b9e2b 28 typedef struct qr_hom qr_hom;
RyoheiHagimoto 0:56c5742b9e2b 29
RyoheiHagimoto 0:56c5742b9e2b 30 typedef struct qr_finder qr_finder;
RyoheiHagimoto 0:56c5742b9e2b 31
RyoheiHagimoto 0:56c5742b9e2b 32 typedef struct qr_hom_cell qr_hom_cell;
RyoheiHagimoto 0:56c5742b9e2b 33 typedef struct qr_sampling_grid qr_sampling_grid;
RyoheiHagimoto 0:56c5742b9e2b 34 typedef struct qr_pack_buf qr_pack_buf;
RyoheiHagimoto 0:56c5742b9e2b 35
RyoheiHagimoto 0:56c5742b9e2b 36 /*The number of bits in an int.
RyoheiHagimoto 0:56c5742b9e2b 37 Note the cast to (int): this prevents this value from "promoting" whole
RyoheiHagimoto 0:56c5742b9e2b 38 expressions to an (unsigned) size_t.*/
RyoheiHagimoto 0:56c5742b9e2b 39 #define QR_INT_BITS ((int)sizeof(int)*CHAR_BIT)
RyoheiHagimoto 0:56c5742b9e2b 40 #define QR_INT_LOGBITS (QR_ILOG(QR_INT_BITS))
RyoheiHagimoto 0:56c5742b9e2b 41
RyoheiHagimoto 0:56c5742b9e2b 42 /*A 14 bit resolution for a homography ensures that the ideal module size for a
RyoheiHagimoto 0:56c5742b9e2b 43 version 40 code differs from that of a version 39 code by at least 2.*/
RyoheiHagimoto 0:56c5742b9e2b 44 #define QR_HOM_BITS (14)
RyoheiHagimoto 0:56c5742b9e2b 45
RyoheiHagimoto 0:56c5742b9e2b 46 /*The number of bits of sub-module precision to use when searching for
RyoheiHagimoto 0:56c5742b9e2b 47 alignment patterns.
RyoheiHagimoto 0:56c5742b9e2b 48 Two bits allows an alignment pattern to be found even if the modules have
RyoheiHagimoto 0:56c5742b9e2b 49 been eroded by up to 50% (due to blurring, etc.).
RyoheiHagimoto 0:56c5742b9e2b 50 This must be at least one, since it affects the dynamic range of the
RyoheiHagimoto 0:56c5742b9e2b 51 transforms, and we sample at half-module resolution to compute a bounding
RyoheiHagimoto 0:56c5742b9e2b 52 quadrilateral for the code.*/
RyoheiHagimoto 0:56c5742b9e2b 53 #define QR_ALIGN_SUBPREC (2)
RyoheiHagimoto 0:56c5742b9e2b 54
RyoheiHagimoto 0:56c5742b9e2b 55
RyoheiHagimoto 0:56c5742b9e2b 56 /* collection of finder lines */
RyoheiHagimoto 0:56c5742b9e2b 57 typedef struct qr_finder_lines {
RyoheiHagimoto 0:56c5742b9e2b 58 qr_finder_line *lines;
RyoheiHagimoto 0:56c5742b9e2b 59 int nlines, clines;
RyoheiHagimoto 0:56c5742b9e2b 60 } qr_finder_lines;
RyoheiHagimoto 0:56c5742b9e2b 61
RyoheiHagimoto 0:56c5742b9e2b 62
RyoheiHagimoto 0:56c5742b9e2b 63 struct qr_reader {
RyoheiHagimoto 0:56c5742b9e2b 64 /*The GF(256) representation used in Reed-Solomon decoding.*/
RyoheiHagimoto 0:56c5742b9e2b 65 rs_gf256 gf;
RyoheiHagimoto 0:56c5742b9e2b 66 /*The random number generator used by RANSAC.*/
RyoheiHagimoto 0:56c5742b9e2b 67 isaac_ctx isaac;
RyoheiHagimoto 0:56c5742b9e2b 68 /* current finder state, horizontal and vertical lines */
RyoheiHagimoto 0:56c5742b9e2b 69 qr_finder_lines finder_lines[2];
RyoheiHagimoto 0:56c5742b9e2b 70 };
RyoheiHagimoto 0:56c5742b9e2b 71
RyoheiHagimoto 0:56c5742b9e2b 72
RyoheiHagimoto 0:56c5742b9e2b 73 /*Initializes a client reader handle.*/
RyoheiHagimoto 0:56c5742b9e2b 74 static void qr_reader_init (qr_reader *reader)
RyoheiHagimoto 0:56c5742b9e2b 75 {
RyoheiHagimoto 0:56c5742b9e2b 76 /*time_t now;
RyoheiHagimoto 0:56c5742b9e2b 77 now=time(NULL);
RyoheiHagimoto 0:56c5742b9e2b 78 isaac_init(&_reader->isaac,&now,sizeof(now));*/
RyoheiHagimoto 0:56c5742b9e2b 79 isaac_init(&reader->isaac, NULL, 0);
RyoheiHagimoto 0:56c5742b9e2b 80 rs_gf256_init(&reader->gf, QR_PPOLY);
RyoheiHagimoto 0:56c5742b9e2b 81 }
RyoheiHagimoto 0:56c5742b9e2b 82
RyoheiHagimoto 0:56c5742b9e2b 83 /*Allocates a client reader handle.*/
RyoheiHagimoto 0:56c5742b9e2b 84 qr_reader *_zbar_qr_create (void)
RyoheiHagimoto 0:56c5742b9e2b 85 {
RyoheiHagimoto 0:56c5742b9e2b 86 qr_reader *reader = (qr_reader*)calloc(1, sizeof(*reader));
RyoheiHagimoto 0:56c5742b9e2b 87 qr_reader_init(reader);
RyoheiHagimoto 0:56c5742b9e2b 88 return(reader);
RyoheiHagimoto 0:56c5742b9e2b 89 }
RyoheiHagimoto 0:56c5742b9e2b 90
RyoheiHagimoto 0:56c5742b9e2b 91 /*Frees a client reader handle.*/
RyoheiHagimoto 0:56c5742b9e2b 92 void _zbar_qr_destroy (qr_reader *reader)
RyoheiHagimoto 0:56c5742b9e2b 93 {
RyoheiHagimoto 0:56c5742b9e2b 94 zprintf(1, "max finder lines = %dx%d\n",
RyoheiHagimoto 0:56c5742b9e2b 95 reader->finder_lines[0].clines,
RyoheiHagimoto 0:56c5742b9e2b 96 reader->finder_lines[1].clines);
RyoheiHagimoto 0:56c5742b9e2b 97 if(reader->finder_lines[0].lines)
RyoheiHagimoto 0:56c5742b9e2b 98 free(reader->finder_lines[0].lines);
RyoheiHagimoto 0:56c5742b9e2b 99 if(reader->finder_lines[1].lines)
RyoheiHagimoto 0:56c5742b9e2b 100 free(reader->finder_lines[1].lines);
RyoheiHagimoto 0:56c5742b9e2b 101 free(reader);
RyoheiHagimoto 0:56c5742b9e2b 102 }
RyoheiHagimoto 0:56c5742b9e2b 103
RyoheiHagimoto 0:56c5742b9e2b 104 /* reset finder state between scans */
RyoheiHagimoto 0:56c5742b9e2b 105 void _zbar_qr_reset (qr_reader *reader)
RyoheiHagimoto 0:56c5742b9e2b 106 {
RyoheiHagimoto 0:56c5742b9e2b 107 reader->finder_lines[0].nlines = 0;
RyoheiHagimoto 0:56c5742b9e2b 108 reader->finder_lines[1].nlines = 0;
RyoheiHagimoto 0:56c5742b9e2b 109 }
RyoheiHagimoto 0:56c5742b9e2b 110
RyoheiHagimoto 0:56c5742b9e2b 111
RyoheiHagimoto 0:56c5742b9e2b 112 /*A cluster of lines crossing a finder pattern (all in the same direction).*/
RyoheiHagimoto 0:56c5742b9e2b 113 struct qr_finder_cluster{
RyoheiHagimoto 0:56c5742b9e2b 114 /*Pointers to the lines crossing the pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 115 qr_finder_line **lines;
RyoheiHagimoto 0:56c5742b9e2b 116 /*The number of lines in the cluster.*/
RyoheiHagimoto 0:56c5742b9e2b 117 int nlines;
RyoheiHagimoto 0:56c5742b9e2b 118 };
RyoheiHagimoto 0:56c5742b9e2b 119
RyoheiHagimoto 0:56c5742b9e2b 120
RyoheiHagimoto 0:56c5742b9e2b 121 /*A point on the edge of a finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 122 These are obtained from the endpoints of the lines crossing this particular
RyoheiHagimoto 0:56c5742b9e2b 123 pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 124 struct qr_finder_edge_pt{
RyoheiHagimoto 0:56c5742b9e2b 125 /*The location of the edge point.*/
RyoheiHagimoto 0:56c5742b9e2b 126 qr_point pos;
RyoheiHagimoto 0:56c5742b9e2b 127 /*A label classifying which edge this belongs to:
RyoheiHagimoto 0:56c5742b9e2b 128 0: negative u edge (left)
RyoheiHagimoto 0:56c5742b9e2b 129 1: positive u edge (right)
RyoheiHagimoto 0:56c5742b9e2b 130 2: negative v edge (top)
RyoheiHagimoto 0:56c5742b9e2b 131 3: positive v edge (bottom)*/
RyoheiHagimoto 0:56c5742b9e2b 132 int edge;
RyoheiHagimoto 0:56c5742b9e2b 133 /*The (signed) perpendicular distance of the edge point from a line parallel
RyoheiHagimoto 0:56c5742b9e2b 134 to the edge passing through the finder center, in (u,v) coordinates.
RyoheiHagimoto 0:56c5742b9e2b 135 This is also re-used by RANSAC to store inlier flags.*/
RyoheiHagimoto 0:56c5742b9e2b 136 int extent;
RyoheiHagimoto 0:56c5742b9e2b 137 };
RyoheiHagimoto 0:56c5742b9e2b 138
RyoheiHagimoto 0:56c5742b9e2b 139
RyoheiHagimoto 0:56c5742b9e2b 140 /*The center of a finder pattern obtained from the crossing of one or more
RyoheiHagimoto 0:56c5742b9e2b 141 clusters of horizontal finder lines with one or more clusters of vertical
RyoheiHagimoto 0:56c5742b9e2b 142 finder lines.*/
RyoheiHagimoto 0:56c5742b9e2b 143 struct qr_finder_center{
RyoheiHagimoto 0:56c5742b9e2b 144 /*The estimated location of the finder center.*/
RyoheiHagimoto 0:56c5742b9e2b 145 qr_point pos;
RyoheiHagimoto 0:56c5742b9e2b 146 /*The list of edge points from the crossing lines.*/
RyoheiHagimoto 0:56c5742b9e2b 147 qr_finder_edge_pt *edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 148 /*The number of edge points from the crossing lines.*/
RyoheiHagimoto 0:56c5742b9e2b 149 int nedge_pts;
RyoheiHagimoto 0:56c5742b9e2b 150 };
RyoheiHagimoto 0:56c5742b9e2b 151
RyoheiHagimoto 0:56c5742b9e2b 152
RyoheiHagimoto 0:56c5742b9e2b 153 static int qr_finder_vline_cmp(const void *_a,const void *_b){
RyoheiHagimoto 0:56c5742b9e2b 154 const qr_finder_line *a;
RyoheiHagimoto 0:56c5742b9e2b 155 const qr_finder_line *b;
RyoheiHagimoto 0:56c5742b9e2b 156 a=(const qr_finder_line *)_a;
RyoheiHagimoto 0:56c5742b9e2b 157 b=(const qr_finder_line *)_b;
RyoheiHagimoto 0:56c5742b9e2b 158 return ((a->pos[0]>b->pos[0])-(a->pos[0]<b->pos[0])<<1)+
RyoheiHagimoto 0:56c5742b9e2b 159 (a->pos[1]>b->pos[1])-(a->pos[1]<b->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 160 }
RyoheiHagimoto 0:56c5742b9e2b 161
RyoheiHagimoto 0:56c5742b9e2b 162 /*Clusters adjacent lines into groups that are large enough to be crossing a
RyoheiHagimoto 0:56c5742b9e2b 163 finder pattern (relative to their length).
RyoheiHagimoto 0:56c5742b9e2b 164 _clusters: The buffer in which to store the clusters found.
RyoheiHagimoto 0:56c5742b9e2b 165 _neighbors: The buffer used to store the lists of lines in each cluster.
RyoheiHagimoto 0:56c5742b9e2b 166 _lines: The list of lines to cluster.
RyoheiHagimoto 0:56c5742b9e2b 167 Horizontal lines must be sorted in ascending order by Y
RyoheiHagimoto 0:56c5742b9e2b 168 coordinate, with ties broken by X coordinate.
RyoheiHagimoto 0:56c5742b9e2b 169 Vertical lines must be sorted in ascending order by X coordinate,
RyoheiHagimoto 0:56c5742b9e2b 170 with ties broken by Y coordinate.
RyoheiHagimoto 0:56c5742b9e2b 171 _nlines: The number of lines in the set of lines to cluster.
RyoheiHagimoto 0:56c5742b9e2b 172 _v: 0 for horizontal lines, or 1 for vertical lines.
RyoheiHagimoto 0:56c5742b9e2b 173 Return: The number of clusters.*/
RyoheiHagimoto 0:56c5742b9e2b 174 static int qr_finder_cluster_lines(qr_finder_cluster *_clusters,
RyoheiHagimoto 0:56c5742b9e2b 175 qr_finder_line **_neighbors,qr_finder_line *_lines,int _nlines,int _v){
RyoheiHagimoto 0:56c5742b9e2b 176 unsigned char *mark;
RyoheiHagimoto 0:56c5742b9e2b 177 qr_finder_line **neighbors;
RyoheiHagimoto 0:56c5742b9e2b 178 int nneighbors;
RyoheiHagimoto 0:56c5742b9e2b 179 int nclusters;
RyoheiHagimoto 0:56c5742b9e2b 180 int i;
RyoheiHagimoto 0:56c5742b9e2b 181 /*TODO: Kalman filters!*/
RyoheiHagimoto 0:56c5742b9e2b 182 mark=(unsigned char *)calloc(_nlines,sizeof(*mark));
RyoheiHagimoto 0:56c5742b9e2b 183 neighbors=_neighbors;
RyoheiHagimoto 0:56c5742b9e2b 184 nclusters=0;
RyoheiHagimoto 0:56c5742b9e2b 185 for(i=0;i<_nlines-1;i++)if(!mark[i]){
RyoheiHagimoto 0:56c5742b9e2b 186 int len;
RyoheiHagimoto 0:56c5742b9e2b 187 int j;
RyoheiHagimoto 0:56c5742b9e2b 188 nneighbors=1;
RyoheiHagimoto 0:56c5742b9e2b 189 neighbors[0]=_lines+i;
RyoheiHagimoto 0:56c5742b9e2b 190 len=_lines[i].len;
RyoheiHagimoto 0:56c5742b9e2b 191 for(j=i+1;j<_nlines;j++)if(!mark[j]){
RyoheiHagimoto 0:56c5742b9e2b 192 const qr_finder_line *a;
RyoheiHagimoto 0:56c5742b9e2b 193 const qr_finder_line *b;
RyoheiHagimoto 0:56c5742b9e2b 194 int thresh;
RyoheiHagimoto 0:56c5742b9e2b 195 a=neighbors[nneighbors-1];
RyoheiHagimoto 0:56c5742b9e2b 196 b=_lines+j;
RyoheiHagimoto 0:56c5742b9e2b 197 /*The clustering threshold is proportional to the size of the lines,
RyoheiHagimoto 0:56c5742b9e2b 198 since minor noise in large areas can interrupt patterns more easily
RyoheiHagimoto 0:56c5742b9e2b 199 at high resolutions.*/
RyoheiHagimoto 0:56c5742b9e2b 200 thresh=a->len+7>>2;
RyoheiHagimoto 0:56c5742b9e2b 201 if(abs(a->pos[1-_v]-b->pos[1-_v])>thresh)break;
RyoheiHagimoto 0:56c5742b9e2b 202 if(abs(a->pos[_v]-b->pos[_v])>thresh)continue;
RyoheiHagimoto 0:56c5742b9e2b 203 if(abs(a->pos[_v]+a->len-b->pos[_v]-b->len)>thresh)continue;
RyoheiHagimoto 0:56c5742b9e2b 204 if(a->boffs>0&&b->boffs>0&&
RyoheiHagimoto 0:56c5742b9e2b 205 abs(a->pos[_v]-a->boffs-b->pos[_v]+b->boffs)>thresh){
RyoheiHagimoto 0:56c5742b9e2b 206 continue;
RyoheiHagimoto 0:56c5742b9e2b 207 }
RyoheiHagimoto 0:56c5742b9e2b 208 if(a->eoffs>0&&b->eoffs>0&&
RyoheiHagimoto 0:56c5742b9e2b 209 abs(a->pos[_v]+a->len+a->eoffs-b->pos[_v]-b->len-b->eoffs)>thresh){
RyoheiHagimoto 0:56c5742b9e2b 210 continue;
RyoheiHagimoto 0:56c5742b9e2b 211 }
RyoheiHagimoto 0:56c5742b9e2b 212 neighbors[nneighbors++]=_lines+j;
RyoheiHagimoto 0:56c5742b9e2b 213 len+=b->len;
RyoheiHagimoto 0:56c5742b9e2b 214 }
RyoheiHagimoto 0:56c5742b9e2b 215 /*We require at least three lines to form a cluster, which eliminates a
RyoheiHagimoto 0:56c5742b9e2b 216 large number of false positives, saving considerable decoding time.
RyoheiHagimoto 0:56c5742b9e2b 217 This should still be sufficient for 1-pixel codes with no noise.*/
RyoheiHagimoto 0:56c5742b9e2b 218 if(nneighbors<3)continue;
RyoheiHagimoto 0:56c5742b9e2b 219 /*The expected number of lines crossing a finder pattern is equal to their
RyoheiHagimoto 0:56c5742b9e2b 220 average length.
RyoheiHagimoto 0:56c5742b9e2b 221 We accept the cluster if size is at least 1/3 their average length (this
RyoheiHagimoto 0:56c5742b9e2b 222 is a very small threshold, but was needed for some test images).*/
RyoheiHagimoto 0:56c5742b9e2b 223 len=((len<<1)+nneighbors)/(nneighbors<<1);
RyoheiHagimoto 0:56c5742b9e2b 224 if(nneighbors*(5<<QR_FINDER_SUBPREC)>=len){
RyoheiHagimoto 0:56c5742b9e2b 225 _clusters[nclusters].lines=neighbors;
RyoheiHagimoto 0:56c5742b9e2b 226 _clusters[nclusters].nlines=nneighbors;
RyoheiHagimoto 0:56c5742b9e2b 227 for(j=0;j<nneighbors;j++)mark[neighbors[j]-_lines]=1;
RyoheiHagimoto 0:56c5742b9e2b 228 neighbors+=nneighbors;
RyoheiHagimoto 0:56c5742b9e2b 229 nclusters++;
RyoheiHagimoto 0:56c5742b9e2b 230 }
RyoheiHagimoto 0:56c5742b9e2b 231 }
RyoheiHagimoto 0:56c5742b9e2b 232 free(mark);
RyoheiHagimoto 0:56c5742b9e2b 233 return nclusters;
RyoheiHagimoto 0:56c5742b9e2b 234 }
RyoheiHagimoto 0:56c5742b9e2b 235
RyoheiHagimoto 0:56c5742b9e2b 236 /*Adds the coordinates of the edge points from the lines contained in the
RyoheiHagimoto 0:56c5742b9e2b 237 given list of clusters to the list of edge points for a finder center.
RyoheiHagimoto 0:56c5742b9e2b 238 Only the edge point position is initialized.
RyoheiHagimoto 0:56c5742b9e2b 239 The edge label and extent are set by qr_finder_edge_pts_aff_classify()
RyoheiHagimoto 0:56c5742b9e2b 240 or qr_finder_edge_pts_hom_classify().
RyoheiHagimoto 0:56c5742b9e2b 241 _edge_pts: The buffer in which to store the edge points.
RyoheiHagimoto 0:56c5742b9e2b 242 _nedge_pts: The current number of edge points in the buffer.
RyoheiHagimoto 0:56c5742b9e2b 243 _neighbors: The list of lines in the cluster.
RyoheiHagimoto 0:56c5742b9e2b 244 _nneighbors: The number of lines in the list of lines in the cluster.
RyoheiHagimoto 0:56c5742b9e2b 245 _v: 0 for horizontal lines and 1 for vertical lines.
RyoheiHagimoto 0:56c5742b9e2b 246 Return: The new total number of edge points.*/
RyoheiHagimoto 0:56c5742b9e2b 247 static int qr_finder_edge_pts_fill(qr_finder_edge_pt *_edge_pts,int _nedge_pts,
RyoheiHagimoto 0:56c5742b9e2b 248 qr_finder_cluster **_neighbors,int _nneighbors,int _v){
RyoheiHagimoto 0:56c5742b9e2b 249 int i;
RyoheiHagimoto 0:56c5742b9e2b 250 for(i=0;i<_nneighbors;i++){
RyoheiHagimoto 0:56c5742b9e2b 251 qr_finder_cluster *c;
RyoheiHagimoto 0:56c5742b9e2b 252 int j;
RyoheiHagimoto 0:56c5742b9e2b 253 c=_neighbors[i];
RyoheiHagimoto 0:56c5742b9e2b 254 for(j=0;j<c->nlines;j++){
RyoheiHagimoto 0:56c5742b9e2b 255 qr_finder_line *l;
RyoheiHagimoto 0:56c5742b9e2b 256 l=c->lines[j];
RyoheiHagimoto 0:56c5742b9e2b 257 if(l->boffs>0){
RyoheiHagimoto 0:56c5742b9e2b 258 _edge_pts[_nedge_pts].pos[0]=l->pos[0];
RyoheiHagimoto 0:56c5742b9e2b 259 _edge_pts[_nedge_pts].pos[1]=l->pos[1];
RyoheiHagimoto 0:56c5742b9e2b 260 _edge_pts[_nedge_pts].pos[_v]-=l->boffs;
RyoheiHagimoto 0:56c5742b9e2b 261 _nedge_pts++;
RyoheiHagimoto 0:56c5742b9e2b 262 }
RyoheiHagimoto 0:56c5742b9e2b 263 if(l->eoffs>0){
RyoheiHagimoto 0:56c5742b9e2b 264 _edge_pts[_nedge_pts].pos[0]=l->pos[0];
RyoheiHagimoto 0:56c5742b9e2b 265 _edge_pts[_nedge_pts].pos[1]=l->pos[1];
RyoheiHagimoto 0:56c5742b9e2b 266 _edge_pts[_nedge_pts].pos[_v]+=l->len+l->eoffs;
RyoheiHagimoto 0:56c5742b9e2b 267 _nedge_pts++;
RyoheiHagimoto 0:56c5742b9e2b 268 }
RyoheiHagimoto 0:56c5742b9e2b 269 }
RyoheiHagimoto 0:56c5742b9e2b 270 }
RyoheiHagimoto 0:56c5742b9e2b 271 return _nedge_pts;
RyoheiHagimoto 0:56c5742b9e2b 272 }
RyoheiHagimoto 0:56c5742b9e2b 273
RyoheiHagimoto 0:56c5742b9e2b 274 static int qr_finder_center_cmp(const void *_a,const void *_b){
RyoheiHagimoto 0:56c5742b9e2b 275 const qr_finder_center *a;
RyoheiHagimoto 0:56c5742b9e2b 276 const qr_finder_center *b;
RyoheiHagimoto 0:56c5742b9e2b 277 a=(const qr_finder_center *)_a;
RyoheiHagimoto 0:56c5742b9e2b 278 b=(const qr_finder_center *)_b;
RyoheiHagimoto 0:56c5742b9e2b 279 return ((b->nedge_pts>a->nedge_pts)-(b->nedge_pts<a->nedge_pts)<<2)+
RyoheiHagimoto 0:56c5742b9e2b 280 ((a->pos[1]>b->pos[1])-(a->pos[1]<b->pos[1])<<1)+
RyoheiHagimoto 0:56c5742b9e2b 281 (a->pos[0]>b->pos[0])-(a->pos[0]<b->pos[0]);
RyoheiHagimoto 0:56c5742b9e2b 282 }
RyoheiHagimoto 0:56c5742b9e2b 283
RyoheiHagimoto 0:56c5742b9e2b 284 /*Determine if a horizontal line crosses a vertical line.
RyoheiHagimoto 0:56c5742b9e2b 285 _hline: The horizontal line.
RyoheiHagimoto 0:56c5742b9e2b 286 _vline: The vertical line.
RyoheiHagimoto 0:56c5742b9e2b 287 Return: A non-zero value if the lines cross, or zero if they do not.*/
RyoheiHagimoto 0:56c5742b9e2b 288 static int qr_finder_lines_are_crossing(const qr_finder_line *_hline,
RyoheiHagimoto 0:56c5742b9e2b 289 const qr_finder_line *_vline){
RyoheiHagimoto 0:56c5742b9e2b 290 return
RyoheiHagimoto 0:56c5742b9e2b 291 _hline->pos[0]<=_vline->pos[0]&&_vline->pos[0]<_hline->pos[0]+_hline->len&&
RyoheiHagimoto 0:56c5742b9e2b 292 _vline->pos[1]<=_hline->pos[1]&&_hline->pos[1]<_vline->pos[1]+_vline->len;
RyoheiHagimoto 0:56c5742b9e2b 293 }
RyoheiHagimoto 0:56c5742b9e2b 294
RyoheiHagimoto 0:56c5742b9e2b 295 /*Finds horizontal clusters that cross corresponding vertical clusters,
RyoheiHagimoto 0:56c5742b9e2b 296 presumably corresponding to a finder center.
RyoheiHagimoto 0:56c5742b9e2b 297 _center: The buffer in which to store putative finder centers.
RyoheiHagimoto 0:56c5742b9e2b 298 _edge_pts: The buffer to use for the edge point lists for each finder
RyoheiHagimoto 0:56c5742b9e2b 299 center.
RyoheiHagimoto 0:56c5742b9e2b 300 _hclusters: The clusters of horizontal lines crossing finder patterns.
RyoheiHagimoto 0:56c5742b9e2b 301 _nhclusters: The number of horizontal line clusters.
RyoheiHagimoto 0:56c5742b9e2b 302 _vclusters: The clusters of vertical lines crossing finder patterns.
RyoheiHagimoto 0:56c5742b9e2b 303 _nvclusters: The number of vertical line clusters.
RyoheiHagimoto 0:56c5742b9e2b 304 Return: The number of putative finder centers.*/
RyoheiHagimoto 0:56c5742b9e2b 305 static int qr_finder_find_crossings(qr_finder_center *_centers,
RyoheiHagimoto 0:56c5742b9e2b 306 qr_finder_edge_pt *_edge_pts,qr_finder_cluster *_hclusters,int _nhclusters,
RyoheiHagimoto 0:56c5742b9e2b 307 qr_finder_cluster *_vclusters,int _nvclusters){
RyoheiHagimoto 0:56c5742b9e2b 308 qr_finder_cluster **hneighbors;
RyoheiHagimoto 0:56c5742b9e2b 309 qr_finder_cluster **vneighbors;
RyoheiHagimoto 0:56c5742b9e2b 310 unsigned char *hmark;
RyoheiHagimoto 0:56c5742b9e2b 311 unsigned char *vmark;
RyoheiHagimoto 0:56c5742b9e2b 312 int ncenters;
RyoheiHagimoto 0:56c5742b9e2b 313 int i;
RyoheiHagimoto 0:56c5742b9e2b 314 int j;
RyoheiHagimoto 0:56c5742b9e2b 315 hneighbors=(qr_finder_cluster **)malloc(_nhclusters*sizeof(*hneighbors));
RyoheiHagimoto 0:56c5742b9e2b 316 vneighbors=(qr_finder_cluster **)malloc(_nvclusters*sizeof(*vneighbors));
RyoheiHagimoto 0:56c5742b9e2b 317 hmark=(unsigned char *)calloc(_nhclusters,sizeof(*hmark));
RyoheiHagimoto 0:56c5742b9e2b 318 vmark=(unsigned char *)calloc(_nvclusters,sizeof(*vmark));
RyoheiHagimoto 0:56c5742b9e2b 319 ncenters=0;
RyoheiHagimoto 0:56c5742b9e2b 320 /*TODO: This may need some re-working.
RyoheiHagimoto 0:56c5742b9e2b 321 We should be finding groups of clusters such that _all_ horizontal lines in
RyoheiHagimoto 0:56c5742b9e2b 322 _all_ horizontal clusters in the group cross _all_ vertical lines in _all_
RyoheiHagimoto 0:56c5742b9e2b 323 vertical clusters in the group.
RyoheiHagimoto 0:56c5742b9e2b 324 This is equivalent to finding the maximum bipartite clique in the
RyoheiHagimoto 0:56c5742b9e2b 325 connectivity graph, which requires linear progamming to solve efficiently.
RyoheiHagimoto 0:56c5742b9e2b 326 In principle, that is easy to do, but a realistic implementation without
RyoheiHagimoto 0:56c5742b9e2b 327 floating point is a lot of work (and computationally expensive).
RyoheiHagimoto 0:56c5742b9e2b 328 Right now we are relying on a sufficient border around the finder patterns
RyoheiHagimoto 0:56c5742b9e2b 329 to prevent false positives.*/
RyoheiHagimoto 0:56c5742b9e2b 330 for(i=0;i<_nhclusters;i++)if(!hmark[i]){
RyoheiHagimoto 0:56c5742b9e2b 331 qr_finder_line *a;
RyoheiHagimoto 0:56c5742b9e2b 332 qr_finder_line *b;
RyoheiHagimoto 0:56c5742b9e2b 333 int nvneighbors;
RyoheiHagimoto 0:56c5742b9e2b 334 int nedge_pts;
RyoheiHagimoto 0:56c5742b9e2b 335 int y;
RyoheiHagimoto 0:56c5742b9e2b 336 a=_hclusters[i].lines[_hclusters[i].nlines>>1];
RyoheiHagimoto 0:56c5742b9e2b 337 y=nvneighbors=0;
RyoheiHagimoto 0:56c5742b9e2b 338 for(j=0;j<_nvclusters;j++)if(!vmark[j]){
RyoheiHagimoto 0:56c5742b9e2b 339 b=_vclusters[j].lines[_vclusters[j].nlines>>1];
RyoheiHagimoto 0:56c5742b9e2b 340 if(qr_finder_lines_are_crossing(a,b)){
RyoheiHagimoto 0:56c5742b9e2b 341 vmark[j]=1;
RyoheiHagimoto 0:56c5742b9e2b 342 y+=(b->pos[1]<<1)+b->len;
RyoheiHagimoto 0:56c5742b9e2b 343 if(b->boffs>0&&b->eoffs>0)y+=b->eoffs-b->boffs;
RyoheiHagimoto 0:56c5742b9e2b 344 vneighbors[nvneighbors++]=_vclusters+j;
RyoheiHagimoto 0:56c5742b9e2b 345 }
RyoheiHagimoto 0:56c5742b9e2b 346 }
RyoheiHagimoto 0:56c5742b9e2b 347 if(nvneighbors>0){
RyoheiHagimoto 0:56c5742b9e2b 348 qr_finder_center *c;
RyoheiHagimoto 0:56c5742b9e2b 349 int nhneighbors;
RyoheiHagimoto 0:56c5742b9e2b 350 int x;
RyoheiHagimoto 0:56c5742b9e2b 351 x=(a->pos[0]<<1)+a->len;
RyoheiHagimoto 0:56c5742b9e2b 352 if(a->boffs>0&&a->eoffs>0)x+=a->eoffs-a->boffs;
RyoheiHagimoto 0:56c5742b9e2b 353 hneighbors[0]=_hclusters+i;
RyoheiHagimoto 0:56c5742b9e2b 354 nhneighbors=1;
RyoheiHagimoto 0:56c5742b9e2b 355 j=nvneighbors>>1;
RyoheiHagimoto 0:56c5742b9e2b 356 b=vneighbors[j]->lines[vneighbors[j]->nlines>>1];
RyoheiHagimoto 0:56c5742b9e2b 357 for(j=i+1;j<_nhclusters;j++)if(!hmark[j]){
RyoheiHagimoto 0:56c5742b9e2b 358 a=_hclusters[j].lines[_hclusters[j].nlines>>1];
RyoheiHagimoto 0:56c5742b9e2b 359 if(qr_finder_lines_are_crossing(a,b)){
RyoheiHagimoto 0:56c5742b9e2b 360 hmark[j]=1;
RyoheiHagimoto 0:56c5742b9e2b 361 x+=(a->pos[0]<<1)+a->len;
RyoheiHagimoto 0:56c5742b9e2b 362 if(a->boffs>0&&a->eoffs>0)x+=a->eoffs-a->boffs;
RyoheiHagimoto 0:56c5742b9e2b 363 hneighbors[nhneighbors++]=_hclusters+j;
RyoheiHagimoto 0:56c5742b9e2b 364 }
RyoheiHagimoto 0:56c5742b9e2b 365 }
RyoheiHagimoto 0:56c5742b9e2b 366 c=_centers+ncenters++;
RyoheiHagimoto 0:56c5742b9e2b 367 c->pos[0]=(x+nhneighbors)/(nhneighbors<<1);
RyoheiHagimoto 0:56c5742b9e2b 368 c->pos[1]=(y+nvneighbors)/(nvneighbors<<1);
RyoheiHagimoto 0:56c5742b9e2b 369 c->edge_pts=_edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 370 nedge_pts=qr_finder_edge_pts_fill(_edge_pts,0,
RyoheiHagimoto 0:56c5742b9e2b 371 hneighbors,nhneighbors,0);
RyoheiHagimoto 0:56c5742b9e2b 372 nedge_pts=qr_finder_edge_pts_fill(_edge_pts,nedge_pts,
RyoheiHagimoto 0:56c5742b9e2b 373 vneighbors,nvneighbors,1);
RyoheiHagimoto 0:56c5742b9e2b 374 c->nedge_pts=nedge_pts;
RyoheiHagimoto 0:56c5742b9e2b 375 _edge_pts+=nedge_pts;
RyoheiHagimoto 0:56c5742b9e2b 376 }
RyoheiHagimoto 0:56c5742b9e2b 377 }
RyoheiHagimoto 0:56c5742b9e2b 378 free(vmark);
RyoheiHagimoto 0:56c5742b9e2b 379 free(hmark);
RyoheiHagimoto 0:56c5742b9e2b 380 free(vneighbors);
RyoheiHagimoto 0:56c5742b9e2b 381 free(hneighbors);
RyoheiHagimoto 0:56c5742b9e2b 382 /*Sort the centers by decreasing numbers of edge points.*/
RyoheiHagimoto 0:56c5742b9e2b 383 qsort(_centers,ncenters,sizeof(*_centers),qr_finder_center_cmp);
RyoheiHagimoto 0:56c5742b9e2b 384 return ncenters;
RyoheiHagimoto 0:56c5742b9e2b 385 }
RyoheiHagimoto 0:56c5742b9e2b 386
RyoheiHagimoto 0:56c5742b9e2b 387 /*Locates a set of putative finder centers in the image.
RyoheiHagimoto 0:56c5742b9e2b 388 First we search for horizontal and vertical lines that have
RyoheiHagimoto 0:56c5742b9e2b 389 (dark:light:dark:light:dark) runs with size ratios of roughly (1:1:3:1:1).
RyoheiHagimoto 0:56c5742b9e2b 390 Then we cluster them into groups such that each subsequent pair of endpoints
RyoheiHagimoto 0:56c5742b9e2b 391 is close to the line before it in the cluster.
RyoheiHagimoto 0:56c5742b9e2b 392 This will locate many line clusters that don't cross a finder pattern, but
RyoheiHagimoto 0:56c5742b9e2b 393 qr_finder_find_crossings() will filter most of them out.
RyoheiHagimoto 0:56c5742b9e2b 394 Where horizontal and vertical clusters cross, a prospective finder center is
RyoheiHagimoto 0:56c5742b9e2b 395 returned.
RyoheiHagimoto 0:56c5742b9e2b 396 _centers: Returns a pointer to a freshly-allocated list of finder centers.
RyoheiHagimoto 0:56c5742b9e2b 397 This must be freed by the caller.
RyoheiHagimoto 0:56c5742b9e2b 398 _edge_pts: Returns a pointer to a freshly-allocated list of edge points
RyoheiHagimoto 0:56c5742b9e2b 399 around those centers.
RyoheiHagimoto 0:56c5742b9e2b 400 This must be freed by the caller.
RyoheiHagimoto 0:56c5742b9e2b 401 _img: The binary image to search.
RyoheiHagimoto 0:56c5742b9e2b 402 _width: The width of the image.
RyoheiHagimoto 0:56c5742b9e2b 403 _height: The height of the image.
RyoheiHagimoto 0:56c5742b9e2b 404 Return: The number of putative finder centers located.*/
RyoheiHagimoto 0:56c5742b9e2b 405 static int qr_finder_centers_locate(qr_finder_center **_centers,
RyoheiHagimoto 0:56c5742b9e2b 406 qr_finder_edge_pt **_edge_pts, qr_reader *reader,
RyoheiHagimoto 0:56c5742b9e2b 407 int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 408 qr_finder_line *hlines = reader->finder_lines[0].lines;
RyoheiHagimoto 0:56c5742b9e2b 409 int nhlines = reader->finder_lines[0].nlines;
RyoheiHagimoto 0:56c5742b9e2b 410 qr_finder_line *vlines = reader->finder_lines[1].lines;
RyoheiHagimoto 0:56c5742b9e2b 411 int nvlines = reader->finder_lines[1].nlines;
RyoheiHagimoto 0:56c5742b9e2b 412
RyoheiHagimoto 0:56c5742b9e2b 413 qr_finder_line **hneighbors;
RyoheiHagimoto 0:56c5742b9e2b 414 qr_finder_cluster *hclusters;
RyoheiHagimoto 0:56c5742b9e2b 415 int nhclusters;
RyoheiHagimoto 0:56c5742b9e2b 416 qr_finder_line **vneighbors;
RyoheiHagimoto 0:56c5742b9e2b 417 qr_finder_cluster *vclusters;
RyoheiHagimoto 0:56c5742b9e2b 418 int nvclusters;
RyoheiHagimoto 0:56c5742b9e2b 419 int ncenters;
RyoheiHagimoto 0:56c5742b9e2b 420
RyoheiHagimoto 0:56c5742b9e2b 421 /*Cluster the detected lines.*/
RyoheiHagimoto 0:56c5742b9e2b 422 hneighbors=(qr_finder_line **)malloc(nhlines*sizeof(*hneighbors));
RyoheiHagimoto 0:56c5742b9e2b 423 /*We require more than one line per cluster, so there are at most nhlines/2.*/
RyoheiHagimoto 0:56c5742b9e2b 424 hclusters=(qr_finder_cluster *)malloc((nhlines>>1)*sizeof(*hclusters));
RyoheiHagimoto 0:56c5742b9e2b 425 nhclusters=qr_finder_cluster_lines(hclusters,hneighbors,hlines,nhlines,0);
RyoheiHagimoto 0:56c5742b9e2b 426 /*We need vertical lines to be sorted by X coordinate, with ties broken by Y
RyoheiHagimoto 0:56c5742b9e2b 427 coordinate, for clustering purposes.
RyoheiHagimoto 0:56c5742b9e2b 428 We scan the image in the opposite order for cache efficiency, so sort the
RyoheiHagimoto 0:56c5742b9e2b 429 lines we found here.*/
RyoheiHagimoto 0:56c5742b9e2b 430 qsort(vlines,nvlines,sizeof(*vlines),qr_finder_vline_cmp);
RyoheiHagimoto 0:56c5742b9e2b 431 vneighbors=(qr_finder_line **)malloc(nvlines*sizeof(*vneighbors));
RyoheiHagimoto 0:56c5742b9e2b 432 /*We require more than one line per cluster, so there are at most nvlines/2.*/
RyoheiHagimoto 0:56c5742b9e2b 433 vclusters=(qr_finder_cluster *)malloc((nvlines>>1)*sizeof(*vclusters));
RyoheiHagimoto 0:56c5742b9e2b 434 nvclusters=qr_finder_cluster_lines(vclusters,vneighbors,vlines,nvlines,1);
RyoheiHagimoto 0:56c5742b9e2b 435 /*Find line crossings among the clusters.*/
RyoheiHagimoto 0:56c5742b9e2b 436 if(nhclusters>=3&&nvclusters>=3){
RyoheiHagimoto 0:56c5742b9e2b 437 qr_finder_edge_pt *edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 438 qr_finder_center *centers;
RyoheiHagimoto 0:56c5742b9e2b 439 int nedge_pts;
RyoheiHagimoto 0:56c5742b9e2b 440 int i;
RyoheiHagimoto 0:56c5742b9e2b 441 nedge_pts=0;
RyoheiHagimoto 0:56c5742b9e2b 442 for(i=0;i<nhclusters;i++)nedge_pts+=hclusters[i].nlines;
RyoheiHagimoto 0:56c5742b9e2b 443 for(i=0;i<nvclusters;i++)nedge_pts+=vclusters[i].nlines;
RyoheiHagimoto 0:56c5742b9e2b 444 nedge_pts<<=1;
RyoheiHagimoto 0:56c5742b9e2b 445 edge_pts=(qr_finder_edge_pt *)malloc(nedge_pts*sizeof(*edge_pts));
RyoheiHagimoto 0:56c5742b9e2b 446 centers=(qr_finder_center *)malloc(
RyoheiHagimoto 0:56c5742b9e2b 447 QR_MINI(nhclusters,nvclusters)*sizeof(*centers));
RyoheiHagimoto 0:56c5742b9e2b 448 ncenters=qr_finder_find_crossings(centers,edge_pts,
RyoheiHagimoto 0:56c5742b9e2b 449 hclusters,nhclusters,vclusters,nvclusters);
RyoheiHagimoto 0:56c5742b9e2b 450 *_centers=centers;
RyoheiHagimoto 0:56c5742b9e2b 451 *_edge_pts=edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 452 }
RyoheiHagimoto 0:56c5742b9e2b 453 else ncenters=0;
RyoheiHagimoto 0:56c5742b9e2b 454 free(vclusters);
RyoheiHagimoto 0:56c5742b9e2b 455 free(vneighbors);
RyoheiHagimoto 0:56c5742b9e2b 456 free(hclusters);
RyoheiHagimoto 0:56c5742b9e2b 457 free(hneighbors);
RyoheiHagimoto 0:56c5742b9e2b 458 return ncenters;
RyoheiHagimoto 0:56c5742b9e2b 459 }
RyoheiHagimoto 0:56c5742b9e2b 460
RyoheiHagimoto 0:56c5742b9e2b 461
RyoheiHagimoto 0:56c5742b9e2b 462
RyoheiHagimoto 0:56c5742b9e2b 463 static void qr_point_translate(qr_point _point,int _dx,int _dy){
RyoheiHagimoto 0:56c5742b9e2b 464 _point[0]+=_dx;
RyoheiHagimoto 0:56c5742b9e2b 465 _point[1]+=_dy;
RyoheiHagimoto 0:56c5742b9e2b 466 }
RyoheiHagimoto 0:56c5742b9e2b 467
RyoheiHagimoto 0:56c5742b9e2b 468 static unsigned qr_point_distance2(const qr_point _p1,const qr_point _p2){
RyoheiHagimoto 0:56c5742b9e2b 469 return (_p1[0]-_p2[0])*(_p1[0]-_p2[0])+(_p1[1]-_p2[1])*(_p1[1]-_p2[1]);
RyoheiHagimoto 0:56c5742b9e2b 470 }
RyoheiHagimoto 0:56c5742b9e2b 471
RyoheiHagimoto 0:56c5742b9e2b 472 /*Returns the cross product of the three points, which is positive if they are
RyoheiHagimoto 0:56c5742b9e2b 473 in CCW order (in a right-handed coordinate system), and 0 if they're
RyoheiHagimoto 0:56c5742b9e2b 474 colinear.*/
RyoheiHagimoto 0:56c5742b9e2b 475 static int qr_point_ccw(const qr_point _p0,
RyoheiHagimoto 0:56c5742b9e2b 476 const qr_point _p1,const qr_point _p2){
RyoheiHagimoto 0:56c5742b9e2b 477 return (_p1[0]-_p0[0])*(_p2[1]-_p0[1])-(_p1[1]-_p0[1])*(_p2[0]-_p0[0]);
RyoheiHagimoto 0:56c5742b9e2b 478 }
RyoheiHagimoto 0:56c5742b9e2b 479
RyoheiHagimoto 0:56c5742b9e2b 480
RyoheiHagimoto 0:56c5742b9e2b 481
RyoheiHagimoto 0:56c5742b9e2b 482 /*Evaluates a line equation at a point.
RyoheiHagimoto 0:56c5742b9e2b 483 _line: The line to evaluate.
RyoheiHagimoto 0:56c5742b9e2b 484 _x: The X coordinate of the point.
RyoheiHagimoto 0:56c5742b9e2b 485 _y: The y coordinate of the point.
RyoheiHagimoto 0:56c5742b9e2b 486 Return: The value of the line equation _line[0]*_x+_line[1]*_y+_line[2].*/
RyoheiHagimoto 0:56c5742b9e2b 487 static int qr_line_eval(qr_line _line,int _x,int _y){
RyoheiHagimoto 0:56c5742b9e2b 488 return _line[0]*_x+_line[1]*_y+_line[2];
RyoheiHagimoto 0:56c5742b9e2b 489 }
RyoheiHagimoto 0:56c5742b9e2b 490
RyoheiHagimoto 0:56c5742b9e2b 491 /*Computes a line passing through the given point using the specified second
RyoheiHagimoto 0:56c5742b9e2b 492 order statistics.
RyoheiHagimoto 0:56c5742b9e2b 493 Given a line defined by the equation
RyoheiHagimoto 0:56c5742b9e2b 494 A*x+B*y+C = 0 ,
RyoheiHagimoto 0:56c5742b9e2b 495 the least squares fit to n points (x_i,y_i) must satisfy the two equations
RyoheiHagimoto 0:56c5742b9e2b 496 A^2 + (Syy - Sxx)/Sxy*A*B - B^2 = 0 ,
RyoheiHagimoto 0:56c5742b9e2b 497 C = -(xbar*A+ybar*B) ,
RyoheiHagimoto 0:56c5742b9e2b 498 where
RyoheiHagimoto 0:56c5742b9e2b 499 xbar = sum(x_i)/n ,
RyoheiHagimoto 0:56c5742b9e2b 500 ybar = sum(y_i)/n ,
RyoheiHagimoto 0:56c5742b9e2b 501 Sxx = sum((x_i-xbar)**2) ,
RyoheiHagimoto 0:56c5742b9e2b 502 Sxy = sum((x_i-xbar)*(y_i-ybar)) ,
RyoheiHagimoto 0:56c5742b9e2b 503 Syy = sum((y_i-ybar)**2) .
RyoheiHagimoto 0:56c5742b9e2b 504 The quadratic can be solved for the ratio (A/B) or (B/A):
RyoheiHagimoto 0:56c5742b9e2b 505 A/B = (Syy + sqrt((Sxx-Syy)**2 + 4*Sxy**2) - Sxx)/(-2*Sxy) ,
RyoheiHagimoto 0:56c5742b9e2b 506 B/A = (Sxx + sqrt((Sxx-Syy)**2 + 4*Sxy**2) - Syy)/(-2*Sxy) .
RyoheiHagimoto 0:56c5742b9e2b 507 We pick the one that leads to the larger ratio to avoid destructive
RyoheiHagimoto 0:56c5742b9e2b 508 cancellation (and e.g., 0/0 for horizontal or vertical lines).
RyoheiHagimoto 0:56c5742b9e2b 509 The above solutions correspond to the actual minimum.
RyoheiHagimoto 0:56c5742b9e2b 510 The other solution of the quadratic corresponds to a saddle point of the
RyoheiHagimoto 0:56c5742b9e2b 511 least squares objective function.
RyoheiHagimoto 0:56c5742b9e2b 512 _l: Returns the fitted line values A, B, and C.
RyoheiHagimoto 0:56c5742b9e2b 513 _x0: The X coordinate of the point the line is supposed to pass through.
RyoheiHagimoto 0:56c5742b9e2b 514 _y0: The Y coordinate of the point the line is supposed to pass through.
RyoheiHagimoto 0:56c5742b9e2b 515 _sxx: The sum Sxx.
RyoheiHagimoto 0:56c5742b9e2b 516 _sxy: The sum Sxy.
RyoheiHagimoto 0:56c5742b9e2b 517 _syy: The sum Syy.
RyoheiHagimoto 0:56c5742b9e2b 518 _res: The maximum number of bits occupied by the product of any two of
RyoheiHagimoto 0:56c5742b9e2b 519 _l[0] or _l[1].
RyoheiHagimoto 0:56c5742b9e2b 520 Smaller numbers give less angular resolution, but allow more overhead
RyoheiHagimoto 0:56c5742b9e2b 521 room for computations.*/
RyoheiHagimoto 0:56c5742b9e2b 522 static void qr_line_fit(qr_line _l,int _x0,int _y0,
RyoheiHagimoto 0:56c5742b9e2b 523 int _sxx,int _sxy,int _syy,int _res){
RyoheiHagimoto 0:56c5742b9e2b 524 int dshift;
RyoheiHagimoto 0:56c5742b9e2b 525 int dround;
RyoheiHagimoto 0:56c5742b9e2b 526 int u;
RyoheiHagimoto 0:56c5742b9e2b 527 int v;
RyoheiHagimoto 0:56c5742b9e2b 528 int w;
RyoheiHagimoto 0:56c5742b9e2b 529 u=abs(_sxx-_syy);
RyoheiHagimoto 0:56c5742b9e2b 530 v=-_sxy<<1;
RyoheiHagimoto 0:56c5742b9e2b 531 w=qr_ihypot(u,v);
RyoheiHagimoto 0:56c5742b9e2b 532 /*Computations in later stages can easily overflow with moderate sizes, so we
RyoheiHagimoto 0:56c5742b9e2b 533 compute a shift factor to scale things down into a managable range.
RyoheiHagimoto 0:56c5742b9e2b 534 We ensure that the product of any two of _l[0] and _l[1] fits within _res
RyoheiHagimoto 0:56c5742b9e2b 535 bits, which allows computation of line intersections without overflow.*/
RyoheiHagimoto 0:56c5742b9e2b 536 dshift=QR_MAXI(0,QR_MAXI(qr_ilog(u),qr_ilog(abs(v)))+1-(_res+1>>1));
RyoheiHagimoto 0:56c5742b9e2b 537 dround=(1<<dshift)>>1;
RyoheiHagimoto 0:56c5742b9e2b 538 if(_sxx>_syy){
RyoheiHagimoto 0:56c5742b9e2b 539 _l[0]=v+dround>>dshift;
RyoheiHagimoto 0:56c5742b9e2b 540 _l[1]=u+w+dround>>dshift;
RyoheiHagimoto 0:56c5742b9e2b 541 }
RyoheiHagimoto 0:56c5742b9e2b 542 else{
RyoheiHagimoto 0:56c5742b9e2b 543 _l[0]=u+w+dround>>dshift;
RyoheiHagimoto 0:56c5742b9e2b 544 _l[1]=v+dround>>dshift;
RyoheiHagimoto 0:56c5742b9e2b 545 }
RyoheiHagimoto 0:56c5742b9e2b 546 _l[2]=-(_x0*_l[0]+_y0*_l[1]);
RyoheiHagimoto 0:56c5742b9e2b 547 }
RyoheiHagimoto 0:56c5742b9e2b 548
RyoheiHagimoto 0:56c5742b9e2b 549 /*Perform a least-squares line fit to a list of points.
RyoheiHagimoto 0:56c5742b9e2b 550 At least two points are required.*/
RyoheiHagimoto 0:56c5742b9e2b 551 static void qr_line_fit_points(qr_line _l,qr_point *_p,int _np,int _res){
RyoheiHagimoto 0:56c5742b9e2b 552 int sx;
RyoheiHagimoto 0:56c5742b9e2b 553 int sy;
RyoheiHagimoto 0:56c5742b9e2b 554 int xmin;
RyoheiHagimoto 0:56c5742b9e2b 555 int xmax;
RyoheiHagimoto 0:56c5742b9e2b 556 int ymin;
RyoheiHagimoto 0:56c5742b9e2b 557 int ymax;
RyoheiHagimoto 0:56c5742b9e2b 558 int xbar;
RyoheiHagimoto 0:56c5742b9e2b 559 int ybar;
RyoheiHagimoto 0:56c5742b9e2b 560 int dx;
RyoheiHagimoto 0:56c5742b9e2b 561 int dy;
RyoheiHagimoto 0:56c5742b9e2b 562 int sxx;
RyoheiHagimoto 0:56c5742b9e2b 563 int sxy;
RyoheiHagimoto 0:56c5742b9e2b 564 int syy;
RyoheiHagimoto 0:56c5742b9e2b 565 int sshift;
RyoheiHagimoto 0:56c5742b9e2b 566 int sround;
RyoheiHagimoto 0:56c5742b9e2b 567 int i;
RyoheiHagimoto 0:56c5742b9e2b 568 sx=sy=0;
RyoheiHagimoto 0:56c5742b9e2b 569 ymax=xmax=INT_MIN;
RyoheiHagimoto 0:56c5742b9e2b 570 ymin=xmin=INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 571 for(i=0;i<_np;i++){
RyoheiHagimoto 0:56c5742b9e2b 572 sx+=_p[i][0];
RyoheiHagimoto 0:56c5742b9e2b 573 xmin=QR_MINI(xmin,_p[i][0]);
RyoheiHagimoto 0:56c5742b9e2b 574 xmax=QR_MAXI(xmax,_p[i][0]);
RyoheiHagimoto 0:56c5742b9e2b 575 sy+=_p[i][1];
RyoheiHagimoto 0:56c5742b9e2b 576 ymin=QR_MINI(ymin,_p[i][1]);
RyoheiHagimoto 0:56c5742b9e2b 577 ymax=QR_MAXI(ymax,_p[i][1]);
RyoheiHagimoto 0:56c5742b9e2b 578 }
RyoheiHagimoto 0:56c5742b9e2b 579 xbar=(sx+(_np>>1))/_np;
RyoheiHagimoto 0:56c5742b9e2b 580 ybar=(sy+(_np>>1))/_np;
RyoheiHagimoto 0:56c5742b9e2b 581 sshift=QR_MAXI(0,qr_ilog(_np*QR_MAXI(QR_MAXI(xmax-xbar,xbar-xmin),
RyoheiHagimoto 0:56c5742b9e2b 582 QR_MAXI(ymax-ybar,ybar-ymin)))-(QR_INT_BITS-1>>1));
RyoheiHagimoto 0:56c5742b9e2b 583 sround=(1<<sshift)>>1;
RyoheiHagimoto 0:56c5742b9e2b 584 sxx=sxy=syy=0;
RyoheiHagimoto 0:56c5742b9e2b 585 for(i=0;i<_np;i++){
RyoheiHagimoto 0:56c5742b9e2b 586 dx=_p[i][0]-xbar+sround>>sshift;
RyoheiHagimoto 0:56c5742b9e2b 587 dy=_p[i][1]-ybar+sround>>sshift;
RyoheiHagimoto 0:56c5742b9e2b 588 sxx+=dx*dx;
RyoheiHagimoto 0:56c5742b9e2b 589 sxy+=dx*dy;
RyoheiHagimoto 0:56c5742b9e2b 590 syy+=dy*dy;
RyoheiHagimoto 0:56c5742b9e2b 591 }
RyoheiHagimoto 0:56c5742b9e2b 592 qr_line_fit(_l,xbar,ybar,sxx,sxy,syy,_res);
RyoheiHagimoto 0:56c5742b9e2b 593 }
RyoheiHagimoto 0:56c5742b9e2b 594
RyoheiHagimoto 0:56c5742b9e2b 595 static void qr_line_orient(qr_line _l,int _x,int _y){
RyoheiHagimoto 0:56c5742b9e2b 596 if(qr_line_eval(_l,_x,_y)<0){
RyoheiHagimoto 0:56c5742b9e2b 597 _l[0]=-_l[0];
RyoheiHagimoto 0:56c5742b9e2b 598 _l[1]=-_l[1];
RyoheiHagimoto 0:56c5742b9e2b 599 _l[2]=-_l[2];
RyoheiHagimoto 0:56c5742b9e2b 600 }
RyoheiHagimoto 0:56c5742b9e2b 601 }
RyoheiHagimoto 0:56c5742b9e2b 602
RyoheiHagimoto 0:56c5742b9e2b 603 static int qr_line_isect(qr_point _p,const qr_line _l0,const qr_line _l1){
RyoheiHagimoto 0:56c5742b9e2b 604 int d;
RyoheiHagimoto 0:56c5742b9e2b 605 int x;
RyoheiHagimoto 0:56c5742b9e2b 606 int y;
RyoheiHagimoto 0:56c5742b9e2b 607 d=_l0[0]*_l1[1]-_l0[1]*_l1[0];
RyoheiHagimoto 0:56c5742b9e2b 608 if(d==0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 609 x=_l0[1]*_l1[2]-_l1[1]*_l0[2];
RyoheiHagimoto 0:56c5742b9e2b 610 y=_l1[0]*_l0[2]-_l0[0]*_l1[2];
RyoheiHagimoto 0:56c5742b9e2b 611 if(d<0){
RyoheiHagimoto 0:56c5742b9e2b 612 x=-x;
RyoheiHagimoto 0:56c5742b9e2b 613 y=-y;
RyoheiHagimoto 0:56c5742b9e2b 614 d=-d;
RyoheiHagimoto 0:56c5742b9e2b 615 }
RyoheiHagimoto 0:56c5742b9e2b 616 _p[0]=QR_DIVROUND(x,d);
RyoheiHagimoto 0:56c5742b9e2b 617 _p[1]=QR_DIVROUND(y,d);
RyoheiHagimoto 0:56c5742b9e2b 618 return 0;
RyoheiHagimoto 0:56c5742b9e2b 619 }
RyoheiHagimoto 0:56c5742b9e2b 620
RyoheiHagimoto 0:56c5742b9e2b 621
RyoheiHagimoto 0:56c5742b9e2b 622
RyoheiHagimoto 0:56c5742b9e2b 623 /*An affine homography.
RyoheiHagimoto 0:56c5742b9e2b 624 This maps from the image (at subpel resolution) to a square domain with
RyoheiHagimoto 0:56c5742b9e2b 625 power-of-two sides (of res bits) and back.*/
RyoheiHagimoto 0:56c5742b9e2b 626 struct qr_aff{
RyoheiHagimoto 0:56c5742b9e2b 627 int fwd[2][2];
RyoheiHagimoto 0:56c5742b9e2b 628 int inv[2][2];
RyoheiHagimoto 0:56c5742b9e2b 629 int x0;
RyoheiHagimoto 0:56c5742b9e2b 630 int y0;
RyoheiHagimoto 0:56c5742b9e2b 631 int res;
RyoheiHagimoto 0:56c5742b9e2b 632 };
RyoheiHagimoto 0:56c5742b9e2b 633
RyoheiHagimoto 0:56c5742b9e2b 634
RyoheiHagimoto 0:56c5742b9e2b 635 static void qr_aff_init(qr_aff *_aff,
RyoheiHagimoto 0:56c5742b9e2b 636 const qr_point _p0,const qr_point _p1,const qr_point _p2,int _res){
RyoheiHagimoto 0:56c5742b9e2b 637 int det;
RyoheiHagimoto 0:56c5742b9e2b 638 int dx1;
RyoheiHagimoto 0:56c5742b9e2b 639 int dy1;
RyoheiHagimoto 0:56c5742b9e2b 640 int dx2;
RyoheiHagimoto 0:56c5742b9e2b 641 int dy2;
RyoheiHagimoto 0:56c5742b9e2b 642 /*det is ensured to be positive by our caller.*/
RyoheiHagimoto 0:56c5742b9e2b 643 det=qr_point_ccw(_p0,_p1,_p2);
RyoheiHagimoto 0:56c5742b9e2b 644 dx1=_p1[0]-_p0[0];
RyoheiHagimoto 0:56c5742b9e2b 645 dx2=_p2[0]-_p0[0];
RyoheiHagimoto 0:56c5742b9e2b 646 dy1=_p1[1]-_p0[1];
RyoheiHagimoto 0:56c5742b9e2b 647 dy2=_p2[1]-_p0[1];
RyoheiHagimoto 0:56c5742b9e2b 648 _aff->fwd[0][0]=dx1;
RyoheiHagimoto 0:56c5742b9e2b 649 _aff->fwd[0][1]=dx2;
RyoheiHagimoto 0:56c5742b9e2b 650 _aff->fwd[1][0]=dy1;
RyoheiHagimoto 0:56c5742b9e2b 651 _aff->fwd[1][1]=dy2;
RyoheiHagimoto 0:56c5742b9e2b 652 _aff->inv[0][0]=QR_DIVROUND(dy2<<_res,det);
RyoheiHagimoto 0:56c5742b9e2b 653 _aff->inv[0][1]=QR_DIVROUND(-dx2<<_res,det);
RyoheiHagimoto 0:56c5742b9e2b 654 _aff->inv[1][0]=QR_DIVROUND(-dy1<<_res,det);
RyoheiHagimoto 0:56c5742b9e2b 655 _aff->inv[1][1]=QR_DIVROUND(dx1<<_res,det);
RyoheiHagimoto 0:56c5742b9e2b 656 _aff->x0=_p0[0];
RyoheiHagimoto 0:56c5742b9e2b 657 _aff->y0=_p0[1];
RyoheiHagimoto 0:56c5742b9e2b 658 _aff->res=_res;
RyoheiHagimoto 0:56c5742b9e2b 659 }
RyoheiHagimoto 0:56c5742b9e2b 660
RyoheiHagimoto 0:56c5742b9e2b 661 /*Map from the image (at subpel resolution) into the square domain.*/
RyoheiHagimoto 0:56c5742b9e2b 662 static void qr_aff_unproject(qr_point _q,const qr_aff *_aff,
RyoheiHagimoto 0:56c5742b9e2b 663 int _x,int _y){
RyoheiHagimoto 0:56c5742b9e2b 664 _q[0]=_aff->inv[0][0]*(_x-_aff->x0)+_aff->inv[0][1]*(_y-_aff->y0);
RyoheiHagimoto 0:56c5742b9e2b 665 _q[1]=_aff->inv[1][0]*(_x-_aff->x0)+_aff->inv[1][1]*(_y-_aff->y0);
RyoheiHagimoto 0:56c5742b9e2b 666 }
RyoheiHagimoto 0:56c5742b9e2b 667
RyoheiHagimoto 0:56c5742b9e2b 668 /*Map from the square domain into the image (at subpel resolution).*/
RyoheiHagimoto 0:56c5742b9e2b 669 static void qr_aff_project(qr_point _p,const qr_aff *_aff,
RyoheiHagimoto 0:56c5742b9e2b 670 int _u,int _v){
RyoheiHagimoto 0:56c5742b9e2b 671 _p[0]=(_aff->fwd[0][0]*_u+_aff->fwd[0][1]*_v+(1<<_aff->res-1)>>_aff->res)
RyoheiHagimoto 0:56c5742b9e2b 672 +_aff->x0;
RyoheiHagimoto 0:56c5742b9e2b 673 _p[1]=(_aff->fwd[1][0]*_u+_aff->fwd[1][1]*_v+(1<<_aff->res-1)>>_aff->res)
RyoheiHagimoto 0:56c5742b9e2b 674 +_aff->y0;
RyoheiHagimoto 0:56c5742b9e2b 675 }
RyoheiHagimoto 0:56c5742b9e2b 676
RyoheiHagimoto 0:56c5742b9e2b 677
RyoheiHagimoto 0:56c5742b9e2b 678
RyoheiHagimoto 0:56c5742b9e2b 679 /*A full homography.
RyoheiHagimoto 0:56c5742b9e2b 680 Like the affine homography, this maps from the image (at subpel resolution)
RyoheiHagimoto 0:56c5742b9e2b 681 to a square domain with power-of-two sides (of res bits) and back.*/
RyoheiHagimoto 0:56c5742b9e2b 682 struct qr_hom{
RyoheiHagimoto 0:56c5742b9e2b 683 int fwd[3][2];
RyoheiHagimoto 0:56c5742b9e2b 684 int inv[3][2];
RyoheiHagimoto 0:56c5742b9e2b 685 int fwd22;
RyoheiHagimoto 0:56c5742b9e2b 686 int inv22;
RyoheiHagimoto 0:56c5742b9e2b 687 int x0;
RyoheiHagimoto 0:56c5742b9e2b 688 int y0;
RyoheiHagimoto 0:56c5742b9e2b 689 int res;
RyoheiHagimoto 0:56c5742b9e2b 690 };
RyoheiHagimoto 0:56c5742b9e2b 691
RyoheiHagimoto 0:56c5742b9e2b 692
RyoheiHagimoto 0:56c5742b9e2b 693 static void qr_hom_init(qr_hom *_hom,int _x0,int _y0,
RyoheiHagimoto 0:56c5742b9e2b 694 int _x1,int _y1,int _x2,int _y2,int _x3,int _y3,int _res){
RyoheiHagimoto 0:56c5742b9e2b 695 int dx10;
RyoheiHagimoto 0:56c5742b9e2b 696 int dx20;
RyoheiHagimoto 0:56c5742b9e2b 697 int dx30;
RyoheiHagimoto 0:56c5742b9e2b 698 int dx31;
RyoheiHagimoto 0:56c5742b9e2b 699 int dx32;
RyoheiHagimoto 0:56c5742b9e2b 700 int dy10;
RyoheiHagimoto 0:56c5742b9e2b 701 int dy20;
RyoheiHagimoto 0:56c5742b9e2b 702 int dy30;
RyoheiHagimoto 0:56c5742b9e2b 703 int dy31;
RyoheiHagimoto 0:56c5742b9e2b 704 int dy32;
RyoheiHagimoto 0:56c5742b9e2b 705 int a20;
RyoheiHagimoto 0:56c5742b9e2b 706 int a21;
RyoheiHagimoto 0:56c5742b9e2b 707 int a22;
RyoheiHagimoto 0:56c5742b9e2b 708 int b0;
RyoheiHagimoto 0:56c5742b9e2b 709 int b1;
RyoheiHagimoto 0:56c5742b9e2b 710 int b2;
RyoheiHagimoto 0:56c5742b9e2b 711 int s1;
RyoheiHagimoto 0:56c5742b9e2b 712 int s2;
RyoheiHagimoto 0:56c5742b9e2b 713 int r1;
RyoheiHagimoto 0:56c5742b9e2b 714 int r2;
RyoheiHagimoto 0:56c5742b9e2b 715 dx10=_x1-_x0;
RyoheiHagimoto 0:56c5742b9e2b 716 dx20=_x2-_x0;
RyoheiHagimoto 0:56c5742b9e2b 717 dx30=_x3-_x0;
RyoheiHagimoto 0:56c5742b9e2b 718 dx31=_x3-_x1;
RyoheiHagimoto 0:56c5742b9e2b 719 dx32=_x3-_x2;
RyoheiHagimoto 0:56c5742b9e2b 720 dy10=_y1-_y0;
RyoheiHagimoto 0:56c5742b9e2b 721 dy20=_y2-_y0;
RyoheiHagimoto 0:56c5742b9e2b 722 dy30=_y3-_y0;
RyoheiHagimoto 0:56c5742b9e2b 723 dy31=_y3-_y1;
RyoheiHagimoto 0:56c5742b9e2b 724 dy32=_y3-_y2;
RyoheiHagimoto 0:56c5742b9e2b 725 a20=dx32*dy10-dx10*dy32;
RyoheiHagimoto 0:56c5742b9e2b 726 a21=dx20*dy31-dx31*dy20;
RyoheiHagimoto 0:56c5742b9e2b 727 a22=dx32*dy31-dx31*dy32;
RyoheiHagimoto 0:56c5742b9e2b 728 /*Figure out if we need to downscale anything.*/
RyoheiHagimoto 0:56c5742b9e2b 729 b0=qr_ilog(QR_MAXI(abs(dx10),abs(dy10)))+qr_ilog(abs(a20+a22));
RyoheiHagimoto 0:56c5742b9e2b 730 b1=qr_ilog(QR_MAXI(abs(dx20),abs(dy20)))+qr_ilog(abs(a21+a22));
RyoheiHagimoto 0:56c5742b9e2b 731 b2=qr_ilog(QR_MAXI(QR_MAXI(abs(a20),abs(a21)),abs(a22)));
RyoheiHagimoto 0:56c5742b9e2b 732 s1=QR_MAXI(0,_res+QR_MAXI(QR_MAXI(b0,b1),b2)-(QR_INT_BITS-2));
RyoheiHagimoto 0:56c5742b9e2b 733 r1=(1<<s1)>>1;
RyoheiHagimoto 0:56c5742b9e2b 734 /*Compute the final coefficients of the forward transform.
RyoheiHagimoto 0:56c5742b9e2b 735 The 32x32->64 bit multiplies are really needed for accuracy with large
RyoheiHagimoto 0:56c5742b9e2b 736 versions.*/
RyoheiHagimoto 0:56c5742b9e2b 737 _hom->fwd[0][0]=QR_FIXMUL(dx10,a20+a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 738 _hom->fwd[0][1]=QR_FIXMUL(dx20,a21+a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 739 _hom->x0=_x0;
RyoheiHagimoto 0:56c5742b9e2b 740 _hom->fwd[1][0]=QR_FIXMUL(dy10,a20+a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 741 _hom->fwd[1][1]=QR_FIXMUL(dy20,a21+a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 742 _hom->y0=_y0;
RyoheiHagimoto 0:56c5742b9e2b 743 _hom->fwd[2][0]=a20+r1>>s1;
RyoheiHagimoto 0:56c5742b9e2b 744 _hom->fwd[2][1]=a21+r1>>s1;
RyoheiHagimoto 0:56c5742b9e2b 745 _hom->fwd22=s1>_res?a22+(r1>>_res)>>s1-_res:a22<<_res-s1;
RyoheiHagimoto 0:56c5742b9e2b 746 /*Now compute the inverse transform.*/
RyoheiHagimoto 0:56c5742b9e2b 747 b0=qr_ilog(QR_MAXI(QR_MAXI(abs(dx10),abs(dx20)),abs(dx30)))+
RyoheiHagimoto 0:56c5742b9e2b 748 qr_ilog(QR_MAXI(abs(_hom->fwd[0][0]),abs(_hom->fwd[1][0])));
RyoheiHagimoto 0:56c5742b9e2b 749 b1=qr_ilog(QR_MAXI(QR_MAXI(abs(dy10),abs(dy20)),abs(dy30)))+
RyoheiHagimoto 0:56c5742b9e2b 750 qr_ilog(QR_MAXI(abs(_hom->fwd[0][1]),abs(_hom->fwd[1][1])));
RyoheiHagimoto 0:56c5742b9e2b 751 b2=qr_ilog(abs(a22))-s1;
RyoheiHagimoto 0:56c5742b9e2b 752 s2=QR_MAXI(0,QR_MAXI(b0,b1)+b2-(QR_INT_BITS-3));
RyoheiHagimoto 0:56c5742b9e2b 753 r2=(1<<s2)>>1;
RyoheiHagimoto 0:56c5742b9e2b 754 s1+=s2;
RyoheiHagimoto 0:56c5742b9e2b 755 r1<<=s2;
RyoheiHagimoto 0:56c5742b9e2b 756 /*The 32x32->64 bit multiplies are really needed for accuracy with large
RyoheiHagimoto 0:56c5742b9e2b 757 versions.*/
RyoheiHagimoto 0:56c5742b9e2b 758 _hom->inv[0][0]=QR_FIXMUL(_hom->fwd[1][1],a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 759 _hom->inv[0][1]=QR_FIXMUL(-_hom->fwd[0][1],a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 760 _hom->inv[1][0]=QR_FIXMUL(-_hom->fwd[1][0],a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 761 _hom->inv[1][1]=QR_FIXMUL(_hom->fwd[0][0],a22,r1,s1);
RyoheiHagimoto 0:56c5742b9e2b 762 _hom->inv[2][0]=QR_FIXMUL(_hom->fwd[1][0],_hom->fwd[2][1],
RyoheiHagimoto 0:56c5742b9e2b 763 -QR_EXTMUL(_hom->fwd[1][1],_hom->fwd[2][0],r2),s2);
RyoheiHagimoto 0:56c5742b9e2b 764 _hom->inv[2][1]=QR_FIXMUL(_hom->fwd[0][1],_hom->fwd[2][0],
RyoheiHagimoto 0:56c5742b9e2b 765 -QR_EXTMUL(_hom->fwd[0][0],_hom->fwd[2][1],r2),s2);
RyoheiHagimoto 0:56c5742b9e2b 766 _hom->inv22=QR_FIXMUL(_hom->fwd[0][0],_hom->fwd[1][1],
RyoheiHagimoto 0:56c5742b9e2b 767 -QR_EXTMUL(_hom->fwd[0][1],_hom->fwd[1][0],r2),s2);
RyoheiHagimoto 0:56c5742b9e2b 768 _hom->res=_res;
RyoheiHagimoto 0:56c5742b9e2b 769 }
RyoheiHagimoto 0:56c5742b9e2b 770
RyoheiHagimoto 0:56c5742b9e2b 771
RyoheiHagimoto 0:56c5742b9e2b 772 /*Map from the image (at subpel resolution) into the square domain.
RyoheiHagimoto 0:56c5742b9e2b 773 Returns a negative value if the point went to infinity.*/
RyoheiHagimoto 0:56c5742b9e2b 774 static int qr_hom_unproject(qr_point _q,const qr_hom *_hom,int _x,int _y){
RyoheiHagimoto 0:56c5742b9e2b 775 int x;
RyoheiHagimoto 0:56c5742b9e2b 776 int y;
RyoheiHagimoto 0:56c5742b9e2b 777 int w;
RyoheiHagimoto 0:56c5742b9e2b 778 _x-=_hom->x0;
RyoheiHagimoto 0:56c5742b9e2b 779 _y-=_hom->y0;
RyoheiHagimoto 0:56c5742b9e2b 780 x=_hom->inv[0][0]*_x+_hom->inv[0][1]*_y;
RyoheiHagimoto 0:56c5742b9e2b 781 y=_hom->inv[1][0]*_x+_hom->inv[1][1]*_y;
RyoheiHagimoto 0:56c5742b9e2b 782 w=_hom->inv[2][0]*_x+_hom->inv[2][1]*_y
RyoheiHagimoto 0:56c5742b9e2b 783 +_hom->inv22+(1<<_hom->res-1)>>_hom->res;
RyoheiHagimoto 0:56c5742b9e2b 784 if(w==0){
RyoheiHagimoto 0:56c5742b9e2b 785 _q[0]=x<0?INT_MIN:INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 786 _q[1]=y<0?INT_MIN:INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 787 return -1;
RyoheiHagimoto 0:56c5742b9e2b 788 }
RyoheiHagimoto 0:56c5742b9e2b 789 else{
RyoheiHagimoto 0:56c5742b9e2b 790 if(w<0){
RyoheiHagimoto 0:56c5742b9e2b 791 x=-x;
RyoheiHagimoto 0:56c5742b9e2b 792 y=-y;
RyoheiHagimoto 0:56c5742b9e2b 793 w=-w;
RyoheiHagimoto 0:56c5742b9e2b 794 }
RyoheiHagimoto 0:56c5742b9e2b 795 _q[0]=QR_DIVROUND(x,w);
RyoheiHagimoto 0:56c5742b9e2b 796 _q[1]=QR_DIVROUND(y,w);
RyoheiHagimoto 0:56c5742b9e2b 797 }
RyoheiHagimoto 0:56c5742b9e2b 798 return 0;
RyoheiHagimoto 0:56c5742b9e2b 799 }
RyoheiHagimoto 0:56c5742b9e2b 800
RyoheiHagimoto 0:56c5742b9e2b 801 /*Finish a partial projection, converting from homogeneous coordinates to the
RyoheiHagimoto 0:56c5742b9e2b 802 normal 2-D representation.
RyoheiHagimoto 0:56c5742b9e2b 803 In loops, we can avoid many multiplies by computing the homogeneous _x, _y,
RyoheiHagimoto 0:56c5742b9e2b 804 and _w incrementally, but we cannot avoid the divisions, done here.*/
RyoheiHagimoto 0:56c5742b9e2b 805 static void qr_hom_fproject(qr_point _p,const qr_hom *_hom,
RyoheiHagimoto 0:56c5742b9e2b 806 int _x,int _y,int _w){
RyoheiHagimoto 0:56c5742b9e2b 807 if(_w==0){
RyoheiHagimoto 0:56c5742b9e2b 808 _p[0]=_x<0?INT_MIN:INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 809 _p[1]=_y<0?INT_MIN:INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 810 }
RyoheiHagimoto 0:56c5742b9e2b 811 else{
RyoheiHagimoto 0:56c5742b9e2b 812 if(_w<0){
RyoheiHagimoto 0:56c5742b9e2b 813 _x=-_x;
RyoheiHagimoto 0:56c5742b9e2b 814 _y=-_y;
RyoheiHagimoto 0:56c5742b9e2b 815 _w=-_w;
RyoheiHagimoto 0:56c5742b9e2b 816 }
RyoheiHagimoto 0:56c5742b9e2b 817 _p[0]=QR_DIVROUND(_x,_w)+_hom->x0;
RyoheiHagimoto 0:56c5742b9e2b 818 _p[1]=QR_DIVROUND(_y,_w)+_hom->y0;
RyoheiHagimoto 0:56c5742b9e2b 819 }
RyoheiHagimoto 0:56c5742b9e2b 820 }
RyoheiHagimoto 0:56c5742b9e2b 821
RyoheiHagimoto 0:56c5742b9e2b 822 #if defined(QR_DEBUG)
RyoheiHagimoto 0:56c5742b9e2b 823 /*Map from the square domain into the image (at subpel resolution).
RyoheiHagimoto 0:56c5742b9e2b 824 Currently only used directly by debug code.*/
RyoheiHagimoto 0:56c5742b9e2b 825 static void qr_hom_project(qr_point _p,const qr_hom *_hom,
RyoheiHagimoto 0:56c5742b9e2b 826 int _u,int _v){
RyoheiHagimoto 0:56c5742b9e2b 827 qr_hom_fproject(_p,_hom,
RyoheiHagimoto 0:56c5742b9e2b 828 _hom->fwd[0][0]*_u+_hom->fwd[0][1]*_v,
RyoheiHagimoto 0:56c5742b9e2b 829 _hom->fwd[1][0]*_u+_hom->fwd[1][1]*_v,
RyoheiHagimoto 0:56c5742b9e2b 830 _hom->fwd[2][0]*_u+_hom->fwd[2][1]*_v+_hom->fwd22);
RyoheiHagimoto 0:56c5742b9e2b 831 }
RyoheiHagimoto 0:56c5742b9e2b 832 #endif
RyoheiHagimoto 0:56c5742b9e2b 833
RyoheiHagimoto 0:56c5742b9e2b 834
RyoheiHagimoto 0:56c5742b9e2b 835
RyoheiHagimoto 0:56c5742b9e2b 836 /*All the information we've collected about a finder pattern in the current
RyoheiHagimoto 0:56c5742b9e2b 837 configuration.*/
RyoheiHagimoto 0:56c5742b9e2b 838 struct qr_finder{
RyoheiHagimoto 0:56c5742b9e2b 839 /*The module size along each axis (in the square domain).*/
RyoheiHagimoto 0:56c5742b9e2b 840 int size[2];
RyoheiHagimoto 0:56c5742b9e2b 841 /*The version estimated from the module size along each axis.*/
RyoheiHagimoto 0:56c5742b9e2b 842 int eversion[2];
RyoheiHagimoto 0:56c5742b9e2b 843 /*The list of classified edge points for each edge.*/
RyoheiHagimoto 0:56c5742b9e2b 844 qr_finder_edge_pt *edge_pts[4];
RyoheiHagimoto 0:56c5742b9e2b 845 /*The number of edge points classified as belonging to each edge.*/
RyoheiHagimoto 0:56c5742b9e2b 846 int nedge_pts[4];
RyoheiHagimoto 0:56c5742b9e2b 847 /*The number of inliers found after running RANSAC on each edge.*/
RyoheiHagimoto 0:56c5742b9e2b 848 int ninliers[4];
RyoheiHagimoto 0:56c5742b9e2b 849 /*The center of the finder pattern (in the square domain).*/
RyoheiHagimoto 0:56c5742b9e2b 850 qr_point o;
RyoheiHagimoto 0:56c5742b9e2b 851 /*The finder center information from the original image.*/
RyoheiHagimoto 0:56c5742b9e2b 852 qr_finder_center *c;
RyoheiHagimoto 0:56c5742b9e2b 853 };
RyoheiHagimoto 0:56c5742b9e2b 854
RyoheiHagimoto 0:56c5742b9e2b 855
RyoheiHagimoto 0:56c5742b9e2b 856 static int qr_cmp_edge_pt(const void *_a,const void *_b){
RyoheiHagimoto 0:56c5742b9e2b 857 const qr_finder_edge_pt *a;
RyoheiHagimoto 0:56c5742b9e2b 858 const qr_finder_edge_pt *b;
RyoheiHagimoto 0:56c5742b9e2b 859 a=(const qr_finder_edge_pt *)_a;
RyoheiHagimoto 0:56c5742b9e2b 860 b=(const qr_finder_edge_pt *)_b;
RyoheiHagimoto 0:56c5742b9e2b 861 return ((a->edge>b->edge)-(a->edge<b->edge)<<1)+
RyoheiHagimoto 0:56c5742b9e2b 862 (a->extent>b->extent)-(a->extent<b->extent);
RyoheiHagimoto 0:56c5742b9e2b 863 }
RyoheiHagimoto 0:56c5742b9e2b 864
RyoheiHagimoto 0:56c5742b9e2b 865 /*Computes the index of the edge each edge point belongs to, and its (signed)
RyoheiHagimoto 0:56c5742b9e2b 866 distance along the corresponding axis from the center of the finder pattern
RyoheiHagimoto 0:56c5742b9e2b 867 (in the square domain).
RyoheiHagimoto 0:56c5742b9e2b 868 The resulting list of edge points is sorted by edge index, with ties broken
RyoheiHagimoto 0:56c5742b9e2b 869 by extent.*/
RyoheiHagimoto 0:56c5742b9e2b 870 static void qr_finder_edge_pts_aff_classify(qr_finder *_f,const qr_aff *_aff){
RyoheiHagimoto 0:56c5742b9e2b 871 qr_finder_center *c;
RyoheiHagimoto 0:56c5742b9e2b 872 int i;
RyoheiHagimoto 0:56c5742b9e2b 873 int e;
RyoheiHagimoto 0:56c5742b9e2b 874 c=_f->c;
RyoheiHagimoto 0:56c5742b9e2b 875 for(e=0;e<4;e++)_f->nedge_pts[e]=0;
RyoheiHagimoto 0:56c5742b9e2b 876 for(i=0;i<c->nedge_pts;i++){
RyoheiHagimoto 0:56c5742b9e2b 877 qr_point q;
RyoheiHagimoto 0:56c5742b9e2b 878 int d;
RyoheiHagimoto 0:56c5742b9e2b 879 qr_aff_unproject(q,_aff,c->edge_pts[i].pos[0],c->edge_pts[i].pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 880 qr_point_translate(q,-_f->o[0],-_f->o[1]);
RyoheiHagimoto 0:56c5742b9e2b 881 d=abs(q[1])>abs(q[0]);
RyoheiHagimoto 0:56c5742b9e2b 882 e=d<<1|(q[d]>=0);
RyoheiHagimoto 0:56c5742b9e2b 883 _f->nedge_pts[e]++;
RyoheiHagimoto 0:56c5742b9e2b 884 c->edge_pts[i].edge=e;
RyoheiHagimoto 0:56c5742b9e2b 885 c->edge_pts[i].extent=q[d];
RyoheiHagimoto 0:56c5742b9e2b 886 }
RyoheiHagimoto 0:56c5742b9e2b 887 qsort(c->edge_pts,c->nedge_pts,sizeof(*c->edge_pts),qr_cmp_edge_pt);
RyoheiHagimoto 0:56c5742b9e2b 888 _f->edge_pts[0]=c->edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 889 for(e=1;e<4;e++)_f->edge_pts[e]=_f->edge_pts[e-1]+_f->nedge_pts[e-1];
RyoheiHagimoto 0:56c5742b9e2b 890 }
RyoheiHagimoto 0:56c5742b9e2b 891
RyoheiHagimoto 0:56c5742b9e2b 892 /*Computes the index of the edge each edge point belongs to, and its (signed)
RyoheiHagimoto 0:56c5742b9e2b 893 distance along the corresponding axis from the center of the finder pattern
RyoheiHagimoto 0:56c5742b9e2b 894 (in the square domain).
RyoheiHagimoto 0:56c5742b9e2b 895 The resulting list of edge points is sorted by edge index, with ties broken
RyoheiHagimoto 0:56c5742b9e2b 896 by extent.*/
RyoheiHagimoto 0:56c5742b9e2b 897 static void qr_finder_edge_pts_hom_classify(qr_finder *_f,const qr_hom *_hom){
RyoheiHagimoto 0:56c5742b9e2b 898 qr_finder_center *c;
RyoheiHagimoto 0:56c5742b9e2b 899 int i;
RyoheiHagimoto 0:56c5742b9e2b 900 int e;
RyoheiHagimoto 0:56c5742b9e2b 901 c=_f->c;
RyoheiHagimoto 0:56c5742b9e2b 902 for(e=0;e<4;e++)_f->nedge_pts[e]=0;
RyoheiHagimoto 0:56c5742b9e2b 903 for(i=0;i<c->nedge_pts;i++){
RyoheiHagimoto 0:56c5742b9e2b 904 qr_point q;
RyoheiHagimoto 0:56c5742b9e2b 905 int d;
RyoheiHagimoto 0:56c5742b9e2b 906 if(qr_hom_unproject(q,_hom,
RyoheiHagimoto 0:56c5742b9e2b 907 c->edge_pts[i].pos[0],c->edge_pts[i].pos[1])>=0){
RyoheiHagimoto 0:56c5742b9e2b 908 qr_point_translate(q,-_f->o[0],-_f->o[1]);
RyoheiHagimoto 0:56c5742b9e2b 909 d=abs(q[1])>abs(q[0]);
RyoheiHagimoto 0:56c5742b9e2b 910 e=d<<1|(q[d]>=0);
RyoheiHagimoto 0:56c5742b9e2b 911 _f->nedge_pts[e]++;
RyoheiHagimoto 0:56c5742b9e2b 912 c->edge_pts[i].edge=e;
RyoheiHagimoto 0:56c5742b9e2b 913 c->edge_pts[i].extent=q[d];
RyoheiHagimoto 0:56c5742b9e2b 914 }
RyoheiHagimoto 0:56c5742b9e2b 915 else{
RyoheiHagimoto 0:56c5742b9e2b 916 c->edge_pts[i].edge=4;
RyoheiHagimoto 0:56c5742b9e2b 917 c->edge_pts[i].extent=q[0];
RyoheiHagimoto 0:56c5742b9e2b 918 }
RyoheiHagimoto 0:56c5742b9e2b 919 }
RyoheiHagimoto 0:56c5742b9e2b 920 qsort(c->edge_pts,c->nedge_pts,sizeof(*c->edge_pts),qr_cmp_edge_pt);
RyoheiHagimoto 0:56c5742b9e2b 921 _f->edge_pts[0]=c->edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 922 for(e=1;e<4;e++)_f->edge_pts[e]=_f->edge_pts[e-1]+_f->nedge_pts[e-1];
RyoheiHagimoto 0:56c5742b9e2b 923 }
RyoheiHagimoto 0:56c5742b9e2b 924
RyoheiHagimoto 0:56c5742b9e2b 925 /*TODO: Perhaps these thresholds should be on the module size instead?
RyoheiHagimoto 0:56c5742b9e2b 926 Unfortunately, I'd need real-world images of codes with larger versions to
RyoheiHagimoto 0:56c5742b9e2b 927 see if these thresholds are still effective, but such versions aren't used
RyoheiHagimoto 0:56c5742b9e2b 928 often.*/
RyoheiHagimoto 0:56c5742b9e2b 929
RyoheiHagimoto 0:56c5742b9e2b 930 /*The amount that the estimated version numbers are allowed to differ from the
RyoheiHagimoto 0:56c5742b9e2b 931 real version number and still be considered valid.*/
RyoheiHagimoto 0:56c5742b9e2b 932 #define QR_SMALL_VERSION_SLACK (1)
RyoheiHagimoto 0:56c5742b9e2b 933 /*Since cell phone cameras can have severe radial distortion, the estimated
RyoheiHagimoto 0:56c5742b9e2b 934 version for larger versions can be off by larger amounts.*/
RyoheiHagimoto 0:56c5742b9e2b 935 #define QR_LARGE_VERSION_SLACK (3)
RyoheiHagimoto 0:56c5742b9e2b 936
RyoheiHagimoto 0:56c5742b9e2b 937 /*Estimates the size of a module after classifying the edge points.
RyoheiHagimoto 0:56c5742b9e2b 938 _width: The distance between UL and UR in the square domain.
RyoheiHagimoto 0:56c5742b9e2b 939 _height: The distance between UL and DL in the square domain.*/
RyoheiHagimoto 0:56c5742b9e2b 940 static int qr_finder_estimate_module_size_and_version(qr_finder *_f,
RyoheiHagimoto 0:56c5742b9e2b 941 int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 942 qr_point offs;
RyoheiHagimoto 0:56c5742b9e2b 943 int sums[4];
RyoheiHagimoto 0:56c5742b9e2b 944 int nsums[4];
RyoheiHagimoto 0:56c5742b9e2b 945 int usize;
RyoheiHagimoto 0:56c5742b9e2b 946 int nusize;
RyoheiHagimoto 0:56c5742b9e2b 947 int vsize;
RyoheiHagimoto 0:56c5742b9e2b 948 int nvsize;
RyoheiHagimoto 0:56c5742b9e2b 949 int uversion;
RyoheiHagimoto 0:56c5742b9e2b 950 int vversion;
RyoheiHagimoto 0:56c5742b9e2b 951 int e;
RyoheiHagimoto 0:56c5742b9e2b 952 offs[0]=offs[1]=0;
RyoheiHagimoto 0:56c5742b9e2b 953 for(e=0;e<4;e++)if(_f->nedge_pts[e]>0){
RyoheiHagimoto 0:56c5742b9e2b 954 qr_finder_edge_pt *edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 955 int sum;
RyoheiHagimoto 0:56c5742b9e2b 956 int mean;
RyoheiHagimoto 0:56c5742b9e2b 957 int n;
RyoheiHagimoto 0:56c5742b9e2b 958 int i;
RyoheiHagimoto 0:56c5742b9e2b 959 /*Average the samples for this edge, dropping the top and bottom 25%.*/
RyoheiHagimoto 0:56c5742b9e2b 960 edge_pts=_f->edge_pts[e];
RyoheiHagimoto 0:56c5742b9e2b 961 n=_f->nedge_pts[e];
RyoheiHagimoto 0:56c5742b9e2b 962 sum=0;
RyoheiHagimoto 0:56c5742b9e2b 963 for(i=(n>>2);i<n-(n>>2);i++)sum+=edge_pts[i].extent;
RyoheiHagimoto 0:56c5742b9e2b 964 n=n-((n>>2)<<1);
RyoheiHagimoto 0:56c5742b9e2b 965 mean=QR_DIVROUND(sum,n);
RyoheiHagimoto 0:56c5742b9e2b 966 offs[e>>1]+=mean;
RyoheiHagimoto 0:56c5742b9e2b 967 sums[e]=sum;
RyoheiHagimoto 0:56c5742b9e2b 968 nsums[e]=n;
RyoheiHagimoto 0:56c5742b9e2b 969 }
RyoheiHagimoto 0:56c5742b9e2b 970 else nsums[e]=sums[e]=0;
RyoheiHagimoto 0:56c5742b9e2b 971 /*If we have samples on both sides of an axis, refine our idea of where the
RyoheiHagimoto 0:56c5742b9e2b 972 unprojected finder center is located.*/
RyoheiHagimoto 0:56c5742b9e2b 973 if(_f->nedge_pts[0]>0&&_f->nedge_pts[1]>0){
RyoheiHagimoto 0:56c5742b9e2b 974 _f->o[0]-=offs[0]>>1;
RyoheiHagimoto 0:56c5742b9e2b 975 sums[0]-=offs[0]*nsums[0]>>1;
RyoheiHagimoto 0:56c5742b9e2b 976 sums[1]-=offs[0]*nsums[1]>>1;
RyoheiHagimoto 0:56c5742b9e2b 977 }
RyoheiHagimoto 0:56c5742b9e2b 978 if(_f->nedge_pts[2]>0&&_f->nedge_pts[3]>0){
RyoheiHagimoto 0:56c5742b9e2b 979 _f->o[1]-=offs[1]>>1;
RyoheiHagimoto 0:56c5742b9e2b 980 sums[2]-=offs[1]*nsums[2]>>1;
RyoheiHagimoto 0:56c5742b9e2b 981 sums[3]-=offs[1]*nsums[3]>>1;
RyoheiHagimoto 0:56c5742b9e2b 982 }
RyoheiHagimoto 0:56c5742b9e2b 983 /*We must have _some_ samples along each axis... if we don't, our transform
RyoheiHagimoto 0:56c5742b9e2b 984 must be pretty severely distorting the original square (e.g., with
RyoheiHagimoto 0:56c5742b9e2b 985 coordinates so large as to cause overflow).*/
RyoheiHagimoto 0:56c5742b9e2b 986 nusize=nsums[0]+nsums[1];
RyoheiHagimoto 0:56c5742b9e2b 987 if(nusize<=0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 988 /*The module size is 1/3 the average edge extent.*/
RyoheiHagimoto 0:56c5742b9e2b 989 nusize*=3;
RyoheiHagimoto 0:56c5742b9e2b 990 usize=sums[1]-sums[0];
RyoheiHagimoto 0:56c5742b9e2b 991 usize=((usize<<1)+nusize)/(nusize<<1);
RyoheiHagimoto 0:56c5742b9e2b 992 if(usize<=0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 993 /*Now estimate the version directly from the module size and the distance
RyoheiHagimoto 0:56c5742b9e2b 994 between the finder patterns.
RyoheiHagimoto 0:56c5742b9e2b 995 This is done independently using the extents along each axis.
RyoheiHagimoto 0:56c5742b9e2b 996 If either falls significantly outside the valid range (1 to 40), reject the
RyoheiHagimoto 0:56c5742b9e2b 997 configuration.*/
RyoheiHagimoto 0:56c5742b9e2b 998 uversion=(_width-8*usize)/(usize<<2);
RyoheiHagimoto 0:56c5742b9e2b 999 if(uversion<1||uversion>40+QR_LARGE_VERSION_SLACK)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1000 /*Now do the same for the other axis.*/
RyoheiHagimoto 0:56c5742b9e2b 1001 nvsize=nsums[2]+nsums[3];
RyoheiHagimoto 0:56c5742b9e2b 1002 if(nvsize<=0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1003 nvsize*=3;
RyoheiHagimoto 0:56c5742b9e2b 1004 vsize=sums[3]-sums[2];
RyoheiHagimoto 0:56c5742b9e2b 1005 vsize=((vsize<<1)+nvsize)/(nvsize<<1);
RyoheiHagimoto 0:56c5742b9e2b 1006 if(vsize<=0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1007 vversion=(_height-8*vsize)/(vsize<<2);
RyoheiHagimoto 0:56c5742b9e2b 1008 if(vversion<1||vversion>40+QR_LARGE_VERSION_SLACK)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1009 /*If the estimated version using extents along one axis is significantly
RyoheiHagimoto 0:56c5742b9e2b 1010 different than the estimated version along the other axis, then the axes
RyoheiHagimoto 0:56c5742b9e2b 1011 have significantly different scalings (relative to the grid).
RyoheiHagimoto 0:56c5742b9e2b 1012 This can happen, e.g., when we have multiple adjacent QR codes, and we've
RyoheiHagimoto 0:56c5742b9e2b 1013 picked two finder patterns from one and the third finder pattern from
RyoheiHagimoto 0:56c5742b9e2b 1014 another, e.g.:
RyoheiHagimoto 0:56c5742b9e2b 1015 X---DL UL---X
RyoheiHagimoto 0:56c5742b9e2b 1016 |.... |....
RyoheiHagimoto 0:56c5742b9e2b 1017 X.... UR....
RyoheiHagimoto 0:56c5742b9e2b 1018 Such a configuration might even pass any other geometric checks if we
RyoheiHagimoto 0:56c5742b9e2b 1019 didn't reject it here.*/
RyoheiHagimoto 0:56c5742b9e2b 1020 if(abs(uversion-vversion)>QR_LARGE_VERSION_SLACK)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1021 _f->size[0]=usize;
RyoheiHagimoto 0:56c5742b9e2b 1022 _f->size[1]=vsize;
RyoheiHagimoto 0:56c5742b9e2b 1023 /*We intentionally do not compute an average version from the sizes along
RyoheiHagimoto 0:56c5742b9e2b 1024 both axes.
RyoheiHagimoto 0:56c5742b9e2b 1025 In the presence of projective distortion, one of them will be much more
RyoheiHagimoto 0:56c5742b9e2b 1026 accurate than the other.*/
RyoheiHagimoto 0:56c5742b9e2b 1027 _f->eversion[0]=uversion;
RyoheiHagimoto 0:56c5742b9e2b 1028 _f->eversion[1]=vversion;
RyoheiHagimoto 0:56c5742b9e2b 1029 return 0;
RyoheiHagimoto 0:56c5742b9e2b 1030 }
RyoheiHagimoto 0:56c5742b9e2b 1031
RyoheiHagimoto 0:56c5742b9e2b 1032 /*Eliminate outliers from the classified edge points with RANSAC.*/
RyoheiHagimoto 0:56c5742b9e2b 1033 static void qr_finder_ransac(qr_finder *_f,const qr_aff *_hom,
RyoheiHagimoto 0:56c5742b9e2b 1034 isaac_ctx *_isaac,int _e){
RyoheiHagimoto 0:56c5742b9e2b 1035 qr_finder_edge_pt *edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 1036 int best_ninliers;
RyoheiHagimoto 0:56c5742b9e2b 1037 int n;
RyoheiHagimoto 0:56c5742b9e2b 1038 edge_pts=_f->edge_pts[_e];
RyoheiHagimoto 0:56c5742b9e2b 1039 n=_f->nedge_pts[_e];
RyoheiHagimoto 0:56c5742b9e2b 1040 best_ninliers=0;
RyoheiHagimoto 0:56c5742b9e2b 1041 if(n>1){
RyoheiHagimoto 0:56c5742b9e2b 1042 int max_iters;
RyoheiHagimoto 0:56c5742b9e2b 1043 int i;
RyoheiHagimoto 0:56c5742b9e2b 1044 int j;
RyoheiHagimoto 0:56c5742b9e2b 1045 /*17 iterations is enough to guarantee an outlier-free sample with more
RyoheiHagimoto 0:56c5742b9e2b 1046 than 99% probability given as many as 50% outliers.*/
RyoheiHagimoto 0:56c5742b9e2b 1047 max_iters=17;
RyoheiHagimoto 0:56c5742b9e2b 1048 for(i=0;i<max_iters;i++){
RyoheiHagimoto 0:56c5742b9e2b 1049 qr_point q0;
RyoheiHagimoto 0:56c5742b9e2b 1050 qr_point q1;
RyoheiHagimoto 0:56c5742b9e2b 1051 int ninliers;
RyoheiHagimoto 0:56c5742b9e2b 1052 int thresh;
RyoheiHagimoto 0:56c5742b9e2b 1053 int p0i;
RyoheiHagimoto 0:56c5742b9e2b 1054 int p1i;
RyoheiHagimoto 0:56c5742b9e2b 1055 int *p0;
RyoheiHagimoto 0:56c5742b9e2b 1056 int *p1;
RyoheiHagimoto 0:56c5742b9e2b 1057 int j;
RyoheiHagimoto 0:56c5742b9e2b 1058 /*Pick two random points on this edge.*/
RyoheiHagimoto 0:56c5742b9e2b 1059 p0i=isaac_next_uint(_isaac,n);
RyoheiHagimoto 0:56c5742b9e2b 1060 p1i=isaac_next_uint(_isaac,n-1);
RyoheiHagimoto 0:56c5742b9e2b 1061 if(p1i>=p0i)p1i++;
RyoheiHagimoto 0:56c5742b9e2b 1062 p0=edge_pts[p0i].pos;
RyoheiHagimoto 0:56c5742b9e2b 1063 p1=edge_pts[p1i].pos;
RyoheiHagimoto 0:56c5742b9e2b 1064 /*If the corresponding line is not within 45 degrees of the proper
RyoheiHagimoto 0:56c5742b9e2b 1065 orientation in the square domain, reject it outright.
RyoheiHagimoto 0:56c5742b9e2b 1066 This can happen, e.g., when highly skewed orientations cause points to
RyoheiHagimoto 0:56c5742b9e2b 1067 be misclassified into the wrong edge.
RyoheiHagimoto 0:56c5742b9e2b 1068 The irony is that using such points might produce a line which _does_
RyoheiHagimoto 0:56c5742b9e2b 1069 pass the corresponding validity checks.*/
RyoheiHagimoto 0:56c5742b9e2b 1070 qr_aff_unproject(q0,_hom,p0[0],p0[1]);
RyoheiHagimoto 0:56c5742b9e2b 1071 qr_aff_unproject(q1,_hom,p1[0],p1[1]);
RyoheiHagimoto 0:56c5742b9e2b 1072 qr_point_translate(q0,-_f->o[0],-_f->o[1]);
RyoheiHagimoto 0:56c5742b9e2b 1073 qr_point_translate(q1,-_f->o[0],-_f->o[1]);
RyoheiHagimoto 0:56c5742b9e2b 1074 if(abs(q0[_e>>1]-q1[_e>>1])>abs(q0[1-(_e>>1)]-q1[1-(_e>>1)]))continue;
RyoheiHagimoto 0:56c5742b9e2b 1075 /*Identify the other edge points which are inliers.
RyoheiHagimoto 0:56c5742b9e2b 1076 The squared distance should be distributed as a \Chi^2 distribution
RyoheiHagimoto 0:56c5742b9e2b 1077 with one degree of freedom, which means for a 95% confidence the
RyoheiHagimoto 0:56c5742b9e2b 1078 point should lie within a factor 3.8414588 ~= 4 times the expected
RyoheiHagimoto 0:56c5742b9e2b 1079 variance of the point locations.
RyoheiHagimoto 0:56c5742b9e2b 1080 We grossly approximate the standard deviation as 1 pixel in one
RyoheiHagimoto 0:56c5742b9e2b 1081 direction, and 0.5 pixels in the other (because we average two
RyoheiHagimoto 0:56c5742b9e2b 1082 coordinates).*/
RyoheiHagimoto 0:56c5742b9e2b 1083 thresh=qr_isqrt(qr_point_distance2(p0,p1)<<2*QR_FINDER_SUBPREC+1);
RyoheiHagimoto 0:56c5742b9e2b 1084 ninliers=0;
RyoheiHagimoto 0:56c5742b9e2b 1085 for(j=0;j<n;j++){
RyoheiHagimoto 0:56c5742b9e2b 1086 if(abs(qr_point_ccw(p0,p1,edge_pts[j].pos))<=thresh){
RyoheiHagimoto 0:56c5742b9e2b 1087 edge_pts[j].extent|=1;
RyoheiHagimoto 0:56c5742b9e2b 1088 ninliers++;
RyoheiHagimoto 0:56c5742b9e2b 1089 }
RyoheiHagimoto 0:56c5742b9e2b 1090 else edge_pts[j].extent&=~1;
RyoheiHagimoto 0:56c5742b9e2b 1091 }
RyoheiHagimoto 0:56c5742b9e2b 1092 if(ninliers>best_ninliers){
RyoheiHagimoto 0:56c5742b9e2b 1093 for(j=0;j<n;j++)edge_pts[j].extent<<=1;
RyoheiHagimoto 0:56c5742b9e2b 1094 best_ninliers=ninliers;
RyoheiHagimoto 0:56c5742b9e2b 1095 /*The actual number of iterations required is
RyoheiHagimoto 0:56c5742b9e2b 1096 log(1-\alpha)/log(1-r*r),
RyoheiHagimoto 0:56c5742b9e2b 1097 where \alpha is the required probability of taking a sample with
RyoheiHagimoto 0:56c5742b9e2b 1098 no outliers (e.g., 0.99) and r is the estimated ratio of inliers
RyoheiHagimoto 0:56c5742b9e2b 1099 (e.g. ninliers/n).
RyoheiHagimoto 0:56c5742b9e2b 1100 This is just a rough (but conservative) approximation, but it
RyoheiHagimoto 0:56c5742b9e2b 1101 should be good enough to stop the iteration early when we find
RyoheiHagimoto 0:56c5742b9e2b 1102 a good set of inliers.*/
RyoheiHagimoto 0:56c5742b9e2b 1103 if(ninliers>n>>1)max_iters=(67*n-63*ninliers-1)/(n<<1);
RyoheiHagimoto 0:56c5742b9e2b 1104 }
RyoheiHagimoto 0:56c5742b9e2b 1105 }
RyoheiHagimoto 0:56c5742b9e2b 1106 /*Now collect all the inliers at the beginning of the list.*/
RyoheiHagimoto 0:56c5742b9e2b 1107 for(i=j=0;j<best_ninliers;i++)if(edge_pts[i].extent&2){
RyoheiHagimoto 0:56c5742b9e2b 1108 if(j<i){
RyoheiHagimoto 0:56c5742b9e2b 1109 qr_finder_edge_pt tmp;
RyoheiHagimoto 0:56c5742b9e2b 1110 *&tmp=*(edge_pts+i);
RyoheiHagimoto 0:56c5742b9e2b 1111 *(edge_pts+j)=*(edge_pts+i);
RyoheiHagimoto 0:56c5742b9e2b 1112 *(edge_pts+i)=*&tmp;
RyoheiHagimoto 0:56c5742b9e2b 1113 }
RyoheiHagimoto 0:56c5742b9e2b 1114 j++;
RyoheiHagimoto 0:56c5742b9e2b 1115 }
RyoheiHagimoto 0:56c5742b9e2b 1116 }
RyoheiHagimoto 0:56c5742b9e2b 1117 _f->ninliers[_e]=best_ninliers;
RyoheiHagimoto 0:56c5742b9e2b 1118 }
RyoheiHagimoto 0:56c5742b9e2b 1119
RyoheiHagimoto 0:56c5742b9e2b 1120 /*Perform a least-squares line fit to an edge of a finder pattern using the
RyoheiHagimoto 0:56c5742b9e2b 1121 inliers found by RANSAC.*/
RyoheiHagimoto 0:56c5742b9e2b 1122 static int qr_line_fit_finder_edge(qr_line _l,
RyoheiHagimoto 0:56c5742b9e2b 1123 const qr_finder *_f,int _e,int _res){
RyoheiHagimoto 0:56c5742b9e2b 1124 qr_finder_edge_pt *edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 1125 qr_point *pts;
RyoheiHagimoto 0:56c5742b9e2b 1126 int npts;
RyoheiHagimoto 0:56c5742b9e2b 1127 int i;
RyoheiHagimoto 0:56c5742b9e2b 1128 npts=_f->ninliers[_e];
RyoheiHagimoto 0:56c5742b9e2b 1129 if(npts<2)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1130 /*We could write a custom version of qr_line_fit_points that accesses
RyoheiHagimoto 0:56c5742b9e2b 1131 edge_pts directly, but this saves on code size and doesn't measurably slow
RyoheiHagimoto 0:56c5742b9e2b 1132 things down.*/
RyoheiHagimoto 0:56c5742b9e2b 1133 pts=(qr_point *)malloc(npts*sizeof(*pts));
RyoheiHagimoto 0:56c5742b9e2b 1134 edge_pts=_f->edge_pts[_e];
RyoheiHagimoto 0:56c5742b9e2b 1135 for(i=0;i<npts;i++){
RyoheiHagimoto 0:56c5742b9e2b 1136 pts[i][0]=edge_pts[i].pos[0];
RyoheiHagimoto 0:56c5742b9e2b 1137 pts[i][1]=edge_pts[i].pos[1];
RyoheiHagimoto 0:56c5742b9e2b 1138 }
RyoheiHagimoto 0:56c5742b9e2b 1139 qr_line_fit_points(_l,pts,npts,_res);
RyoheiHagimoto 0:56c5742b9e2b 1140 /*Make sure the center of the finder pattern lies in the positive halfspace
RyoheiHagimoto 0:56c5742b9e2b 1141 of the line.*/
RyoheiHagimoto 0:56c5742b9e2b 1142 qr_line_orient(_l,_f->c->pos[0],_f->c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 1143 free(pts);
RyoheiHagimoto 0:56c5742b9e2b 1144 return 0;
RyoheiHagimoto 0:56c5742b9e2b 1145 }
RyoheiHagimoto 0:56c5742b9e2b 1146
RyoheiHagimoto 0:56c5742b9e2b 1147 /*Perform a least-squares line fit to a pair of common finder edges using the
RyoheiHagimoto 0:56c5742b9e2b 1148 inliers found by RANSAC.
RyoheiHagimoto 0:56c5742b9e2b 1149 Unlike a normal edge fit, we guarantee that this one succeeds by creating at
RyoheiHagimoto 0:56c5742b9e2b 1150 least one point on each edge using the estimated module size if it has no
RyoheiHagimoto 0:56c5742b9e2b 1151 inliers.*/
RyoheiHagimoto 0:56c5742b9e2b 1152 static void qr_line_fit_finder_pair(qr_line _l,const qr_aff *_aff,
RyoheiHagimoto 0:56c5742b9e2b 1153 const qr_finder *_f0,const qr_finder *_f1,int _e){
RyoheiHagimoto 0:56c5742b9e2b 1154 qr_point *pts;
RyoheiHagimoto 0:56c5742b9e2b 1155 int npts;
RyoheiHagimoto 0:56c5742b9e2b 1156 qr_finder_edge_pt *edge_pts;
RyoheiHagimoto 0:56c5742b9e2b 1157 qr_point q;
RyoheiHagimoto 0:56c5742b9e2b 1158 int n0;
RyoheiHagimoto 0:56c5742b9e2b 1159 int n1;
RyoheiHagimoto 0:56c5742b9e2b 1160 int i;
RyoheiHagimoto 0:56c5742b9e2b 1161 n0=_f0->ninliers[_e];
RyoheiHagimoto 0:56c5742b9e2b 1162 n1=_f1->ninliers[_e];
RyoheiHagimoto 0:56c5742b9e2b 1163 /*We could write a custom version of qr_line_fit_points that accesses
RyoheiHagimoto 0:56c5742b9e2b 1164 edge_pts directly, but this saves on code size and doesn't measurably slow
RyoheiHagimoto 0:56c5742b9e2b 1165 things down.*/
RyoheiHagimoto 0:56c5742b9e2b 1166 npts=QR_MAXI(n0,1)+QR_MAXI(n1,1);
RyoheiHagimoto 0:56c5742b9e2b 1167 pts=(qr_point *)malloc(npts*sizeof(*pts));
RyoheiHagimoto 0:56c5742b9e2b 1168 if(n0>0){
RyoheiHagimoto 0:56c5742b9e2b 1169 edge_pts=_f0->edge_pts[_e];
RyoheiHagimoto 0:56c5742b9e2b 1170 for(i=0;i<n0;i++){
RyoheiHagimoto 0:56c5742b9e2b 1171 pts[i][0]=edge_pts[i].pos[0];
RyoheiHagimoto 0:56c5742b9e2b 1172 pts[i][1]=edge_pts[i].pos[1];
RyoheiHagimoto 0:56c5742b9e2b 1173 }
RyoheiHagimoto 0:56c5742b9e2b 1174 }
RyoheiHagimoto 0:56c5742b9e2b 1175 else{
RyoheiHagimoto 0:56c5742b9e2b 1176 q[0]=_f0->o[0];
RyoheiHagimoto 0:56c5742b9e2b 1177 q[1]=_f0->o[1];
RyoheiHagimoto 0:56c5742b9e2b 1178 q[_e>>1]+=_f0->size[_e>>1]*(2*(_e&1)-1);
RyoheiHagimoto 0:56c5742b9e2b 1179 qr_aff_project(pts[0],_aff,q[0],q[1]);
RyoheiHagimoto 0:56c5742b9e2b 1180 n0++;
RyoheiHagimoto 0:56c5742b9e2b 1181 }
RyoheiHagimoto 0:56c5742b9e2b 1182 if(n1>0){
RyoheiHagimoto 0:56c5742b9e2b 1183 edge_pts=_f1->edge_pts[_e];
RyoheiHagimoto 0:56c5742b9e2b 1184 for(i=0;i<n1;i++){
RyoheiHagimoto 0:56c5742b9e2b 1185 pts[n0+i][0]=edge_pts[i].pos[0];
RyoheiHagimoto 0:56c5742b9e2b 1186 pts[n0+i][1]=edge_pts[i].pos[1];
RyoheiHagimoto 0:56c5742b9e2b 1187 }
RyoheiHagimoto 0:56c5742b9e2b 1188 }
RyoheiHagimoto 0:56c5742b9e2b 1189 else{
RyoheiHagimoto 0:56c5742b9e2b 1190 q[0]=_f1->o[0];
RyoheiHagimoto 0:56c5742b9e2b 1191 q[1]=_f1->o[1];
RyoheiHagimoto 0:56c5742b9e2b 1192 q[_e>>1]+=_f1->size[_e>>1]*(2*(_e&1)-1);
RyoheiHagimoto 0:56c5742b9e2b 1193 qr_aff_project(pts[n0],_aff,q[0],q[1]);
RyoheiHagimoto 0:56c5742b9e2b 1194 n1++;
RyoheiHagimoto 0:56c5742b9e2b 1195 }
RyoheiHagimoto 0:56c5742b9e2b 1196 qr_line_fit_points(_l,pts,npts,_aff->res);
RyoheiHagimoto 0:56c5742b9e2b 1197 /*Make sure at least one finder center lies in the positive halfspace.*/
RyoheiHagimoto 0:56c5742b9e2b 1198 qr_line_orient(_l,_f0->c->pos[0],_f0->c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 1199 free(pts);
RyoheiHagimoto 0:56c5742b9e2b 1200 }
RyoheiHagimoto 0:56c5742b9e2b 1201
RyoheiHagimoto 0:56c5742b9e2b 1202 static int qr_finder_quick_crossing_check(const unsigned char *_img,
RyoheiHagimoto 0:56c5742b9e2b 1203 int _width,int _height,int _x0,int _y0,int _x1,int _y1,int _v){
RyoheiHagimoto 0:56c5742b9e2b 1204 /*The points must be inside the image, and have a !_v:_v:!_v pattern.
RyoheiHagimoto 0:56c5742b9e2b 1205 We don't scan the whole line initially, but quickly reject if the endpoints
RyoheiHagimoto 0:56c5742b9e2b 1206 aren't !_v, or the midpoint isn't _v.
RyoheiHagimoto 0:56c5742b9e2b 1207 If either end point is out of the image, or we don't encounter a _v pixel,
RyoheiHagimoto 0:56c5742b9e2b 1208 we return a negative value, indicating the region should be considered
RyoheiHagimoto 0:56c5742b9e2b 1209 empty.
RyoheiHagimoto 0:56c5742b9e2b 1210 Otherwise, we return a positive value to indicate it is non-empty.*/
RyoheiHagimoto 0:56c5742b9e2b 1211 if(_x0<0||_x0>=_width||_y0<0||_y0>=_height||
RyoheiHagimoto 0:56c5742b9e2b 1212 _x1<0||_x1>=_width||_y1<0||_y1>=_height){
RyoheiHagimoto 0:56c5742b9e2b 1213 return -1;
RyoheiHagimoto 0:56c5742b9e2b 1214 }
RyoheiHagimoto 0:56c5742b9e2b 1215 if(!_img[_y0*_width+_x0]!=_v||!_img[_y1*_width+_x1]!=_v)return 1;
RyoheiHagimoto 0:56c5742b9e2b 1216 if(!_img[(_y0+_y1>>1)*_width+(_x0+_x1>>1)]==_v)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1217 return 0;
RyoheiHagimoto 0:56c5742b9e2b 1218 }
RyoheiHagimoto 0:56c5742b9e2b 1219
RyoheiHagimoto 0:56c5742b9e2b 1220 /*Locate the midpoint of a _v segment along a !_v:_v:!_v line from (_x0,_y0) to
RyoheiHagimoto 0:56c5742b9e2b 1221 (_x1,_y1).
RyoheiHagimoto 0:56c5742b9e2b 1222 All coordinates, which are NOT in subpel resolution, must lie inside the
RyoheiHagimoto 0:56c5742b9e2b 1223 image, and the endpoints are already assumed to have the value !_v.
RyoheiHagimoto 0:56c5742b9e2b 1224 The returned value is in subpel resolution.*/
RyoheiHagimoto 0:56c5742b9e2b 1225 static int qr_finder_locate_crossing(const unsigned char *_img,
RyoheiHagimoto 0:56c5742b9e2b 1226 int _width,int _height,int _x0,int _y0,int _x1,int _y1,int _v,qr_point _p){
RyoheiHagimoto 0:56c5742b9e2b 1227 qr_point x0;
RyoheiHagimoto 0:56c5742b9e2b 1228 qr_point x1;
RyoheiHagimoto 0:56c5742b9e2b 1229 qr_point dx;
RyoheiHagimoto 0:56c5742b9e2b 1230 int step[2];
RyoheiHagimoto 0:56c5742b9e2b 1231 int steep;
RyoheiHagimoto 0:56c5742b9e2b 1232 int err;
RyoheiHagimoto 0:56c5742b9e2b 1233 int derr;
RyoheiHagimoto 0:56c5742b9e2b 1234 /*Use Bresenham's algorithm to trace along the line and find the exact
RyoheiHagimoto 0:56c5742b9e2b 1235 transitions from !_v to _v and back.*/
RyoheiHagimoto 0:56c5742b9e2b 1236 x0[0]=_x0;
RyoheiHagimoto 0:56c5742b9e2b 1237 x0[1]=_y0;
RyoheiHagimoto 0:56c5742b9e2b 1238 x1[0]=_x1;
RyoheiHagimoto 0:56c5742b9e2b 1239 x1[1]=_y1;
RyoheiHagimoto 0:56c5742b9e2b 1240 dx[0]=abs(_x1-_x0);
RyoheiHagimoto 0:56c5742b9e2b 1241 dx[1]=abs(_y1-_y0);
RyoheiHagimoto 0:56c5742b9e2b 1242 steep=dx[1]>dx[0];
RyoheiHagimoto 0:56c5742b9e2b 1243 err=0;
RyoheiHagimoto 0:56c5742b9e2b 1244 derr=dx[1-steep];
RyoheiHagimoto 0:56c5742b9e2b 1245 step[0]=((_x0<_x1)<<1)-1;
RyoheiHagimoto 0:56c5742b9e2b 1246 step[1]=((_y0<_y1)<<1)-1;
RyoheiHagimoto 0:56c5742b9e2b 1247 /*Find the first crossing from !_v to _v.*/
RyoheiHagimoto 0:56c5742b9e2b 1248 for(;;){
RyoheiHagimoto 0:56c5742b9e2b 1249 /*If we make it all the way to the other side, there's no crossing.*/
RyoheiHagimoto 0:56c5742b9e2b 1250 if(x0[steep]==x1[steep])return -1;
RyoheiHagimoto 0:56c5742b9e2b 1251 x0[steep]+=step[steep];
RyoheiHagimoto 0:56c5742b9e2b 1252 err+=derr;
RyoheiHagimoto 0:56c5742b9e2b 1253 if(err<<1>dx[steep]){
RyoheiHagimoto 0:56c5742b9e2b 1254 x0[1-steep]+=step[1-steep];
RyoheiHagimoto 0:56c5742b9e2b 1255 err-=dx[steep];
RyoheiHagimoto 0:56c5742b9e2b 1256 }
RyoheiHagimoto 0:56c5742b9e2b 1257 if(!_img[x0[1]*_width+x0[0]]!=_v)break;
RyoheiHagimoto 0:56c5742b9e2b 1258 }
RyoheiHagimoto 0:56c5742b9e2b 1259 /*Find the last crossing from _v to !_v.*/
RyoheiHagimoto 0:56c5742b9e2b 1260 err=0;
RyoheiHagimoto 0:56c5742b9e2b 1261 for(;;){
RyoheiHagimoto 0:56c5742b9e2b 1262 if(x0[steep]==x1[steep])break;
RyoheiHagimoto 0:56c5742b9e2b 1263 x1[steep]-=step[steep];
RyoheiHagimoto 0:56c5742b9e2b 1264 err+=derr;
RyoheiHagimoto 0:56c5742b9e2b 1265 if(err<<1>dx[steep]){
RyoheiHagimoto 0:56c5742b9e2b 1266 x1[1-steep]-=step[1-steep];
RyoheiHagimoto 0:56c5742b9e2b 1267 err-=dx[steep];
RyoheiHagimoto 0:56c5742b9e2b 1268 }
RyoheiHagimoto 0:56c5742b9e2b 1269 if(!_img[x1[1]*_width+x1[0]]!=_v)break;
RyoheiHagimoto 0:56c5742b9e2b 1270 }
RyoheiHagimoto 0:56c5742b9e2b 1271 /*Return the midpoint of the _v segment.*/
RyoheiHagimoto 0:56c5742b9e2b 1272 _p[0]=(x0[0]+x1[0]+1<<QR_FINDER_SUBPREC)>>1;
RyoheiHagimoto 0:56c5742b9e2b 1273 _p[1]=(x0[1]+x1[1]+1<<QR_FINDER_SUBPREC)>>1;
RyoheiHagimoto 0:56c5742b9e2b 1274 return 0;
RyoheiHagimoto 0:56c5742b9e2b 1275 }
RyoheiHagimoto 0:56c5742b9e2b 1276
RyoheiHagimoto 0:56c5742b9e2b 1277 static int qr_aff_line_step(const qr_aff *_aff,qr_line _l,
RyoheiHagimoto 0:56c5742b9e2b 1278 int _v,int _du,int *_dv){
RyoheiHagimoto 0:56c5742b9e2b 1279 int shift;
RyoheiHagimoto 0:56c5742b9e2b 1280 int round;
RyoheiHagimoto 0:56c5742b9e2b 1281 int dv;
RyoheiHagimoto 0:56c5742b9e2b 1282 int n;
RyoheiHagimoto 0:56c5742b9e2b 1283 int d;
RyoheiHagimoto 0:56c5742b9e2b 1284 n=_aff->fwd[0][_v]*_l[0]+_aff->fwd[1][_v]*_l[1];
RyoheiHagimoto 0:56c5742b9e2b 1285 d=_aff->fwd[0][1-_v]*_l[0]+_aff->fwd[1][1-_v]*_l[1];
RyoheiHagimoto 0:56c5742b9e2b 1286 if(d<0){
RyoheiHagimoto 0:56c5742b9e2b 1287 n=-n;
RyoheiHagimoto 0:56c5742b9e2b 1288 d=-d;
RyoheiHagimoto 0:56c5742b9e2b 1289 }
RyoheiHagimoto 0:56c5742b9e2b 1290 shift=QR_MAXI(0,qr_ilog(_du)+qr_ilog(abs(n))+3-QR_INT_BITS);
RyoheiHagimoto 0:56c5742b9e2b 1291 round=(1<<shift)>>1;
RyoheiHagimoto 0:56c5742b9e2b 1292 n=n+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 1293 d=d+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 1294 /*The line should not be outside 45 degrees of horizontal/vertical.
RyoheiHagimoto 0:56c5742b9e2b 1295 TODO: We impose this restriction to help ensure the loop below terminates,
RyoheiHagimoto 0:56c5742b9e2b 1296 but it should not technically be required.
RyoheiHagimoto 0:56c5742b9e2b 1297 It also, however, ensures we avoid division by zero.*/
RyoheiHagimoto 0:56c5742b9e2b 1298 if(abs(n)>=d)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1299 n=-_du*n;
RyoheiHagimoto 0:56c5742b9e2b 1300 dv=QR_DIVROUND(n,d);
RyoheiHagimoto 0:56c5742b9e2b 1301 if(abs(dv)>=_du)return -1;
RyoheiHagimoto 0:56c5742b9e2b 1302 *_dv=dv;
RyoheiHagimoto 0:56c5742b9e2b 1303 return 0;
RyoheiHagimoto 0:56c5742b9e2b 1304 }
RyoheiHagimoto 0:56c5742b9e2b 1305
RyoheiHagimoto 0:56c5742b9e2b 1306 /*Computes the Hamming distance between two bit patterns (the number of bits
RyoheiHagimoto 0:56c5742b9e2b 1307 that differ).
RyoheiHagimoto 0:56c5742b9e2b 1308 May stop counting after _maxdiff differences.*/
RyoheiHagimoto 0:56c5742b9e2b 1309 static int qr_hamming_dist(unsigned _y1,unsigned _y2,int _maxdiff){
RyoheiHagimoto 0:56c5742b9e2b 1310 unsigned y;
RyoheiHagimoto 0:56c5742b9e2b 1311 int ret;
RyoheiHagimoto 0:56c5742b9e2b 1312 y=_y1^_y2;
RyoheiHagimoto 0:56c5742b9e2b 1313 for(ret=0;ret<_maxdiff&&y;ret++)y&=y-1;
RyoheiHagimoto 0:56c5742b9e2b 1314 return ret;
RyoheiHagimoto 0:56c5742b9e2b 1315 }
RyoheiHagimoto 0:56c5742b9e2b 1316
RyoheiHagimoto 0:56c5742b9e2b 1317 /*Retrieve a bit (guaranteed to be 0 or 1) from the image, given coordinates in
RyoheiHagimoto 0:56c5742b9e2b 1318 subpel resolution which have not been bounds checked.*/
RyoheiHagimoto 0:56c5742b9e2b 1319 static int qr_img_get_bit(const unsigned char *_img,int _width,int _height,
RyoheiHagimoto 0:56c5742b9e2b 1320 int _x,int _y){
RyoheiHagimoto 0:56c5742b9e2b 1321 _x>>=QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1322 _y>>=QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1323 return _img[QR_CLAMPI(0,_y,_height-1)*_width+QR_CLAMPI(0,_x,_width-1)]!=0;
RyoheiHagimoto 0:56c5742b9e2b 1324 }
RyoheiHagimoto 0:56c5742b9e2b 1325
RyoheiHagimoto 0:56c5742b9e2b 1326 #if defined(QR_DEBUG)
RyoheiHagimoto 0:56c5742b9e2b 1327 #include "image.h"
RyoheiHagimoto 0:56c5742b9e2b 1328
RyoheiHagimoto 0:56c5742b9e2b 1329 static void qr_finder_dump_aff_undistorted(qr_finder *_ul,qr_finder *_ur,
RyoheiHagimoto 0:56c5742b9e2b 1330 qr_finder *_dl,qr_aff *_aff,const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 1331 unsigned char *gimg;
RyoheiHagimoto 0:56c5742b9e2b 1332 FILE *fout;
RyoheiHagimoto 0:56c5742b9e2b 1333 int lpsz;
RyoheiHagimoto 0:56c5742b9e2b 1334 int pixel_size;
RyoheiHagimoto 0:56c5742b9e2b 1335 int dim;
RyoheiHagimoto 0:56c5742b9e2b 1336 int min;
RyoheiHagimoto 0:56c5742b9e2b 1337 int max;
RyoheiHagimoto 0:56c5742b9e2b 1338 int u;
RyoheiHagimoto 0:56c5742b9e2b 1339 int y;
RyoheiHagimoto 0:56c5742b9e2b 1340 int i;
RyoheiHagimoto 0:56c5742b9e2b 1341 int j;
RyoheiHagimoto 0:56c5742b9e2b 1342 lpsz=qr_ilog(_ur->size[0]+_ur->size[1]+_dl->size[0]+_dl->size[1])-6;
RyoheiHagimoto 0:56c5742b9e2b 1343 pixel_size=1<<lpsz;
RyoheiHagimoto 0:56c5742b9e2b 1344 dim=(1<<_aff->res-lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1345 gimg=(unsigned char *)malloc(dim*dim*sizeof(*gimg));
RyoheiHagimoto 0:56c5742b9e2b 1346 for(i=0;i<dim;i++)for(j=0;j<dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 1347 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 1348 qr_aff_project(p,_aff,(j-64)<<lpsz,(i-64)<<lpsz);
RyoheiHagimoto 0:56c5742b9e2b 1349 gimg[i*dim+j]=_img[
RyoheiHagimoto 0:56c5742b9e2b 1350 QR_CLAMPI(0,p[1]>>QR_FINDER_SUBPREC,_height-1)*_width+
RyoheiHagimoto 0:56c5742b9e2b 1351 QR_CLAMPI(0,p[0]>>QR_FINDER_SUBPREC,_width-1)];
RyoheiHagimoto 0:56c5742b9e2b 1352 }
RyoheiHagimoto 0:56c5742b9e2b 1353 {
RyoheiHagimoto 0:56c5742b9e2b 1354 min=(_ur->o[0]-7*_ur->size[0]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1355 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1356 max=(_ur->o[0]+7*_ur->size[0]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1357 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1358 for(y=-7;y<=7;y++){
RyoheiHagimoto 0:56c5742b9e2b 1359 i=(_ur->o[1]+y*_ur->size[1]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1360 if(i<0||i>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1361 for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1362 }
RyoheiHagimoto 0:56c5742b9e2b 1363 min=(_ur->o[1]-7*_ur->size[1]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1364 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1365 max=(_ur->o[1]+7*_ur->size[1]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1366 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1367 for(u=-7;u<=7;u++){
RyoheiHagimoto 0:56c5742b9e2b 1368 j=(_ur->o[0]+u*_ur->size[0]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1369 if(j<0||j>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1370 for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1371 }
RyoheiHagimoto 0:56c5742b9e2b 1372 }
RyoheiHagimoto 0:56c5742b9e2b 1373 {
RyoheiHagimoto 0:56c5742b9e2b 1374 min=(_dl->o[0]-7*_dl->size[0]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1375 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1376 max=(_dl->o[0]+7*_dl->size[0]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1377 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1378 for(y=-7;y<=7;y++){
RyoheiHagimoto 0:56c5742b9e2b 1379 i=(_dl->o[1]+y*_dl->size[1]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1380 if(i<0||i>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1381 for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1382 }
RyoheiHagimoto 0:56c5742b9e2b 1383 min=(_dl->o[1]-7*_dl->size[1]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1384 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1385 max=(_dl->o[1]+7*_dl->size[1]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1386 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1387 for(u=-7;u<=7;u++){
RyoheiHagimoto 0:56c5742b9e2b 1388 j=(_dl->o[0]+u*_dl->size[0]>>lpsz)+64;
RyoheiHagimoto 0:56c5742b9e2b 1389 if(j<0||j>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1390 for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1391 }
RyoheiHagimoto 0:56c5742b9e2b 1392 }
RyoheiHagimoto 0:56c5742b9e2b 1393 fout=fopen("undistorted_aff.png","wb");
RyoheiHagimoto 0:56c5742b9e2b 1394 image_write_png(gimg,dim,dim,fout);
RyoheiHagimoto 0:56c5742b9e2b 1395 fclose(fout);
RyoheiHagimoto 0:56c5742b9e2b 1396 free(gimg);
RyoheiHagimoto 0:56c5742b9e2b 1397 }
RyoheiHagimoto 0:56c5742b9e2b 1398
RyoheiHagimoto 0:56c5742b9e2b 1399 static void qr_finder_dump_hom_undistorted(qr_finder *_ul,qr_finder *_ur,
RyoheiHagimoto 0:56c5742b9e2b 1400 qr_finder *_dl,qr_hom *_hom,const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 1401 unsigned char *gimg;
RyoheiHagimoto 0:56c5742b9e2b 1402 FILE *fout;
RyoheiHagimoto 0:56c5742b9e2b 1403 int lpsz;
RyoheiHagimoto 0:56c5742b9e2b 1404 int pixel_size;
RyoheiHagimoto 0:56c5742b9e2b 1405 int dim;
RyoheiHagimoto 0:56c5742b9e2b 1406 int min;
RyoheiHagimoto 0:56c5742b9e2b 1407 int max;
RyoheiHagimoto 0:56c5742b9e2b 1408 int u;
RyoheiHagimoto 0:56c5742b9e2b 1409 int v;
RyoheiHagimoto 0:56c5742b9e2b 1410 int i;
RyoheiHagimoto 0:56c5742b9e2b 1411 int j;
RyoheiHagimoto 0:56c5742b9e2b 1412 lpsz=qr_ilog(_ur->size[0]+_ur->size[1]+_dl->size[0]+_dl->size[1])-6;
RyoheiHagimoto 0:56c5742b9e2b 1413 pixel_size=1<<lpsz;
RyoheiHagimoto 0:56c5742b9e2b 1414 dim=(1<<_hom->res-lpsz)+256;
RyoheiHagimoto 0:56c5742b9e2b 1415 gimg=(unsigned char *)malloc(dim*dim*sizeof(*gimg));
RyoheiHagimoto 0:56c5742b9e2b 1416 for(i=0;i<dim;i++)for(j=0;j<dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 1417 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 1418 qr_hom_project(p,_hom,(j-128)<<lpsz,(i-128)<<lpsz);
RyoheiHagimoto 0:56c5742b9e2b 1419 gimg[i*dim+j]=_img[
RyoheiHagimoto 0:56c5742b9e2b 1420 QR_CLAMPI(0,p[1]>>QR_FINDER_SUBPREC,_height-1)*_width+
RyoheiHagimoto 0:56c5742b9e2b 1421 QR_CLAMPI(0,p[0]>>QR_FINDER_SUBPREC,_width-1)];
RyoheiHagimoto 0:56c5742b9e2b 1422 }
RyoheiHagimoto 0:56c5742b9e2b 1423 {
RyoheiHagimoto 0:56c5742b9e2b 1424 min=(_ur->o[0]-7*_ur->size[0]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1425 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1426 max=(_ur->o[0]+7*_ur->size[0]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1427 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1428 for(v=-7;v<=7;v++){
RyoheiHagimoto 0:56c5742b9e2b 1429 i=(_ur->o[1]+v*_ur->size[1]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1430 if(i<0||i>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1431 for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1432 }
RyoheiHagimoto 0:56c5742b9e2b 1433 min=(_ur->o[1]-7*_ur->size[1]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1434 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1435 max=(_ur->o[1]+7*_ur->size[1]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1436 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1437 for(u=-7;u<=7;u++){
RyoheiHagimoto 0:56c5742b9e2b 1438 j=(_ur->o[0]+u*_ur->size[0]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1439 if(j<0||j>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1440 for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1441 }
RyoheiHagimoto 0:56c5742b9e2b 1442 }
RyoheiHagimoto 0:56c5742b9e2b 1443 {
RyoheiHagimoto 0:56c5742b9e2b 1444 min=(_dl->o[0]-7*_dl->size[0]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1445 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1446 max=(_dl->o[0]+7*_dl->size[0]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1447 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1448 for(v=-7;v<=7;v++){
RyoheiHagimoto 0:56c5742b9e2b 1449 i=(_dl->o[1]+v*_dl->size[1]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1450 if(i<0||i>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1451 for(j=min;j<max;j++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1452 }
RyoheiHagimoto 0:56c5742b9e2b 1453 min=(_dl->o[1]-7*_dl->size[1]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1454 if(min<0)min=0;
RyoheiHagimoto 0:56c5742b9e2b 1455 max=(_dl->o[1]+7*_dl->size[1]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1456 if(max>dim)max=dim;
RyoheiHagimoto 0:56c5742b9e2b 1457 for(u=-7;u<=7;u++){
RyoheiHagimoto 0:56c5742b9e2b 1458 j=(_dl->o[0]+u*_dl->size[0]>>lpsz)+128;
RyoheiHagimoto 0:56c5742b9e2b 1459 if(j<0||j>=dim)continue;
RyoheiHagimoto 0:56c5742b9e2b 1460 for(i=min;i<max;i++)gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 1461 }
RyoheiHagimoto 0:56c5742b9e2b 1462 }
RyoheiHagimoto 0:56c5742b9e2b 1463 fout=fopen("undistorted_hom.png","wb");
RyoheiHagimoto 0:56c5742b9e2b 1464 image_write_png(gimg,dim,dim,fout);
RyoheiHagimoto 0:56c5742b9e2b 1465 fclose(fout);
RyoheiHagimoto 0:56c5742b9e2b 1466 free(gimg);
RyoheiHagimoto 0:56c5742b9e2b 1467 }
RyoheiHagimoto 0:56c5742b9e2b 1468 #endif
RyoheiHagimoto 0:56c5742b9e2b 1469
RyoheiHagimoto 0:56c5742b9e2b 1470
RyoheiHagimoto 0:56c5742b9e2b 1471
RyoheiHagimoto 0:56c5742b9e2b 1472 /*A homography from one region of the grid back to the image.
RyoheiHagimoto 0:56c5742b9e2b 1473 Unlike a qr_hom, this does not include an inverse transform and maps directly
RyoheiHagimoto 0:56c5742b9e2b 1474 from the grid points, not a square with power-of-two sides.*/
RyoheiHagimoto 0:56c5742b9e2b 1475 struct qr_hom_cell{
RyoheiHagimoto 0:56c5742b9e2b 1476 int fwd[3][3];
RyoheiHagimoto 0:56c5742b9e2b 1477 int x0;
RyoheiHagimoto 0:56c5742b9e2b 1478 int y0;
RyoheiHagimoto 0:56c5742b9e2b 1479 int u0;
RyoheiHagimoto 0:56c5742b9e2b 1480 int v0;
RyoheiHagimoto 0:56c5742b9e2b 1481 };
RyoheiHagimoto 0:56c5742b9e2b 1482
RyoheiHagimoto 0:56c5742b9e2b 1483
RyoheiHagimoto 0:56c5742b9e2b 1484 static void qr_hom_cell_init(qr_hom_cell *_cell,int _u0,int _v0,
RyoheiHagimoto 0:56c5742b9e2b 1485 int _u1,int _v1,int _u2,int _v2,int _u3,int _v3,int _x0,int _y0,
RyoheiHagimoto 0:56c5742b9e2b 1486 int _x1,int _y1,int _x2,int _y2,int _x3,int _y3){
RyoheiHagimoto 0:56c5742b9e2b 1487 int du10;
RyoheiHagimoto 0:56c5742b9e2b 1488 int du20;
RyoheiHagimoto 0:56c5742b9e2b 1489 int du30;
RyoheiHagimoto 0:56c5742b9e2b 1490 int du31;
RyoheiHagimoto 0:56c5742b9e2b 1491 int du32;
RyoheiHagimoto 0:56c5742b9e2b 1492 int dv10;
RyoheiHagimoto 0:56c5742b9e2b 1493 int dv20;
RyoheiHagimoto 0:56c5742b9e2b 1494 int dv30;
RyoheiHagimoto 0:56c5742b9e2b 1495 int dv31;
RyoheiHagimoto 0:56c5742b9e2b 1496 int dv32;
RyoheiHagimoto 0:56c5742b9e2b 1497 int dx10;
RyoheiHagimoto 0:56c5742b9e2b 1498 int dx20;
RyoheiHagimoto 0:56c5742b9e2b 1499 int dx30;
RyoheiHagimoto 0:56c5742b9e2b 1500 int dx31;
RyoheiHagimoto 0:56c5742b9e2b 1501 int dx32;
RyoheiHagimoto 0:56c5742b9e2b 1502 int dy10;
RyoheiHagimoto 0:56c5742b9e2b 1503 int dy20;
RyoheiHagimoto 0:56c5742b9e2b 1504 int dy30;
RyoheiHagimoto 0:56c5742b9e2b 1505 int dy31;
RyoheiHagimoto 0:56c5742b9e2b 1506 int dy32;
RyoheiHagimoto 0:56c5742b9e2b 1507 int a00;
RyoheiHagimoto 0:56c5742b9e2b 1508 int a01;
RyoheiHagimoto 0:56c5742b9e2b 1509 int a02;
RyoheiHagimoto 0:56c5742b9e2b 1510 int a10;
RyoheiHagimoto 0:56c5742b9e2b 1511 int a11;
RyoheiHagimoto 0:56c5742b9e2b 1512 int a12;
RyoheiHagimoto 0:56c5742b9e2b 1513 int a20;
RyoheiHagimoto 0:56c5742b9e2b 1514 int a21;
RyoheiHagimoto 0:56c5742b9e2b 1515 int a22;
RyoheiHagimoto 0:56c5742b9e2b 1516 int i00;
RyoheiHagimoto 0:56c5742b9e2b 1517 int i01;
RyoheiHagimoto 0:56c5742b9e2b 1518 int i10;
RyoheiHagimoto 0:56c5742b9e2b 1519 int i11;
RyoheiHagimoto 0:56c5742b9e2b 1520 int i20;
RyoheiHagimoto 0:56c5742b9e2b 1521 int i21;
RyoheiHagimoto 0:56c5742b9e2b 1522 int i22;
RyoheiHagimoto 0:56c5742b9e2b 1523 int b0;
RyoheiHagimoto 0:56c5742b9e2b 1524 int b1;
RyoheiHagimoto 0:56c5742b9e2b 1525 int b2;
RyoheiHagimoto 0:56c5742b9e2b 1526 int shift;
RyoheiHagimoto 0:56c5742b9e2b 1527 int round;
RyoheiHagimoto 0:56c5742b9e2b 1528 int x;
RyoheiHagimoto 0:56c5742b9e2b 1529 int y;
RyoheiHagimoto 0:56c5742b9e2b 1530 int w;
RyoheiHagimoto 0:56c5742b9e2b 1531 /*First, correct for the arrangement of the source points.
RyoheiHagimoto 0:56c5742b9e2b 1532 We take advantage of the fact that we know the source points have a very
RyoheiHagimoto 0:56c5742b9e2b 1533 limited dynamic range (so there will never be overflow) and a small amount
RyoheiHagimoto 0:56c5742b9e2b 1534 of projective distortion.*/
RyoheiHagimoto 0:56c5742b9e2b 1535 du10=_u1-_u0;
RyoheiHagimoto 0:56c5742b9e2b 1536 du20=_u2-_u0;
RyoheiHagimoto 0:56c5742b9e2b 1537 du30=_u3-_u0;
RyoheiHagimoto 0:56c5742b9e2b 1538 du31=_u3-_u1;
RyoheiHagimoto 0:56c5742b9e2b 1539 du32=_u3-_u2;
RyoheiHagimoto 0:56c5742b9e2b 1540 dv10=_v1-_v0;
RyoheiHagimoto 0:56c5742b9e2b 1541 dv20=_v2-_v0;
RyoheiHagimoto 0:56c5742b9e2b 1542 dv30=_v3-_v0;
RyoheiHagimoto 0:56c5742b9e2b 1543 dv31=_v3-_v1;
RyoheiHagimoto 0:56c5742b9e2b 1544 dv32=_v3-_v2;
RyoheiHagimoto 0:56c5742b9e2b 1545 /*Compute the coefficients of the forward transform from the unit square to
RyoheiHagimoto 0:56c5742b9e2b 1546 the source point configuration.*/
RyoheiHagimoto 0:56c5742b9e2b 1547 a20=du32*dv10-du10*dv32;
RyoheiHagimoto 0:56c5742b9e2b 1548 a21=du20*dv31-du31*dv20;
RyoheiHagimoto 0:56c5742b9e2b 1549 if(a20||a21)a22=du32*dv31-du31*dv32;
RyoheiHagimoto 0:56c5742b9e2b 1550 /*If the source grid points aren't in a non-affine arrangement, there's no
RyoheiHagimoto 0:56c5742b9e2b 1551 reason to scale everything by du32*dv31-du31*dv32.
RyoheiHagimoto 0:56c5742b9e2b 1552 Not doing so allows a much larger dynamic range, and is the only way we can
RyoheiHagimoto 0:56c5742b9e2b 1553 initialize a base cell that covers the whole grid.*/
RyoheiHagimoto 0:56c5742b9e2b 1554 else a22=1;
RyoheiHagimoto 0:56c5742b9e2b 1555 a00=du10*(a20+a22);
RyoheiHagimoto 0:56c5742b9e2b 1556 a01=du20*(a21+a22);
RyoheiHagimoto 0:56c5742b9e2b 1557 a10=dv10*(a20+a22);
RyoheiHagimoto 0:56c5742b9e2b 1558 a11=dv20*(a21+a22);
RyoheiHagimoto 0:56c5742b9e2b 1559 /*Now compute the inverse transform.*/
RyoheiHagimoto 0:56c5742b9e2b 1560 i00=a11*a22;
RyoheiHagimoto 0:56c5742b9e2b 1561 i01=-a01*a22;
RyoheiHagimoto 0:56c5742b9e2b 1562 i10=-a10*a22;
RyoheiHagimoto 0:56c5742b9e2b 1563 i11=a00*a22;
RyoheiHagimoto 0:56c5742b9e2b 1564 i20=a10*a21-a11*a20;
RyoheiHagimoto 0:56c5742b9e2b 1565 i21=a01*a20-a00*a21;
RyoheiHagimoto 0:56c5742b9e2b 1566 i22=a00*a11-a01*a10;
RyoheiHagimoto 0:56c5742b9e2b 1567 /*Invert the coefficients.
RyoheiHagimoto 0:56c5742b9e2b 1568 Since i22 is the largest, we divide it by all the others.
RyoheiHagimoto 0:56c5742b9e2b 1569 The quotient is often exact (e.g., when the source points contain no
RyoheiHagimoto 0:56c5742b9e2b 1570 projective distortion), and is never zero.
RyoheiHagimoto 0:56c5742b9e2b 1571 Hence we can use zero to signal "infinity" when the divisor is zero.*/
RyoheiHagimoto 0:56c5742b9e2b 1572 if(i00)i00=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i00)),i00);
RyoheiHagimoto 0:56c5742b9e2b 1573 if(i01)i01=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i01)),i01);
RyoheiHagimoto 0:56c5742b9e2b 1574 if(i10)i10=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i10)),i10);
RyoheiHagimoto 0:56c5742b9e2b 1575 if(i11)i11=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i11)),i11);
RyoheiHagimoto 0:56c5742b9e2b 1576 if(i20)i20=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i20)),i20);
RyoheiHagimoto 0:56c5742b9e2b 1577 if(i21)i21=QR_FLIPSIGNI(QR_DIVROUND(i22,abs(i21)),i21);
RyoheiHagimoto 0:56c5742b9e2b 1578 /*Now compute the map from the unit square into the image.*/
RyoheiHagimoto 0:56c5742b9e2b 1579 dx10=_x1-_x0;
RyoheiHagimoto 0:56c5742b9e2b 1580 dx20=_x2-_x0;
RyoheiHagimoto 0:56c5742b9e2b 1581 dx30=_x3-_x0;
RyoheiHagimoto 0:56c5742b9e2b 1582 dx31=_x3-_x1;
RyoheiHagimoto 0:56c5742b9e2b 1583 dx32=_x3-_x2;
RyoheiHagimoto 0:56c5742b9e2b 1584 dy10=_y1-_y0;
RyoheiHagimoto 0:56c5742b9e2b 1585 dy20=_y2-_y0;
RyoheiHagimoto 0:56c5742b9e2b 1586 dy30=_y3-_y0;
RyoheiHagimoto 0:56c5742b9e2b 1587 dy31=_y3-_y1;
RyoheiHagimoto 0:56c5742b9e2b 1588 dy32=_y3-_y2;
RyoheiHagimoto 0:56c5742b9e2b 1589 a20=dx32*dy10-dx10*dy32;
RyoheiHagimoto 0:56c5742b9e2b 1590 a21=dx20*dy31-dx31*dy20;
RyoheiHagimoto 0:56c5742b9e2b 1591 a22=dx32*dy31-dx31*dy32;
RyoheiHagimoto 0:56c5742b9e2b 1592 /*Figure out if we need to downscale anything.*/
RyoheiHagimoto 0:56c5742b9e2b 1593 b0=qr_ilog(QR_MAXI(abs(dx10),abs(dy10)))+qr_ilog(abs(a20+a22));
RyoheiHagimoto 0:56c5742b9e2b 1594 b1=qr_ilog(QR_MAXI(abs(dx20),abs(dy20)))+qr_ilog(abs(a21+a22));
RyoheiHagimoto 0:56c5742b9e2b 1595 b2=qr_ilog(QR_MAXI(QR_MAXI(abs(a20),abs(a21)),abs(a22)));
RyoheiHagimoto 0:56c5742b9e2b 1596 shift=QR_MAXI(0,QR_MAXI(QR_MAXI(b0,b1),b2)-(QR_INT_BITS-3-QR_ALIGN_SUBPREC));
RyoheiHagimoto 0:56c5742b9e2b 1597 round=(1<<shift)>>1;
RyoheiHagimoto 0:56c5742b9e2b 1598 /*Compute the final coefficients of the forward transform.*/
RyoheiHagimoto 0:56c5742b9e2b 1599 a00=QR_FIXMUL(dx10,a20+a22,round,shift);
RyoheiHagimoto 0:56c5742b9e2b 1600 a01=QR_FIXMUL(dx20,a21+a22,round,shift);
RyoheiHagimoto 0:56c5742b9e2b 1601 a10=QR_FIXMUL(dy10,a20+a22,round,shift);
RyoheiHagimoto 0:56c5742b9e2b 1602 a11=QR_FIXMUL(dy20,a21+a22,round,shift);
RyoheiHagimoto 0:56c5742b9e2b 1603 /*And compose the two transforms.
RyoheiHagimoto 0:56c5742b9e2b 1604 Since we inverted the coefficients above, we divide by them here instead
RyoheiHagimoto 0:56c5742b9e2b 1605 of multiplying.
RyoheiHagimoto 0:56c5742b9e2b 1606 This lets us take advantage of the full dynamic range.
RyoheiHagimoto 0:56c5742b9e2b 1607 Note a zero divisor is really "infinity", and thus the quotient should also
RyoheiHagimoto 0:56c5742b9e2b 1608 be zero.*/
RyoheiHagimoto 0:56c5742b9e2b 1609 _cell->fwd[0][0]=(i00?QR_DIVROUND(a00,i00):0)+(i10?QR_DIVROUND(a01,i10):0);
RyoheiHagimoto 0:56c5742b9e2b 1610 _cell->fwd[0][1]=(i01?QR_DIVROUND(a00,i01):0)+(i11?QR_DIVROUND(a01,i11):0);
RyoheiHagimoto 0:56c5742b9e2b 1611 _cell->fwd[1][0]=(i00?QR_DIVROUND(a10,i00):0)+(i10?QR_DIVROUND(a11,i10):0);
RyoheiHagimoto 0:56c5742b9e2b 1612 _cell->fwd[1][1]=(i01?QR_DIVROUND(a10,i01):0)+(i11?QR_DIVROUND(a11,i11):0);
RyoheiHagimoto 0:56c5742b9e2b 1613 _cell->fwd[2][0]=(i00?QR_DIVROUND(a20,i00):0)+(i10?QR_DIVROUND(a21,i10):0)
RyoheiHagimoto 0:56c5742b9e2b 1614 +(i20?QR_DIVROUND(a22,i20):0)+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 1615 _cell->fwd[2][1]=(i01?QR_DIVROUND(a20,i01):0)+(i11?QR_DIVROUND(a21,i11):0)
RyoheiHagimoto 0:56c5742b9e2b 1616 +(i21?QR_DIVROUND(a22,i21):0)+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 1617 _cell->fwd[2][2]=a22+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 1618 /*Mathematically, a02 and a12 are exactly zero.
RyoheiHagimoto 0:56c5742b9e2b 1619 However, that concentrates all of the rounding error in the (_u3,_v3)
RyoheiHagimoto 0:56c5742b9e2b 1620 corner; we compute offsets which distribute it over the whole range.*/
RyoheiHagimoto 0:56c5742b9e2b 1621 x=_cell->fwd[0][0]*du10+_cell->fwd[0][1]*dv10;
RyoheiHagimoto 0:56c5742b9e2b 1622 y=_cell->fwd[1][0]*du10+_cell->fwd[1][1]*dv10;
RyoheiHagimoto 0:56c5742b9e2b 1623 w=_cell->fwd[2][0]*du10+_cell->fwd[2][1]*dv10+_cell->fwd[2][2];
RyoheiHagimoto 0:56c5742b9e2b 1624 a02=dx10*w-x;
RyoheiHagimoto 0:56c5742b9e2b 1625 a12=dy10*w-y;
RyoheiHagimoto 0:56c5742b9e2b 1626 x=_cell->fwd[0][0]*du20+_cell->fwd[0][1]*dv20;
RyoheiHagimoto 0:56c5742b9e2b 1627 y=_cell->fwd[1][0]*du20+_cell->fwd[1][1]*dv20;
RyoheiHagimoto 0:56c5742b9e2b 1628 w=_cell->fwd[2][0]*du20+_cell->fwd[2][1]*dv20+_cell->fwd[2][2];
RyoheiHagimoto 0:56c5742b9e2b 1629 a02+=dx20*w-x;
RyoheiHagimoto 0:56c5742b9e2b 1630 a12+=dy20*w-y;
RyoheiHagimoto 0:56c5742b9e2b 1631 x=_cell->fwd[0][0]*du30+_cell->fwd[0][1]*dv30;
RyoheiHagimoto 0:56c5742b9e2b 1632 y=_cell->fwd[1][0]*du30+_cell->fwd[1][1]*dv30;
RyoheiHagimoto 0:56c5742b9e2b 1633 w=_cell->fwd[2][0]*du30+_cell->fwd[2][1]*dv30+_cell->fwd[2][2];
RyoheiHagimoto 0:56c5742b9e2b 1634 a02+=dx30*w-x;
RyoheiHagimoto 0:56c5742b9e2b 1635 a12+=dy30*w-y;
RyoheiHagimoto 0:56c5742b9e2b 1636 _cell->fwd[0][2]=a02+2>>2;
RyoheiHagimoto 0:56c5742b9e2b 1637 _cell->fwd[1][2]=a12+2>>2;
RyoheiHagimoto 0:56c5742b9e2b 1638 _cell->x0=_x0;
RyoheiHagimoto 0:56c5742b9e2b 1639 _cell->y0=_y0;
RyoheiHagimoto 0:56c5742b9e2b 1640 _cell->u0=_u0;
RyoheiHagimoto 0:56c5742b9e2b 1641 _cell->v0=_v0;
RyoheiHagimoto 0:56c5742b9e2b 1642 }
RyoheiHagimoto 0:56c5742b9e2b 1643
RyoheiHagimoto 0:56c5742b9e2b 1644 /*Finish a partial projection, converting from homogeneous coordinates to the
RyoheiHagimoto 0:56c5742b9e2b 1645 normal 2-D representation.
RyoheiHagimoto 0:56c5742b9e2b 1646 In loops, we can avoid many multiplies by computing the homogeneous _x, _y,
RyoheiHagimoto 0:56c5742b9e2b 1647 and _w incrementally, but we cannot avoid the divisions, done here.*/
RyoheiHagimoto 0:56c5742b9e2b 1648 static void qr_hom_cell_fproject(qr_point _p,const qr_hom_cell *_cell,
RyoheiHagimoto 0:56c5742b9e2b 1649 int _x,int _y,int _w){
RyoheiHagimoto 0:56c5742b9e2b 1650 if(_w==0){
RyoheiHagimoto 0:56c5742b9e2b 1651 _p[0]=_x<0?INT_MIN:INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 1652 _p[1]=_y<0?INT_MIN:INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 1653 }
RyoheiHagimoto 0:56c5742b9e2b 1654 else{
RyoheiHagimoto 0:56c5742b9e2b 1655 if(_w<0){
RyoheiHagimoto 0:56c5742b9e2b 1656 _x=-_x;
RyoheiHagimoto 0:56c5742b9e2b 1657 _y=-_y;
RyoheiHagimoto 0:56c5742b9e2b 1658 _w=-_w;
RyoheiHagimoto 0:56c5742b9e2b 1659 }
RyoheiHagimoto 0:56c5742b9e2b 1660 _p[0]=QR_DIVROUND(_x,_w)+_cell->x0;
RyoheiHagimoto 0:56c5742b9e2b 1661 _p[1]=QR_DIVROUND(_y,_w)+_cell->y0;
RyoheiHagimoto 0:56c5742b9e2b 1662 }
RyoheiHagimoto 0:56c5742b9e2b 1663 }
RyoheiHagimoto 0:56c5742b9e2b 1664
RyoheiHagimoto 0:56c5742b9e2b 1665 static void qr_hom_cell_project(qr_point _p,const qr_hom_cell *_cell,
RyoheiHagimoto 0:56c5742b9e2b 1666 int _u,int _v,int _res){
RyoheiHagimoto 0:56c5742b9e2b 1667 _u-=_cell->u0<<_res;
RyoheiHagimoto 0:56c5742b9e2b 1668 _v-=_cell->v0<<_res;
RyoheiHagimoto 0:56c5742b9e2b 1669 qr_hom_cell_fproject(_p,_cell,
RyoheiHagimoto 0:56c5742b9e2b 1670 _cell->fwd[0][0]*_u+_cell->fwd[0][1]*_v+(_cell->fwd[0][2]<<_res),
RyoheiHagimoto 0:56c5742b9e2b 1671 _cell->fwd[1][0]*_u+_cell->fwd[1][1]*_v+(_cell->fwd[1][2]<<_res),
RyoheiHagimoto 0:56c5742b9e2b 1672 _cell->fwd[2][0]*_u+_cell->fwd[2][1]*_v+(_cell->fwd[2][2]<<_res));
RyoheiHagimoto 0:56c5742b9e2b 1673 }
RyoheiHagimoto 0:56c5742b9e2b 1674
RyoheiHagimoto 0:56c5742b9e2b 1675
RyoheiHagimoto 0:56c5742b9e2b 1676
RyoheiHagimoto 0:56c5742b9e2b 1677 /*Retrieves the bits corresponding to the alignment pattern template centered
RyoheiHagimoto 0:56c5742b9e2b 1678 at the given location in the original image (at subpel precision).*/
RyoheiHagimoto 0:56c5742b9e2b 1679 static unsigned qr_alignment_pattern_fetch(qr_point _p[5][5],int _x0,int _y0,
RyoheiHagimoto 0:56c5742b9e2b 1680 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 1681 unsigned v;
RyoheiHagimoto 0:56c5742b9e2b 1682 int i;
RyoheiHagimoto 0:56c5742b9e2b 1683 int j;
RyoheiHagimoto 0:56c5742b9e2b 1684 int k;
RyoheiHagimoto 0:56c5742b9e2b 1685 int dx;
RyoheiHagimoto 0:56c5742b9e2b 1686 int dy;
RyoheiHagimoto 0:56c5742b9e2b 1687 dx=_x0-_p[2][2][0];
RyoheiHagimoto 0:56c5742b9e2b 1688 dy=_y0-_p[2][2][1];
RyoheiHagimoto 0:56c5742b9e2b 1689 v=0;
RyoheiHagimoto 0:56c5742b9e2b 1690 for(k=i=0;i<5;i++)for(j=0;j<5;j++,k++){
RyoheiHagimoto 0:56c5742b9e2b 1691 v|=qr_img_get_bit(_img,_width,_height,_p[i][j][0]+dx,_p[i][j][1]+dy)<<k;
RyoheiHagimoto 0:56c5742b9e2b 1692 }
RyoheiHagimoto 0:56c5742b9e2b 1693 return v;
RyoheiHagimoto 0:56c5742b9e2b 1694 }
RyoheiHagimoto 0:56c5742b9e2b 1695
RyoheiHagimoto 0:56c5742b9e2b 1696 /*Searches for an alignment pattern near the given location.*/
RyoheiHagimoto 0:56c5742b9e2b 1697 static int qr_alignment_pattern_search(qr_point _p,const qr_hom_cell *_cell,
RyoheiHagimoto 0:56c5742b9e2b 1698 int _u,int _v,int _r,const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 1699 qr_point c[4];
RyoheiHagimoto 0:56c5742b9e2b 1700 int nc[4];
RyoheiHagimoto 0:56c5742b9e2b 1701 qr_point p[5][5];
RyoheiHagimoto 0:56c5742b9e2b 1702 qr_point pc;
RyoheiHagimoto 0:56c5742b9e2b 1703 unsigned best_match;
RyoheiHagimoto 0:56c5742b9e2b 1704 int best_dist;
RyoheiHagimoto 0:56c5742b9e2b 1705 int bestx;
RyoheiHagimoto 0:56c5742b9e2b 1706 int besty;
RyoheiHagimoto 0:56c5742b9e2b 1707 unsigned match;
RyoheiHagimoto 0:56c5742b9e2b 1708 int dist;
RyoheiHagimoto 0:56c5742b9e2b 1709 int u;
RyoheiHagimoto 0:56c5742b9e2b 1710 int v;
RyoheiHagimoto 0:56c5742b9e2b 1711 int x0;
RyoheiHagimoto 0:56c5742b9e2b 1712 int y0;
RyoheiHagimoto 0:56c5742b9e2b 1713 int w0;
RyoheiHagimoto 0:56c5742b9e2b 1714 int x;
RyoheiHagimoto 0:56c5742b9e2b 1715 int y;
RyoheiHagimoto 0:56c5742b9e2b 1716 int w;
RyoheiHagimoto 0:56c5742b9e2b 1717 int dxdu;
RyoheiHagimoto 0:56c5742b9e2b 1718 int dydu;
RyoheiHagimoto 0:56c5742b9e2b 1719 int dwdu;
RyoheiHagimoto 0:56c5742b9e2b 1720 int dxdv;
RyoheiHagimoto 0:56c5742b9e2b 1721 int dydv;
RyoheiHagimoto 0:56c5742b9e2b 1722 int dwdv;
RyoheiHagimoto 0:56c5742b9e2b 1723 int dx;
RyoheiHagimoto 0:56c5742b9e2b 1724 int dy;
RyoheiHagimoto 0:56c5742b9e2b 1725 int i;
RyoheiHagimoto 0:56c5742b9e2b 1726 int j;
RyoheiHagimoto 0:56c5742b9e2b 1727 /*Build up a basic template using _cell to control shape and scale.
RyoheiHagimoto 0:56c5742b9e2b 1728 We project the points in the template back to the image just once, since if
RyoheiHagimoto 0:56c5742b9e2b 1729 the alignment pattern has moved, we don't really know why.
RyoheiHagimoto 0:56c5742b9e2b 1730 If it's because of radial distortion, or the code wasn't flat, or something
RyoheiHagimoto 0:56c5742b9e2b 1731 else, there's no reason to expect that a re-projection around each
RyoheiHagimoto 0:56c5742b9e2b 1732 subsequent search point would be any closer to the actual shape than our
RyoheiHagimoto 0:56c5742b9e2b 1733 first projection.
RyoheiHagimoto 0:56c5742b9e2b 1734 Therefore we simply slide this template around, as is.*/
RyoheiHagimoto 0:56c5742b9e2b 1735 u=(_u-2)-_cell->u0;
RyoheiHagimoto 0:56c5742b9e2b 1736 v=(_v-2)-_cell->v0;
RyoheiHagimoto 0:56c5742b9e2b 1737 x0=_cell->fwd[0][0]*u+_cell->fwd[0][1]*v+_cell->fwd[0][2];
RyoheiHagimoto 0:56c5742b9e2b 1738 y0=_cell->fwd[1][0]*u+_cell->fwd[1][1]*v+_cell->fwd[1][2];
RyoheiHagimoto 0:56c5742b9e2b 1739 w0=_cell->fwd[2][0]*u+_cell->fwd[2][1]*v+_cell->fwd[2][2];
RyoheiHagimoto 0:56c5742b9e2b 1740 dxdu=_cell->fwd[0][0];
RyoheiHagimoto 0:56c5742b9e2b 1741 dydu=_cell->fwd[1][0];
RyoheiHagimoto 0:56c5742b9e2b 1742 dwdu=_cell->fwd[2][0];
RyoheiHagimoto 0:56c5742b9e2b 1743 dxdv=_cell->fwd[0][1];
RyoheiHagimoto 0:56c5742b9e2b 1744 dydv=_cell->fwd[1][1];
RyoheiHagimoto 0:56c5742b9e2b 1745 dwdv=_cell->fwd[2][1];
RyoheiHagimoto 0:56c5742b9e2b 1746 for(i=0;i<5;i++){
RyoheiHagimoto 0:56c5742b9e2b 1747 x=x0;
RyoheiHagimoto 0:56c5742b9e2b 1748 y=y0;
RyoheiHagimoto 0:56c5742b9e2b 1749 w=w0;
RyoheiHagimoto 0:56c5742b9e2b 1750 for(j=0;j<5;j++){
RyoheiHagimoto 0:56c5742b9e2b 1751 qr_hom_cell_fproject(p[i][j],_cell,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 1752 x+=dxdu;
RyoheiHagimoto 0:56c5742b9e2b 1753 y+=dydu;
RyoheiHagimoto 0:56c5742b9e2b 1754 w+=dwdu;
RyoheiHagimoto 0:56c5742b9e2b 1755 }
RyoheiHagimoto 0:56c5742b9e2b 1756 x0+=dxdv;
RyoheiHagimoto 0:56c5742b9e2b 1757 y0+=dydv;
RyoheiHagimoto 0:56c5742b9e2b 1758 w0+=dwdv;
RyoheiHagimoto 0:56c5742b9e2b 1759 }
RyoheiHagimoto 0:56c5742b9e2b 1760 bestx=p[2][2][0];
RyoheiHagimoto 0:56c5742b9e2b 1761 besty=p[2][2][1];
RyoheiHagimoto 0:56c5742b9e2b 1762 best_match=qr_alignment_pattern_fetch(p,bestx,besty,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 1763 best_dist=qr_hamming_dist(best_match,0x1F8D63F,25);
RyoheiHagimoto 0:56c5742b9e2b 1764 if(best_dist>0){
RyoheiHagimoto 0:56c5742b9e2b 1765 u=_u-_cell->u0;
RyoheiHagimoto 0:56c5742b9e2b 1766 v=_v-_cell->v0;
RyoheiHagimoto 0:56c5742b9e2b 1767 x=_cell->fwd[0][0]*u+_cell->fwd[0][1]*v+_cell->fwd[0][2]<<QR_ALIGN_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1768 y=_cell->fwd[1][0]*u+_cell->fwd[1][1]*v+_cell->fwd[1][2]<<QR_ALIGN_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1769 w=_cell->fwd[2][0]*u+_cell->fwd[2][1]*v+_cell->fwd[2][2]<<QR_ALIGN_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1770 /*Search an area at most _r modules around the target location, in
RyoheiHagimoto 0:56c5742b9e2b 1771 concentric squares..*/
RyoheiHagimoto 0:56c5742b9e2b 1772 for(i=1;i<_r<<QR_ALIGN_SUBPREC;i++){
RyoheiHagimoto 0:56c5742b9e2b 1773 int side_len;
RyoheiHagimoto 0:56c5742b9e2b 1774 side_len=(i<<1)-1;
RyoheiHagimoto 0:56c5742b9e2b 1775 x-=dxdu+dxdv;
RyoheiHagimoto 0:56c5742b9e2b 1776 y-=dydu+dydv;
RyoheiHagimoto 0:56c5742b9e2b 1777 w-=dwdu+dwdv;
RyoheiHagimoto 0:56c5742b9e2b 1778 for(j=0;j<4*side_len;j++){
RyoheiHagimoto 0:56c5742b9e2b 1779 int dir;
RyoheiHagimoto 0:56c5742b9e2b 1780 qr_hom_cell_fproject(pc,_cell,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 1781 match=qr_alignment_pattern_fetch(p,pc[0],pc[1],_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 1782 dist=qr_hamming_dist(match,0x1F8D63F,best_dist+1);
RyoheiHagimoto 0:56c5742b9e2b 1783 if(dist<best_dist){
RyoheiHagimoto 0:56c5742b9e2b 1784 best_match=match;
RyoheiHagimoto 0:56c5742b9e2b 1785 best_dist=dist;
RyoheiHagimoto 0:56c5742b9e2b 1786 bestx=pc[0];
RyoheiHagimoto 0:56c5742b9e2b 1787 besty=pc[1];
RyoheiHagimoto 0:56c5742b9e2b 1788 }
RyoheiHagimoto 0:56c5742b9e2b 1789 if(j<2*side_len){
RyoheiHagimoto 0:56c5742b9e2b 1790 dir=j>=side_len;
RyoheiHagimoto 0:56c5742b9e2b 1791 x+=_cell->fwd[0][dir];
RyoheiHagimoto 0:56c5742b9e2b 1792 y+=_cell->fwd[1][dir];
RyoheiHagimoto 0:56c5742b9e2b 1793 w+=_cell->fwd[2][dir];
RyoheiHagimoto 0:56c5742b9e2b 1794 }
RyoheiHagimoto 0:56c5742b9e2b 1795 else{
RyoheiHagimoto 0:56c5742b9e2b 1796 dir=j>=3*side_len;
RyoheiHagimoto 0:56c5742b9e2b 1797 x-=_cell->fwd[0][dir];
RyoheiHagimoto 0:56c5742b9e2b 1798 y-=_cell->fwd[1][dir];
RyoheiHagimoto 0:56c5742b9e2b 1799 w-=_cell->fwd[2][dir];
RyoheiHagimoto 0:56c5742b9e2b 1800 }
RyoheiHagimoto 0:56c5742b9e2b 1801 if(!best_dist)break;
RyoheiHagimoto 0:56c5742b9e2b 1802 }
RyoheiHagimoto 0:56c5742b9e2b 1803 if(!best_dist)break;
RyoheiHagimoto 0:56c5742b9e2b 1804 }
RyoheiHagimoto 0:56c5742b9e2b 1805 }
RyoheiHagimoto 0:56c5742b9e2b 1806 /*If the best result we got was sufficiently bad, reject the match.
RyoheiHagimoto 0:56c5742b9e2b 1807 If we're wrong and we include it, we can grossly distort the nearby
RyoheiHagimoto 0:56c5742b9e2b 1808 region, whereas using the initial starting point should at least be
RyoheiHagimoto 0:56c5742b9e2b 1809 consistent with the geometry we already have.*/
RyoheiHagimoto 0:56c5742b9e2b 1810 if(best_dist>6){
RyoheiHagimoto 0:56c5742b9e2b 1811 _p[0]=p[2][2][0];
RyoheiHagimoto 0:56c5742b9e2b 1812 _p[1]=p[2][2][1];
RyoheiHagimoto 0:56c5742b9e2b 1813 return -1;
RyoheiHagimoto 0:56c5742b9e2b 1814 }
RyoheiHagimoto 0:56c5742b9e2b 1815 /*Now try to get a more accurate location of the pattern center.*/
RyoheiHagimoto 0:56c5742b9e2b 1816 dx=bestx-p[2][2][0];
RyoheiHagimoto 0:56c5742b9e2b 1817 dy=besty-p[2][2][1];
RyoheiHagimoto 0:56c5742b9e2b 1818 memset(nc,0,sizeof(nc));
RyoheiHagimoto 0:56c5742b9e2b 1819 memset(c,0,sizeof(c));
RyoheiHagimoto 0:56c5742b9e2b 1820 /*We consider 8 lines across the finder pattern in turn.
RyoheiHagimoto 0:56c5742b9e2b 1821 If we actually found a symmetric pattern along that line, search for its
RyoheiHagimoto 0:56c5742b9e2b 1822 exact center in the image.
RyoheiHagimoto 0:56c5742b9e2b 1823 There are plenty more lines we could use if these don't work, but if we've
RyoheiHagimoto 0:56c5742b9e2b 1824 found anything remotely close to an alignment pattern, we should be able
RyoheiHagimoto 0:56c5742b9e2b 1825 to use most of these.*/
RyoheiHagimoto 0:56c5742b9e2b 1826 for(i=0;i<8;i++){
RyoheiHagimoto 0:56c5742b9e2b 1827 static const unsigned MASK_TESTS[8][2]={
RyoheiHagimoto 0:56c5742b9e2b 1828 {0x1040041,0x1000001},{0x0041040,0x0001000},
RyoheiHagimoto 0:56c5742b9e2b 1829 {0x0110110,0x0100010},{0x0011100,0x0001000},
RyoheiHagimoto 0:56c5742b9e2b 1830 {0x0420084,0x0400004},{0x0021080,0x0001000},
RyoheiHagimoto 0:56c5742b9e2b 1831 {0x0006C00,0x0004400},{0x0003800,0x0001000},
RyoheiHagimoto 0:56c5742b9e2b 1832 };
RyoheiHagimoto 0:56c5742b9e2b 1833 static const unsigned char MASK_COORDS[8][2]={
RyoheiHagimoto 0:56c5742b9e2b 1834 {0,0},{1,1},{4,0},{3,1},{2,0},{2,1},{0,2},{1,2}
RyoheiHagimoto 0:56c5742b9e2b 1835 };
RyoheiHagimoto 0:56c5742b9e2b 1836 if((best_match&MASK_TESTS[i][0])==MASK_TESTS[i][1]){
RyoheiHagimoto 0:56c5742b9e2b 1837 int x0;
RyoheiHagimoto 0:56c5742b9e2b 1838 int y0;
RyoheiHagimoto 0:56c5742b9e2b 1839 int x1;
RyoheiHagimoto 0:56c5742b9e2b 1840 int y1;
RyoheiHagimoto 0:56c5742b9e2b 1841 x0=p[MASK_COORDS[i][1]][MASK_COORDS[i][0]][0]+dx>>QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1842 if(x0<0||x0>=_width)continue;
RyoheiHagimoto 0:56c5742b9e2b 1843 y0=p[MASK_COORDS[i][1]][MASK_COORDS[i][0]][1]+dy>>QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1844 if(y0<0||y0>=_height)continue;
RyoheiHagimoto 0:56c5742b9e2b 1845 x1=p[4-MASK_COORDS[i][1]][4-MASK_COORDS[i][0]][0]+dx>>QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1846 if(x1<0||x1>=_width)continue;
RyoheiHagimoto 0:56c5742b9e2b 1847 y1=p[4-MASK_COORDS[i][1]][4-MASK_COORDS[i][0]][1]+dy>>QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 1848 if(y1<0||y1>=_height)continue;
RyoheiHagimoto 0:56c5742b9e2b 1849 if(!qr_finder_locate_crossing(_img,_width,_height,x0,y0,x1,y1,i&1,pc)){
RyoheiHagimoto 0:56c5742b9e2b 1850 int w;
RyoheiHagimoto 0:56c5742b9e2b 1851 int cx;
RyoheiHagimoto 0:56c5742b9e2b 1852 int cy;
RyoheiHagimoto 0:56c5742b9e2b 1853 cx=pc[0]-bestx;
RyoheiHagimoto 0:56c5742b9e2b 1854 cy=pc[1]-besty;
RyoheiHagimoto 0:56c5742b9e2b 1855 if(i&1){
RyoheiHagimoto 0:56c5742b9e2b 1856 /*Weight crossings around the center dot more highly, as they are
RyoheiHagimoto 0:56c5742b9e2b 1857 generally more reliable.*/
RyoheiHagimoto 0:56c5742b9e2b 1858 w=3;
RyoheiHagimoto 0:56c5742b9e2b 1859 cx+=cx<<1;
RyoheiHagimoto 0:56c5742b9e2b 1860 cy+=cy<<1;
RyoheiHagimoto 0:56c5742b9e2b 1861 }
RyoheiHagimoto 0:56c5742b9e2b 1862 else w=1;
RyoheiHagimoto 0:56c5742b9e2b 1863 nc[i>>1]+=w;
RyoheiHagimoto 0:56c5742b9e2b 1864 c[i>>1][0]+=cx;
RyoheiHagimoto 0:56c5742b9e2b 1865 c[i>>1][1]+=cy;
RyoheiHagimoto 0:56c5742b9e2b 1866 }
RyoheiHagimoto 0:56c5742b9e2b 1867 }
RyoheiHagimoto 0:56c5742b9e2b 1868 }
RyoheiHagimoto 0:56c5742b9e2b 1869 /*Sum offsets from lines in orthogonal directions.*/
RyoheiHagimoto 0:56c5742b9e2b 1870 for(i=0;i<2;i++){
RyoheiHagimoto 0:56c5742b9e2b 1871 int a;
RyoheiHagimoto 0:56c5742b9e2b 1872 int b;
RyoheiHagimoto 0:56c5742b9e2b 1873 a=nc[i<<1];
RyoheiHagimoto 0:56c5742b9e2b 1874 b=nc[i<<1|1];
RyoheiHagimoto 0:56c5742b9e2b 1875 if(a&&b){
RyoheiHagimoto 0:56c5742b9e2b 1876 int w;
RyoheiHagimoto 0:56c5742b9e2b 1877 w=QR_MAXI(a,b);
RyoheiHagimoto 0:56c5742b9e2b 1878 c[i<<1][0]=QR_DIVROUND(w*(b*c[i<<1][0]+a*c[i<<1|1][0]),a*b);
RyoheiHagimoto 0:56c5742b9e2b 1879 c[i<<1][1]=QR_DIVROUND(w*(b*c[i<<1][1]+a*c[i<<1|1][1]),a*b);
RyoheiHagimoto 0:56c5742b9e2b 1880 nc[i<<1]=w<<1;
RyoheiHagimoto 0:56c5742b9e2b 1881 }
RyoheiHagimoto 0:56c5742b9e2b 1882 else{
RyoheiHagimoto 0:56c5742b9e2b 1883 c[i<<1][0]+=c[i<<1|1][0];
RyoheiHagimoto 0:56c5742b9e2b 1884 c[i<<1][1]+=c[i<<1|1][1];
RyoheiHagimoto 0:56c5742b9e2b 1885 nc[i<<1]+=b;
RyoheiHagimoto 0:56c5742b9e2b 1886 }
RyoheiHagimoto 0:56c5742b9e2b 1887 }
RyoheiHagimoto 0:56c5742b9e2b 1888 /*Average offsets from pairs of orthogonal lines.*/
RyoheiHagimoto 0:56c5742b9e2b 1889 c[0][0]+=c[2][0];
RyoheiHagimoto 0:56c5742b9e2b 1890 c[0][1]+=c[2][1];
RyoheiHagimoto 0:56c5742b9e2b 1891 nc[0]+=nc[2];
RyoheiHagimoto 0:56c5742b9e2b 1892 /*If we actually found any such lines, apply the adjustment.*/
RyoheiHagimoto 0:56c5742b9e2b 1893 if(nc[0]){
RyoheiHagimoto 0:56c5742b9e2b 1894 dx=QR_DIVROUND(c[0][0],nc[0]);
RyoheiHagimoto 0:56c5742b9e2b 1895 dy=QR_DIVROUND(c[0][1],nc[0]);
RyoheiHagimoto 0:56c5742b9e2b 1896 /*But only if it doesn't make things worse.*/
RyoheiHagimoto 0:56c5742b9e2b 1897 match=qr_alignment_pattern_fetch(p,bestx+dx,besty+dy,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 1898 dist=qr_hamming_dist(match,0x1F8D63F,best_dist+1);
RyoheiHagimoto 0:56c5742b9e2b 1899 if(dist<=best_dist){
RyoheiHagimoto 0:56c5742b9e2b 1900 bestx+=dx;
RyoheiHagimoto 0:56c5742b9e2b 1901 besty+=dy;
RyoheiHagimoto 0:56c5742b9e2b 1902 }
RyoheiHagimoto 0:56c5742b9e2b 1903 }
RyoheiHagimoto 0:56c5742b9e2b 1904 _p[0]=bestx;
RyoheiHagimoto 0:56c5742b9e2b 1905 _p[1]=besty;
RyoheiHagimoto 0:56c5742b9e2b 1906 return 0;
RyoheiHagimoto 0:56c5742b9e2b 1907 }
RyoheiHagimoto 0:56c5742b9e2b 1908
RyoheiHagimoto 0:56c5742b9e2b 1909 static int qr_hom_fit(qr_hom *_hom,qr_finder *_ul,qr_finder *_ur,
RyoheiHagimoto 0:56c5742b9e2b 1910 qr_finder *_dl,qr_point _p[4],const qr_aff *_aff,isaac_ctx *_isaac,
RyoheiHagimoto 0:56c5742b9e2b 1911 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 1912 qr_point *b;
RyoheiHagimoto 0:56c5742b9e2b 1913 int nb;
RyoheiHagimoto 0:56c5742b9e2b 1914 int cb;
RyoheiHagimoto 0:56c5742b9e2b 1915 qr_point *r;
RyoheiHagimoto 0:56c5742b9e2b 1916 int nr;
RyoheiHagimoto 0:56c5742b9e2b 1917 int cr;
RyoheiHagimoto 0:56c5742b9e2b 1918 qr_line l[4];
RyoheiHagimoto 0:56c5742b9e2b 1919 qr_point q;
RyoheiHagimoto 0:56c5742b9e2b 1920 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 1921 int ox;
RyoheiHagimoto 0:56c5742b9e2b 1922 int oy;
RyoheiHagimoto 0:56c5742b9e2b 1923 int ru;
RyoheiHagimoto 0:56c5742b9e2b 1924 int rv;
RyoheiHagimoto 0:56c5742b9e2b 1925 int dru;
RyoheiHagimoto 0:56c5742b9e2b 1926 int drv;
RyoheiHagimoto 0:56c5742b9e2b 1927 int bu;
RyoheiHagimoto 0:56c5742b9e2b 1928 int bv;
RyoheiHagimoto 0:56c5742b9e2b 1929 int dbu;
RyoheiHagimoto 0:56c5742b9e2b 1930 int dbv;
RyoheiHagimoto 0:56c5742b9e2b 1931 int rx;
RyoheiHagimoto 0:56c5742b9e2b 1932 int ry;
RyoheiHagimoto 0:56c5742b9e2b 1933 int drxi;
RyoheiHagimoto 0:56c5742b9e2b 1934 int dryi;
RyoheiHagimoto 0:56c5742b9e2b 1935 int drxj;
RyoheiHagimoto 0:56c5742b9e2b 1936 int dryj;
RyoheiHagimoto 0:56c5742b9e2b 1937 int rdone;
RyoheiHagimoto 0:56c5742b9e2b 1938 int nrempty;
RyoheiHagimoto 0:56c5742b9e2b 1939 int rlastfit;
RyoheiHagimoto 0:56c5742b9e2b 1940 int bx;
RyoheiHagimoto 0:56c5742b9e2b 1941 int by;
RyoheiHagimoto 0:56c5742b9e2b 1942 int dbxi;
RyoheiHagimoto 0:56c5742b9e2b 1943 int dbyi;
RyoheiHagimoto 0:56c5742b9e2b 1944 int dbxj;
RyoheiHagimoto 0:56c5742b9e2b 1945 int dbyj;
RyoheiHagimoto 0:56c5742b9e2b 1946 int bdone;
RyoheiHagimoto 0:56c5742b9e2b 1947 int nbempty;
RyoheiHagimoto 0:56c5742b9e2b 1948 int blastfit;
RyoheiHagimoto 0:56c5742b9e2b 1949 int shift;
RyoheiHagimoto 0:56c5742b9e2b 1950 int round;
RyoheiHagimoto 0:56c5742b9e2b 1951 int version4;
RyoheiHagimoto 0:56c5742b9e2b 1952 int brx;
RyoheiHagimoto 0:56c5742b9e2b 1953 int bry;
RyoheiHagimoto 0:56c5742b9e2b 1954 int i;
RyoheiHagimoto 0:56c5742b9e2b 1955 /*We attempt to correct large-scale perspective distortion by fitting lines
RyoheiHagimoto 0:56c5742b9e2b 1956 to the edge of the code area.
RyoheiHagimoto 0:56c5742b9e2b 1957 We could also look for an alignment pattern now, but that wouldn't work for
RyoheiHagimoto 0:56c5742b9e2b 1958 version 1 codes, which have no alignment pattern.
RyoheiHagimoto 0:56c5742b9e2b 1959 Even if the code is supposed to have one, there's go guarantee we'd find it
RyoheiHagimoto 0:56c5742b9e2b 1960 intact.*/
RyoheiHagimoto 0:56c5742b9e2b 1961 /*Fitting lines is easy for the edges on which we have two finder patterns.
RyoheiHagimoto 0:56c5742b9e2b 1962 After the fit, UL is guaranteed to be on the proper side, but if either of
RyoheiHagimoto 0:56c5742b9e2b 1963 the other two finder patterns aren't, something is wrong.*/
RyoheiHagimoto 0:56c5742b9e2b 1964 qr_finder_ransac(_ul,_aff,_isaac,0);
RyoheiHagimoto 0:56c5742b9e2b 1965 qr_finder_ransac(_dl,_aff,_isaac,0);
RyoheiHagimoto 0:56c5742b9e2b 1966 qr_line_fit_finder_pair(l[0],_aff,_ul,_dl,0);
RyoheiHagimoto 0:56c5742b9e2b 1967 if(qr_line_eval(l[0],_dl->c->pos[0],_dl->c->pos[1])<0||
RyoheiHagimoto 0:56c5742b9e2b 1968 qr_line_eval(l[0],_ur->c->pos[0],_ur->c->pos[1])<0){
RyoheiHagimoto 0:56c5742b9e2b 1969 return -1;
RyoheiHagimoto 0:56c5742b9e2b 1970 }
RyoheiHagimoto 0:56c5742b9e2b 1971 qr_finder_ransac(_ul,_aff,_isaac,2);
RyoheiHagimoto 0:56c5742b9e2b 1972 qr_finder_ransac(_ur,_aff,_isaac,2);
RyoheiHagimoto 0:56c5742b9e2b 1973 qr_line_fit_finder_pair(l[2],_aff,_ul,_ur,2);
RyoheiHagimoto 0:56c5742b9e2b 1974 if(qr_line_eval(l[2],_dl->c->pos[0],_dl->c->pos[1])<0||
RyoheiHagimoto 0:56c5742b9e2b 1975 qr_line_eval(l[2],_ur->c->pos[0],_ur->c->pos[1])<0){
RyoheiHagimoto 0:56c5742b9e2b 1976 return -1;
RyoheiHagimoto 0:56c5742b9e2b 1977 }
RyoheiHagimoto 0:56c5742b9e2b 1978 /*The edges which only have one finder pattern are more difficult.
RyoheiHagimoto 0:56c5742b9e2b 1979 We start by fitting a line to the edge of the one finder pattern we do
RyoheiHagimoto 0:56c5742b9e2b 1980 have.
RyoheiHagimoto 0:56c5742b9e2b 1981 This can fail due to an insufficient number of sample points, and even if
RyoheiHagimoto 0:56c5742b9e2b 1982 it succeeds can be fairly inaccurate, because all of the points are
RyoheiHagimoto 0:56c5742b9e2b 1983 clustered in one corner of the QR code.
RyoheiHagimoto 0:56c5742b9e2b 1984 If it fails, we just use an axis-aligned line in the affine coordinate
RyoheiHagimoto 0:56c5742b9e2b 1985 system.
RyoheiHagimoto 0:56c5742b9e2b 1986 Then we walk along the edge of the entire code, looking for
RyoheiHagimoto 0:56c5742b9e2b 1987 light:dark:light patterns perpendicular to the edge.
RyoheiHagimoto 0:56c5742b9e2b 1988 Wherever we find one, we take the center of the dark portion as an
RyoheiHagimoto 0:56c5742b9e2b 1989 additional sample point.
RyoheiHagimoto 0:56c5742b9e2b 1990 At the end, we re-fit the line using all such sample points found.*/
RyoheiHagimoto 0:56c5742b9e2b 1991 drv=_ur->size[1]>>1;
RyoheiHagimoto 0:56c5742b9e2b 1992 qr_finder_ransac(_ur,_aff,_isaac,1);
RyoheiHagimoto 0:56c5742b9e2b 1993 if(qr_line_fit_finder_edge(l[1],_ur,1,_aff->res)>=0){
RyoheiHagimoto 0:56c5742b9e2b 1994 if(qr_line_eval(l[1],_ul->c->pos[0],_ul->c->pos[1])<0||
RyoheiHagimoto 0:56c5742b9e2b 1995 qr_line_eval(l[1],_dl->c->pos[0],_dl->c->pos[1])<0){
RyoheiHagimoto 0:56c5742b9e2b 1996 return -1;
RyoheiHagimoto 0:56c5742b9e2b 1997 }
RyoheiHagimoto 0:56c5742b9e2b 1998 /*Figure out the change in ru for a given change in rv when stepping along
RyoheiHagimoto 0:56c5742b9e2b 1999 the fitted line.*/
RyoheiHagimoto 0:56c5742b9e2b 2000 if(qr_aff_line_step(_aff,l[1],1,drv,&dru)<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 2001 }
RyoheiHagimoto 0:56c5742b9e2b 2002 else dru=0;
RyoheiHagimoto 0:56c5742b9e2b 2003 ru=_ur->o[0]+3*_ur->size[0]-2*dru;
RyoheiHagimoto 0:56c5742b9e2b 2004 rv=_ur->o[1]-2*drv;
RyoheiHagimoto 0:56c5742b9e2b 2005 dbu=_dl->size[0]>>1;
RyoheiHagimoto 0:56c5742b9e2b 2006 qr_finder_ransac(_dl,_aff,_isaac,3);
RyoheiHagimoto 0:56c5742b9e2b 2007 if(qr_line_fit_finder_edge(l[3],_dl,3,_aff->res)>=0){
RyoheiHagimoto 0:56c5742b9e2b 2008 if(qr_line_eval(l[3],_ul->c->pos[0],_ul->c->pos[1])<0||
RyoheiHagimoto 0:56c5742b9e2b 2009 qr_line_eval(l[3],_ur->c->pos[0],_ur->c->pos[1])<0){
RyoheiHagimoto 0:56c5742b9e2b 2010 return -1;
RyoheiHagimoto 0:56c5742b9e2b 2011 }
RyoheiHagimoto 0:56c5742b9e2b 2012 /*Figure out the change in bv for a given change in bu when stepping along
RyoheiHagimoto 0:56c5742b9e2b 2013 the fitted line.*/
RyoheiHagimoto 0:56c5742b9e2b 2014 if(qr_aff_line_step(_aff,l[3],0,dbu,&dbv)<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 2015 }
RyoheiHagimoto 0:56c5742b9e2b 2016 else dbv=0;
RyoheiHagimoto 0:56c5742b9e2b 2017 bu=_dl->o[0]-2*dbu;
RyoheiHagimoto 0:56c5742b9e2b 2018 bv=_dl->o[1]+3*_dl->size[1]-2*dbv;
RyoheiHagimoto 0:56c5742b9e2b 2019 /*Set up the initial point lists.*/
RyoheiHagimoto 0:56c5742b9e2b 2020 nr=rlastfit=_ur->ninliers[1];
RyoheiHagimoto 0:56c5742b9e2b 2021 cr=nr+(_dl->o[1]-rv+drv-1)/drv;
RyoheiHagimoto 0:56c5742b9e2b 2022 r=(qr_point *)malloc(cr*sizeof(*r));
RyoheiHagimoto 0:56c5742b9e2b 2023 for(i=0;i<_ur->ninliers[1];i++){
RyoheiHagimoto 0:56c5742b9e2b 2024 memcpy(r[i],_ur->edge_pts[1][i].pos,sizeof(r[i]));
RyoheiHagimoto 0:56c5742b9e2b 2025 }
RyoheiHagimoto 0:56c5742b9e2b 2026 nb=blastfit=_dl->ninliers[3];
RyoheiHagimoto 0:56c5742b9e2b 2027 cb=nb+(_ur->o[0]-bu+dbu-1)/dbu;
RyoheiHagimoto 0:56c5742b9e2b 2028 b=(qr_point *)malloc(cb*sizeof(*b));
RyoheiHagimoto 0:56c5742b9e2b 2029 for(i=0;i<_dl->ninliers[3];i++){
RyoheiHagimoto 0:56c5742b9e2b 2030 memcpy(b[i],_dl->edge_pts[3][i].pos,sizeof(b[i]));
RyoheiHagimoto 0:56c5742b9e2b 2031 }
RyoheiHagimoto 0:56c5742b9e2b 2032 /*Set up the step parameters for the affine projection.*/
RyoheiHagimoto 0:56c5742b9e2b 2033 ox=(_aff->x0<<_aff->res)+(1<<_aff->res-1);
RyoheiHagimoto 0:56c5742b9e2b 2034 oy=(_aff->y0<<_aff->res)+(1<<_aff->res-1);
RyoheiHagimoto 0:56c5742b9e2b 2035 rx=_aff->fwd[0][0]*ru+_aff->fwd[0][1]*rv+ox;
RyoheiHagimoto 0:56c5742b9e2b 2036 ry=_aff->fwd[1][0]*ru+_aff->fwd[1][1]*rv+oy;
RyoheiHagimoto 0:56c5742b9e2b 2037 drxi=_aff->fwd[0][0]*dru+_aff->fwd[0][1]*drv;
RyoheiHagimoto 0:56c5742b9e2b 2038 dryi=_aff->fwd[1][0]*dru+_aff->fwd[1][1]*drv;
RyoheiHagimoto 0:56c5742b9e2b 2039 drxj=_aff->fwd[0][0]*_ur->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2040 dryj=_aff->fwd[1][0]*_ur->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2041 bx=_aff->fwd[0][0]*bu+_aff->fwd[0][1]*bv+ox;
RyoheiHagimoto 0:56c5742b9e2b 2042 by=_aff->fwd[1][0]*bu+_aff->fwd[1][1]*bv+oy;
RyoheiHagimoto 0:56c5742b9e2b 2043 dbxi=_aff->fwd[0][0]*dbu+_aff->fwd[0][1]*dbv;
RyoheiHagimoto 0:56c5742b9e2b 2044 dbyi=_aff->fwd[1][0]*dbu+_aff->fwd[1][1]*dbv;
RyoheiHagimoto 0:56c5742b9e2b 2045 dbxj=_aff->fwd[0][1]*_dl->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2046 dbyj=_aff->fwd[1][1]*_dl->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2047 /*Now step along the lines, looking for new sample points.*/
RyoheiHagimoto 0:56c5742b9e2b 2048 nrempty=nbempty=0;
RyoheiHagimoto 0:56c5742b9e2b 2049 for(;;){
RyoheiHagimoto 0:56c5742b9e2b 2050 int ret;
RyoheiHagimoto 0:56c5742b9e2b 2051 int x0;
RyoheiHagimoto 0:56c5742b9e2b 2052 int y0;
RyoheiHagimoto 0:56c5742b9e2b 2053 int x1;
RyoheiHagimoto 0:56c5742b9e2b 2054 int y1;
RyoheiHagimoto 0:56c5742b9e2b 2055 /*If we take too many steps without encountering a non-zero pixel, assume
RyoheiHagimoto 0:56c5742b9e2b 2056 we have wandered off the edge and stop looking before we hit the other
RyoheiHagimoto 0:56c5742b9e2b 2057 side of the quiet region.
RyoheiHagimoto 0:56c5742b9e2b 2058 Otherwise, stop when the lines cross (if they do so inside the affine
RyoheiHagimoto 0:56c5742b9e2b 2059 region) or come close to crossing (outside the affine region).
RyoheiHagimoto 0:56c5742b9e2b 2060 TODO: We don't have any way of detecting when we've wandered into the
RyoheiHagimoto 0:56c5742b9e2b 2061 code interior; we could stop if the outside sample ever shows up dark,
RyoheiHagimoto 0:56c5742b9e2b 2062 but this could happen because of noise in the quiet region, too.*/
RyoheiHagimoto 0:56c5742b9e2b 2063 rdone=rv>=QR_MINI(bv,_dl->o[1]+bv>>1)||nrempty>14;
RyoheiHagimoto 0:56c5742b9e2b 2064 bdone=bu>=QR_MINI(ru,_ur->o[0]+ru>>1)||nbempty>14;
RyoheiHagimoto 0:56c5742b9e2b 2065 if(!rdone&&(bdone||rv<bu)){
RyoheiHagimoto 0:56c5742b9e2b 2066 x0=rx+drxj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2067 y0=ry+dryj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2068 x1=rx-drxj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2069 y1=ry-dryj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2070 if(nr>=cr){
RyoheiHagimoto 0:56c5742b9e2b 2071 cr=cr<<1|1;
RyoheiHagimoto 0:56c5742b9e2b 2072 r=(qr_point *)realloc(r,cr*sizeof(*r));
RyoheiHagimoto 0:56c5742b9e2b 2073 }
RyoheiHagimoto 0:56c5742b9e2b 2074 ret=qr_finder_quick_crossing_check(_img,_width,_height,x0,y0,x1,y1,1);
RyoheiHagimoto 0:56c5742b9e2b 2075 if(!ret){
RyoheiHagimoto 0:56c5742b9e2b 2076 ret=qr_finder_locate_crossing(_img,_width,_height,x0,y0,x1,y1,1,r[nr]);
RyoheiHagimoto 0:56c5742b9e2b 2077 }
RyoheiHagimoto 0:56c5742b9e2b 2078 if(ret>=0){
RyoheiHagimoto 0:56c5742b9e2b 2079 if(!ret){
RyoheiHagimoto 0:56c5742b9e2b 2080 qr_aff_unproject(q,_aff,r[nr][0],r[nr][1]);
RyoheiHagimoto 0:56c5742b9e2b 2081 /*Move the current point halfway towards the crossing.
RyoheiHagimoto 0:56c5742b9e2b 2082 We don't move the whole way to give us some robustness to noise.*/
RyoheiHagimoto 0:56c5742b9e2b 2083 ru=ru+q[0]>>1;
RyoheiHagimoto 0:56c5742b9e2b 2084 /*But ensure that rv monotonically increases.*/
RyoheiHagimoto 0:56c5742b9e2b 2085 if(q[1]+drv>rv)rv=rv+q[1]>>1;
RyoheiHagimoto 0:56c5742b9e2b 2086 rx=_aff->fwd[0][0]*ru+_aff->fwd[0][1]*rv+ox;
RyoheiHagimoto 0:56c5742b9e2b 2087 ry=_aff->fwd[1][0]*ru+_aff->fwd[1][1]*rv+oy;
RyoheiHagimoto 0:56c5742b9e2b 2088 nr++;
RyoheiHagimoto 0:56c5742b9e2b 2089 /*Re-fit the line to update the step direction periodically.*/
RyoheiHagimoto 0:56c5742b9e2b 2090 if(nr>QR_MAXI(1,rlastfit+(rlastfit>>2))){
RyoheiHagimoto 0:56c5742b9e2b 2091 qr_line_fit_points(l[1],r,nr,_aff->res);
RyoheiHagimoto 0:56c5742b9e2b 2092 if(qr_aff_line_step(_aff,l[1],1,drv,&dru)>=0){
RyoheiHagimoto 0:56c5742b9e2b 2093 drxi=_aff->fwd[0][0]*dru+_aff->fwd[0][1]*drv;
RyoheiHagimoto 0:56c5742b9e2b 2094 dryi=_aff->fwd[1][0]*dru+_aff->fwd[1][1]*drv;
RyoheiHagimoto 0:56c5742b9e2b 2095 }
RyoheiHagimoto 0:56c5742b9e2b 2096 rlastfit=nr;
RyoheiHagimoto 0:56c5742b9e2b 2097 }
RyoheiHagimoto 0:56c5742b9e2b 2098 }
RyoheiHagimoto 0:56c5742b9e2b 2099 else nrempty=0;
RyoheiHagimoto 0:56c5742b9e2b 2100 }
RyoheiHagimoto 0:56c5742b9e2b 2101 else nrempty++;
RyoheiHagimoto 0:56c5742b9e2b 2102 ru+=dru;
RyoheiHagimoto 0:56c5742b9e2b 2103 /*Our final defense: if we overflow, stop.*/
RyoheiHagimoto 0:56c5742b9e2b 2104 if(rv+drv>rv)rv+=drv;
RyoheiHagimoto 0:56c5742b9e2b 2105 else nrempty=INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 2106 rx+=drxi;
RyoheiHagimoto 0:56c5742b9e2b 2107 ry+=dryi;
RyoheiHagimoto 0:56c5742b9e2b 2108 }
RyoheiHagimoto 0:56c5742b9e2b 2109 else if(!bdone){
RyoheiHagimoto 0:56c5742b9e2b 2110 x0=bx+dbxj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2111 y0=by+dbyj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2112 x1=bx-dbxj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2113 y1=by-dbyj>>_aff->res+QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2114 if(nb>=cb){
RyoheiHagimoto 0:56c5742b9e2b 2115 cb=cb<<1|1;
RyoheiHagimoto 0:56c5742b9e2b 2116 b=(qr_point *)realloc(b,cb*sizeof(*b));
RyoheiHagimoto 0:56c5742b9e2b 2117 }
RyoheiHagimoto 0:56c5742b9e2b 2118 ret=qr_finder_quick_crossing_check(_img,_width,_height,x0,y0,x1,y1,1);
RyoheiHagimoto 0:56c5742b9e2b 2119 if(!ret){
RyoheiHagimoto 0:56c5742b9e2b 2120 ret=qr_finder_locate_crossing(_img,_width,_height,x0,y0,x1,y1,1,b[nb]);
RyoheiHagimoto 0:56c5742b9e2b 2121 }
RyoheiHagimoto 0:56c5742b9e2b 2122 if(ret>=0){
RyoheiHagimoto 0:56c5742b9e2b 2123 if(!ret){
RyoheiHagimoto 0:56c5742b9e2b 2124 qr_aff_unproject(q,_aff,b[nb][0],b[nb][1]);
RyoheiHagimoto 0:56c5742b9e2b 2125 /*Move the current point halfway towards the crossing.
RyoheiHagimoto 0:56c5742b9e2b 2126 We don't move the whole way to give us some robustness to noise.*/
RyoheiHagimoto 0:56c5742b9e2b 2127 /*But ensure that bu monotonically increases.*/
RyoheiHagimoto 0:56c5742b9e2b 2128 if(q[0]+dbu>bu)bu=bu+q[0]>>1;
RyoheiHagimoto 0:56c5742b9e2b 2129 bv=bv+q[1]>>1;
RyoheiHagimoto 0:56c5742b9e2b 2130 bx=_aff->fwd[0][0]*bu+_aff->fwd[0][1]*bv+ox;
RyoheiHagimoto 0:56c5742b9e2b 2131 by=_aff->fwd[1][0]*bu+_aff->fwd[1][1]*bv+oy;
RyoheiHagimoto 0:56c5742b9e2b 2132 nb++;
RyoheiHagimoto 0:56c5742b9e2b 2133 /*Re-fit the line to update the step direction periodically.*/
RyoheiHagimoto 0:56c5742b9e2b 2134 if(nb>QR_MAXI(1,blastfit+(blastfit>>2))){
RyoheiHagimoto 0:56c5742b9e2b 2135 qr_line_fit_points(l[3],b,nb,_aff->res);
RyoheiHagimoto 0:56c5742b9e2b 2136 if(qr_aff_line_step(_aff,l[3],0,dbu,&dbv)>=0){
RyoheiHagimoto 0:56c5742b9e2b 2137 dbxi=_aff->fwd[0][0]*dbu+_aff->fwd[0][1]*dbv;
RyoheiHagimoto 0:56c5742b9e2b 2138 dbyi=_aff->fwd[1][0]*dbu+_aff->fwd[1][1]*dbv;
RyoheiHagimoto 0:56c5742b9e2b 2139 }
RyoheiHagimoto 0:56c5742b9e2b 2140 blastfit=nb;
RyoheiHagimoto 0:56c5742b9e2b 2141 }
RyoheiHagimoto 0:56c5742b9e2b 2142 }
RyoheiHagimoto 0:56c5742b9e2b 2143 nbempty=0;
RyoheiHagimoto 0:56c5742b9e2b 2144 }
RyoheiHagimoto 0:56c5742b9e2b 2145 else nbempty++;
RyoheiHagimoto 0:56c5742b9e2b 2146 /*Our final defense: if we overflow, stop.*/
RyoheiHagimoto 0:56c5742b9e2b 2147 if(bu+dbu>bu)bu+=dbu;
RyoheiHagimoto 0:56c5742b9e2b 2148 else nbempty=INT_MAX;
RyoheiHagimoto 0:56c5742b9e2b 2149 bv+=dbv;
RyoheiHagimoto 0:56c5742b9e2b 2150 bx+=dbxi;
RyoheiHagimoto 0:56c5742b9e2b 2151 by+=dbyi;
RyoheiHagimoto 0:56c5742b9e2b 2152 }
RyoheiHagimoto 0:56c5742b9e2b 2153 else break;
RyoheiHagimoto 0:56c5742b9e2b 2154 }
RyoheiHagimoto 0:56c5742b9e2b 2155 /*Fit the new lines.
RyoheiHagimoto 0:56c5742b9e2b 2156 If we _still_ don't have enough sample points, then just use an
RyoheiHagimoto 0:56c5742b9e2b 2157 axis-aligned line from the affine coordinate system (e.g., one parallel
RyoheiHagimoto 0:56c5742b9e2b 2158 to the opposite edge in the image).*/
RyoheiHagimoto 0:56c5742b9e2b 2159 if(nr>1)qr_line_fit_points(l[1],r,nr,_aff->res);
RyoheiHagimoto 0:56c5742b9e2b 2160 else{
RyoheiHagimoto 0:56c5742b9e2b 2161 qr_aff_project(p,_aff,_ur->o[0]+3*_ur->size[0],_ur->o[1]);
RyoheiHagimoto 0:56c5742b9e2b 2162 shift=QR_MAXI(0,
RyoheiHagimoto 0:56c5742b9e2b 2163 qr_ilog(QR_MAXI(abs(_aff->fwd[0][1]),abs(_aff->fwd[1][1])))
RyoheiHagimoto 0:56c5742b9e2b 2164 -(_aff->res+1>>1));
RyoheiHagimoto 0:56c5742b9e2b 2165 round=(1<<shift)>>1;
RyoheiHagimoto 0:56c5742b9e2b 2166 l[1][0]=_aff->fwd[1][1]+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 2167 l[1][1]=-_aff->fwd[0][1]+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 2168 l[1][2]=-(l[1][0]*p[0]+l[1][1]*p[1]);
RyoheiHagimoto 0:56c5742b9e2b 2169 }
RyoheiHagimoto 0:56c5742b9e2b 2170 free(r);
RyoheiHagimoto 0:56c5742b9e2b 2171 if(nb>1)qr_line_fit_points(l[3],b,nb,_aff->res);
RyoheiHagimoto 0:56c5742b9e2b 2172 else{
RyoheiHagimoto 0:56c5742b9e2b 2173 qr_aff_project(p,_aff,_dl->o[0],_dl->o[1]+3*_dl->size[1]);
RyoheiHagimoto 0:56c5742b9e2b 2174 shift=QR_MAXI(0,
RyoheiHagimoto 0:56c5742b9e2b 2175 qr_ilog(QR_MAXI(abs(_aff->fwd[0][1]),abs(_aff->fwd[1][1])))
RyoheiHagimoto 0:56c5742b9e2b 2176 -(_aff->res+1>>1));
RyoheiHagimoto 0:56c5742b9e2b 2177 round=(1<<shift)>>1;
RyoheiHagimoto 0:56c5742b9e2b 2178 l[3][0]=_aff->fwd[1][0]+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 2179 l[3][1]=-_aff->fwd[0][0]+round>>shift;
RyoheiHagimoto 0:56c5742b9e2b 2180 l[3][2]=-(l[1][0]*p[0]+l[1][1]*p[1]);
RyoheiHagimoto 0:56c5742b9e2b 2181 }
RyoheiHagimoto 0:56c5742b9e2b 2182 free(b);
RyoheiHagimoto 0:56c5742b9e2b 2183 for(i=0;i<4;i++){
RyoheiHagimoto 0:56c5742b9e2b 2184 if(qr_line_isect(_p[i],l[i&1],l[2+(i>>1)])<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 2185 /*It's plausible for points to be somewhat outside the image, but too far
RyoheiHagimoto 0:56c5742b9e2b 2186 and too much of the pattern will be gone for it to be decodable.*/
RyoheiHagimoto 0:56c5742b9e2b 2187 if(_p[i][0]<-_width<<QR_FINDER_SUBPREC||
RyoheiHagimoto 0:56c5742b9e2b 2188 _p[i][0]>=_width<<QR_FINDER_SUBPREC+1||
RyoheiHagimoto 0:56c5742b9e2b 2189 _p[i][1]<-_height<<QR_FINDER_SUBPREC||
RyoheiHagimoto 0:56c5742b9e2b 2190 _p[i][1]>=_height<<QR_FINDER_SUBPREC+1){
RyoheiHagimoto 0:56c5742b9e2b 2191 return -1;
RyoheiHagimoto 0:56c5742b9e2b 2192 }
RyoheiHagimoto 0:56c5742b9e2b 2193 }
RyoheiHagimoto 0:56c5742b9e2b 2194 /*By default, use the edge intersection point for the bottom-right corner.*/
RyoheiHagimoto 0:56c5742b9e2b 2195 brx=_p[3][0];
RyoheiHagimoto 0:56c5742b9e2b 2196 bry=_p[3][1];
RyoheiHagimoto 0:56c5742b9e2b 2197 /*However, if our average version estimate is greater than 1, NOW we try to
RyoheiHagimoto 0:56c5742b9e2b 2198 search for an alignment pattern.
RyoheiHagimoto 0:56c5742b9e2b 2199 We get a much better success rate by doing this after our initial attempt
RyoheiHagimoto 0:56c5742b9e2b 2200 to promote the transform to a homography than before.
RyoheiHagimoto 0:56c5742b9e2b 2201 You might also think it would be more reliable to use the interior finder
RyoheiHagimoto 0:56c5742b9e2b 2202 pattern edges, since the outer ones may be obscured or damaged, and it
RyoheiHagimoto 0:56c5742b9e2b 2203 would save us a reprojection below, since they would form a nice square
RyoheiHagimoto 0:56c5742b9e2b 2204 with the location of the alignment pattern, but this turns out to be a bad
RyoheiHagimoto 0:56c5742b9e2b 2205 idea.
RyoheiHagimoto 0:56c5742b9e2b 2206 Non-linear distortion is usually maximal on the outside edge, and thus
RyoheiHagimoto 0:56c5742b9e2b 2207 estimating the grid position from points on the interior means we might
RyoheiHagimoto 0:56c5742b9e2b 2208 get mis-aligned by the time we reach the edge.*/
RyoheiHagimoto 0:56c5742b9e2b 2209 version4=_ul->eversion[0]+_ul->eversion[1]+_ur->eversion[0]+_dl->eversion[1];
RyoheiHagimoto 0:56c5742b9e2b 2210 if(version4>4){
RyoheiHagimoto 0:56c5742b9e2b 2211 qr_hom_cell cell;
RyoheiHagimoto 0:56c5742b9e2b 2212 qr_point p3;
RyoheiHagimoto 0:56c5742b9e2b 2213 int dim;
RyoheiHagimoto 0:56c5742b9e2b 2214 dim=17+version4;
RyoheiHagimoto 0:56c5742b9e2b 2215 qr_hom_cell_init(&cell,0,0,dim-1,0,0,dim-1,dim-1,dim-1,
RyoheiHagimoto 0:56c5742b9e2b 2216 _p[0][0],_p[0][1],_p[1][0],_p[1][1],
RyoheiHagimoto 0:56c5742b9e2b 2217 _p[2][0],_p[2][1],_p[3][0],_p[3][1]);
RyoheiHagimoto 0:56c5742b9e2b 2218 if(qr_alignment_pattern_search(p3,&cell,dim-7,dim-7,4,
RyoheiHagimoto 0:56c5742b9e2b 2219 _img,_width,_height)>=0){
RyoheiHagimoto 0:56c5742b9e2b 2220 int c21;
RyoheiHagimoto 0:56c5742b9e2b 2221 int dx21;
RyoheiHagimoto 0:56c5742b9e2b 2222 int dy21;
RyoheiHagimoto 0:56c5742b9e2b 2223 int mask;
RyoheiHagimoto 0:56c5742b9e2b 2224 int w;
RyoheiHagimoto 0:56c5742b9e2b 2225 /*There's no real need to update the bounding box corner, and in fact we
RyoheiHagimoto 0:56c5742b9e2b 2226 actively perform worse if we do.
RyoheiHagimoto 0:56c5742b9e2b 2227 Clearly it was good enough for us to find this alignment pattern, so
RyoheiHagimoto 0:56c5742b9e2b 2228 it should be good enough to use for grid initialization.
RyoheiHagimoto 0:56c5742b9e2b 2229 The point of doing the search was to get more accurate version
RyoheiHagimoto 0:56c5742b9e2b 2230 estimates and a better chance of decoding the version and format info.
RyoheiHagimoto 0:56c5742b9e2b 2231 This is particularly important for small versions that have no encoded
RyoheiHagimoto 0:56c5742b9e2b 2232 version info, since any mismatch in version renders the code
RyoheiHagimoto 0:56c5742b9e2b 2233 undecodable.*/
RyoheiHagimoto 0:56c5742b9e2b 2234 /*We do, however, need four points in a square to initialize our
RyoheiHagimoto 0:56c5742b9e2b 2235 homography, so project the point from the alignment center to the
RyoheiHagimoto 0:56c5742b9e2b 2236 corner of the code area.*/
RyoheiHagimoto 0:56c5742b9e2b 2237 c21=_p[2][0]*_p[1][1]-_p[2][1]*_p[1][0];
RyoheiHagimoto 0:56c5742b9e2b 2238 dx21=_p[2][0]-_p[1][0];
RyoheiHagimoto 0:56c5742b9e2b 2239 dy21=_p[2][1]-_p[1][1];
RyoheiHagimoto 0:56c5742b9e2b 2240 w=(dim-7)*c21
RyoheiHagimoto 0:56c5742b9e2b 2241 +(dim-13)*(_p[0][0]*dy21-_p[0][1]*dx21)+6*(p3[0]*dy21-p3[1]*dx21);
RyoheiHagimoto 0:56c5742b9e2b 2242 mask=QR_SIGNMASK(w);
RyoheiHagimoto 0:56c5742b9e2b 2243 w=abs(w);
RyoheiHagimoto 0:56c5742b9e2b 2244 brx=(int)QR_DIVROUND(QR_EXTMUL((dim-7)*_p[0][0],p3[0]*dy21,
RyoheiHagimoto 0:56c5742b9e2b 2245 QR_EXTMUL((dim-13)*p3[0],c21-_p[0][1]*dx21,
RyoheiHagimoto 0:56c5742b9e2b 2246 QR_EXTMUL(6*_p[0][0],c21-p3[1]*dx21,0)))+mask^mask,w);
RyoheiHagimoto 0:56c5742b9e2b 2247 bry=(int)QR_DIVROUND(QR_EXTMUL((dim-7)*_p[0][1],-p3[1]*dx21,
RyoheiHagimoto 0:56c5742b9e2b 2248 QR_EXTMUL((dim-13)*p3[1],c21+_p[0][0]*dy21,
RyoheiHagimoto 0:56c5742b9e2b 2249 QR_EXTMUL(6*_p[0][1],c21+p3[0]*dy21,0)))+mask^mask,w);
RyoheiHagimoto 0:56c5742b9e2b 2250 }
RyoheiHagimoto 0:56c5742b9e2b 2251 }
RyoheiHagimoto 0:56c5742b9e2b 2252 /*Now we have four points that map to a square: initialize the projection.*/
RyoheiHagimoto 0:56c5742b9e2b 2253 qr_hom_init(_hom,_p[0][0],_p[0][1],_p[1][0],_p[1][1],
RyoheiHagimoto 0:56c5742b9e2b 2254 _p[2][0],_p[2][1],brx,bry,QR_HOM_BITS);
RyoheiHagimoto 0:56c5742b9e2b 2255 return 0;
RyoheiHagimoto 0:56c5742b9e2b 2256 }
RyoheiHagimoto 0:56c5742b9e2b 2257
RyoheiHagimoto 0:56c5742b9e2b 2258
RyoheiHagimoto 0:56c5742b9e2b 2259
RyoheiHagimoto 0:56c5742b9e2b 2260 /*The BCH(18,6,3) codes are only used for version information, which must lie
RyoheiHagimoto 0:56c5742b9e2b 2261 between 7 and 40 (inclusive).*/
RyoheiHagimoto 0:56c5742b9e2b 2262 static const unsigned BCH18_6_CODES[34]={
RyoheiHagimoto 0:56c5742b9e2b 2263 0x07C94,
RyoheiHagimoto 0:56c5742b9e2b 2264 0x085BC,0x09A99,0x0A4D3,0x0BBF6,0x0C762,0x0D847,0x0E60D,0x0F928,
RyoheiHagimoto 0:56c5742b9e2b 2265 0x10B78,0x1145D,0x12A17,0x13532,0x149A6,0x15683,0x168C9,0x177EC,
RyoheiHagimoto 0:56c5742b9e2b 2266 0x18EC4,0x191E1,0x1AFAB,0x1B08E,0x1CC1A,0x1D33F,0x1ED75,0x1F250,
RyoheiHagimoto 0:56c5742b9e2b 2267 0x209D5,0x216F0,0x228BA,0x2379F,0x24B0B,0x2542E,0x26A64,0x27541,
RyoheiHagimoto 0:56c5742b9e2b 2268 0x28C69
RyoheiHagimoto 0:56c5742b9e2b 2269 };
RyoheiHagimoto 0:56c5742b9e2b 2270
RyoheiHagimoto 0:56c5742b9e2b 2271 /*Corrects a BCH(18,6,3) code word.
RyoheiHagimoto 0:56c5742b9e2b 2272 _y: Contains the code word to be checked on input, and the corrected value on
RyoheiHagimoto 0:56c5742b9e2b 2273 output.
RyoheiHagimoto 0:56c5742b9e2b 2274 Return: The number of errors.
RyoheiHagimoto 0:56c5742b9e2b 2275 If more than 3 errors are detected, returns a negative value and
RyoheiHagimoto 0:56c5742b9e2b 2276 performs no correction.*/
RyoheiHagimoto 0:56c5742b9e2b 2277 static int bch18_6_correct(unsigned *_y){
RyoheiHagimoto 0:56c5742b9e2b 2278 unsigned x;
RyoheiHagimoto 0:56c5742b9e2b 2279 unsigned y;
RyoheiHagimoto 0:56c5742b9e2b 2280 int nerrs;
RyoheiHagimoto 0:56c5742b9e2b 2281 y=*_y;
RyoheiHagimoto 0:56c5742b9e2b 2282 /*Check the easy case first: see if the data bits were uncorrupted.*/
RyoheiHagimoto 0:56c5742b9e2b 2283 x=y>>12;
RyoheiHagimoto 0:56c5742b9e2b 2284 if(x>=7&&x<=40){
RyoheiHagimoto 0:56c5742b9e2b 2285 nerrs=qr_hamming_dist(y,BCH18_6_CODES[x-7],4);
RyoheiHagimoto 0:56c5742b9e2b 2286 if(nerrs<4){
RyoheiHagimoto 0:56c5742b9e2b 2287 *_y=BCH18_6_CODES[x-7];
RyoheiHagimoto 0:56c5742b9e2b 2288 return nerrs;
RyoheiHagimoto 0:56c5742b9e2b 2289 }
RyoheiHagimoto 0:56c5742b9e2b 2290 }
RyoheiHagimoto 0:56c5742b9e2b 2291 /*Exhaustive search is faster than field operations in GF(19).*/
RyoheiHagimoto 0:56c5742b9e2b 2292 for(x=0;x<34;x++)if(x+7!=y>>12){
RyoheiHagimoto 0:56c5742b9e2b 2293 nerrs=qr_hamming_dist(y,BCH18_6_CODES[x],4);
RyoheiHagimoto 0:56c5742b9e2b 2294 if(nerrs<4){
RyoheiHagimoto 0:56c5742b9e2b 2295 *_y=BCH18_6_CODES[x];
RyoheiHagimoto 0:56c5742b9e2b 2296 return nerrs;
RyoheiHagimoto 0:56c5742b9e2b 2297 }
RyoheiHagimoto 0:56c5742b9e2b 2298 }
RyoheiHagimoto 0:56c5742b9e2b 2299 return -1;
RyoheiHagimoto 0:56c5742b9e2b 2300 }
RyoheiHagimoto 0:56c5742b9e2b 2301
RyoheiHagimoto 0:56c5742b9e2b 2302 #if 0
RyoheiHagimoto 0:56c5742b9e2b 2303 static unsigned bch18_6_encode(unsigned _x){
RyoheiHagimoto 0:56c5742b9e2b 2304 return (-(_x&1)&0x01F25)^(-(_x>>1&1)&0x0216F)^(-(_x>>2&1)&0x042DE)^
RyoheiHagimoto 0:56c5742b9e2b 2305 (-(_x>>3&1)&0x085BC)^(-(_x>>4&1)&0x10B78)^(-(_x>>5&1)&0x209D5);
RyoheiHagimoto 0:56c5742b9e2b 2306 }
RyoheiHagimoto 0:56c5742b9e2b 2307 #endif
RyoheiHagimoto 0:56c5742b9e2b 2308
RyoheiHagimoto 0:56c5742b9e2b 2309 /*Reads the version bits near a finder module and decodes the version number.*/
RyoheiHagimoto 0:56c5742b9e2b 2310 static int qr_finder_version_decode(qr_finder *_f,const qr_hom *_hom,
RyoheiHagimoto 0:56c5742b9e2b 2311 const unsigned char *_img,int _width,int _height,int _dir){
RyoheiHagimoto 0:56c5742b9e2b 2312 qr_point q;
RyoheiHagimoto 0:56c5742b9e2b 2313 unsigned v;
RyoheiHagimoto 0:56c5742b9e2b 2314 int x0;
RyoheiHagimoto 0:56c5742b9e2b 2315 int y0;
RyoheiHagimoto 0:56c5742b9e2b 2316 int w0;
RyoheiHagimoto 0:56c5742b9e2b 2317 int dxi;
RyoheiHagimoto 0:56c5742b9e2b 2318 int dyi;
RyoheiHagimoto 0:56c5742b9e2b 2319 int dwi;
RyoheiHagimoto 0:56c5742b9e2b 2320 int dxj;
RyoheiHagimoto 0:56c5742b9e2b 2321 int dyj;
RyoheiHagimoto 0:56c5742b9e2b 2322 int dwj;
RyoheiHagimoto 0:56c5742b9e2b 2323 int ret;
RyoheiHagimoto 0:56c5742b9e2b 2324 int i;
RyoheiHagimoto 0:56c5742b9e2b 2325 int j;
RyoheiHagimoto 0:56c5742b9e2b 2326 int k;
RyoheiHagimoto 0:56c5742b9e2b 2327 v=0;
RyoheiHagimoto 0:56c5742b9e2b 2328 q[_dir]=_f->o[_dir]-7*_f->size[_dir];
RyoheiHagimoto 0:56c5742b9e2b 2329 q[1-_dir]=_f->o[1-_dir]-3*_f->size[1-_dir];
RyoheiHagimoto 0:56c5742b9e2b 2330 x0=_hom->fwd[0][0]*q[0]+_hom->fwd[0][1]*q[1];
RyoheiHagimoto 0:56c5742b9e2b 2331 y0=_hom->fwd[1][0]*q[0]+_hom->fwd[1][1]*q[1];
RyoheiHagimoto 0:56c5742b9e2b 2332 w0=_hom->fwd[2][0]*q[0]+_hom->fwd[2][1]*q[1]+_hom->fwd22;
RyoheiHagimoto 0:56c5742b9e2b 2333 dxi=_hom->fwd[0][1-_dir]*_f->size[1-_dir];
RyoheiHagimoto 0:56c5742b9e2b 2334 dyi=_hom->fwd[1][1-_dir]*_f->size[1-_dir];
RyoheiHagimoto 0:56c5742b9e2b 2335 dwi=_hom->fwd[2][1-_dir]*_f->size[1-_dir];
RyoheiHagimoto 0:56c5742b9e2b 2336 dxj=_hom->fwd[0][_dir]*_f->size[_dir];
RyoheiHagimoto 0:56c5742b9e2b 2337 dyj=_hom->fwd[1][_dir]*_f->size[_dir];
RyoheiHagimoto 0:56c5742b9e2b 2338 dwj=_hom->fwd[2][_dir]*_f->size[_dir];
RyoheiHagimoto 0:56c5742b9e2b 2339 for(k=i=0;i<6;i++){
RyoheiHagimoto 0:56c5742b9e2b 2340 int x;
RyoheiHagimoto 0:56c5742b9e2b 2341 int y;
RyoheiHagimoto 0:56c5742b9e2b 2342 int w;
RyoheiHagimoto 0:56c5742b9e2b 2343 x=x0;
RyoheiHagimoto 0:56c5742b9e2b 2344 y=y0;
RyoheiHagimoto 0:56c5742b9e2b 2345 w=w0;
RyoheiHagimoto 0:56c5742b9e2b 2346 for(j=0;j<3;j++,k++){
RyoheiHagimoto 0:56c5742b9e2b 2347 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 2348 qr_hom_fproject(p,_hom,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 2349 v|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k;
RyoheiHagimoto 0:56c5742b9e2b 2350 x+=dxj;
RyoheiHagimoto 0:56c5742b9e2b 2351 y+=dyj;
RyoheiHagimoto 0:56c5742b9e2b 2352 w+=dwj;
RyoheiHagimoto 0:56c5742b9e2b 2353 }
RyoheiHagimoto 0:56c5742b9e2b 2354 x0+=dxi;
RyoheiHagimoto 0:56c5742b9e2b 2355 y0+=dyi;
RyoheiHagimoto 0:56c5742b9e2b 2356 w0+=dwi;
RyoheiHagimoto 0:56c5742b9e2b 2357 }
RyoheiHagimoto 0:56c5742b9e2b 2358 ret=bch18_6_correct(&v);
RyoheiHagimoto 0:56c5742b9e2b 2359 /*TODO: I'd certainly hope the order the version bits is accessed in is
RyoheiHagimoto 0:56c5742b9e2b 2360 well-defined, but I seem to have images for two different codes with the
RyoheiHagimoto 0:56c5742b9e2b 2361 same version using two different orders?
RyoheiHagimoto 0:56c5742b9e2b 2362 Maybe the other one is a model 1 code?
RyoheiHagimoto 0:56c5742b9e2b 2363 Even if I parse the version here, I can't decode the rest of the code.
RyoheiHagimoto 0:56c5742b9e2b 2364 If this is really needed, we should just re-order the bits.*/
RyoheiHagimoto 0:56c5742b9e2b 2365 #if 0
RyoheiHagimoto 0:56c5742b9e2b 2366 if(ret<0){
RyoheiHagimoto 0:56c5742b9e2b 2367 /*17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RyoheiHagimoto 0:56c5742b9e2b 2368 0 3 6 9 12 15 1 4 7 10 13 16 2 5 8 11 14 17
RyoheiHagimoto 0:56c5742b9e2b 2369 17 13 9 5 1 -3 10 6 2 -2 -6-10 3 -1 -5 -9-13-17*/
RyoheiHagimoto 0:56c5742b9e2b 2370 v=0;
RyoheiHagimoto 0:56c5742b9e2b 2371 for(k=i=0;i<3;i++){
RyoheiHagimoto 0:56c5742b9e2b 2372 p[_dir]=_f->o[_dir]+_f->size[_dir]*(-5-i);
RyoheiHagimoto 0:56c5742b9e2b 2373 for(j=0;j<6;j++,k++){
RyoheiHagimoto 0:56c5742b9e2b 2374 qr_point q;
RyoheiHagimoto 0:56c5742b9e2b 2375 p[1-_dir]=_f->o[1-_dir]+_f->size[1-_dir]*(2-j);
RyoheiHagimoto 0:56c5742b9e2b 2376 qr_hom_project(q,_hom,p[0],p[1]);
RyoheiHagimoto 0:56c5742b9e2b 2377 v|=qr_img_get_bit(_img,_width,_height,q[0],q[1])<<k;
RyoheiHagimoto 0:56c5742b9e2b 2378 }
RyoheiHagimoto 0:56c5742b9e2b 2379 }
RyoheiHagimoto 0:56c5742b9e2b 2380 ret=bch18_6_correct(&v);
RyoheiHagimoto 0:56c5742b9e2b 2381 }
RyoheiHagimoto 0:56c5742b9e2b 2382 #endif
RyoheiHagimoto 0:56c5742b9e2b 2383 return ret>=0?(int)(v>>12):ret;
RyoheiHagimoto 0:56c5742b9e2b 2384 }
RyoheiHagimoto 0:56c5742b9e2b 2385
RyoheiHagimoto 0:56c5742b9e2b 2386 /*Reads the format info bits near the finder modules and decodes them.*/
RyoheiHagimoto 0:56c5742b9e2b 2387 static int qr_finder_fmt_info_decode(qr_finder *_ul,qr_finder *_ur,
RyoheiHagimoto 0:56c5742b9e2b 2388 qr_finder *_dl,const qr_hom *_hom,
RyoheiHagimoto 0:56c5742b9e2b 2389 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 2390 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 2391 unsigned lo[2];
RyoheiHagimoto 0:56c5742b9e2b 2392 unsigned hi[2];
RyoheiHagimoto 0:56c5742b9e2b 2393 int u;
RyoheiHagimoto 0:56c5742b9e2b 2394 int v;
RyoheiHagimoto 0:56c5742b9e2b 2395 int x;
RyoheiHagimoto 0:56c5742b9e2b 2396 int y;
RyoheiHagimoto 0:56c5742b9e2b 2397 int w;
RyoheiHagimoto 0:56c5742b9e2b 2398 int dx;
RyoheiHagimoto 0:56c5742b9e2b 2399 int dy;
RyoheiHagimoto 0:56c5742b9e2b 2400 int dw;
RyoheiHagimoto 0:56c5742b9e2b 2401 int fmt_info[4];
RyoheiHagimoto 0:56c5742b9e2b 2402 int count[4];
RyoheiHagimoto 0:56c5742b9e2b 2403 int nerrs[4];
RyoheiHagimoto 0:56c5742b9e2b 2404 int nfmt_info;
RyoheiHagimoto 0:56c5742b9e2b 2405 int besti;
RyoheiHagimoto 0:56c5742b9e2b 2406 int imax;
RyoheiHagimoto 0:56c5742b9e2b 2407 int di;
RyoheiHagimoto 0:56c5742b9e2b 2408 int i;
RyoheiHagimoto 0:56c5742b9e2b 2409 int k;
RyoheiHagimoto 0:56c5742b9e2b 2410 /*Read the bits around the UL corner.*/
RyoheiHagimoto 0:56c5742b9e2b 2411 lo[0]=0;
RyoheiHagimoto 0:56c5742b9e2b 2412 u=_ul->o[0]+5*_ul->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2413 v=_ul->o[1]-3*_ul->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2414 x=_hom->fwd[0][0]*u+_hom->fwd[0][1]*v;
RyoheiHagimoto 0:56c5742b9e2b 2415 y=_hom->fwd[1][0]*u+_hom->fwd[1][1]*v;
RyoheiHagimoto 0:56c5742b9e2b 2416 w=_hom->fwd[2][0]*u+_hom->fwd[2][1]*v+_hom->fwd22;
RyoheiHagimoto 0:56c5742b9e2b 2417 dx=_hom->fwd[0][1]*_ul->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2418 dy=_hom->fwd[1][1]*_ul->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2419 dw=_hom->fwd[2][1]*_ul->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2420 for(k=i=0;;i++){
RyoheiHagimoto 0:56c5742b9e2b 2421 /*Skip the timing pattern row.*/
RyoheiHagimoto 0:56c5742b9e2b 2422 if(i!=6){
RyoheiHagimoto 0:56c5742b9e2b 2423 qr_hom_fproject(p,_hom,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 2424 lo[0]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k++;
RyoheiHagimoto 0:56c5742b9e2b 2425 /*Don't advance q in the last iteration... we'll start the next loop from
RyoheiHagimoto 0:56c5742b9e2b 2426 the current position.*/
RyoheiHagimoto 0:56c5742b9e2b 2427 if(i>=8)break;
RyoheiHagimoto 0:56c5742b9e2b 2428 }
RyoheiHagimoto 0:56c5742b9e2b 2429 x+=dx;
RyoheiHagimoto 0:56c5742b9e2b 2430 y+=dy;
RyoheiHagimoto 0:56c5742b9e2b 2431 w+=dw;
RyoheiHagimoto 0:56c5742b9e2b 2432 }
RyoheiHagimoto 0:56c5742b9e2b 2433 hi[0]=0;
RyoheiHagimoto 0:56c5742b9e2b 2434 dx=-_hom->fwd[0][0]*_ul->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2435 dy=-_hom->fwd[1][0]*_ul->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2436 dw=-_hom->fwd[2][0]*_ul->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2437 while(i-->0){
RyoheiHagimoto 0:56c5742b9e2b 2438 x+=dx;
RyoheiHagimoto 0:56c5742b9e2b 2439 y+=dy;
RyoheiHagimoto 0:56c5742b9e2b 2440 w+=dw;
RyoheiHagimoto 0:56c5742b9e2b 2441 /*Skip the timing pattern column.*/
RyoheiHagimoto 0:56c5742b9e2b 2442 if(i!=6){
RyoheiHagimoto 0:56c5742b9e2b 2443 qr_hom_fproject(p,_hom,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 2444 hi[0]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k++;
RyoheiHagimoto 0:56c5742b9e2b 2445 }
RyoheiHagimoto 0:56c5742b9e2b 2446 }
RyoheiHagimoto 0:56c5742b9e2b 2447 /*Read the bits next to the UR corner.*/
RyoheiHagimoto 0:56c5742b9e2b 2448 lo[1]=0;
RyoheiHagimoto 0:56c5742b9e2b 2449 u=_ur->o[0]+3*_ur->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2450 v=_ur->o[1]+5*_ur->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2451 x=_hom->fwd[0][0]*u+_hom->fwd[0][1]*v;
RyoheiHagimoto 0:56c5742b9e2b 2452 y=_hom->fwd[1][0]*u+_hom->fwd[1][1]*v;
RyoheiHagimoto 0:56c5742b9e2b 2453 w=_hom->fwd[2][0]*u+_hom->fwd[2][1]*v+_hom->fwd22;
RyoheiHagimoto 0:56c5742b9e2b 2454 dx=-_hom->fwd[0][0]*_ur->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2455 dy=-_hom->fwd[1][0]*_ur->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2456 dw=-_hom->fwd[2][0]*_ur->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2457 for(k=0;k<8;k++){
RyoheiHagimoto 0:56c5742b9e2b 2458 qr_hom_fproject(p,_hom,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 2459 lo[1]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k;
RyoheiHagimoto 0:56c5742b9e2b 2460 x+=dx;
RyoheiHagimoto 0:56c5742b9e2b 2461 y+=dy;
RyoheiHagimoto 0:56c5742b9e2b 2462 w+=dw;
RyoheiHagimoto 0:56c5742b9e2b 2463 }
RyoheiHagimoto 0:56c5742b9e2b 2464 /*Read the bits next to the DL corner.*/
RyoheiHagimoto 0:56c5742b9e2b 2465 hi[1]=0;
RyoheiHagimoto 0:56c5742b9e2b 2466 u=_dl->o[0]+5*_dl->size[0];
RyoheiHagimoto 0:56c5742b9e2b 2467 v=_dl->o[1]-3*_dl->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2468 x=_hom->fwd[0][0]*u+_hom->fwd[0][1]*v;
RyoheiHagimoto 0:56c5742b9e2b 2469 y=_hom->fwd[1][0]*u+_hom->fwd[1][1]*v;
RyoheiHagimoto 0:56c5742b9e2b 2470 w=_hom->fwd[2][0]*u+_hom->fwd[2][1]*v+_hom->fwd22;
RyoheiHagimoto 0:56c5742b9e2b 2471 dx=_hom->fwd[0][1]*_dl->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2472 dy=_hom->fwd[1][1]*_dl->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2473 dw=_hom->fwd[2][1]*_dl->size[1];
RyoheiHagimoto 0:56c5742b9e2b 2474 for(k=8;k<15;k++){
RyoheiHagimoto 0:56c5742b9e2b 2475 qr_hom_fproject(p,_hom,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 2476 hi[1]|=qr_img_get_bit(_img,_width,_height,p[0],p[1])<<k;
RyoheiHagimoto 0:56c5742b9e2b 2477 x+=dx;
RyoheiHagimoto 0:56c5742b9e2b 2478 y+=dy;
RyoheiHagimoto 0:56c5742b9e2b 2479 w+=dw;
RyoheiHagimoto 0:56c5742b9e2b 2480 }
RyoheiHagimoto 0:56c5742b9e2b 2481 /*For the 8th bit we have 3 samples... use the majority value.
RyoheiHagimoto 0:56c5742b9e2b 2482 TODO: The DL bit appears to be wrong as much as right? Guess it's not
RyoheiHagimoto 0:56c5742b9e2b 2483 really a third copy after all, but doesn't appear to be used for data.
RyoheiHagimoto 0:56c5742b9e2b 2484 i=((lo[0]>>7&1)+(lo[1]>>7&1)+(hi[1]>>7&1)>>1)<<7;
RyoheiHagimoto 0:56c5742b9e2b 2485 lo[0]=lo[0]&~0x80|i;
RyoheiHagimoto 0:56c5742b9e2b 2486 lo[1]=lo[1]&~0x80|i;
RyoheiHagimoto 0:56c5742b9e2b 2487 hi[1]&=~0x80;*/
RyoheiHagimoto 0:56c5742b9e2b 2488 /*For the remaining bits we have two samples... try them in all
RyoheiHagimoto 0:56c5742b9e2b 2489 combinations and pick the most popular valid code, breaking ties using
RyoheiHagimoto 0:56c5742b9e2b 2490 the number of bit errors.*/
RyoheiHagimoto 0:56c5742b9e2b 2491 imax=2<<(hi[0]!=hi[1]);
RyoheiHagimoto 0:56c5742b9e2b 2492 di=1+(lo[0]==lo[1]);
RyoheiHagimoto 0:56c5742b9e2b 2493 nfmt_info=0;
RyoheiHagimoto 0:56c5742b9e2b 2494 for(i=0;i<imax;i+=di){
RyoheiHagimoto 0:56c5742b9e2b 2495 unsigned v;
RyoheiHagimoto 0:56c5742b9e2b 2496 int ret;
RyoheiHagimoto 0:56c5742b9e2b 2497 int j;
RyoheiHagimoto 0:56c5742b9e2b 2498 v=(lo[i&1]|hi[i>>1])^0x5412;
RyoheiHagimoto 0:56c5742b9e2b 2499 ret=bch15_5_correct(&v);
RyoheiHagimoto 0:56c5742b9e2b 2500 v>>=10;
RyoheiHagimoto 0:56c5742b9e2b 2501 if(ret<0)ret=4;
RyoheiHagimoto 0:56c5742b9e2b 2502 for(j=0;;j++){
RyoheiHagimoto 0:56c5742b9e2b 2503 if(j>=nfmt_info){
RyoheiHagimoto 0:56c5742b9e2b 2504 fmt_info[j]=v;
RyoheiHagimoto 0:56c5742b9e2b 2505 count[j]=1;
RyoheiHagimoto 0:56c5742b9e2b 2506 nerrs[j]=ret;
RyoheiHagimoto 0:56c5742b9e2b 2507 nfmt_info++;
RyoheiHagimoto 0:56c5742b9e2b 2508 break;
RyoheiHagimoto 0:56c5742b9e2b 2509 }
RyoheiHagimoto 0:56c5742b9e2b 2510 if(fmt_info[j]==(int)v){
RyoheiHagimoto 0:56c5742b9e2b 2511 count[j]++;
RyoheiHagimoto 0:56c5742b9e2b 2512 if(ret<nerrs[j])nerrs[j]=ret;
RyoheiHagimoto 0:56c5742b9e2b 2513 break;
RyoheiHagimoto 0:56c5742b9e2b 2514 }
RyoheiHagimoto 0:56c5742b9e2b 2515 }
RyoheiHagimoto 0:56c5742b9e2b 2516 }
RyoheiHagimoto 0:56c5742b9e2b 2517 besti=0;
RyoheiHagimoto 0:56c5742b9e2b 2518 for(i=1;i<nfmt_info;i++){
RyoheiHagimoto 0:56c5742b9e2b 2519 if(nerrs[besti]>3&&nerrs[i]<=3||
RyoheiHagimoto 0:56c5742b9e2b 2520 count[i]>count[besti]||count[i]==count[besti]&&nerrs[i]<nerrs[besti]){
RyoheiHagimoto 0:56c5742b9e2b 2521 besti=i;
RyoheiHagimoto 0:56c5742b9e2b 2522 }
RyoheiHagimoto 0:56c5742b9e2b 2523 }
RyoheiHagimoto 0:56c5742b9e2b 2524 return nerrs[besti]<4?fmt_info[besti]:-1;
RyoheiHagimoto 0:56c5742b9e2b 2525 }
RyoheiHagimoto 0:56c5742b9e2b 2526
RyoheiHagimoto 0:56c5742b9e2b 2527
RyoheiHagimoto 0:56c5742b9e2b 2528
RyoheiHagimoto 0:56c5742b9e2b 2529 /*The grid used to sample the image bits.
RyoheiHagimoto 0:56c5742b9e2b 2530 The grid is divided into separate cells bounded by finder patterns and/or
RyoheiHagimoto 0:56c5742b9e2b 2531 alignment patterns, and a separate map back to the original image is
RyoheiHagimoto 0:56c5742b9e2b 2532 constructed for each cell.
RyoheiHagimoto 0:56c5742b9e2b 2533 All of these structural elements, as well as the timing patterns, version
RyoheiHagimoto 0:56c5742b9e2b 2534 info, and format info, are marked in fpmask so they can easily be skipped
RyoheiHagimoto 0:56c5742b9e2b 2535 during decode.*/
RyoheiHagimoto 0:56c5742b9e2b 2536 struct qr_sampling_grid{
RyoheiHagimoto 0:56c5742b9e2b 2537 qr_hom_cell *cells[6];
RyoheiHagimoto 0:56c5742b9e2b 2538 unsigned *fpmask;
RyoheiHagimoto 0:56c5742b9e2b 2539 int cell_limits[6];
RyoheiHagimoto 0:56c5742b9e2b 2540 int ncells;
RyoheiHagimoto 0:56c5742b9e2b 2541 };
RyoheiHagimoto 0:56c5742b9e2b 2542
RyoheiHagimoto 0:56c5742b9e2b 2543
RyoheiHagimoto 0:56c5742b9e2b 2544 /*Mark a given region as belonging to the function pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 2545 static void qr_sampling_grid_fp_mask_rect(qr_sampling_grid *_grid,int _dim,
RyoheiHagimoto 0:56c5742b9e2b 2546 int _u,int _v,int _w,int _h){
RyoheiHagimoto 0:56c5742b9e2b 2547 int i;
RyoheiHagimoto 0:56c5742b9e2b 2548 int j;
RyoheiHagimoto 0:56c5742b9e2b 2549 int stride;
RyoheiHagimoto 0:56c5742b9e2b 2550 stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
RyoheiHagimoto 0:56c5742b9e2b 2551 /*Note that we store bits column-wise, since that's how they're read out of
RyoheiHagimoto 0:56c5742b9e2b 2552 the grid.*/
RyoheiHagimoto 0:56c5742b9e2b 2553 for(j=_u;j<_u+_w;j++)for(i=_v;i<_v+_h;i++){
RyoheiHagimoto 0:56c5742b9e2b 2554 _grid->fpmask[j*stride+(i>>QR_INT_LOGBITS)]|=1<<(i&QR_INT_BITS-1);
RyoheiHagimoto 0:56c5742b9e2b 2555 }
RyoheiHagimoto 0:56c5742b9e2b 2556 }
RyoheiHagimoto 0:56c5742b9e2b 2557
RyoheiHagimoto 0:56c5742b9e2b 2558 /*Determine if a given grid location is inside the function pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 2559 static int qr_sampling_grid_is_in_fp(const qr_sampling_grid *_grid,int _dim,
RyoheiHagimoto 0:56c5742b9e2b 2560 int _u,int _v){
RyoheiHagimoto 0:56c5742b9e2b 2561 return _grid->fpmask[_u*(_dim+QR_INT_BITS-1>>QR_INT_LOGBITS)
RyoheiHagimoto 0:56c5742b9e2b 2562 +(_v>>QR_INT_LOGBITS)]>>(_v&QR_INT_BITS-1)&1;
RyoheiHagimoto 0:56c5742b9e2b 2563 }
RyoheiHagimoto 0:56c5742b9e2b 2564
RyoheiHagimoto 0:56c5742b9e2b 2565 /*The spacing between alignment patterns after the second for versions >= 7.
RyoheiHagimoto 0:56c5742b9e2b 2566 We could compact this more, but the code to access it would eliminate the
RyoheiHagimoto 0:56c5742b9e2b 2567 gains.*/
RyoheiHagimoto 0:56c5742b9e2b 2568 static const unsigned char QR_ALIGNMENT_SPACING[34]={
RyoheiHagimoto 0:56c5742b9e2b 2569 16,18,20,22,24,26,28,
RyoheiHagimoto 0:56c5742b9e2b 2570 20,22,24,24,26,28,28,
RyoheiHagimoto 0:56c5742b9e2b 2571 22,24,24,26,26,28,28,
RyoheiHagimoto 0:56c5742b9e2b 2572 24,24,26,26,26,28,28,
RyoheiHagimoto 0:56c5742b9e2b 2573 24,26,26,26,28,28
RyoheiHagimoto 0:56c5742b9e2b 2574 };
RyoheiHagimoto 0:56c5742b9e2b 2575
RyoheiHagimoto 0:56c5742b9e2b 2576 static inline void qr_svg_points(const char *cls,
RyoheiHagimoto 0:56c5742b9e2b 2577 qr_point *p,
RyoheiHagimoto 0:56c5742b9e2b 2578 int n)
RyoheiHagimoto 0:56c5742b9e2b 2579 {
RyoheiHagimoto 0:56c5742b9e2b 2580 svg_path_start(cls, 1, 0, 0);
RyoheiHagimoto 0:56c5742b9e2b 2581 int i;
RyoheiHagimoto 0:56c5742b9e2b 2582 for(i = 0; i < n; i++, p++)
RyoheiHagimoto 0:56c5742b9e2b 2583 svg_path_moveto(SVG_ABS, p[0][0], p[0][1]);
RyoheiHagimoto 0:56c5742b9e2b 2584 svg_path_end();
RyoheiHagimoto 0:56c5742b9e2b 2585 }
RyoheiHagimoto 0:56c5742b9e2b 2586
RyoheiHagimoto 0:56c5742b9e2b 2587 /*Initialize the sampling grid for each region of the code.
RyoheiHagimoto 0:56c5742b9e2b 2588 _version: The (decoded) version number.
RyoheiHagimoto 0:56c5742b9e2b 2589 _ul_pos: The location of the UL finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 2590 _ur_pos: The location of the UR finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 2591 _dl_pos: The location of the DL finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 2592 _p: On input, contains estimated positions of the four corner modules.
RyoheiHagimoto 0:56c5742b9e2b 2593 On output, contains a bounding quadrilateral for the code.
RyoheiHagimoto 0:56c5742b9e2b 2594 _img: The binary input image.
RyoheiHagimoto 0:56c5742b9e2b 2595 _width: The width of the input image.
RyoheiHagimoto 0:56c5742b9e2b 2596 _height: The height of the input image.
RyoheiHagimoto 0:56c5742b9e2b 2597 Return: 0 on success, or a negative value on error.*/
RyoheiHagimoto 0:56c5742b9e2b 2598 static void qr_sampling_grid_init(qr_sampling_grid *_grid,int _version,
RyoheiHagimoto 0:56c5742b9e2b 2599 const qr_point _ul_pos,const qr_point _ur_pos,const qr_point _dl_pos,
RyoheiHagimoto 0:56c5742b9e2b 2600 qr_point _p[4],const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 2601 qr_hom_cell base_cell;
RyoheiHagimoto 0:56c5742b9e2b 2602 int align_pos[7];
RyoheiHagimoto 0:56c5742b9e2b 2603 int dim;
RyoheiHagimoto 0:56c5742b9e2b 2604 int nalign;
RyoheiHagimoto 0:56c5742b9e2b 2605 int i;
RyoheiHagimoto 0:56c5742b9e2b 2606 dim=17+(_version<<2);
RyoheiHagimoto 0:56c5742b9e2b 2607 nalign=(_version/7)+2;
RyoheiHagimoto 0:56c5742b9e2b 2608 /*Create a base cell to bootstrap the alignment pattern search.*/
RyoheiHagimoto 0:56c5742b9e2b 2609 qr_hom_cell_init(&base_cell,0,0,dim-1,0,0,dim-1,dim-1,dim-1,
RyoheiHagimoto 0:56c5742b9e2b 2610 _p[0][0],_p[0][1],_p[1][0],_p[1][1],_p[2][0],_p[2][1],_p[3][0],_p[3][1]);
RyoheiHagimoto 0:56c5742b9e2b 2611 /*Allocate the array of cells.*/
RyoheiHagimoto 0:56c5742b9e2b 2612 _grid->ncells=nalign-1;
RyoheiHagimoto 0:56c5742b9e2b 2613 _grid->cells[0]=(qr_hom_cell *)malloc(
RyoheiHagimoto 0:56c5742b9e2b 2614 (nalign-1)*(nalign-1)*sizeof(*_grid->cells[0]));
RyoheiHagimoto 0:56c5742b9e2b 2615 for(i=1;i<_grid->ncells;i++)_grid->cells[i]=_grid->cells[i-1]+_grid->ncells;
RyoheiHagimoto 0:56c5742b9e2b 2616 /*Initialize the function pattern mask.*/
RyoheiHagimoto 0:56c5742b9e2b 2617 _grid->fpmask=(unsigned *)calloc(dim,
RyoheiHagimoto 0:56c5742b9e2b 2618 (dim+QR_INT_BITS-1>>QR_INT_LOGBITS)*sizeof(*_grid->fpmask));
RyoheiHagimoto 0:56c5742b9e2b 2619 /*Mask out the finder patterns (and separators and format info bits).*/
RyoheiHagimoto 0:56c5742b9e2b 2620 qr_sampling_grid_fp_mask_rect(_grid,dim,0,0,9,9);
RyoheiHagimoto 0:56c5742b9e2b 2621 qr_sampling_grid_fp_mask_rect(_grid,dim,0,dim-8,9,8);
RyoheiHagimoto 0:56c5742b9e2b 2622 qr_sampling_grid_fp_mask_rect(_grid,dim,dim-8,0,8,9);
RyoheiHagimoto 0:56c5742b9e2b 2623 /*Mask out the version number bits.*/
RyoheiHagimoto 0:56c5742b9e2b 2624 if(_version>6){
RyoheiHagimoto 0:56c5742b9e2b 2625 qr_sampling_grid_fp_mask_rect(_grid,dim,0,dim-11,6,3);
RyoheiHagimoto 0:56c5742b9e2b 2626 qr_sampling_grid_fp_mask_rect(_grid,dim,dim-11,0,3,6);
RyoheiHagimoto 0:56c5742b9e2b 2627 }
RyoheiHagimoto 0:56c5742b9e2b 2628 /*Mask out the timing patterns.*/
RyoheiHagimoto 0:56c5742b9e2b 2629 qr_sampling_grid_fp_mask_rect(_grid,dim,9,6,dim-17,1);
RyoheiHagimoto 0:56c5742b9e2b 2630 qr_sampling_grid_fp_mask_rect(_grid,dim,6,9,1,dim-17);
RyoheiHagimoto 0:56c5742b9e2b 2631 /*If we have no alignment patterns (e.g., this is a version 1 code), just use
RyoheiHagimoto 0:56c5742b9e2b 2632 the base cell and hope it's good enough.*/
RyoheiHagimoto 0:56c5742b9e2b 2633 if(_version<2)memcpy(_grid->cells[0],&base_cell,sizeof(base_cell));
RyoheiHagimoto 0:56c5742b9e2b 2634 else{
RyoheiHagimoto 0:56c5742b9e2b 2635 qr_point *q;
RyoheiHagimoto 0:56c5742b9e2b 2636 qr_point *p;
RyoheiHagimoto 0:56c5742b9e2b 2637 int j;
RyoheiHagimoto 0:56c5742b9e2b 2638 int k;
RyoheiHagimoto 0:56c5742b9e2b 2639 q=(qr_point *)malloc(nalign*nalign*sizeof(*q));
RyoheiHagimoto 0:56c5742b9e2b 2640 p=(qr_point *)malloc(nalign*nalign*sizeof(*p));
RyoheiHagimoto 0:56c5742b9e2b 2641 /*Initialize the alignment pattern position list.*/
RyoheiHagimoto 0:56c5742b9e2b 2642 align_pos[0]=6;
RyoheiHagimoto 0:56c5742b9e2b 2643 align_pos[nalign-1]=dim-7;
RyoheiHagimoto 0:56c5742b9e2b 2644 if(_version>6){
RyoheiHagimoto 0:56c5742b9e2b 2645 int d;
RyoheiHagimoto 0:56c5742b9e2b 2646 d=QR_ALIGNMENT_SPACING[_version-7];
RyoheiHagimoto 0:56c5742b9e2b 2647 for(i=nalign-1;i-->1;)align_pos[i]=align_pos[i+1]-d;
RyoheiHagimoto 0:56c5742b9e2b 2648 }
RyoheiHagimoto 0:56c5742b9e2b 2649 /*Three of the corners use a finder pattern instead of a separate
RyoheiHagimoto 0:56c5742b9e2b 2650 alignment pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 2651 q[0][0]=3;
RyoheiHagimoto 0:56c5742b9e2b 2652 q[0][1]=3;
RyoheiHagimoto 0:56c5742b9e2b 2653 p[0][0]=_ul_pos[0];
RyoheiHagimoto 0:56c5742b9e2b 2654 p[0][1]=_ul_pos[1];
RyoheiHagimoto 0:56c5742b9e2b 2655 q[nalign-1][0]=dim-4;
RyoheiHagimoto 0:56c5742b9e2b 2656 q[nalign-1][1]=3;
RyoheiHagimoto 0:56c5742b9e2b 2657 p[nalign-1][0]=_ur_pos[0];
RyoheiHagimoto 0:56c5742b9e2b 2658 p[nalign-1][1]=_ur_pos[1];
RyoheiHagimoto 0:56c5742b9e2b 2659 q[(nalign-1)*nalign][0]=3;
RyoheiHagimoto 0:56c5742b9e2b 2660 q[(nalign-1)*nalign][1]=dim-4;
RyoheiHagimoto 0:56c5742b9e2b 2661 p[(nalign-1)*nalign][0]=_dl_pos[0];
RyoheiHagimoto 0:56c5742b9e2b 2662 p[(nalign-1)*nalign][1]=_dl_pos[1];
RyoheiHagimoto 0:56c5742b9e2b 2663 /*Scan for alignment patterns using a diagonal sweep.*/
RyoheiHagimoto 0:56c5742b9e2b 2664 for(k=1;k<2*nalign-1;k++){
RyoheiHagimoto 0:56c5742b9e2b 2665 int jmin;
RyoheiHagimoto 0:56c5742b9e2b 2666 int jmax;
RyoheiHagimoto 0:56c5742b9e2b 2667 jmax=QR_MINI(k,nalign-1)-(k==nalign-1);
RyoheiHagimoto 0:56c5742b9e2b 2668 jmin=QR_MAXI(0,k-(nalign-1))+(k==nalign-1);
RyoheiHagimoto 0:56c5742b9e2b 2669 for(j=jmin;j<=jmax;j++){
RyoheiHagimoto 0:56c5742b9e2b 2670 qr_hom_cell *cell;
RyoheiHagimoto 0:56c5742b9e2b 2671 int u;
RyoheiHagimoto 0:56c5742b9e2b 2672 int v;
RyoheiHagimoto 0:56c5742b9e2b 2673 int k;
RyoheiHagimoto 0:56c5742b9e2b 2674 i=jmax-(j-jmin);
RyoheiHagimoto 0:56c5742b9e2b 2675 k=i*nalign+j;
RyoheiHagimoto 0:56c5742b9e2b 2676 u=align_pos[j];
RyoheiHagimoto 0:56c5742b9e2b 2677 v=align_pos[i];
RyoheiHagimoto 0:56c5742b9e2b 2678 q[k][0]=u;
RyoheiHagimoto 0:56c5742b9e2b 2679 q[k][1]=v;
RyoheiHagimoto 0:56c5742b9e2b 2680 /*Mask out the alignment pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 2681 qr_sampling_grid_fp_mask_rect(_grid,dim,u-2,v-2,5,5);
RyoheiHagimoto 0:56c5742b9e2b 2682 /*Pick a cell to use to govern the alignment pattern search.*/
RyoheiHagimoto 0:56c5742b9e2b 2683 if(i>1&&j>1){
RyoheiHagimoto 0:56c5742b9e2b 2684 qr_point p0;
RyoheiHagimoto 0:56c5742b9e2b 2685 qr_point p1;
RyoheiHagimoto 0:56c5742b9e2b 2686 qr_point p2;
RyoheiHagimoto 0:56c5742b9e2b 2687 /*Each predictor is basically a straight-line extrapolation from two
RyoheiHagimoto 0:56c5742b9e2b 2688 neighboring alignment patterns (except possibly near the opposing
RyoheiHagimoto 0:56c5742b9e2b 2689 finder patterns).*/
RyoheiHagimoto 0:56c5742b9e2b 2690 qr_hom_cell_project(p0,_grid->cells[i-2]+j-1,u,v,0);
RyoheiHagimoto 0:56c5742b9e2b 2691 qr_hom_cell_project(p1,_grid->cells[i-2]+j-2,u,v,0);
RyoheiHagimoto 0:56c5742b9e2b 2692 qr_hom_cell_project(p2,_grid->cells[i-1]+j-2,u,v,0);
RyoheiHagimoto 0:56c5742b9e2b 2693 /*Take the median of the predictions as the search center.*/
RyoheiHagimoto 0:56c5742b9e2b 2694 QR_SORT2I(p0[0],p1[0]);
RyoheiHagimoto 0:56c5742b9e2b 2695 QR_SORT2I(p0[1],p1[1]);
RyoheiHagimoto 0:56c5742b9e2b 2696 QR_SORT2I(p1[0],p2[0]);
RyoheiHagimoto 0:56c5742b9e2b 2697 QR_SORT2I(p1[1],p2[1]);
RyoheiHagimoto 0:56c5742b9e2b 2698 QR_SORT2I(p0[0],p1[0]);
RyoheiHagimoto 0:56c5742b9e2b 2699 QR_SORT2I(p0[1],p1[1]);
RyoheiHagimoto 0:56c5742b9e2b 2700 /*We need a cell that has the target point at a known (u,v) location.
RyoheiHagimoto 0:56c5742b9e2b 2701 Since our cells don't have inverses, just construct one from our
RyoheiHagimoto 0:56c5742b9e2b 2702 neighboring points.*/
RyoheiHagimoto 0:56c5742b9e2b 2703 cell=_grid->cells[i-1]+j-1;
RyoheiHagimoto 0:56c5742b9e2b 2704 qr_hom_cell_init(cell,
RyoheiHagimoto 0:56c5742b9e2b 2705 q[k-nalign-1][0],q[k-nalign-1][1],q[k-nalign][0],q[k-nalign][1],
RyoheiHagimoto 0:56c5742b9e2b 2706 q[k-1][0],q[k-1][1],q[k][0],q[k][1],
RyoheiHagimoto 0:56c5742b9e2b 2707 p[k-nalign-1][0],p[k-nalign-1][1],p[k-nalign][0],p[k-nalign][1],
RyoheiHagimoto 0:56c5742b9e2b 2708 p[k-1][0],p[k-1][1],p1[0],p1[1]);
RyoheiHagimoto 0:56c5742b9e2b 2709 }
RyoheiHagimoto 0:56c5742b9e2b 2710 else if(i>1&&j>0)cell=_grid->cells[i-2]+j-1;
RyoheiHagimoto 0:56c5742b9e2b 2711 else if(i>0&&j>1)cell=_grid->cells[i-1]+j-2;
RyoheiHagimoto 0:56c5742b9e2b 2712 else cell=&base_cell;
RyoheiHagimoto 0:56c5742b9e2b 2713 /*Use a very small search radius.
RyoheiHagimoto 0:56c5742b9e2b 2714 A large displacement here usually means a false positive (e.g., when
RyoheiHagimoto 0:56c5742b9e2b 2715 the real alignment pattern is damaged or missing), which can
RyoheiHagimoto 0:56c5742b9e2b 2716 severely distort the projection.*/
RyoheiHagimoto 0:56c5742b9e2b 2717 qr_alignment_pattern_search(p[k],cell,u,v,2,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 2718 if(i>0&&j>0){
RyoheiHagimoto 0:56c5742b9e2b 2719 qr_hom_cell_init(_grid->cells[i-1]+j-1,
RyoheiHagimoto 0:56c5742b9e2b 2720 q[k-nalign-1][0],q[k-nalign-1][1],q[k-nalign][0],q[k-nalign][1],
RyoheiHagimoto 0:56c5742b9e2b 2721 q[k-1][0],q[k-1][1],q[k][0],q[k][1],
RyoheiHagimoto 0:56c5742b9e2b 2722 p[k-nalign-1][0],p[k-nalign-1][1],p[k-nalign][0],p[k-nalign][1],
RyoheiHagimoto 0:56c5742b9e2b 2723 p[k-1][0],p[k-1][1],p[k][0],p[k][1]);
RyoheiHagimoto 0:56c5742b9e2b 2724 }
RyoheiHagimoto 0:56c5742b9e2b 2725 }
RyoheiHagimoto 0:56c5742b9e2b 2726 }
RyoheiHagimoto 0:56c5742b9e2b 2727 qr_svg_points("align", p, nalign * nalign);
RyoheiHagimoto 0:56c5742b9e2b 2728 free(q);
RyoheiHagimoto 0:56c5742b9e2b 2729 free(p);
RyoheiHagimoto 0:56c5742b9e2b 2730 }
RyoheiHagimoto 0:56c5742b9e2b 2731 /*Set the limits over which each cell is used.*/
RyoheiHagimoto 0:56c5742b9e2b 2732 memcpy(_grid->cell_limits,align_pos+1,
RyoheiHagimoto 0:56c5742b9e2b 2733 (_grid->ncells-1)*sizeof(*_grid->cell_limits));
RyoheiHagimoto 0:56c5742b9e2b 2734 _grid->cell_limits[_grid->ncells-1]=dim;
RyoheiHagimoto 0:56c5742b9e2b 2735 /*Produce a bounding square for the code (to mark finder centers with).
RyoheiHagimoto 0:56c5742b9e2b 2736 Because of non-linear distortion, this might not actually bound the code,
RyoheiHagimoto 0:56c5742b9e2b 2737 but it should be good enough.
RyoheiHagimoto 0:56c5742b9e2b 2738 I don't think it's worth computing a convex hull or anything silly like
RyoheiHagimoto 0:56c5742b9e2b 2739 that.*/
RyoheiHagimoto 0:56c5742b9e2b 2740 qr_hom_cell_project(_p[0],_grid->cells[0]+0,-1,-1,1);
RyoheiHagimoto 0:56c5742b9e2b 2741 qr_hom_cell_project(_p[1],_grid->cells[0]+_grid->ncells-1,(dim<<1)-1,-1,1);
RyoheiHagimoto 0:56c5742b9e2b 2742 qr_hom_cell_project(_p[2],_grid->cells[_grid->ncells-1]+0,-1,(dim<<1)-1,1);
RyoheiHagimoto 0:56c5742b9e2b 2743 qr_hom_cell_project(_p[3],_grid->cells[_grid->ncells-1]+_grid->ncells-1,
RyoheiHagimoto 0:56c5742b9e2b 2744 (dim<<1)-1,(dim<<1)-1,1);
RyoheiHagimoto 0:56c5742b9e2b 2745 /*Clamp the points somewhere near the image (this is really just in case a
RyoheiHagimoto 0:56c5742b9e2b 2746 corner is near the plane at infinity).*/
RyoheiHagimoto 0:56c5742b9e2b 2747 for(i=0;i<4;i++){
RyoheiHagimoto 0:56c5742b9e2b 2748 _p[i][0]=QR_CLAMPI(-_width<<QR_FINDER_SUBPREC,_p[i][0],
RyoheiHagimoto 0:56c5742b9e2b 2749 _width<<QR_FINDER_SUBPREC+1);
RyoheiHagimoto 0:56c5742b9e2b 2750 _p[i][1]=QR_CLAMPI(-_height<<QR_FINDER_SUBPREC,_p[i][1],
RyoheiHagimoto 0:56c5742b9e2b 2751 _height<<QR_FINDER_SUBPREC+1);
RyoheiHagimoto 0:56c5742b9e2b 2752 }
RyoheiHagimoto 0:56c5742b9e2b 2753 /*TODO: Make fine adjustments using the timing patterns.
RyoheiHagimoto 0:56c5742b9e2b 2754 Possible strategy: scan the timing pattern at QR_ALIGN_SUBPREC (or finer)
RyoheiHagimoto 0:56c5742b9e2b 2755 resolution, use dynamic programming to match midpoints between
RyoheiHagimoto 0:56c5742b9e2b 2756 transitions to the ideal grid locations.*/
RyoheiHagimoto 0:56c5742b9e2b 2757 }
RyoheiHagimoto 0:56c5742b9e2b 2758
RyoheiHagimoto 0:56c5742b9e2b 2759 static void qr_sampling_grid_clear(qr_sampling_grid *_grid){
RyoheiHagimoto 0:56c5742b9e2b 2760 free(_grid->fpmask);
RyoheiHagimoto 0:56c5742b9e2b 2761 free(_grid->cells[0]);
RyoheiHagimoto 0:56c5742b9e2b 2762 }
RyoheiHagimoto 0:56c5742b9e2b 2763
RyoheiHagimoto 0:56c5742b9e2b 2764
RyoheiHagimoto 0:56c5742b9e2b 2765
RyoheiHagimoto 0:56c5742b9e2b 2766 #if defined(QR_DEBUG)
RyoheiHagimoto 0:56c5742b9e2b 2767 static void qr_sampling_grid_dump(qr_sampling_grid *_grid,int _version,
RyoheiHagimoto 0:56c5742b9e2b 2768 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 2769 unsigned char *gimg;
RyoheiHagimoto 0:56c5742b9e2b 2770 FILE *fout;
RyoheiHagimoto 0:56c5742b9e2b 2771 int dim;
RyoheiHagimoto 0:56c5742b9e2b 2772 int u;
RyoheiHagimoto 0:56c5742b9e2b 2773 int v;
RyoheiHagimoto 0:56c5742b9e2b 2774 int x;
RyoheiHagimoto 0:56c5742b9e2b 2775 int y;
RyoheiHagimoto 0:56c5742b9e2b 2776 int w;
RyoheiHagimoto 0:56c5742b9e2b 2777 int i;
RyoheiHagimoto 0:56c5742b9e2b 2778 int j;
RyoheiHagimoto 0:56c5742b9e2b 2779 int r;
RyoheiHagimoto 0:56c5742b9e2b 2780 int s;
RyoheiHagimoto 0:56c5742b9e2b 2781 dim=17+(_version<<2)+8<<QR_ALIGN_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2782 gimg=(unsigned char *)malloc(dim*dim*sizeof(*gimg));
RyoheiHagimoto 0:56c5742b9e2b 2783 for(i=0;i<dim;i++)for(j=0;j<dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2784 qr_hom_cell *cell;
RyoheiHagimoto 0:56c5742b9e2b 2785 if(i>=(4<<QR_ALIGN_SUBPREC)&&i<=dim-(5<<QR_ALIGN_SUBPREC)&&
RyoheiHagimoto 0:56c5742b9e2b 2786 j>=(4<<QR_ALIGN_SUBPREC)&&j<=dim-(5<<QR_ALIGN_SUBPREC)&&
RyoheiHagimoto 0:56c5742b9e2b 2787 ((!(i&(1<<QR_ALIGN_SUBPREC)-1))^(!(j&(1<<QR_ALIGN_SUBPREC)-1)))){
RyoheiHagimoto 0:56c5742b9e2b 2788 gimg[i*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2789 }
RyoheiHagimoto 0:56c5742b9e2b 2790 else{
RyoheiHagimoto 0:56c5742b9e2b 2791 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 2792 u=(j>>QR_ALIGN_SUBPREC)-4;
RyoheiHagimoto 0:56c5742b9e2b 2793 v=(i>>QR_ALIGN_SUBPREC)-4;
RyoheiHagimoto 0:56c5742b9e2b 2794 for(r=0;r<_grid->ncells-1;r++)if(u<_grid->cell_limits[r])break;
RyoheiHagimoto 0:56c5742b9e2b 2795 for(s=0;s<_grid->ncells-1;s++)if(v<_grid->cell_limits[s])break;
RyoheiHagimoto 0:56c5742b9e2b 2796 cell=_grid->cells[s]+r;
RyoheiHagimoto 0:56c5742b9e2b 2797 u=j-(cell->u0+4<<QR_ALIGN_SUBPREC);
RyoheiHagimoto 0:56c5742b9e2b 2798 v=i-(cell->v0+4<<QR_ALIGN_SUBPREC);
RyoheiHagimoto 0:56c5742b9e2b 2799 x=cell->fwd[0][0]*u+cell->fwd[0][1]*v+(cell->fwd[0][2]<<QR_ALIGN_SUBPREC);
RyoheiHagimoto 0:56c5742b9e2b 2800 y=cell->fwd[1][0]*u+cell->fwd[1][1]*v+(cell->fwd[1][2]<<QR_ALIGN_SUBPREC);
RyoheiHagimoto 0:56c5742b9e2b 2801 w=cell->fwd[2][0]*u+cell->fwd[2][1]*v+(cell->fwd[2][2]<<QR_ALIGN_SUBPREC);
RyoheiHagimoto 0:56c5742b9e2b 2802 qr_hom_cell_fproject(p,cell,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 2803 gimg[i*dim+j]=_img[
RyoheiHagimoto 0:56c5742b9e2b 2804 QR_CLAMPI(0,p[1]>>QR_FINDER_SUBPREC,_height-1)*_width+
RyoheiHagimoto 0:56c5742b9e2b 2805 QR_CLAMPI(0,p[0]>>QR_FINDER_SUBPREC,_width-1)];
RyoheiHagimoto 0:56c5742b9e2b 2806 }
RyoheiHagimoto 0:56c5742b9e2b 2807 }
RyoheiHagimoto 0:56c5742b9e2b 2808 for(v=0;v<17+(_version<<2);v++)for(u=0;u<17+(_version<<2);u++){
RyoheiHagimoto 0:56c5742b9e2b 2809 if(qr_sampling_grid_is_in_fp(_grid,17+(_version<<2),u,v)){
RyoheiHagimoto 0:56c5742b9e2b 2810 j=u+4<<QR_ALIGN_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2811 i=v+4<<QR_ALIGN_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 2812 gimg[(i-1)*dim+j-1]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2813 gimg[(i-1)*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2814 gimg[(i-1)*dim+j+1]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2815 gimg[i*dim+j-1]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2816 gimg[i*dim+j+1]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2817 gimg[(i+1)*dim+j-1]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2818 gimg[(i+1)*dim+j]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2819 gimg[(i+1)*dim+j+1]=0x7F;
RyoheiHagimoto 0:56c5742b9e2b 2820 }
RyoheiHagimoto 0:56c5742b9e2b 2821 }
RyoheiHagimoto 0:56c5742b9e2b 2822 fout=fopen("grid.png","wb");
RyoheiHagimoto 0:56c5742b9e2b 2823 image_write_png(gimg,dim,dim,fout);
RyoheiHagimoto 0:56c5742b9e2b 2824 fclose(fout);
RyoheiHagimoto 0:56c5742b9e2b 2825 free(gimg);
RyoheiHagimoto 0:56c5742b9e2b 2826 }
RyoheiHagimoto 0:56c5742b9e2b 2827 #endif
RyoheiHagimoto 0:56c5742b9e2b 2828
RyoheiHagimoto 0:56c5742b9e2b 2829 /*Generate the data mask corresponding to the given mask pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 2830 static void qr_data_mask_fill(unsigned *_mask,int _dim,int _pattern){
RyoheiHagimoto 0:56c5742b9e2b 2831 int stride;
RyoheiHagimoto 0:56c5742b9e2b 2832 int i;
RyoheiHagimoto 0:56c5742b9e2b 2833 int j;
RyoheiHagimoto 0:56c5742b9e2b 2834 stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
RyoheiHagimoto 0:56c5742b9e2b 2835 /*Note that we store bits column-wise, since that's how they're read out of
RyoheiHagimoto 0:56c5742b9e2b 2836 the grid.*/
RyoheiHagimoto 0:56c5742b9e2b 2837 switch(_pattern){
RyoheiHagimoto 0:56c5742b9e2b 2838 /*10101010 i+j+1&1
RyoheiHagimoto 0:56c5742b9e2b 2839 01010101
RyoheiHagimoto 0:56c5742b9e2b 2840 10101010
RyoheiHagimoto 0:56c5742b9e2b 2841 01010101*/
RyoheiHagimoto 0:56c5742b9e2b 2842 case 0:{
RyoheiHagimoto 0:56c5742b9e2b 2843 int m;
RyoheiHagimoto 0:56c5742b9e2b 2844 m=0x55;
RyoheiHagimoto 0:56c5742b9e2b 2845 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2846 memset(_mask+j*stride,m,stride*sizeof(*_mask));
RyoheiHagimoto 0:56c5742b9e2b 2847 m^=0xFF;
RyoheiHagimoto 0:56c5742b9e2b 2848 }
RyoheiHagimoto 0:56c5742b9e2b 2849 }break;
RyoheiHagimoto 0:56c5742b9e2b 2850 /*11111111 i+1&1
RyoheiHagimoto 0:56c5742b9e2b 2851 00000000
RyoheiHagimoto 0:56c5742b9e2b 2852 11111111
RyoheiHagimoto 0:56c5742b9e2b 2853 00000000*/
RyoheiHagimoto 0:56c5742b9e2b 2854 case 1:memset(_mask,0x55,_dim*stride*sizeof(*_mask));break;
RyoheiHagimoto 0:56c5742b9e2b 2855 /*10010010 (j+1)%3&1
RyoheiHagimoto 0:56c5742b9e2b 2856 10010010
RyoheiHagimoto 0:56c5742b9e2b 2857 10010010
RyoheiHagimoto 0:56c5742b9e2b 2858 10010010*/
RyoheiHagimoto 0:56c5742b9e2b 2859 case 2:{
RyoheiHagimoto 0:56c5742b9e2b 2860 unsigned m;
RyoheiHagimoto 0:56c5742b9e2b 2861 m=0xFF;
RyoheiHagimoto 0:56c5742b9e2b 2862 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2863 memset(_mask+j*stride,m&0xFF,stride*sizeof(*_mask));
RyoheiHagimoto 0:56c5742b9e2b 2864 m=m<<8|m>>16;
RyoheiHagimoto 0:56c5742b9e2b 2865 }
RyoheiHagimoto 0:56c5742b9e2b 2866 }break;
RyoheiHagimoto 0:56c5742b9e2b 2867 /*10010010 (i+j+1)%3&1
RyoheiHagimoto 0:56c5742b9e2b 2868 00100100
RyoheiHagimoto 0:56c5742b9e2b 2869 01001001
RyoheiHagimoto 0:56c5742b9e2b 2870 10010010*/
RyoheiHagimoto 0:56c5742b9e2b 2871 case 3:{
RyoheiHagimoto 0:56c5742b9e2b 2872 unsigned mi;
RyoheiHagimoto 0:56c5742b9e2b 2873 unsigned mj;
RyoheiHagimoto 0:56c5742b9e2b 2874 mj=0;
RyoheiHagimoto 0:56c5742b9e2b 2875 for(i=0;i<(QR_INT_BITS+2)/3;i++)mj|=1<<3*i;
RyoheiHagimoto 0:56c5742b9e2b 2876 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2877 mi=mj;
RyoheiHagimoto 0:56c5742b9e2b 2878 for(i=0;i<stride;i++){
RyoheiHagimoto 0:56c5742b9e2b 2879 _mask[j*stride+i]=mi;
RyoheiHagimoto 0:56c5742b9e2b 2880 mi=mi>>QR_INT_BITS%3|mi<<3-QR_INT_BITS%3;
RyoheiHagimoto 0:56c5742b9e2b 2881 }
RyoheiHagimoto 0:56c5742b9e2b 2882 mj=mj>>1|mj<<2;
RyoheiHagimoto 0:56c5742b9e2b 2883 }
RyoheiHagimoto 0:56c5742b9e2b 2884 }break;
RyoheiHagimoto 0:56c5742b9e2b 2885 /*11100011 (i>>1)+(j/3)+1&1
RyoheiHagimoto 0:56c5742b9e2b 2886 11100011
RyoheiHagimoto 0:56c5742b9e2b 2887 00011100
RyoheiHagimoto 0:56c5742b9e2b 2888 00011100*/
RyoheiHagimoto 0:56c5742b9e2b 2889 case 4:{
RyoheiHagimoto 0:56c5742b9e2b 2890 unsigned m;
RyoheiHagimoto 0:56c5742b9e2b 2891 m=7;
RyoheiHagimoto 0:56c5742b9e2b 2892 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2893 memset(_mask+j*stride,(0xCC^-(m&1))&0xFF,stride*sizeof(*_mask));
RyoheiHagimoto 0:56c5742b9e2b 2894 m=m>>1|m<<5;
RyoheiHagimoto 0:56c5742b9e2b 2895 }
RyoheiHagimoto 0:56c5742b9e2b 2896 }break;
RyoheiHagimoto 0:56c5742b9e2b 2897 /*11111111 !((i*j)%6)
RyoheiHagimoto 0:56c5742b9e2b 2898 10000010
RyoheiHagimoto 0:56c5742b9e2b 2899 10010010
RyoheiHagimoto 0:56c5742b9e2b 2900 10101010*/
RyoheiHagimoto 0:56c5742b9e2b 2901 case 5:{
RyoheiHagimoto 0:56c5742b9e2b 2902 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2903 unsigned m;
RyoheiHagimoto 0:56c5742b9e2b 2904 m=0;
RyoheiHagimoto 0:56c5742b9e2b 2905 for(i=0;i<6;i++)m|=!((i*j)%6)<<i;
RyoheiHagimoto 0:56c5742b9e2b 2906 for(i=6;i<QR_INT_BITS;i<<=1)m|=m<<i;
RyoheiHagimoto 0:56c5742b9e2b 2907 for(i=0;i<stride;i++){
RyoheiHagimoto 0:56c5742b9e2b 2908 _mask[j*stride+i]=m;
RyoheiHagimoto 0:56c5742b9e2b 2909 m=m>>QR_INT_BITS%6|m<<6-QR_INT_BITS%6;
RyoheiHagimoto 0:56c5742b9e2b 2910 }
RyoheiHagimoto 0:56c5742b9e2b 2911 }
RyoheiHagimoto 0:56c5742b9e2b 2912 }break;
RyoheiHagimoto 0:56c5742b9e2b 2913 /*11111111 (i*j)%3+i*j+1&1
RyoheiHagimoto 0:56c5742b9e2b 2914 11100011
RyoheiHagimoto 0:56c5742b9e2b 2915 11011011
RyoheiHagimoto 0:56c5742b9e2b 2916 10101010*/
RyoheiHagimoto 0:56c5742b9e2b 2917 case 6:{
RyoheiHagimoto 0:56c5742b9e2b 2918 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2919 unsigned m;
RyoheiHagimoto 0:56c5742b9e2b 2920 m=0;
RyoheiHagimoto 0:56c5742b9e2b 2921 for(i=0;i<6;i++)m|=((i*j)%3+i*j+1&1)<<i;
RyoheiHagimoto 0:56c5742b9e2b 2922 for(i=6;i<QR_INT_BITS;i<<=1)m|=m<<i;
RyoheiHagimoto 0:56c5742b9e2b 2923 for(i=0;i<stride;i++){
RyoheiHagimoto 0:56c5742b9e2b 2924 _mask[j*stride+i]=m;
RyoheiHagimoto 0:56c5742b9e2b 2925 m=m>>QR_INT_BITS%6|m<<6-QR_INT_BITS%6;
RyoheiHagimoto 0:56c5742b9e2b 2926 }
RyoheiHagimoto 0:56c5742b9e2b 2927 }
RyoheiHagimoto 0:56c5742b9e2b 2928 }break;
RyoheiHagimoto 0:56c5742b9e2b 2929 /*10101010 (i*j)%3+i+j+1&1
RyoheiHagimoto 0:56c5742b9e2b 2930 00011100
RyoheiHagimoto 0:56c5742b9e2b 2931 10001110
RyoheiHagimoto 0:56c5742b9e2b 2932 01010101*/
RyoheiHagimoto 0:56c5742b9e2b 2933 default:{
RyoheiHagimoto 0:56c5742b9e2b 2934 for(j=0;j<_dim;j++){
RyoheiHagimoto 0:56c5742b9e2b 2935 unsigned m;
RyoheiHagimoto 0:56c5742b9e2b 2936 m=0;
RyoheiHagimoto 0:56c5742b9e2b 2937 for(i=0;i<6;i++)m|=((i*j)%3+i+j+1&1)<<i;
RyoheiHagimoto 0:56c5742b9e2b 2938 for(i=6;i<QR_INT_BITS;i<<=1)m|=m<<i;
RyoheiHagimoto 0:56c5742b9e2b 2939 for(i=0;i<stride;i++){
RyoheiHagimoto 0:56c5742b9e2b 2940 _mask[j*stride+i]=m;
RyoheiHagimoto 0:56c5742b9e2b 2941 m=m>>QR_INT_BITS%6|m<<6-QR_INT_BITS%6;
RyoheiHagimoto 0:56c5742b9e2b 2942 }
RyoheiHagimoto 0:56c5742b9e2b 2943 }
RyoheiHagimoto 0:56c5742b9e2b 2944 }break;
RyoheiHagimoto 0:56c5742b9e2b 2945 }
RyoheiHagimoto 0:56c5742b9e2b 2946 }
RyoheiHagimoto 0:56c5742b9e2b 2947
RyoheiHagimoto 0:56c5742b9e2b 2948 static void qr_sampling_grid_sample(const qr_sampling_grid *_grid,
RyoheiHagimoto 0:56c5742b9e2b 2949 unsigned *_data_bits,int _dim,int _fmt_info,
RyoheiHagimoto 0:56c5742b9e2b 2950 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 2951 int stride;
RyoheiHagimoto 0:56c5742b9e2b 2952 int u0;
RyoheiHagimoto 0:56c5742b9e2b 2953 int u1;
RyoheiHagimoto 0:56c5742b9e2b 2954 int j;
RyoheiHagimoto 0:56c5742b9e2b 2955 /*We initialize the buffer with the data mask and XOR bits into it as we read
RyoheiHagimoto 0:56c5742b9e2b 2956 them out of the image instead of unmasking in a separate step.*/
RyoheiHagimoto 0:56c5742b9e2b 2957 qr_data_mask_fill(_data_bits,_dim,_fmt_info&7);
RyoheiHagimoto 0:56c5742b9e2b 2958 stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
RyoheiHagimoto 0:56c5742b9e2b 2959 u0=0;
RyoheiHagimoto 0:56c5742b9e2b 2960 svg_path_start("sampling-grid", 1, 0, 0);
RyoheiHagimoto 0:56c5742b9e2b 2961 /*We read data cell-by-cell to avoid having to constantly change which
RyoheiHagimoto 0:56c5742b9e2b 2962 projection we're using as we read each bit.
RyoheiHagimoto 0:56c5742b9e2b 2963 This (and the position-dependent data mask) is the reason we buffer the
RyoheiHagimoto 0:56c5742b9e2b 2964 bits we read instead of converting them directly to codewords here.
RyoheiHagimoto 0:56c5742b9e2b 2965 Note that bits are stored column-wise, since that's how we'll scan them.*/
RyoheiHagimoto 0:56c5742b9e2b 2966 for(j=0;j<_grid->ncells;j++){
RyoheiHagimoto 0:56c5742b9e2b 2967 int i;
RyoheiHagimoto 0:56c5742b9e2b 2968 int v0;
RyoheiHagimoto 0:56c5742b9e2b 2969 int v1;
RyoheiHagimoto 0:56c5742b9e2b 2970 u1=_grid->cell_limits[j];
RyoheiHagimoto 0:56c5742b9e2b 2971 v0=0;
RyoheiHagimoto 0:56c5742b9e2b 2972 for(i=0;i<_grid->ncells;i++){
RyoheiHagimoto 0:56c5742b9e2b 2973 qr_hom_cell *cell;
RyoheiHagimoto 0:56c5742b9e2b 2974 int x0;
RyoheiHagimoto 0:56c5742b9e2b 2975 int y0;
RyoheiHagimoto 0:56c5742b9e2b 2976 int w0;
RyoheiHagimoto 0:56c5742b9e2b 2977 int u;
RyoheiHagimoto 0:56c5742b9e2b 2978 int du;
RyoheiHagimoto 0:56c5742b9e2b 2979 int dv;
RyoheiHagimoto 0:56c5742b9e2b 2980 v1=_grid->cell_limits[i];
RyoheiHagimoto 0:56c5742b9e2b 2981 cell=_grid->cells[i]+j;
RyoheiHagimoto 0:56c5742b9e2b 2982 du=u0-cell->u0;
RyoheiHagimoto 0:56c5742b9e2b 2983 dv=v0-cell->v0;
RyoheiHagimoto 0:56c5742b9e2b 2984 x0=cell->fwd[0][0]*du+cell->fwd[0][1]*dv+cell->fwd[0][2];
RyoheiHagimoto 0:56c5742b9e2b 2985 y0=cell->fwd[1][0]*du+cell->fwd[1][1]*dv+cell->fwd[1][2];
RyoheiHagimoto 0:56c5742b9e2b 2986 w0=cell->fwd[2][0]*du+cell->fwd[2][1]*dv+cell->fwd[2][2];
RyoheiHagimoto 0:56c5742b9e2b 2987 for(u=u0;u<u1;u++){
RyoheiHagimoto 0:56c5742b9e2b 2988 int x;
RyoheiHagimoto 0:56c5742b9e2b 2989 int y;
RyoheiHagimoto 0:56c5742b9e2b 2990 int w;
RyoheiHagimoto 0:56c5742b9e2b 2991 int v;
RyoheiHagimoto 0:56c5742b9e2b 2992 x=x0;
RyoheiHagimoto 0:56c5742b9e2b 2993 y=y0;
RyoheiHagimoto 0:56c5742b9e2b 2994 w=w0;
RyoheiHagimoto 0:56c5742b9e2b 2995 for(v=v0;v<v1;v++){
RyoheiHagimoto 0:56c5742b9e2b 2996 /*Skip doing all the divisions and bounds checks if the bit is in the
RyoheiHagimoto 0:56c5742b9e2b 2997 function pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 2998 if(!qr_sampling_grid_is_in_fp(_grid,_dim,u,v)){
RyoheiHagimoto 0:56c5742b9e2b 2999 qr_point p;
RyoheiHagimoto 0:56c5742b9e2b 3000 qr_hom_cell_fproject(p,cell,x,y,w);
RyoheiHagimoto 0:56c5742b9e2b 3001 _data_bits[u*stride+(v>>QR_INT_LOGBITS)]^=
RyoheiHagimoto 0:56c5742b9e2b 3002 qr_img_get_bit(_img,_width,_height,p[0],p[1])<<(v&QR_INT_BITS-1);
RyoheiHagimoto 0:56c5742b9e2b 3003 svg_path_moveto(SVG_ABS, p[0], p[1]);
RyoheiHagimoto 0:56c5742b9e2b 3004 }
RyoheiHagimoto 0:56c5742b9e2b 3005 x+=cell->fwd[0][1];
RyoheiHagimoto 0:56c5742b9e2b 3006 y+=cell->fwd[1][1];
RyoheiHagimoto 0:56c5742b9e2b 3007 w+=cell->fwd[2][1];
RyoheiHagimoto 0:56c5742b9e2b 3008 }
RyoheiHagimoto 0:56c5742b9e2b 3009 x0+=cell->fwd[0][0];
RyoheiHagimoto 0:56c5742b9e2b 3010 y0+=cell->fwd[1][0];
RyoheiHagimoto 0:56c5742b9e2b 3011 w0+=cell->fwd[2][0];
RyoheiHagimoto 0:56c5742b9e2b 3012 }
RyoheiHagimoto 0:56c5742b9e2b 3013 v0=v1;
RyoheiHagimoto 0:56c5742b9e2b 3014 }
RyoheiHagimoto 0:56c5742b9e2b 3015 u0=u1;
RyoheiHagimoto 0:56c5742b9e2b 3016 }
RyoheiHagimoto 0:56c5742b9e2b 3017 svg_path_end();
RyoheiHagimoto 0:56c5742b9e2b 3018 }
RyoheiHagimoto 0:56c5742b9e2b 3019
RyoheiHagimoto 0:56c5742b9e2b 3020 /*Arranges the sample bits read by qr_sampling_grid_sample() into bytes and
RyoheiHagimoto 0:56c5742b9e2b 3021 groups those bytes into Reed-Solomon blocks.
RyoheiHagimoto 0:56c5742b9e2b 3022 The individual block pointers are destroyed by this routine.*/
RyoheiHagimoto 0:56c5742b9e2b 3023 static void qr_samples_unpack(unsigned char **_blocks,int _nblocks,
RyoheiHagimoto 0:56c5742b9e2b 3024 int _nshort_data,int _nshort_blocks,const unsigned *_data_bits,
RyoheiHagimoto 0:56c5742b9e2b 3025 const unsigned *_fp_mask,int _dim){
RyoheiHagimoto 0:56c5742b9e2b 3026 unsigned bits;
RyoheiHagimoto 0:56c5742b9e2b 3027 int biti;
RyoheiHagimoto 0:56c5742b9e2b 3028 int stride;
RyoheiHagimoto 0:56c5742b9e2b 3029 int blocki;
RyoheiHagimoto 0:56c5742b9e2b 3030 int blockj;
RyoheiHagimoto 0:56c5742b9e2b 3031 int i;
RyoheiHagimoto 0:56c5742b9e2b 3032 int j;
RyoheiHagimoto 0:56c5742b9e2b 3033 stride=_dim+QR_INT_BITS-1>>QR_INT_LOGBITS;
RyoheiHagimoto 0:56c5742b9e2b 3034 /*If _all_ the blocks are short, don't skip anything (see below).*/
RyoheiHagimoto 0:56c5742b9e2b 3035 if(_nshort_blocks>=_nblocks)_nshort_blocks=0;
RyoheiHagimoto 0:56c5742b9e2b 3036 /*Scan columns in pairs from right to left.*/
RyoheiHagimoto 0:56c5742b9e2b 3037 bits=0;
RyoheiHagimoto 0:56c5742b9e2b 3038 for(blocki=blockj=biti=0,j=_dim-1;j>0;j-=2){
RyoheiHagimoto 0:56c5742b9e2b 3039 unsigned data1;
RyoheiHagimoto 0:56c5742b9e2b 3040 unsigned data2;
RyoheiHagimoto 0:56c5742b9e2b 3041 unsigned fp_mask1;
RyoheiHagimoto 0:56c5742b9e2b 3042 unsigned fp_mask2;
RyoheiHagimoto 0:56c5742b9e2b 3043 int nbits;
RyoheiHagimoto 0:56c5742b9e2b 3044 int l;
RyoheiHagimoto 0:56c5742b9e2b 3045 /*Scan up a pair of columns.*/
RyoheiHagimoto 0:56c5742b9e2b 3046 nbits=(_dim-1&QR_INT_BITS-1)+1;
RyoheiHagimoto 0:56c5742b9e2b 3047 l=j*stride;
RyoheiHagimoto 0:56c5742b9e2b 3048 for(i=stride;i-->0;){
RyoheiHagimoto 0:56c5742b9e2b 3049 data1=_data_bits[l+i];
RyoheiHagimoto 0:56c5742b9e2b 3050 fp_mask1=_fp_mask[l+i];
RyoheiHagimoto 0:56c5742b9e2b 3051 data2=_data_bits[l+i-stride];
RyoheiHagimoto 0:56c5742b9e2b 3052 fp_mask2=_fp_mask[l+i-stride];
RyoheiHagimoto 0:56c5742b9e2b 3053 while(nbits-->0){
RyoheiHagimoto 0:56c5742b9e2b 3054 /*Pull a bit from the right column.*/
RyoheiHagimoto 0:56c5742b9e2b 3055 if(!(fp_mask1>>nbits&1)){
RyoheiHagimoto 0:56c5742b9e2b 3056 bits=bits<<1|data1>>nbits&1;
RyoheiHagimoto 0:56c5742b9e2b 3057 biti++;
RyoheiHagimoto 0:56c5742b9e2b 3058 }
RyoheiHagimoto 0:56c5742b9e2b 3059 /*Pull a bit from the left column.*/
RyoheiHagimoto 0:56c5742b9e2b 3060 if(!(fp_mask2>>nbits&1)){
RyoheiHagimoto 0:56c5742b9e2b 3061 bits=bits<<1|data2>>nbits&1;
RyoheiHagimoto 0:56c5742b9e2b 3062 biti++;
RyoheiHagimoto 0:56c5742b9e2b 3063 }
RyoheiHagimoto 0:56c5742b9e2b 3064 /*If we finished a byte, drop it in a block.*/
RyoheiHagimoto 0:56c5742b9e2b 3065 if(biti>=8){
RyoheiHagimoto 0:56c5742b9e2b 3066 biti-=8;
RyoheiHagimoto 0:56c5742b9e2b 3067 *_blocks[blocki++]++=(unsigned char)(bits>>biti);
RyoheiHagimoto 0:56c5742b9e2b 3068 /*For whatever reason, the long blocks are at the _end_ of the list,
RyoheiHagimoto 0:56c5742b9e2b 3069 instead of the beginning.
RyoheiHagimoto 0:56c5742b9e2b 3070 Even worse, the extra bytes they get come at the end of the data
RyoheiHagimoto 0:56c5742b9e2b 3071 bytes, before the parity bytes.
RyoheiHagimoto 0:56c5742b9e2b 3072 Hence the logic here: when we've filled up the data portion of the
RyoheiHagimoto 0:56c5742b9e2b 3073 short blocks, skip directly to the long blocks for the next byte.
RyoheiHagimoto 0:56c5742b9e2b 3074 It's also the reason we increment _blocks[blocki] on each store,
RyoheiHagimoto 0:56c5742b9e2b 3075 instead of just indexing with blockj (after this iteration the
RyoheiHagimoto 0:56c5742b9e2b 3076 number of bytes in each block differs).*/
RyoheiHagimoto 0:56c5742b9e2b 3077 if(blocki>=_nblocks)blocki=++blockj==_nshort_data?_nshort_blocks:0;
RyoheiHagimoto 0:56c5742b9e2b 3078 }
RyoheiHagimoto 0:56c5742b9e2b 3079 }
RyoheiHagimoto 0:56c5742b9e2b 3080 nbits=QR_INT_BITS;
RyoheiHagimoto 0:56c5742b9e2b 3081 }
RyoheiHagimoto 0:56c5742b9e2b 3082 j-=2;
RyoheiHagimoto 0:56c5742b9e2b 3083 /*Skip the column with the vertical timing pattern.*/
RyoheiHagimoto 0:56c5742b9e2b 3084 if(j==6)j--;
RyoheiHagimoto 0:56c5742b9e2b 3085 /*Scan down a pair of columns.*/
RyoheiHagimoto 0:56c5742b9e2b 3086 l=j*stride;
RyoheiHagimoto 0:56c5742b9e2b 3087 for(i=0;i<stride;i++){
RyoheiHagimoto 0:56c5742b9e2b 3088 data1=_data_bits[l+i];
RyoheiHagimoto 0:56c5742b9e2b 3089 fp_mask1=_fp_mask[l+i];
RyoheiHagimoto 0:56c5742b9e2b 3090 data2=_data_bits[l+i-stride];
RyoheiHagimoto 0:56c5742b9e2b 3091 fp_mask2=_fp_mask[l+i-stride];
RyoheiHagimoto 0:56c5742b9e2b 3092 nbits=QR_MINI(_dim-(i<<QR_INT_LOGBITS),QR_INT_BITS);
RyoheiHagimoto 0:56c5742b9e2b 3093 while(nbits-->0){
RyoheiHagimoto 0:56c5742b9e2b 3094 /*Pull a bit from the right column.*/
RyoheiHagimoto 0:56c5742b9e2b 3095 if(!(fp_mask1&1)){
RyoheiHagimoto 0:56c5742b9e2b 3096 bits=bits<<1|data1&1;
RyoheiHagimoto 0:56c5742b9e2b 3097 biti++;
RyoheiHagimoto 0:56c5742b9e2b 3098 }
RyoheiHagimoto 0:56c5742b9e2b 3099 data1>>=1;
RyoheiHagimoto 0:56c5742b9e2b 3100 fp_mask1>>=1;
RyoheiHagimoto 0:56c5742b9e2b 3101 /*Pull a bit from the left column.*/
RyoheiHagimoto 0:56c5742b9e2b 3102 if(!(fp_mask2&1)){
RyoheiHagimoto 0:56c5742b9e2b 3103 bits=bits<<1|data2&1;
RyoheiHagimoto 0:56c5742b9e2b 3104 biti++;
RyoheiHagimoto 0:56c5742b9e2b 3105 }
RyoheiHagimoto 0:56c5742b9e2b 3106 data2>>=1;
RyoheiHagimoto 0:56c5742b9e2b 3107 fp_mask2>>=1;
RyoheiHagimoto 0:56c5742b9e2b 3108 /*If we finished a byte, drop it in a block.*/
RyoheiHagimoto 0:56c5742b9e2b 3109 if(biti>=8){
RyoheiHagimoto 0:56c5742b9e2b 3110 biti-=8;
RyoheiHagimoto 0:56c5742b9e2b 3111 *_blocks[blocki++]++=(unsigned char)(bits>>biti);
RyoheiHagimoto 0:56c5742b9e2b 3112 /*See comments on the "up" loop for the reason behind this mess.*/
RyoheiHagimoto 0:56c5742b9e2b 3113 if(blocki>=_nblocks)blocki=++blockj==_nshort_data?_nshort_blocks:0;
RyoheiHagimoto 0:56c5742b9e2b 3114 }
RyoheiHagimoto 0:56c5742b9e2b 3115 }
RyoheiHagimoto 0:56c5742b9e2b 3116 }
RyoheiHagimoto 0:56c5742b9e2b 3117 }
RyoheiHagimoto 0:56c5742b9e2b 3118 }
RyoheiHagimoto 0:56c5742b9e2b 3119
RyoheiHagimoto 0:56c5742b9e2b 3120
RyoheiHagimoto 0:56c5742b9e2b 3121 /*Bit reading code blatantly stolen^W^Wadapted from libogg/libtheora (because
RyoheiHagimoto 0:56c5742b9e2b 3122 I've already debugged it and I know it works).
RyoheiHagimoto 0:56c5742b9e2b 3123 Portions (C) Xiph.Org Foundation 1994-2008, BSD-style license.*/
RyoheiHagimoto 0:56c5742b9e2b 3124 struct qr_pack_buf{
RyoheiHagimoto 0:56c5742b9e2b 3125 const unsigned char *buf;
RyoheiHagimoto 0:56c5742b9e2b 3126 int endbyte;
RyoheiHagimoto 0:56c5742b9e2b 3127 int endbit;
RyoheiHagimoto 0:56c5742b9e2b 3128 int storage;
RyoheiHagimoto 0:56c5742b9e2b 3129 };
RyoheiHagimoto 0:56c5742b9e2b 3130
RyoheiHagimoto 0:56c5742b9e2b 3131
RyoheiHagimoto 0:56c5742b9e2b 3132 static void qr_pack_buf_init(qr_pack_buf *_b,
RyoheiHagimoto 0:56c5742b9e2b 3133 const unsigned char *_data,int _ndata){
RyoheiHagimoto 0:56c5742b9e2b 3134 _b->buf=_data;
RyoheiHagimoto 0:56c5742b9e2b 3135 _b->storage=_ndata;
RyoheiHagimoto 0:56c5742b9e2b 3136 _b->endbyte=_b->endbit=0;
RyoheiHagimoto 0:56c5742b9e2b 3137 }
RyoheiHagimoto 0:56c5742b9e2b 3138
RyoheiHagimoto 0:56c5742b9e2b 3139 /*Assumes 0<=_bits<=16.*/
RyoheiHagimoto 0:56c5742b9e2b 3140 static int qr_pack_buf_read(qr_pack_buf *_b,int _bits){
RyoheiHagimoto 0:56c5742b9e2b 3141 const unsigned char *p;
RyoheiHagimoto 0:56c5742b9e2b 3142 unsigned ret;
RyoheiHagimoto 0:56c5742b9e2b 3143 int m;
RyoheiHagimoto 0:56c5742b9e2b 3144 int d;
RyoheiHagimoto 0:56c5742b9e2b 3145 m=16-_bits;
RyoheiHagimoto 0:56c5742b9e2b 3146 _bits+=_b->endbit;
RyoheiHagimoto 0:56c5742b9e2b 3147 d=_b->storage-_b->endbyte;
RyoheiHagimoto 0:56c5742b9e2b 3148 if(d<=2){
RyoheiHagimoto 0:56c5742b9e2b 3149 /*Not the main path.*/
RyoheiHagimoto 0:56c5742b9e2b 3150 if(d*8<_bits){
RyoheiHagimoto 0:56c5742b9e2b 3151 _b->endbyte+=_bits>>3;
RyoheiHagimoto 0:56c5742b9e2b 3152 _b->endbit=_bits&7;
RyoheiHagimoto 0:56c5742b9e2b 3153 return -1;
RyoheiHagimoto 0:56c5742b9e2b 3154 }
RyoheiHagimoto 0:56c5742b9e2b 3155 /*Special case to avoid reading p[0] below, which might be past the end of
RyoheiHagimoto 0:56c5742b9e2b 3156 the buffer; also skips some useless accounting.*/
RyoheiHagimoto 0:56c5742b9e2b 3157 else if(!_bits)return 0;
RyoheiHagimoto 0:56c5742b9e2b 3158 }
RyoheiHagimoto 0:56c5742b9e2b 3159 p=_b->buf+_b->endbyte;
RyoheiHagimoto 0:56c5742b9e2b 3160 ret=p[0]<<8+_b->endbit;
RyoheiHagimoto 0:56c5742b9e2b 3161 if(_bits>8){
RyoheiHagimoto 0:56c5742b9e2b 3162 ret|=p[1]<<_b->endbit;
RyoheiHagimoto 0:56c5742b9e2b 3163 if(_bits>16)ret|=p[2]>>8-_b->endbit;
RyoheiHagimoto 0:56c5742b9e2b 3164 }
RyoheiHagimoto 0:56c5742b9e2b 3165 _b->endbyte+=_bits>>3;
RyoheiHagimoto 0:56c5742b9e2b 3166 _b->endbit=_bits&7;
RyoheiHagimoto 0:56c5742b9e2b 3167 return (ret&0xFFFF)>>m;
RyoheiHagimoto 0:56c5742b9e2b 3168 }
RyoheiHagimoto 0:56c5742b9e2b 3169
RyoheiHagimoto 0:56c5742b9e2b 3170 static int qr_pack_buf_avail(const qr_pack_buf *_b){
RyoheiHagimoto 0:56c5742b9e2b 3171 return (_b->storage-_b->endbyte<<3)-_b->endbit;
RyoheiHagimoto 0:56c5742b9e2b 3172 }
RyoheiHagimoto 0:56c5742b9e2b 3173
RyoheiHagimoto 0:56c5742b9e2b 3174
RyoheiHagimoto 0:56c5742b9e2b 3175 /*The characters available in QR_MODE_ALNUM.*/
RyoheiHagimoto 0:56c5742b9e2b 3176 static const unsigned char QR_ALNUM_TABLE[45]={
RyoheiHagimoto 0:56c5742b9e2b 3177 '0','1','2','3','4','5','6','7','8','9',
RyoheiHagimoto 0:56c5742b9e2b 3178 'A','B','C','D','E','F','G','H','I','J',
RyoheiHagimoto 0:56c5742b9e2b 3179 'K','L','M','N','O','P','Q','R','S','T',
RyoheiHagimoto 0:56c5742b9e2b 3180 'U','V','W','X','Y','Z',' ','$','%','*',
RyoheiHagimoto 0:56c5742b9e2b 3181 '+','-','.','/',':'
RyoheiHagimoto 0:56c5742b9e2b 3182 };
RyoheiHagimoto 0:56c5742b9e2b 3183
RyoheiHagimoto 0:56c5742b9e2b 3184 static int qr_code_data_parse(qr_code_data *_qrdata,int _version,
RyoheiHagimoto 0:56c5742b9e2b 3185 const unsigned char *_data,int _ndata){
RyoheiHagimoto 0:56c5742b9e2b 3186 qr_pack_buf qpb;
RyoheiHagimoto 0:56c5742b9e2b 3187 int centries;
RyoheiHagimoto 0:56c5742b9e2b 3188 int len_bits_idx;
RyoheiHagimoto 0:56c5742b9e2b 3189 /*Entries are stored directly in the struct during parsing.
RyoheiHagimoto 0:56c5742b9e2b 3190 Caller cleans up any allocated data on failure.*/
RyoheiHagimoto 0:56c5742b9e2b 3191 _qrdata->entries=NULL;
RyoheiHagimoto 0:56c5742b9e2b 3192 _qrdata->nentries=0;
RyoheiHagimoto 0:56c5742b9e2b 3193 _qrdata->sa_size=0;
RyoheiHagimoto 0:56c5742b9e2b 3194 centries=0;
RyoheiHagimoto 0:56c5742b9e2b 3195 /*The versions are divided into 3 ranges that each use a different number of
RyoheiHagimoto 0:56c5742b9e2b 3196 bits for length fields.*/
RyoheiHagimoto 0:56c5742b9e2b 3197 len_bits_idx=(_version>9)+(_version>26);
RyoheiHagimoto 0:56c5742b9e2b 3198 qr_pack_buf_init(&qpb,_data,_ndata);
RyoheiHagimoto 0:56c5742b9e2b 3199 /*While we have enough bits to read a mode...*/
RyoheiHagimoto 0:56c5742b9e2b 3200 while(qr_pack_buf_avail(&qpb)>=4){
RyoheiHagimoto 0:56c5742b9e2b 3201 qr_code_data_entry *entry;
RyoheiHagimoto 0:56c5742b9e2b 3202 int mode;
RyoheiHagimoto 0:56c5742b9e2b 3203 mode=qr_pack_buf_read(&qpb,4);
RyoheiHagimoto 0:56c5742b9e2b 3204 /*Mode 0 is a terminator.*/
RyoheiHagimoto 0:56c5742b9e2b 3205 if(!mode)break;
RyoheiHagimoto 0:56c5742b9e2b 3206 if(_qrdata->nentries>=centries){
RyoheiHagimoto 0:56c5742b9e2b 3207 centries=centries<<1|1;
RyoheiHagimoto 0:56c5742b9e2b 3208 _qrdata->entries=(qr_code_data_entry *)realloc(_qrdata->entries,
RyoheiHagimoto 0:56c5742b9e2b 3209 centries*sizeof(*_qrdata->entries));
RyoheiHagimoto 0:56c5742b9e2b 3210 }
RyoheiHagimoto 0:56c5742b9e2b 3211 entry=_qrdata->entries+_qrdata->nentries++;
RyoheiHagimoto 0:56c5742b9e2b 3212 /*Set the mode to an invalid value until we allocate a buffer for it.
RyoheiHagimoto 0:56c5742b9e2b 3213 This ensures we don't try to free it on clean-up until then.*/
RyoheiHagimoto 0:56c5742b9e2b 3214 entry->mode=-1;
RyoheiHagimoto 0:56c5742b9e2b 3215 switch(mode){
RyoheiHagimoto 0:56c5742b9e2b 3216 /*The number of bits used to encode the character count for each version
RyoheiHagimoto 0:56c5742b9e2b 3217 range and each data mode.*/
RyoheiHagimoto 0:56c5742b9e2b 3218 static const unsigned char LEN_BITS[3][4]={
RyoheiHagimoto 0:56c5742b9e2b 3219 {10, 9, 8, 8},
RyoheiHagimoto 0:56c5742b9e2b 3220 {12,11,16,10},
RyoheiHagimoto 0:56c5742b9e2b 3221 {14,13,16,12}
RyoheiHagimoto 0:56c5742b9e2b 3222 };
RyoheiHagimoto 0:56c5742b9e2b 3223 case QR_MODE_NUM:{
RyoheiHagimoto 0:56c5742b9e2b 3224 unsigned char *buf;
RyoheiHagimoto 0:56c5742b9e2b 3225 unsigned bits;
RyoheiHagimoto 0:56c5742b9e2b 3226 int len;
RyoheiHagimoto 0:56c5742b9e2b 3227 int count;
RyoheiHagimoto 0:56c5742b9e2b 3228 int rem;
RyoheiHagimoto 0:56c5742b9e2b 3229 len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][0]);
RyoheiHagimoto 0:56c5742b9e2b 3230 if(len<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3231 /*Check to see if there are enough bits left now, so we don't have to
RyoheiHagimoto 0:56c5742b9e2b 3232 in the decode loop.*/
RyoheiHagimoto 0:56c5742b9e2b 3233 count=len/3;
RyoheiHagimoto 0:56c5742b9e2b 3234 rem=len%3;
RyoheiHagimoto 0:56c5742b9e2b 3235 if(qr_pack_buf_avail(&qpb)<10*count+7*(rem>>1&1)+4*(rem&1))return -1;
RyoheiHagimoto 0:56c5742b9e2b 3236 entry->mode=mode;
RyoheiHagimoto 0:56c5742b9e2b 3237 entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf));
RyoheiHagimoto 0:56c5742b9e2b 3238 entry->payload.data.len=len;
RyoheiHagimoto 0:56c5742b9e2b 3239 /*Read groups of 3 digits encoded in 10 bits.*/
RyoheiHagimoto 0:56c5742b9e2b 3240 while(count-->0){
RyoheiHagimoto 0:56c5742b9e2b 3241 bits=qr_pack_buf_read(&qpb,10);
RyoheiHagimoto 0:56c5742b9e2b 3242 if(bits>=1000)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3243 *buf++=(unsigned char)('0'+bits/100);
RyoheiHagimoto 0:56c5742b9e2b 3244 bits%=100;
RyoheiHagimoto 0:56c5742b9e2b 3245 *buf++=(unsigned char)('0'+bits/10);
RyoheiHagimoto 0:56c5742b9e2b 3246 *buf++=(unsigned char)('0'+bits%10);
RyoheiHagimoto 0:56c5742b9e2b 3247 }
RyoheiHagimoto 0:56c5742b9e2b 3248 /*Read the last two digits encoded in 7 bits.*/
RyoheiHagimoto 0:56c5742b9e2b 3249 if(rem>1){
RyoheiHagimoto 0:56c5742b9e2b 3250 bits=qr_pack_buf_read(&qpb,7);
RyoheiHagimoto 0:56c5742b9e2b 3251 if(bits>=100)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3252 *buf++=(unsigned char)('0'+bits/10);
RyoheiHagimoto 0:56c5742b9e2b 3253 *buf++=(unsigned char)('0'+bits%10);
RyoheiHagimoto 0:56c5742b9e2b 3254 }
RyoheiHagimoto 0:56c5742b9e2b 3255 /*Or the last one digit encoded in 4 bits.*/
RyoheiHagimoto 0:56c5742b9e2b 3256 else if(rem){
RyoheiHagimoto 0:56c5742b9e2b 3257 bits=qr_pack_buf_read(&qpb,4);
RyoheiHagimoto 0:56c5742b9e2b 3258 if(bits>=10)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3259 *buf++=(unsigned char)('0'+bits);
RyoheiHagimoto 0:56c5742b9e2b 3260 }
RyoheiHagimoto 0:56c5742b9e2b 3261 }break;
RyoheiHagimoto 0:56c5742b9e2b 3262 case QR_MODE_ALNUM:{
RyoheiHagimoto 0:56c5742b9e2b 3263 unsigned char *buf;
RyoheiHagimoto 0:56c5742b9e2b 3264 unsigned bits;
RyoheiHagimoto 0:56c5742b9e2b 3265 int len;
RyoheiHagimoto 0:56c5742b9e2b 3266 int count;
RyoheiHagimoto 0:56c5742b9e2b 3267 int rem;
RyoheiHagimoto 0:56c5742b9e2b 3268 len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][1]);
RyoheiHagimoto 0:56c5742b9e2b 3269 if(len<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3270 /*Check to see if there are enough bits left now, so we don't have to
RyoheiHagimoto 0:56c5742b9e2b 3271 in the decode loop.*/
RyoheiHagimoto 0:56c5742b9e2b 3272 count=len>>1;
RyoheiHagimoto 0:56c5742b9e2b 3273 rem=len&1;
RyoheiHagimoto 0:56c5742b9e2b 3274 if(qr_pack_buf_avail(&qpb)<11*count+6*rem)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3275 entry->mode=mode;
RyoheiHagimoto 0:56c5742b9e2b 3276 entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf));
RyoheiHagimoto 0:56c5742b9e2b 3277 entry->payload.data.len=len;
RyoheiHagimoto 0:56c5742b9e2b 3278 /*Read groups of two characters encoded in 11 bits.*/
RyoheiHagimoto 0:56c5742b9e2b 3279 while(count-->0){
RyoheiHagimoto 0:56c5742b9e2b 3280 bits=qr_pack_buf_read(&qpb,11);
RyoheiHagimoto 0:56c5742b9e2b 3281 if(bits>=2025)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3282 *buf++=QR_ALNUM_TABLE[bits/45];
RyoheiHagimoto 0:56c5742b9e2b 3283 *buf++=QR_ALNUM_TABLE[bits%45];
RyoheiHagimoto 0:56c5742b9e2b 3284 len-=2;
RyoheiHagimoto 0:56c5742b9e2b 3285 }
RyoheiHagimoto 0:56c5742b9e2b 3286 /*Read the last character encoded in 6 bits.*/
RyoheiHagimoto 0:56c5742b9e2b 3287 if(rem){
RyoheiHagimoto 0:56c5742b9e2b 3288 bits=qr_pack_buf_read(&qpb,6);
RyoheiHagimoto 0:56c5742b9e2b 3289 if(bits>=45)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3290 *buf++=QR_ALNUM_TABLE[bits];
RyoheiHagimoto 0:56c5742b9e2b 3291 }
RyoheiHagimoto 0:56c5742b9e2b 3292 }break;
RyoheiHagimoto 0:56c5742b9e2b 3293 /*Structured-append header.*/
RyoheiHagimoto 0:56c5742b9e2b 3294 case QR_MODE_STRUCT:{
RyoheiHagimoto 0:56c5742b9e2b 3295 int bits;
RyoheiHagimoto 0:56c5742b9e2b 3296 entry->mode=mode;
RyoheiHagimoto 0:56c5742b9e2b 3297 bits=qr_pack_buf_read(&qpb,16);
RyoheiHagimoto 0:56c5742b9e2b 3298 if(bits<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3299 /*We also save a copy of the data in _qrdata for easy reference when
RyoheiHagimoto 0:56c5742b9e2b 3300 grouping structured-append codes.
RyoheiHagimoto 0:56c5742b9e2b 3301 If for some reason the code has multiple S-A headers, last one wins
RyoheiHagimoto 0:56c5742b9e2b 3302 (TODO: should we return an error instead?).*/
RyoheiHagimoto 0:56c5742b9e2b 3303 _qrdata->sa_index=entry->payload.sa.sa_index=
RyoheiHagimoto 0:56c5742b9e2b 3304 (unsigned char)(bits>>12&0xF);
RyoheiHagimoto 0:56c5742b9e2b 3305 _qrdata->sa_size=entry->payload.sa.sa_size=
RyoheiHagimoto 0:56c5742b9e2b 3306 (unsigned char)((bits>>8&0xF)+1);
RyoheiHagimoto 0:56c5742b9e2b 3307 _qrdata->sa_parity=entry->payload.sa.sa_parity=
RyoheiHagimoto 0:56c5742b9e2b 3308 (unsigned char)(bits&0xFF);
RyoheiHagimoto 0:56c5742b9e2b 3309 }break;
RyoheiHagimoto 0:56c5742b9e2b 3310 case QR_MODE_BYTE:{
RyoheiHagimoto 0:56c5742b9e2b 3311 unsigned char *buf;
RyoheiHagimoto 0:56c5742b9e2b 3312 int len;
RyoheiHagimoto 0:56c5742b9e2b 3313 len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][2]);
RyoheiHagimoto 0:56c5742b9e2b 3314 if(len<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3315 /*Check to see if there are enough bits left now, so we don't have to
RyoheiHagimoto 0:56c5742b9e2b 3316 in the decode loop.*/
RyoheiHagimoto 0:56c5742b9e2b 3317 if(qr_pack_buf_avail(&qpb)<len<<3)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3318 entry->mode=mode;
RyoheiHagimoto 0:56c5742b9e2b 3319 entry->payload.data.buf=buf=(unsigned char *)malloc(len*sizeof(*buf));
RyoheiHagimoto 0:56c5742b9e2b 3320 entry->payload.data.len=len;
RyoheiHagimoto 0:56c5742b9e2b 3321 while(len-->0)*buf++=(unsigned char)qr_pack_buf_read(&qpb,8);
RyoheiHagimoto 0:56c5742b9e2b 3322 }break;
RyoheiHagimoto 0:56c5742b9e2b 3323 /*FNC1 first position marker.*/
RyoheiHagimoto 0:56c5742b9e2b 3324 case QR_MODE_FNC1_1ST:entry->mode=mode;break;
RyoheiHagimoto 0:56c5742b9e2b 3325 /*Extended Channel Interpretation data.*/
RyoheiHagimoto 0:56c5742b9e2b 3326 case QR_MODE_ECI:{
RyoheiHagimoto 0:56c5742b9e2b 3327 unsigned val;
RyoheiHagimoto 0:56c5742b9e2b 3328 int bits;
RyoheiHagimoto 0:56c5742b9e2b 3329 /*ECI uses a variable-width encoding similar to UTF-8*/
RyoheiHagimoto 0:56c5742b9e2b 3330 bits=qr_pack_buf_read(&qpb,8);
RyoheiHagimoto 0:56c5742b9e2b 3331 if(bits<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3332 /*One byte:*/
RyoheiHagimoto 0:56c5742b9e2b 3333 if(!(bits&0x80))val=bits;
RyoheiHagimoto 0:56c5742b9e2b 3334 /*Two bytes:*/
RyoheiHagimoto 0:56c5742b9e2b 3335 else if(!(bits&0x40)){
RyoheiHagimoto 0:56c5742b9e2b 3336 val=bits&0x3F<<8;
RyoheiHagimoto 0:56c5742b9e2b 3337 bits=qr_pack_buf_read(&qpb,8);
RyoheiHagimoto 0:56c5742b9e2b 3338 if(bits<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3339 val|=bits;
RyoheiHagimoto 0:56c5742b9e2b 3340 }
RyoheiHagimoto 0:56c5742b9e2b 3341 /*Three bytes:*/
RyoheiHagimoto 0:56c5742b9e2b 3342 else if(!(bits&0x20)){
RyoheiHagimoto 0:56c5742b9e2b 3343 val=bits&0x1F<<16;
RyoheiHagimoto 0:56c5742b9e2b 3344 bits=qr_pack_buf_read(&qpb,16);
RyoheiHagimoto 0:56c5742b9e2b 3345 if(bits<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3346 val|=bits;
RyoheiHagimoto 0:56c5742b9e2b 3347 /*Valid ECI values are 0...999999.*/
RyoheiHagimoto 0:56c5742b9e2b 3348 if(val>=1000000)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3349 }
RyoheiHagimoto 0:56c5742b9e2b 3350 /*Invalid lead byte.*/
RyoheiHagimoto 0:56c5742b9e2b 3351 else return -1;
RyoheiHagimoto 0:56c5742b9e2b 3352 entry->mode=mode;
RyoheiHagimoto 0:56c5742b9e2b 3353 entry->payload.eci=val;
RyoheiHagimoto 0:56c5742b9e2b 3354 }break;
RyoheiHagimoto 0:56c5742b9e2b 3355 case QR_MODE_KANJI:{
RyoheiHagimoto 0:56c5742b9e2b 3356 unsigned char *buf;
RyoheiHagimoto 0:56c5742b9e2b 3357 unsigned bits;
RyoheiHagimoto 0:56c5742b9e2b 3358 int len;
RyoheiHagimoto 0:56c5742b9e2b 3359 len=qr_pack_buf_read(&qpb,LEN_BITS[len_bits_idx][3]);
RyoheiHagimoto 0:56c5742b9e2b 3360 if(len<0)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3361 /*Check to see if there are enough bits left now, so we don't have to
RyoheiHagimoto 0:56c5742b9e2b 3362 in the decode loop.*/
RyoheiHagimoto 0:56c5742b9e2b 3363 if(qr_pack_buf_avail(&qpb)<13*len)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3364 entry->mode=mode;
RyoheiHagimoto 0:56c5742b9e2b 3365 entry->payload.data.buf=buf=(unsigned char *)malloc(2*len*sizeof(*buf));
RyoheiHagimoto 0:56c5742b9e2b 3366 entry->payload.data.len=2*len;
RyoheiHagimoto 0:56c5742b9e2b 3367 /*Decode 2-byte SJIS characters encoded in 13 bits.*/
RyoheiHagimoto 0:56c5742b9e2b 3368 while(len-->0){
RyoheiHagimoto 0:56c5742b9e2b 3369 bits=qr_pack_buf_read(&qpb,13);
RyoheiHagimoto 0:56c5742b9e2b 3370 bits=(bits/0xC0<<8|bits%0xC0)+0x8140;
RyoheiHagimoto 0:56c5742b9e2b 3371 if(bits>=0xA000)bits+=0x4000;
RyoheiHagimoto 0:56c5742b9e2b 3372 /*Are values 0xXX7F, 0xXXFD...0xXXFF always invalid?
RyoheiHagimoto 0:56c5742b9e2b 3373 Should we reject them here?*/
RyoheiHagimoto 0:56c5742b9e2b 3374 *buf++=(unsigned char)(bits>>8);
RyoheiHagimoto 0:56c5742b9e2b 3375 *buf++=(unsigned char)(bits&0xFF);
RyoheiHagimoto 0:56c5742b9e2b 3376 }
RyoheiHagimoto 0:56c5742b9e2b 3377 }break;
RyoheiHagimoto 0:56c5742b9e2b 3378 /*FNC1 second position marker.*/
RyoheiHagimoto 0:56c5742b9e2b 3379 case QR_MODE_FNC1_2ND:entry->mode=mode;break;
RyoheiHagimoto 0:56c5742b9e2b 3380 /*Unknown mode number:*/
RyoheiHagimoto 0:56c5742b9e2b 3381 default:{
RyoheiHagimoto 0:56c5742b9e2b 3382 /*Unfortunately, because we have to understand the format of a mode to
RyoheiHagimoto 0:56c5742b9e2b 3383 know how many bits it occupies, we can't skip unknown modes.
RyoheiHagimoto 0:56c5742b9e2b 3384 Therefore we have to fail.*/
RyoheiHagimoto 0:56c5742b9e2b 3385 return -1;
RyoheiHagimoto 0:56c5742b9e2b 3386 }break;
RyoheiHagimoto 0:56c5742b9e2b 3387 }
RyoheiHagimoto 0:56c5742b9e2b 3388 }
RyoheiHagimoto 0:56c5742b9e2b 3389 /*TODO: If there was a S-A header, we should compute the parity of this
RyoheiHagimoto 0:56c5742b9e2b 3390 code; how are non-data modes handled (ECI, FNC1)?*/
RyoheiHagimoto 0:56c5742b9e2b 3391 _qrdata->self_parity=0;
RyoheiHagimoto 0:56c5742b9e2b 3392 /*Success.*/
RyoheiHagimoto 0:56c5742b9e2b 3393 _qrdata->entries=(qr_code_data_entry *)realloc(_qrdata->entries,
RyoheiHagimoto 0:56c5742b9e2b 3394 _qrdata->nentries*sizeof(*_qrdata->entries));
RyoheiHagimoto 0:56c5742b9e2b 3395 return 0;
RyoheiHagimoto 0:56c5742b9e2b 3396 }
RyoheiHagimoto 0:56c5742b9e2b 3397
RyoheiHagimoto 0:56c5742b9e2b 3398 static void qr_code_data_clear(qr_code_data *_qrdata){
RyoheiHagimoto 0:56c5742b9e2b 3399 int i;
RyoheiHagimoto 0:56c5742b9e2b 3400 for(i=0;i<_qrdata->nentries;i++){
RyoheiHagimoto 0:56c5742b9e2b 3401 if(QR_MODE_HAS_DATA(_qrdata->entries[i].mode)){
RyoheiHagimoto 0:56c5742b9e2b 3402 free(_qrdata->entries[i].payload.data.buf);
RyoheiHagimoto 0:56c5742b9e2b 3403 }
RyoheiHagimoto 0:56c5742b9e2b 3404 }
RyoheiHagimoto 0:56c5742b9e2b 3405 free(_qrdata->entries);
RyoheiHagimoto 0:56c5742b9e2b 3406 }
RyoheiHagimoto 0:56c5742b9e2b 3407
RyoheiHagimoto 0:56c5742b9e2b 3408
RyoheiHagimoto 0:56c5742b9e2b 3409 void qr_code_data_list_init(qr_code_data_list *_qrlist){
RyoheiHagimoto 0:56c5742b9e2b 3410 _qrlist->qrdata=NULL;
RyoheiHagimoto 0:56c5742b9e2b 3411 _qrlist->nqrdata=_qrlist->cqrdata=0;
RyoheiHagimoto 0:56c5742b9e2b 3412 }
RyoheiHagimoto 0:56c5742b9e2b 3413
RyoheiHagimoto 0:56c5742b9e2b 3414 void qr_code_data_list_clear(qr_code_data_list *_qrlist){
RyoheiHagimoto 0:56c5742b9e2b 3415 int i;
RyoheiHagimoto 0:56c5742b9e2b 3416 for(i=0;i<_qrlist->nqrdata;i++)qr_code_data_clear(_qrlist->qrdata+i);
RyoheiHagimoto 0:56c5742b9e2b 3417 free(_qrlist->qrdata);
RyoheiHagimoto 0:56c5742b9e2b 3418 qr_code_data_list_init(_qrlist);
RyoheiHagimoto 0:56c5742b9e2b 3419 }
RyoheiHagimoto 0:56c5742b9e2b 3420
RyoheiHagimoto 0:56c5742b9e2b 3421 static void qr_code_data_list_add(qr_code_data_list *_qrlist,
RyoheiHagimoto 0:56c5742b9e2b 3422 qr_code_data *_qrdata){
RyoheiHagimoto 0:56c5742b9e2b 3423 if(_qrlist->nqrdata>=_qrlist->cqrdata){
RyoheiHagimoto 0:56c5742b9e2b 3424 _qrlist->cqrdata=_qrlist->cqrdata<<1|1;
RyoheiHagimoto 0:56c5742b9e2b 3425 _qrlist->qrdata=(qr_code_data *)realloc(_qrlist->qrdata,
RyoheiHagimoto 0:56c5742b9e2b 3426 _qrlist->cqrdata*sizeof(*_qrlist->qrdata));
RyoheiHagimoto 0:56c5742b9e2b 3427 }
RyoheiHagimoto 0:56c5742b9e2b 3428 memcpy(_qrlist->qrdata+_qrlist->nqrdata++,_qrdata,sizeof(*_qrdata));
RyoheiHagimoto 0:56c5742b9e2b 3429 }
RyoheiHagimoto 0:56c5742b9e2b 3430
RyoheiHagimoto 0:56c5742b9e2b 3431 #if 0
RyoheiHagimoto 0:56c5742b9e2b 3432 static const unsigned short QR_NCODEWORDS[40]={
RyoheiHagimoto 0:56c5742b9e2b 3433 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
RyoheiHagimoto 0:56c5742b9e2b 3434 404, 466, 532, 581, 655, 733, 815, 901, 991,1085,
RyoheiHagimoto 0:56c5742b9e2b 3435 1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,
RyoheiHagimoto 0:56c5742b9e2b 3436 2323,2465,2611,2761,2876,3034,3196,3362,3532,3706
RyoheiHagimoto 0:56c5742b9e2b 3437 };
RyoheiHagimoto 0:56c5742b9e2b 3438 #endif
RyoheiHagimoto 0:56c5742b9e2b 3439
RyoheiHagimoto 0:56c5742b9e2b 3440 /*The total number of codewords in a QR code.*/
RyoheiHagimoto 0:56c5742b9e2b 3441 static int qr_code_ncodewords(unsigned _version){
RyoheiHagimoto 0:56c5742b9e2b 3442 unsigned nalign;
RyoheiHagimoto 0:56c5742b9e2b 3443 /*This is 24-27 instructions on ARM in thumb mode, or a 26-32 byte savings
RyoheiHagimoto 0:56c5742b9e2b 3444 over just using a table (not counting the instructions that would be
RyoheiHagimoto 0:56c5742b9e2b 3445 needed to do the table lookup).*/
RyoheiHagimoto 0:56c5742b9e2b 3446 if(_version==1)return 26;
RyoheiHagimoto 0:56c5742b9e2b 3447 nalign=(_version/7)+2;
RyoheiHagimoto 0:56c5742b9e2b 3448 return (_version<<4)*(_version+8)
RyoheiHagimoto 0:56c5742b9e2b 3449 -(5*nalign)*(5*nalign-2)+36*(_version<7)+83>>3;
RyoheiHagimoto 0:56c5742b9e2b 3450 }
RyoheiHagimoto 0:56c5742b9e2b 3451
RyoheiHagimoto 0:56c5742b9e2b 3452 #if 0
RyoheiHagimoto 0:56c5742b9e2b 3453 /*The number of parity bytes per Reed-Solomon block for each version and error
RyoheiHagimoto 0:56c5742b9e2b 3454 correction level.*/
RyoheiHagimoto 0:56c5742b9e2b 3455 static const unsigned char QR_RS_NPAR[40][4]={
RyoheiHagimoto 0:56c5742b9e2b 3456 { 7,10,13,17},{10,16,22,28},{15,26,18,22},{20,18,26,16},
RyoheiHagimoto 0:56c5742b9e2b 3457 {26,24,18,22},{18,16,24,28},{20,18,18,26},{24,22,22,26},
RyoheiHagimoto 0:56c5742b9e2b 3458 {30,22,20,24},{18,26,24,28},{20,30,28,24},{24,22,26,28},
RyoheiHagimoto 0:56c5742b9e2b 3459 {26,22,24,22},{30,24,20,24},{22,24,30,24},{24,28,24,30},
RyoheiHagimoto 0:56c5742b9e2b 3460 {28,28,28,28},{30,26,28,28},{28,26,26,26},{28,26,30,28},
RyoheiHagimoto 0:56c5742b9e2b 3461 {28,26,28,30},{28,28,30,24},{30,28,30,30},{30,28,30,30},
RyoheiHagimoto 0:56c5742b9e2b 3462 {26,28,30,30},{28,28,28,30},{30,28,30,30},{30,28,30,30},
RyoheiHagimoto 0:56c5742b9e2b 3463 {30,28,30,30},{30,28,30,30},{30,28,30,30},{30,28,30,30},
RyoheiHagimoto 0:56c5742b9e2b 3464 {30,28,30,30},{30,28,30,30},{30,28,30,30},{30,28,30,30},
RyoheiHagimoto 0:56c5742b9e2b 3465 {30,28,30,30},{30,28,30,30},{30,28,30,30},{30,28,30,30}
RyoheiHagimoto 0:56c5742b9e2b 3466 };
RyoheiHagimoto 0:56c5742b9e2b 3467 #endif
RyoheiHagimoto 0:56c5742b9e2b 3468
RyoheiHagimoto 0:56c5742b9e2b 3469 /*Bulk data for the number of parity bytes per Reed-Solomon block.*/
RyoheiHagimoto 0:56c5742b9e2b 3470 static const unsigned char QR_RS_NPAR_VALS[71]={
RyoheiHagimoto 0:56c5742b9e2b 3471 /*[ 0]*/ 7,10,13,17,
RyoheiHagimoto 0:56c5742b9e2b 3472 /*[ 4]*/10,16,22, 28,26,26, 26,22, 24,22,22, 26,24,18,22,
RyoheiHagimoto 0:56c5742b9e2b 3473 /*[19]*/15,26,18, 22,24, 30,24,20,24,
RyoheiHagimoto 0:56c5742b9e2b 3474 /*[28]*/18,16,24, 28, 28, 28,28,30,24,
RyoheiHagimoto 0:56c5742b9e2b 3475 /*[37]*/20,18, 18,26, 24,28,24, 30,26,28, 28, 26,28,30, 30,22,20,24,
RyoheiHagimoto 0:56c5742b9e2b 3476 /*[55]*/20,18,26,16,
RyoheiHagimoto 0:56c5742b9e2b 3477 /*[59]*/20,30,28, 24,22,26, 28,26, 30,28,30,30
RyoheiHagimoto 0:56c5742b9e2b 3478 };
RyoheiHagimoto 0:56c5742b9e2b 3479
RyoheiHagimoto 0:56c5742b9e2b 3480 /*An offset into QR_RS_NPAR_DATA for each version that gives the number of
RyoheiHagimoto 0:56c5742b9e2b 3481 parity bytes per Reed-Solomon block for each error correction level.*/
RyoheiHagimoto 0:56c5742b9e2b 3482 static const unsigned char QR_RS_NPAR_OFFS[40]={
RyoheiHagimoto 0:56c5742b9e2b 3483 0, 4,19,55,15,28,37,12,51,39,
RyoheiHagimoto 0:56c5742b9e2b 3484 59,62,10,24,22,41,31,44, 7,65,
RyoheiHagimoto 0:56c5742b9e2b 3485 47,33,67,67,48,32,67,67,67,67,
RyoheiHagimoto 0:56c5742b9e2b 3486 67,67,67,67,67,67,67,67,67,67
RyoheiHagimoto 0:56c5742b9e2b 3487 };
RyoheiHagimoto 0:56c5742b9e2b 3488
RyoheiHagimoto 0:56c5742b9e2b 3489 /*The number of Reed-Solomon blocks for each version and error correction
RyoheiHagimoto 0:56c5742b9e2b 3490 level.*/
RyoheiHagimoto 0:56c5742b9e2b 3491 static const unsigned char QR_RS_NBLOCKS[40][4]={
RyoheiHagimoto 0:56c5742b9e2b 3492 { 1, 1, 1, 1},{ 1, 1, 1, 1},{ 1, 1, 2, 2},{ 1, 2, 2, 4},
RyoheiHagimoto 0:56c5742b9e2b 3493 { 1, 2, 4, 4},{ 2, 4, 4, 4},{ 2, 4, 6, 5},{ 2, 4, 6, 6},
RyoheiHagimoto 0:56c5742b9e2b 3494 { 2, 5, 8, 8},{ 4, 5, 8, 8},{ 4, 5, 8,11},{ 4, 8,10,11},
RyoheiHagimoto 0:56c5742b9e2b 3495 { 4, 9,12,16},{ 4, 9,16,16},{ 6,10,12,18},{ 6,10,17,16},
RyoheiHagimoto 0:56c5742b9e2b 3496 { 6,11,16,19},{ 6,13,18,21},{ 7,14,21,25},{ 8,16,20,25},
RyoheiHagimoto 0:56c5742b9e2b 3497 { 8,17,23,25},{ 9,17,23,34},{ 9,18,25,30},{10,20,27,32},
RyoheiHagimoto 0:56c5742b9e2b 3498 {12,21,29,35},{12,23,34,37},{12,25,34,40},{13,26,35,42},
RyoheiHagimoto 0:56c5742b9e2b 3499 {14,28,38,45},{15,29,40,48},{16,31,43,51},{17,33,45,54},
RyoheiHagimoto 0:56c5742b9e2b 3500 {18,35,48,57},{19,37,51,60},{19,38,53,63},{20,40,56,66},
RyoheiHagimoto 0:56c5742b9e2b 3501 {21,43,59,70},{22,45,62,74},{24,47,65,77},{25,49,68,81}
RyoheiHagimoto 0:56c5742b9e2b 3502 };
RyoheiHagimoto 0:56c5742b9e2b 3503
RyoheiHagimoto 0:56c5742b9e2b 3504 /*Attempts to fully decode a QR code.
RyoheiHagimoto 0:56c5742b9e2b 3505 _qrdata: Returns the parsed code data.
RyoheiHagimoto 0:56c5742b9e2b 3506 _gf: Used for Reed-Solomon error correction.
RyoheiHagimoto 0:56c5742b9e2b 3507 _ul_pos: The location of the UL finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 3508 _ur_pos: The location of the UR finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 3509 _dl_pos: The location of the DL finder pattern.
RyoheiHagimoto 0:56c5742b9e2b 3510 _version: The (decoded) version number.
RyoheiHagimoto 0:56c5742b9e2b 3511 _fmt_info: The decoded format info.
RyoheiHagimoto 0:56c5742b9e2b 3512 _img: The binary input image.
RyoheiHagimoto 0:56c5742b9e2b 3513 _width: The width of the input image.
RyoheiHagimoto 0:56c5742b9e2b 3514 _height: The height of the input image.
RyoheiHagimoto 0:56c5742b9e2b 3515 Return: 0 on success, or a negative value on error.*/
RyoheiHagimoto 0:56c5742b9e2b 3516 static int qr_code_decode(qr_code_data *_qrdata,const rs_gf256 *_gf,
RyoheiHagimoto 0:56c5742b9e2b 3517 const qr_point _ul_pos,const qr_point _ur_pos,const qr_point _dl_pos,
RyoheiHagimoto 0:56c5742b9e2b 3518 int _version,int _fmt_info,
RyoheiHagimoto 0:56c5742b9e2b 3519 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 3520 qr_sampling_grid grid;
RyoheiHagimoto 0:56c5742b9e2b 3521 unsigned *data_bits;
RyoheiHagimoto 0:56c5742b9e2b 3522 unsigned char **blocks;
RyoheiHagimoto 0:56c5742b9e2b 3523 unsigned char *block_data;
RyoheiHagimoto 0:56c5742b9e2b 3524 int nblocks;
RyoheiHagimoto 0:56c5742b9e2b 3525 int nshort_blocks;
RyoheiHagimoto 0:56c5742b9e2b 3526 int ncodewords;
RyoheiHagimoto 0:56c5742b9e2b 3527 int block_sz;
RyoheiHagimoto 0:56c5742b9e2b 3528 int ecc_level;
RyoheiHagimoto 0:56c5742b9e2b 3529 int ndata;
RyoheiHagimoto 0:56c5742b9e2b 3530 int npar;
RyoheiHagimoto 0:56c5742b9e2b 3531 int dim;
RyoheiHagimoto 0:56c5742b9e2b 3532 int ret;
RyoheiHagimoto 0:56c5742b9e2b 3533 int i;
RyoheiHagimoto 0:56c5742b9e2b 3534 /*Read the bits out of the image.*/
RyoheiHagimoto 0:56c5742b9e2b 3535 qr_sampling_grid_init(&grid,_version,_ul_pos,_ur_pos,_dl_pos,_qrdata->bbox,
RyoheiHagimoto 0:56c5742b9e2b 3536 _img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3537 #if defined(QR_DEBUG)
RyoheiHagimoto 0:56c5742b9e2b 3538 qr_sampling_grid_dump(&grid,_version,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3539 #endif
RyoheiHagimoto 0:56c5742b9e2b 3540 dim=17+(_version<<2);
RyoheiHagimoto 0:56c5742b9e2b 3541 data_bits=(unsigned *)malloc(
RyoheiHagimoto 0:56c5742b9e2b 3542 dim*(dim+QR_INT_BITS-1>>QR_INT_LOGBITS)*sizeof(*data_bits));
RyoheiHagimoto 0:56c5742b9e2b 3543 qr_sampling_grid_sample(&grid,data_bits,dim,_fmt_info,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3544 /*Group those bits into Reed-Solomon codewords.*/
RyoheiHagimoto 0:56c5742b9e2b 3545 ecc_level=(_fmt_info>>3)^1;
RyoheiHagimoto 0:56c5742b9e2b 3546 nblocks=QR_RS_NBLOCKS[_version-1][ecc_level];
RyoheiHagimoto 0:56c5742b9e2b 3547 npar=*(QR_RS_NPAR_VALS+QR_RS_NPAR_OFFS[_version-1]+ecc_level);
RyoheiHagimoto 0:56c5742b9e2b 3548 ncodewords=qr_code_ncodewords(_version);
RyoheiHagimoto 0:56c5742b9e2b 3549 block_sz=ncodewords/nblocks;
RyoheiHagimoto 0:56c5742b9e2b 3550 nshort_blocks=nblocks-(ncodewords%nblocks);
RyoheiHagimoto 0:56c5742b9e2b 3551 blocks=(unsigned char **)malloc(nblocks*sizeof(*blocks));
RyoheiHagimoto 0:56c5742b9e2b 3552 block_data=(unsigned char *)malloc(ncodewords*sizeof(*block_data));
RyoheiHagimoto 0:56c5742b9e2b 3553 blocks[0]=block_data;
RyoheiHagimoto 0:56c5742b9e2b 3554 for(i=1;i<nblocks;i++)blocks[i]=blocks[i-1]+block_sz+(i>nshort_blocks);
RyoheiHagimoto 0:56c5742b9e2b 3555 qr_samples_unpack(blocks,nblocks,block_sz-npar,nshort_blocks,
RyoheiHagimoto 0:56c5742b9e2b 3556 data_bits,grid.fpmask,dim);
RyoheiHagimoto 0:56c5742b9e2b 3557 qr_sampling_grid_clear(&grid);
RyoheiHagimoto 0:56c5742b9e2b 3558 free(blocks);
RyoheiHagimoto 0:56c5742b9e2b 3559 free(data_bits);
RyoheiHagimoto 0:56c5742b9e2b 3560 /*Perform the error correction.*/
RyoheiHagimoto 0:56c5742b9e2b 3561 ndata=0;
RyoheiHagimoto 0:56c5742b9e2b 3562 ncodewords=0;
RyoheiHagimoto 0:56c5742b9e2b 3563 ret=0;
RyoheiHagimoto 0:56c5742b9e2b 3564 for(i=0;i<nblocks;i++){
RyoheiHagimoto 0:56c5742b9e2b 3565 int block_szi;
RyoheiHagimoto 0:56c5742b9e2b 3566 int ndatai;
RyoheiHagimoto 0:56c5742b9e2b 3567 block_szi=block_sz+(i>=nshort_blocks);
RyoheiHagimoto 0:56c5742b9e2b 3568 if(rs_correct(_gf,QR_M0,block_data+ncodewords,block_szi,npar,NULL,0)<0){
RyoheiHagimoto 0:56c5742b9e2b 3569 ret=-1;
RyoheiHagimoto 0:56c5742b9e2b 3570 break;
RyoheiHagimoto 0:56c5742b9e2b 3571 }
RyoheiHagimoto 0:56c5742b9e2b 3572 ndatai=block_szi-npar;
RyoheiHagimoto 0:56c5742b9e2b 3573 memmove(block_data+ndata,block_data+ncodewords,ndatai*sizeof(*block_data));
RyoheiHagimoto 0:56c5742b9e2b 3574 ncodewords+=block_szi;
RyoheiHagimoto 0:56c5742b9e2b 3575 ndata+=ndatai;
RyoheiHagimoto 0:56c5742b9e2b 3576 }
RyoheiHagimoto 0:56c5742b9e2b 3577 /*Parse the corrected bitstream.*/
RyoheiHagimoto 0:56c5742b9e2b 3578 if(ret>=0){
RyoheiHagimoto 0:56c5742b9e2b 3579 ret=qr_code_data_parse(_qrdata,_version,block_data,ndata);
RyoheiHagimoto 0:56c5742b9e2b 3580 /*We could return any partially decoded data, but then we'd have to have
RyoheiHagimoto 0:56c5742b9e2b 3581 API support for that; a mode ignoring ECC errors might also be useful.*/
RyoheiHagimoto 0:56c5742b9e2b 3582 if(ret<0)qr_code_data_clear(_qrdata);
RyoheiHagimoto 0:56c5742b9e2b 3583 _qrdata->version=_version;
RyoheiHagimoto 0:56c5742b9e2b 3584 _qrdata->ecc_level=ecc_level;
RyoheiHagimoto 0:56c5742b9e2b 3585 }
RyoheiHagimoto 0:56c5742b9e2b 3586 free(block_data);
RyoheiHagimoto 0:56c5742b9e2b 3587 return ret;
RyoheiHagimoto 0:56c5742b9e2b 3588 }
RyoheiHagimoto 0:56c5742b9e2b 3589
RyoheiHagimoto 0:56c5742b9e2b 3590 /*Searches for an arrangement of these three finder centers that yields a valid
RyoheiHagimoto 0:56c5742b9e2b 3591 configuration.
RyoheiHagimoto 0:56c5742b9e2b 3592 _c: On input, the three finder centers to consider in any order.
RyoheiHagimoto 0:56c5742b9e2b 3593 Return: The detected version number, or a negative value on error.*/
RyoheiHagimoto 0:56c5742b9e2b 3594 static int qr_reader_try_configuration(qr_reader *_reader,
RyoheiHagimoto 0:56c5742b9e2b 3595 qr_code_data *_qrdata,const unsigned char *_img,int _width,int _height,
RyoheiHagimoto 0:56c5742b9e2b 3596 qr_finder_center *_c[3]){
RyoheiHagimoto 0:56c5742b9e2b 3597 int ci[7];
RyoheiHagimoto 0:56c5742b9e2b 3598 unsigned maxd;
RyoheiHagimoto 0:56c5742b9e2b 3599 int ccw;
RyoheiHagimoto 0:56c5742b9e2b 3600 int i0;
RyoheiHagimoto 0:56c5742b9e2b 3601 int i;
RyoheiHagimoto 0:56c5742b9e2b 3602 /*Sort the points in counter-clockwise order.*/
RyoheiHagimoto 0:56c5742b9e2b 3603 ccw=qr_point_ccw(_c[0]->pos,_c[1]->pos,_c[2]->pos);
RyoheiHagimoto 0:56c5742b9e2b 3604 /*Colinear points can't be the corners of a quadrilateral.*/
RyoheiHagimoto 0:56c5742b9e2b 3605 if(!ccw)return -1;
RyoheiHagimoto 0:56c5742b9e2b 3606 /*Include a few extra copies of the cyclical list to avoid mods.*/
RyoheiHagimoto 0:56c5742b9e2b 3607 ci[6]=ci[3]=ci[0]=0;
RyoheiHagimoto 0:56c5742b9e2b 3608 ci[4]=ci[1]=1+(ccw<0);
RyoheiHagimoto 0:56c5742b9e2b 3609 ci[5]=ci[2]=2-(ccw<0);
RyoheiHagimoto 0:56c5742b9e2b 3610 /*Assume the points farthest from each other are the opposite corners, and
RyoheiHagimoto 0:56c5742b9e2b 3611 find the top-left point.*/
RyoheiHagimoto 0:56c5742b9e2b 3612 maxd=qr_point_distance2(_c[1]->pos,_c[2]->pos);
RyoheiHagimoto 0:56c5742b9e2b 3613 i0=0;
RyoheiHagimoto 0:56c5742b9e2b 3614 for(i=1;i<3;i++){
RyoheiHagimoto 0:56c5742b9e2b 3615 unsigned d;
RyoheiHagimoto 0:56c5742b9e2b 3616 d=qr_point_distance2(_c[ci[i+1]]->pos,_c[ci[i+2]]->pos);
RyoheiHagimoto 0:56c5742b9e2b 3617 if(d>maxd){
RyoheiHagimoto 0:56c5742b9e2b 3618 i0=i;
RyoheiHagimoto 0:56c5742b9e2b 3619 maxd=d;
RyoheiHagimoto 0:56c5742b9e2b 3620 }
RyoheiHagimoto 0:56c5742b9e2b 3621 }
RyoheiHagimoto 0:56c5742b9e2b 3622 /*However, try all three possible orderings, just to be sure (a severely
RyoheiHagimoto 0:56c5742b9e2b 3623 skewed projection could move opposite corners closer than adjacent).*/
RyoheiHagimoto 0:56c5742b9e2b 3624 for(i=i0;i<i0+3;i++){
RyoheiHagimoto 0:56c5742b9e2b 3625 qr_aff aff;
RyoheiHagimoto 0:56c5742b9e2b 3626 qr_hom hom;
RyoheiHagimoto 0:56c5742b9e2b 3627 qr_finder ul;
RyoheiHagimoto 0:56c5742b9e2b 3628 qr_finder ur;
RyoheiHagimoto 0:56c5742b9e2b 3629 qr_finder dl;
RyoheiHagimoto 0:56c5742b9e2b 3630 int res;
RyoheiHagimoto 0:56c5742b9e2b 3631 int ur_version;
RyoheiHagimoto 0:56c5742b9e2b 3632 int dl_version;
RyoheiHagimoto 0:56c5742b9e2b 3633 int fmt_info;
RyoheiHagimoto 0:56c5742b9e2b 3634 ul.c=_c[ci[i]];
RyoheiHagimoto 0:56c5742b9e2b 3635 ur.c=_c[ci[i+1]];
RyoheiHagimoto 0:56c5742b9e2b 3636 dl.c=_c[ci[i+2]];
RyoheiHagimoto 0:56c5742b9e2b 3637 /*Estimate the module size and version number from the two opposite corners.
RyoheiHagimoto 0:56c5742b9e2b 3638 The module size is not constant in the image, so we compute an affine
RyoheiHagimoto 0:56c5742b9e2b 3639 projection from the three points we have to a square domain, and
RyoheiHagimoto 0:56c5742b9e2b 3640 estimate it there.
RyoheiHagimoto 0:56c5742b9e2b 3641 Although it should be the same along both axes, we keep separate
RyoheiHagimoto 0:56c5742b9e2b 3642 estimates to account for any remaining projective distortion.*/
RyoheiHagimoto 0:56c5742b9e2b 3643 res=QR_INT_BITS-2-QR_FINDER_SUBPREC-qr_ilog(QR_MAXI(_width,_height)-1);
RyoheiHagimoto 0:56c5742b9e2b 3644 qr_aff_init(&aff,ul.c->pos,ur.c->pos,dl.c->pos,res);
RyoheiHagimoto 0:56c5742b9e2b 3645 qr_aff_unproject(ur.o,&aff,ur.c->pos[0],ur.c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3646 qr_finder_edge_pts_aff_classify(&ur,&aff);
RyoheiHagimoto 0:56c5742b9e2b 3647 if(qr_finder_estimate_module_size_and_version(&ur,1<<res,1<<res)<0)continue;
RyoheiHagimoto 0:56c5742b9e2b 3648 qr_aff_unproject(dl.o,&aff,dl.c->pos[0],dl.c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3649 qr_finder_edge_pts_aff_classify(&dl,&aff);
RyoheiHagimoto 0:56c5742b9e2b 3650 if(qr_finder_estimate_module_size_and_version(&dl,1<<res,1<<res)<0)continue;
RyoheiHagimoto 0:56c5742b9e2b 3651 /*If the estimated versions are significantly different, reject the
RyoheiHagimoto 0:56c5742b9e2b 3652 configuration.*/
RyoheiHagimoto 0:56c5742b9e2b 3653 if(abs(ur.eversion[1]-dl.eversion[0])>QR_LARGE_VERSION_SLACK)continue;
RyoheiHagimoto 0:56c5742b9e2b 3654 qr_aff_unproject(ul.o,&aff,ul.c->pos[0],ul.c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3655 qr_finder_edge_pts_aff_classify(&ul,&aff);
RyoheiHagimoto 0:56c5742b9e2b 3656 if(qr_finder_estimate_module_size_and_version(&ul,1<<res,1<<res)<0||
RyoheiHagimoto 0:56c5742b9e2b 3657 abs(ul.eversion[1]-ur.eversion[1])>QR_LARGE_VERSION_SLACK||
RyoheiHagimoto 0:56c5742b9e2b 3658 abs(ul.eversion[0]-dl.eversion[0])>QR_LARGE_VERSION_SLACK){
RyoheiHagimoto 0:56c5742b9e2b 3659 continue;
RyoheiHagimoto 0:56c5742b9e2b 3660 }
RyoheiHagimoto 0:56c5742b9e2b 3661 #if defined(QR_DEBUG)
RyoheiHagimoto 0:56c5742b9e2b 3662 qr_finder_dump_aff_undistorted(&ul,&ur,&dl,&aff,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3663 #endif
RyoheiHagimoto 0:56c5742b9e2b 3664 /*If we made it this far, upgrade the affine homography to a full
RyoheiHagimoto 0:56c5742b9e2b 3665 homography.*/
RyoheiHagimoto 0:56c5742b9e2b 3666 if(qr_hom_fit(&hom,&ul,&ur,&dl,_qrdata->bbox,&aff,
RyoheiHagimoto 0:56c5742b9e2b 3667 &_reader->isaac,_img,_width,_height)<0){
RyoheiHagimoto 0:56c5742b9e2b 3668 continue;
RyoheiHagimoto 0:56c5742b9e2b 3669 }
RyoheiHagimoto 0:56c5742b9e2b 3670 qr_hom_unproject(ul.o,&hom,ul.c->pos[0],ul.c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3671 qr_hom_unproject(ur.o,&hom,ur.c->pos[0],ur.c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3672 qr_hom_unproject(dl.o,&hom,dl.c->pos[0],dl.c->pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3673 qr_finder_edge_pts_hom_classify(&ur,&hom);
RyoheiHagimoto 0:56c5742b9e2b 3674 if(qr_finder_estimate_module_size_and_version(&ur,
RyoheiHagimoto 0:56c5742b9e2b 3675 ur.o[0]-ul.o[0],ur.o[0]-ul.o[0])<0){
RyoheiHagimoto 0:56c5742b9e2b 3676 continue;
RyoheiHagimoto 0:56c5742b9e2b 3677 }
RyoheiHagimoto 0:56c5742b9e2b 3678 qr_finder_edge_pts_hom_classify(&dl,&hom);
RyoheiHagimoto 0:56c5742b9e2b 3679 if(qr_finder_estimate_module_size_and_version(&dl,
RyoheiHagimoto 0:56c5742b9e2b 3680 dl.o[1]-ul.o[1],dl.o[1]-ul.o[1])<0){
RyoheiHagimoto 0:56c5742b9e2b 3681 continue;
RyoheiHagimoto 0:56c5742b9e2b 3682 }
RyoheiHagimoto 0:56c5742b9e2b 3683 #if defined(QR_DEBUG)
RyoheiHagimoto 0:56c5742b9e2b 3684 qr_finder_dump_hom_undistorted(&ul,&ur,&dl,&hom,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3685 #endif
RyoheiHagimoto 0:56c5742b9e2b 3686 /*If we have a small version (less than 7), there's no encoded version
RyoheiHagimoto 0:56c5742b9e2b 3687 information.
RyoheiHagimoto 0:56c5742b9e2b 3688 If the estimated version on the two corners matches and is sufficiently
RyoheiHagimoto 0:56c5742b9e2b 3689 small, we assume this is the case.*/
RyoheiHagimoto 0:56c5742b9e2b 3690 if(ur.eversion[1]==dl.eversion[0]&&ur.eversion[1]<7){
RyoheiHagimoto 0:56c5742b9e2b 3691 /*We used to do a whole bunch of extra geometric checks for small
RyoheiHagimoto 0:56c5742b9e2b 3692 versions, because with just an affine correction, it was fairly easy
RyoheiHagimoto 0:56c5742b9e2b 3693 to estimate two consistent module sizes given a random configuration.
RyoheiHagimoto 0:56c5742b9e2b 3694 However, now that we're estimating a full homography, these appear to
RyoheiHagimoto 0:56c5742b9e2b 3695 be unnecessary.*/
RyoheiHagimoto 0:56c5742b9e2b 3696 #if 0
RyoheiHagimoto 0:56c5742b9e2b 3697 static const signed char LINE_TESTS[12][6]={
RyoheiHagimoto 0:56c5742b9e2b 3698 /*DL left, UL > 0, UR > 0*/
RyoheiHagimoto 0:56c5742b9e2b 3699 {2,0,0, 1,1, 1},
RyoheiHagimoto 0:56c5742b9e2b 3700 /*DL right, UL > 0, UR < 0*/
RyoheiHagimoto 0:56c5742b9e2b 3701 {2,1,0, 1,1,-1},
RyoheiHagimoto 0:56c5742b9e2b 3702 /*UR top, UL > 0, DL > 0*/
RyoheiHagimoto 0:56c5742b9e2b 3703 {1,2,0, 1,2, 1},
RyoheiHagimoto 0:56c5742b9e2b 3704 /*UR bottom, UL > 0, DL < 0*/
RyoheiHagimoto 0:56c5742b9e2b 3705 {1,3,0, 1,2,-1},
RyoheiHagimoto 0:56c5742b9e2b 3706 /*UR left, DL < 0, UL < 0*/
RyoheiHagimoto 0:56c5742b9e2b 3707 {1,0,2,-1,0,-1},
RyoheiHagimoto 0:56c5742b9e2b 3708 /*UR right, DL > 0, UL > 0*/
RyoheiHagimoto 0:56c5742b9e2b 3709 {1,1,2, 1,0, 1},
RyoheiHagimoto 0:56c5742b9e2b 3710 /*DL top, UR < 0, UL < 0*/
RyoheiHagimoto 0:56c5742b9e2b 3711 {2,2,1,-1,0,-1},
RyoheiHagimoto 0:56c5742b9e2b 3712 /*DL bottom, UR > 0, UL > 0*/
RyoheiHagimoto 0:56c5742b9e2b 3713 {2,3,1, 1,0, 1},
RyoheiHagimoto 0:56c5742b9e2b 3714 /*UL left, DL > 0, UR > 0*/
RyoheiHagimoto 0:56c5742b9e2b 3715 {0,0,2, 1,1, 1},
RyoheiHagimoto 0:56c5742b9e2b 3716 /*UL right, DL > 0, UR < 0*/
RyoheiHagimoto 0:56c5742b9e2b 3717 {0,1,2, 1,1,-1},
RyoheiHagimoto 0:56c5742b9e2b 3718 /*UL top, UR > 0, DL > 0*/
RyoheiHagimoto 0:56c5742b9e2b 3719 {0,2,1, 1,2, 1},
RyoheiHagimoto 0:56c5742b9e2b 3720 /*UL bottom, UR > 0, DL < 0*/
RyoheiHagimoto 0:56c5742b9e2b 3721 {0,3,1, 1,2,-1}
RyoheiHagimoto 0:56c5742b9e2b 3722 };
RyoheiHagimoto 0:56c5742b9e2b 3723 qr_finder *f[3];
RyoheiHagimoto 0:56c5742b9e2b 3724 int j;
RyoheiHagimoto 0:56c5742b9e2b 3725 /*Start by decoding the format information.
RyoheiHagimoto 0:56c5742b9e2b 3726 This is cheap, but unlikely to reject invalid configurations.
RyoheiHagimoto 0:56c5742b9e2b 3727 56.25% of all bitstrings are valid, and we mix and match several pieces
RyoheiHagimoto 0:56c5742b9e2b 3728 until we find a valid combination, so our real chances of finding a
RyoheiHagimoto 0:56c5742b9e2b 3729 valid codeword in random bits are even higher.*/
RyoheiHagimoto 0:56c5742b9e2b 3730 fmt_info=qr_finder_fmt_info_decode(&ul,&ur,&dl,&aff,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3731 if(fmt_info<0)continue;
RyoheiHagimoto 0:56c5742b9e2b 3732 /*Now we fit lines to the edges of each finder pattern and check to make
RyoheiHagimoto 0:56c5742b9e2b 3733 sure the centers of the other finder patterns lie on the proper side.*/
RyoheiHagimoto 0:56c5742b9e2b 3734 f[0]=&ul;
RyoheiHagimoto 0:56c5742b9e2b 3735 f[1]=&ur;
RyoheiHagimoto 0:56c5742b9e2b 3736 f[2]=&dl;
RyoheiHagimoto 0:56c5742b9e2b 3737 for(j=0;j<12;j++){
RyoheiHagimoto 0:56c5742b9e2b 3738 const signed char *t;
RyoheiHagimoto 0:56c5742b9e2b 3739 qr_line l0;
RyoheiHagimoto 0:56c5742b9e2b 3740 int *p;
RyoheiHagimoto 0:56c5742b9e2b 3741 t=LINE_TESTS[j];
RyoheiHagimoto 0:56c5742b9e2b 3742 qr_finder_ransac(f[t[0]],&aff,&_reader->isaac,t[1]);
RyoheiHagimoto 0:56c5742b9e2b 3743 /*We may not have enough points to fit a line accurately here.
RyoheiHagimoto 0:56c5742b9e2b 3744 If not, we just skip the test.*/
RyoheiHagimoto 0:56c5742b9e2b 3745 if(qr_line_fit_finder_edge(l0,f[t[0]],t[1],res)<0)continue;
RyoheiHagimoto 0:56c5742b9e2b 3746 p=f[t[2]]->c->pos;
RyoheiHagimoto 0:56c5742b9e2b 3747 if(qr_line_eval(l0,p[0],p[1])*t[3]<0)break;
RyoheiHagimoto 0:56c5742b9e2b 3748 p=f[t[4]]->c->pos;
RyoheiHagimoto 0:56c5742b9e2b 3749 if(qr_line_eval(l0,p[0],p[1])*t[5]<0)break;
RyoheiHagimoto 0:56c5742b9e2b 3750 }
RyoheiHagimoto 0:56c5742b9e2b 3751 if(j<12)continue;
RyoheiHagimoto 0:56c5742b9e2b 3752 /*All tests passed.*/
RyoheiHagimoto 0:56c5742b9e2b 3753 #endif
RyoheiHagimoto 0:56c5742b9e2b 3754 ur_version=ur.eversion[1];
RyoheiHagimoto 0:56c5742b9e2b 3755 }
RyoheiHagimoto 0:56c5742b9e2b 3756 else{
RyoheiHagimoto 0:56c5742b9e2b 3757 /*If the estimated versions are significantly different, reject the
RyoheiHagimoto 0:56c5742b9e2b 3758 configuration.*/
RyoheiHagimoto 0:56c5742b9e2b 3759 if(abs(ur.eversion[1]-dl.eversion[0])>QR_LARGE_VERSION_SLACK)continue;
RyoheiHagimoto 0:56c5742b9e2b 3760 /*Otherwise we try to read the actual version data from the image.
RyoheiHagimoto 0:56c5742b9e2b 3761 If the real version is not sufficiently close to our estimated version,
RyoheiHagimoto 0:56c5742b9e2b 3762 then we assume there was an unrecoverable decoding error (so many bit
RyoheiHagimoto 0:56c5742b9e2b 3763 errors we were within 3 errors of another valid code), and throw that
RyoheiHagimoto 0:56c5742b9e2b 3764 value away.
RyoheiHagimoto 0:56c5742b9e2b 3765 If no decoded version could be sufficiently close, we don't even try.*/
RyoheiHagimoto 0:56c5742b9e2b 3766 if(ur.eversion[1]>=7-QR_LARGE_VERSION_SLACK){
RyoheiHagimoto 0:56c5742b9e2b 3767 ur_version=qr_finder_version_decode(&ur,&hom,_img,_width,_height,0);
RyoheiHagimoto 0:56c5742b9e2b 3768 if(abs(ur_version-ur.eversion[1])>QR_LARGE_VERSION_SLACK)ur_version=-1;
RyoheiHagimoto 0:56c5742b9e2b 3769 }
RyoheiHagimoto 0:56c5742b9e2b 3770 else ur_version=-1;
RyoheiHagimoto 0:56c5742b9e2b 3771 if(dl.eversion[0]>=7-QR_LARGE_VERSION_SLACK){
RyoheiHagimoto 0:56c5742b9e2b 3772 dl_version=qr_finder_version_decode(&dl,&hom,_img,_width,_height,1);
RyoheiHagimoto 0:56c5742b9e2b 3773 if(abs(dl_version-dl.eversion[0])>QR_LARGE_VERSION_SLACK)dl_version=-1;
RyoheiHagimoto 0:56c5742b9e2b 3774 }
RyoheiHagimoto 0:56c5742b9e2b 3775 else dl_version=-1;
RyoheiHagimoto 0:56c5742b9e2b 3776 /*If we got at least one valid version, or we got two and they match,
RyoheiHagimoto 0:56c5742b9e2b 3777 then we found a valid configuration.*/
RyoheiHagimoto 0:56c5742b9e2b 3778 if(ur_version>=0){
RyoheiHagimoto 0:56c5742b9e2b 3779 if(dl_version>=0&&dl_version!=ur_version)continue;
RyoheiHagimoto 0:56c5742b9e2b 3780 }
RyoheiHagimoto 0:56c5742b9e2b 3781 else if(dl_version<0)continue;
RyoheiHagimoto 0:56c5742b9e2b 3782 else ur_version=dl_version;
RyoheiHagimoto 0:56c5742b9e2b 3783 }
RyoheiHagimoto 0:56c5742b9e2b 3784 qr_finder_edge_pts_hom_classify(&ul,&hom);
RyoheiHagimoto 0:56c5742b9e2b 3785 if(qr_finder_estimate_module_size_and_version(&ul,
RyoheiHagimoto 0:56c5742b9e2b 3786 ur.o[0]-dl.o[0],dl.o[1]-ul.o[1])<0||
RyoheiHagimoto 0:56c5742b9e2b 3787 abs(ul.eversion[1]-ur.eversion[1])>QR_SMALL_VERSION_SLACK||
RyoheiHagimoto 0:56c5742b9e2b 3788 abs(ul.eversion[0]-dl.eversion[0])>QR_SMALL_VERSION_SLACK){
RyoheiHagimoto 0:56c5742b9e2b 3789 continue;
RyoheiHagimoto 0:56c5742b9e2b 3790 }
RyoheiHagimoto 0:56c5742b9e2b 3791 fmt_info=qr_finder_fmt_info_decode(&ul,&ur,&dl,&hom,_img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3792 if(fmt_info<0)continue;
RyoheiHagimoto 0:56c5742b9e2b 3793 if(qr_code_decode(_qrdata,&_reader->gf,ul.c->pos,ur.c->pos,dl.c->pos,
RyoheiHagimoto 0:56c5742b9e2b 3794 ur_version,fmt_info,_img,_width,_height)<0){
RyoheiHagimoto 0:56c5742b9e2b 3795 /*TODO: Maybe somebody flipped the code?
RyoheiHagimoto 0:56c5742b9e2b 3796 We'd still get a valid version, and probably valid (but incorrect)
RyoheiHagimoto 0:56c5742b9e2b 3797 format info.
RyoheiHagimoto 0:56c5742b9e2b 3798 After we've come this far, it should be a simple matter to check.*/
RyoheiHagimoto 0:56c5742b9e2b 3799 continue;
RyoheiHagimoto 0:56c5742b9e2b 3800 }
RyoheiHagimoto 0:56c5742b9e2b 3801 return ur_version;
RyoheiHagimoto 0:56c5742b9e2b 3802 }
RyoheiHagimoto 0:56c5742b9e2b 3803 return -1;
RyoheiHagimoto 0:56c5742b9e2b 3804 }
RyoheiHagimoto 0:56c5742b9e2b 3805
RyoheiHagimoto 0:56c5742b9e2b 3806 void qr_reader_match_centers(qr_reader *_reader,qr_code_data_list *_qrlist,
RyoheiHagimoto 0:56c5742b9e2b 3807 qr_finder_center *_centers,int _ncenters,
RyoheiHagimoto 0:56c5742b9e2b 3808 const unsigned char *_img,int _width,int _height){
RyoheiHagimoto 0:56c5742b9e2b 3809 /*The number of centers should be small, so an O(n^3) exhaustive search of
RyoheiHagimoto 0:56c5742b9e2b 3810 which ones go together should be reasonable.*/
RyoheiHagimoto 0:56c5742b9e2b 3811 unsigned char *mark;
RyoheiHagimoto 0:56c5742b9e2b 3812 int i;
RyoheiHagimoto 0:56c5742b9e2b 3813 int j;
RyoheiHagimoto 0:56c5742b9e2b 3814 int k;
RyoheiHagimoto 0:56c5742b9e2b 3815 mark=(unsigned char *)calloc(_ncenters,sizeof(*mark));
RyoheiHagimoto 0:56c5742b9e2b 3816 for(i=0;i<_ncenters;i++){
RyoheiHagimoto 0:56c5742b9e2b 3817 /*TODO: We might be able to accelerate this step significantly by
RyoheiHagimoto 0:56c5742b9e2b 3818 considering the remaining finder centers in a more intelligent order,
RyoheiHagimoto 0:56c5742b9e2b 3819 based on the first finder center we just chose.*/
RyoheiHagimoto 0:56c5742b9e2b 3820 for(j=i+1;!mark[i]&&j<_ncenters;j++){
RyoheiHagimoto 0:56c5742b9e2b 3821 for(k=j+1;!mark[j]&&k<_ncenters;k++)if(!mark[k]){
RyoheiHagimoto 0:56c5742b9e2b 3822 qr_finder_center *c[3];
RyoheiHagimoto 0:56c5742b9e2b 3823 qr_code_data qrdata;
RyoheiHagimoto 0:56c5742b9e2b 3824 int version;
RyoheiHagimoto 0:56c5742b9e2b 3825 c[0]=_centers+i;
RyoheiHagimoto 0:56c5742b9e2b 3826 c[1]=_centers+j;
RyoheiHagimoto 0:56c5742b9e2b 3827 c[2]=_centers+k;
RyoheiHagimoto 0:56c5742b9e2b 3828 version=qr_reader_try_configuration(_reader,&qrdata,
RyoheiHagimoto 0:56c5742b9e2b 3829 _img,_width,_height,c);
RyoheiHagimoto 0:56c5742b9e2b 3830 if(version>=0){
RyoheiHagimoto 0:56c5742b9e2b 3831 int ninside;
RyoheiHagimoto 0:56c5742b9e2b 3832 int l;
RyoheiHagimoto 0:56c5742b9e2b 3833 /*Add the data to the list.*/
RyoheiHagimoto 0:56c5742b9e2b 3834 qr_code_data_list_add(_qrlist,&qrdata);
RyoheiHagimoto 0:56c5742b9e2b 3835 /*Convert the bounding box we're returning to the user to normal
RyoheiHagimoto 0:56c5742b9e2b 3836 image coordinates.*/
RyoheiHagimoto 0:56c5742b9e2b 3837 for(l=0;l<4;l++){
RyoheiHagimoto 0:56c5742b9e2b 3838 _qrlist->qrdata[_qrlist->nqrdata-1].bbox[l][0]>>=QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 3839 _qrlist->qrdata[_qrlist->nqrdata-1].bbox[l][1]>>=QR_FINDER_SUBPREC;
RyoheiHagimoto 0:56c5742b9e2b 3840 }
RyoheiHagimoto 0:56c5742b9e2b 3841 /*Mark these centers as used.*/
RyoheiHagimoto 0:56c5742b9e2b 3842 mark[i]=mark[j]=mark[k]=1;
RyoheiHagimoto 0:56c5742b9e2b 3843 /*Find any other finder centers located inside this code.*/
RyoheiHagimoto 0:56c5742b9e2b 3844 for(l=ninside=0;l<_ncenters;l++)if(!mark[l]){
RyoheiHagimoto 0:56c5742b9e2b 3845 if(qr_point_ccw(qrdata.bbox[0],qrdata.bbox[1],_centers[l].pos)>=0&&
RyoheiHagimoto 0:56c5742b9e2b 3846 qr_point_ccw(qrdata.bbox[1],qrdata.bbox[3],_centers[l].pos)>=0&&
RyoheiHagimoto 0:56c5742b9e2b 3847 qr_point_ccw(qrdata.bbox[3],qrdata.bbox[2],_centers[l].pos)>=0&&
RyoheiHagimoto 0:56c5742b9e2b 3848 qr_point_ccw(qrdata.bbox[2],qrdata.bbox[0],_centers[l].pos)>=0){
RyoheiHagimoto 0:56c5742b9e2b 3849 mark[l]=2;
RyoheiHagimoto 0:56c5742b9e2b 3850 ninside++;
RyoheiHagimoto 0:56c5742b9e2b 3851 }
RyoheiHagimoto 0:56c5742b9e2b 3852 }
RyoheiHagimoto 0:56c5742b9e2b 3853 if(ninside>=3){
RyoheiHagimoto 0:56c5742b9e2b 3854 /*We might have a "Double QR": a code inside a code.
RyoheiHagimoto 0:56c5742b9e2b 3855 Copy the relevant centers to a new array and do a search confined
RyoheiHagimoto 0:56c5742b9e2b 3856 to that subset.*/
RyoheiHagimoto 0:56c5742b9e2b 3857 qr_finder_center *inside;
RyoheiHagimoto 0:56c5742b9e2b 3858 inside=(qr_finder_center *)malloc(ninside*sizeof(*inside));
RyoheiHagimoto 0:56c5742b9e2b 3859 for(l=ninside=0;l<_ncenters;l++){
RyoheiHagimoto 0:56c5742b9e2b 3860 if(mark[l]==2)*&inside[ninside++]=*&_centers[l];
RyoheiHagimoto 0:56c5742b9e2b 3861 }
RyoheiHagimoto 0:56c5742b9e2b 3862 qr_reader_match_centers(_reader,_qrlist,inside,ninside,
RyoheiHagimoto 0:56c5742b9e2b 3863 _img,_width,_height);
RyoheiHagimoto 0:56c5742b9e2b 3864 free(inside);
RyoheiHagimoto 0:56c5742b9e2b 3865 }
RyoheiHagimoto 0:56c5742b9e2b 3866 /*Mark _all_ such centers used: codes cannot partially overlap.*/
RyoheiHagimoto 0:56c5742b9e2b 3867 for(l=0;l<_ncenters;l++)if(mark[l]==2)mark[l]=1;
RyoheiHagimoto 0:56c5742b9e2b 3868 }
RyoheiHagimoto 0:56c5742b9e2b 3869 }
RyoheiHagimoto 0:56c5742b9e2b 3870 }
RyoheiHagimoto 0:56c5742b9e2b 3871 }
RyoheiHagimoto 0:56c5742b9e2b 3872 free(mark);
RyoheiHagimoto 0:56c5742b9e2b 3873 }
RyoheiHagimoto 0:56c5742b9e2b 3874
RyoheiHagimoto 0:56c5742b9e2b 3875 int _zbar_qr_found_line (qr_reader *reader,
RyoheiHagimoto 0:56c5742b9e2b 3876 int dir,
RyoheiHagimoto 0:56c5742b9e2b 3877 const qr_finder_line *line)
RyoheiHagimoto 0:56c5742b9e2b 3878 {
RyoheiHagimoto 0:56c5742b9e2b 3879 /* minimally intrusive brute force version */
RyoheiHagimoto 0:56c5742b9e2b 3880 qr_finder_lines *lines = &reader->finder_lines[dir];
RyoheiHagimoto 0:56c5742b9e2b 3881
RyoheiHagimoto 0:56c5742b9e2b 3882 if(lines->nlines >= lines->clines) {
RyoheiHagimoto 0:56c5742b9e2b 3883 lines->clines *= 2;
RyoheiHagimoto 0:56c5742b9e2b 3884 lines->lines = realloc(lines->lines,
RyoheiHagimoto 0:56c5742b9e2b 3885 ++lines->clines * sizeof(*lines->lines));
RyoheiHagimoto 0:56c5742b9e2b 3886 }
RyoheiHagimoto 0:56c5742b9e2b 3887
RyoheiHagimoto 0:56c5742b9e2b 3888 memcpy(lines->lines + lines->nlines++, line, sizeof(*line));
RyoheiHagimoto 0:56c5742b9e2b 3889
RyoheiHagimoto 0:56c5742b9e2b 3890 return(0);
RyoheiHagimoto 0:56c5742b9e2b 3891 }
RyoheiHagimoto 0:56c5742b9e2b 3892
RyoheiHagimoto 0:56c5742b9e2b 3893 static inline void qr_svg_centers (const qr_finder_center *centers,
RyoheiHagimoto 0:56c5742b9e2b 3894 int ncenters)
RyoheiHagimoto 0:56c5742b9e2b 3895 {
RyoheiHagimoto 0:56c5742b9e2b 3896 int i, j;
RyoheiHagimoto 0:56c5742b9e2b 3897 svg_path_start("centers", 1, 0, 0);
RyoheiHagimoto 0:56c5742b9e2b 3898 for(i = 0; i < ncenters; i++)
RyoheiHagimoto 0:56c5742b9e2b 3899 svg_path_moveto(SVG_ABS, centers[i].pos[0], centers[i].pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3900 svg_path_end();
RyoheiHagimoto 0:56c5742b9e2b 3901
RyoheiHagimoto 0:56c5742b9e2b 3902 svg_path_start("edge-pts", 1, 0, 0);
RyoheiHagimoto 0:56c5742b9e2b 3903 for(i = 0; i < ncenters; i++) {
RyoheiHagimoto 0:56c5742b9e2b 3904 const qr_finder_center *cen = centers + i;
RyoheiHagimoto 0:56c5742b9e2b 3905 for(j = 0; j < cen->nedge_pts; j++)
RyoheiHagimoto 0:56c5742b9e2b 3906 svg_path_moveto(SVG_ABS,
RyoheiHagimoto 0:56c5742b9e2b 3907 cen->edge_pts[j].pos[0], cen->edge_pts[j].pos[1]);
RyoheiHagimoto 0:56c5742b9e2b 3908 }
RyoheiHagimoto 0:56c5742b9e2b 3909 svg_path_end();
RyoheiHagimoto 0:56c5742b9e2b 3910 }
RyoheiHagimoto 0:56c5742b9e2b 3911
RyoheiHagimoto 0:56c5742b9e2b 3912 int _zbar_qr_decode (qr_reader *reader,
RyoheiHagimoto 0:56c5742b9e2b 3913 zbar_image_scanner_t *iscn,
RyoheiHagimoto 0:56c5742b9e2b 3914 zbar_image_t *img)
RyoheiHagimoto 0:56c5742b9e2b 3915 {
RyoheiHagimoto 0:56c5742b9e2b 3916 int nqrdata = 0;
RyoheiHagimoto 0:56c5742b9e2b 3917 qr_finder_edge_pt *edge_pts = NULL;
RyoheiHagimoto 0:56c5742b9e2b 3918 qr_finder_center *centers = NULL;
RyoheiHagimoto 0:56c5742b9e2b 3919
RyoheiHagimoto 0:56c5742b9e2b 3920 if(reader->finder_lines[0].nlines < 9 ||
RyoheiHagimoto 0:56c5742b9e2b 3921 reader->finder_lines[1].nlines < 9)
RyoheiHagimoto 0:56c5742b9e2b 3922 return(0);
RyoheiHagimoto 0:56c5742b9e2b 3923
RyoheiHagimoto 0:56c5742b9e2b 3924 svg_group_start("finder", 0, 1. / (1 << QR_FINDER_SUBPREC), 0, 0, 0);
RyoheiHagimoto 0:56c5742b9e2b 3925
RyoheiHagimoto 0:56c5742b9e2b 3926 int ncenters = qr_finder_centers_locate(&centers, &edge_pts, reader, 0, 0);
RyoheiHagimoto 0:56c5742b9e2b 3927
RyoheiHagimoto 0:56c5742b9e2b 3928 zprintf(14, "%dx%d finders, %d centers:\n",
RyoheiHagimoto 0:56c5742b9e2b 3929 reader->finder_lines[0].nlines,
RyoheiHagimoto 0:56c5742b9e2b 3930 reader->finder_lines[1].nlines,
RyoheiHagimoto 0:56c5742b9e2b 3931 ncenters);
RyoheiHagimoto 0:56c5742b9e2b 3932 qr_svg_centers(centers, ncenters);
RyoheiHagimoto 0:56c5742b9e2b 3933
RyoheiHagimoto 0:56c5742b9e2b 3934 if(ncenters >= 3) {
RyoheiHagimoto 0:56c5742b9e2b 3935 void *bin = qr_binarize(img->data, img->width, img->height);
RyoheiHagimoto 0:56c5742b9e2b 3936
RyoheiHagimoto 0:56c5742b9e2b 3937 qr_code_data_list qrlist;
RyoheiHagimoto 0:56c5742b9e2b 3938 qr_code_data_list_init(&qrlist);
RyoheiHagimoto 0:56c5742b9e2b 3939
RyoheiHagimoto 0:56c5742b9e2b 3940 qr_reader_match_centers(reader, &qrlist, centers, ncenters,
RyoheiHagimoto 0:56c5742b9e2b 3941 bin, img->width, img->height);
RyoheiHagimoto 0:56c5742b9e2b 3942
RyoheiHagimoto 0:56c5742b9e2b 3943 if(qrlist.nqrdata > 0)
RyoheiHagimoto 0:56c5742b9e2b 3944 nqrdata = qr_code_data_list_extract_text(&qrlist, iscn, img);
RyoheiHagimoto 0:56c5742b9e2b 3945
RyoheiHagimoto 0:56c5742b9e2b 3946 qr_code_data_list_clear(&qrlist);
RyoheiHagimoto 0:56c5742b9e2b 3947 free(bin);
RyoheiHagimoto 0:56c5742b9e2b 3948 }
RyoheiHagimoto 0:56c5742b9e2b 3949 svg_group_end();
RyoheiHagimoto 0:56c5742b9e2b 3950
RyoheiHagimoto 0:56c5742b9e2b 3951 if(centers)
RyoheiHagimoto 0:56c5742b9e2b 3952 free(centers);
RyoheiHagimoto 0:56c5742b9e2b 3953 if(edge_pts)
RyoheiHagimoto 0:56c5742b9e2b 3954 free(edge_pts);
RyoheiHagimoto 0:56c5742b9e2b 3955 return(nqrdata);
RyoheiHagimoto 0:56c5742b9e2b 3956 }
RyoheiHagimoto 0:56c5742b9e2b 3957