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 <stdio.h>
RyoheiHagimoto 0:56c5742b9e2b 7 #include <stdlib.h>
RyoheiHagimoto 0:56c5742b9e2b 8 #include <string.h>
RyoheiHagimoto 0:56c5742b9e2b 9 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 10 typedef void *iconv_t;
RyoheiHagimoto 0:56c5742b9e2b 11 #else
RyoheiHagimoto 0:56c5742b9e2b 12 #include <iconv.h>
RyoheiHagimoto 0:56c5742b9e2b 13 #endif
RyoheiHagimoto 0:56c5742b9e2b 14 #include "qrcode.h"
RyoheiHagimoto 0:56c5742b9e2b 15 #include "qrdec.h"
RyoheiHagimoto 0:56c5742b9e2b 16 #include "util.h"
RyoheiHagimoto 0:56c5742b9e2b 17 #include "image.h"
RyoheiHagimoto 0:56c5742b9e2b 18 #include "error.h"
RyoheiHagimoto 0:56c5742b9e2b 19 #include "img_scanner.h"
RyoheiHagimoto 0:56c5742b9e2b 20
RyoheiHagimoto 0:56c5742b9e2b 21 static int text_is_ascii(const unsigned char *_text,int _len){
RyoheiHagimoto 0:56c5742b9e2b 22 int i;
RyoheiHagimoto 0:56c5742b9e2b 23 for(i=0;i<_len;i++)if(_text[i]>=0x80)return 0;
RyoheiHagimoto 0:56c5742b9e2b 24 return 1;
RyoheiHagimoto 0:56c5742b9e2b 25 }
RyoheiHagimoto 0:56c5742b9e2b 26
RyoheiHagimoto 0:56c5742b9e2b 27 static int text_is_latin1(const unsigned char *_text,int _len){
RyoheiHagimoto 0:56c5742b9e2b 28 int i;
RyoheiHagimoto 0:56c5742b9e2b 29 for(i=0;i<_len;i++){
RyoheiHagimoto 0:56c5742b9e2b 30 /*The following line fails to compile correctly with gcc 3.4.4 on ARM with
RyoheiHagimoto 0:56c5742b9e2b 31 any optimizations enabled.*/
RyoheiHagimoto 0:56c5742b9e2b 32 if(_text[i]>=0x80&&_text[i]<0xA0)return 0;
RyoheiHagimoto 0:56c5742b9e2b 33 }
RyoheiHagimoto 0:56c5742b9e2b 34 return 1;
RyoheiHagimoto 0:56c5742b9e2b 35 }
RyoheiHagimoto 0:56c5742b9e2b 36
RyoheiHagimoto 0:56c5742b9e2b 37 static void enc_list_mtf(iconv_t _enc_list[3],iconv_t _enc){
RyoheiHagimoto 0:56c5742b9e2b 38 int i;
RyoheiHagimoto 0:56c5742b9e2b 39 for(i=0;i<3;i++)if(_enc_list[i]==_enc){
RyoheiHagimoto 0:56c5742b9e2b 40 int j;
RyoheiHagimoto 0:56c5742b9e2b 41 for(j=i;j-->0;)_enc_list[j+1]=_enc_list[j];
RyoheiHagimoto 0:56c5742b9e2b 42 _enc_list[0]=_enc;
RyoheiHagimoto 0:56c5742b9e2b 43 break;
RyoheiHagimoto 0:56c5742b9e2b 44 }
RyoheiHagimoto 0:56c5742b9e2b 45 }
RyoheiHagimoto 0:56c5742b9e2b 46
RyoheiHagimoto 0:56c5742b9e2b 47 int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist,
RyoheiHagimoto 0:56c5742b9e2b 48 zbar_image_scanner_t *iscn,
RyoheiHagimoto 0:56c5742b9e2b 49 zbar_image_t *img)
RyoheiHagimoto 0:56c5742b9e2b 50 {
RyoheiHagimoto 0:56c5742b9e2b 51 iconv_t sjis_cd;
RyoheiHagimoto 0:56c5742b9e2b 52 iconv_t utf8_cd;
RyoheiHagimoto 0:56c5742b9e2b 53 iconv_t latin1_cd;
RyoheiHagimoto 0:56c5742b9e2b 54 const qr_code_data *qrdata;
RyoheiHagimoto 0:56c5742b9e2b 55 int nqrdata;
RyoheiHagimoto 0:56c5742b9e2b 56 unsigned char *mark;
RyoheiHagimoto 0:56c5742b9e2b 57 char **text;
RyoheiHagimoto 0:56c5742b9e2b 58 int ntext;
RyoheiHagimoto 0:56c5742b9e2b 59 int i;
RyoheiHagimoto 0:56c5742b9e2b 60 qrdata=_qrlist->qrdata;
RyoheiHagimoto 0:56c5742b9e2b 61 nqrdata=_qrlist->nqrdata;
RyoheiHagimoto 0:56c5742b9e2b 62 text=(char **)malloc(nqrdata*sizeof(*text));
RyoheiHagimoto 0:56c5742b9e2b 63 mark=(unsigned char *)calloc(nqrdata,sizeof(*mark));
RyoheiHagimoto 0:56c5742b9e2b 64 ntext=0;
RyoheiHagimoto 0:56c5742b9e2b 65 /*This is the encoding the standard says is the default.*/
RyoheiHagimoto 0:56c5742b9e2b 66 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 67 latin1_cd="ISO8859-1"; // dummy address
RyoheiHagimoto 0:56c5742b9e2b 68 #else
RyoheiHagimoto 0:56c5742b9e2b 69 latin1_cd=iconv_open("UTF-8","ISO8859-1");
RyoheiHagimoto 0:56c5742b9e2b 70 #endif
RyoheiHagimoto 0:56c5742b9e2b 71 /*But this one is often used, as well.*/
RyoheiHagimoto 0:56c5742b9e2b 72 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 73 sjis_cd="SJIS"; // dummy address
RyoheiHagimoto 0:56c5742b9e2b 74 #else
RyoheiHagimoto 0:56c5742b9e2b 75 sjis_cd=iconv_open("UTF-8","SJIS");
RyoheiHagimoto 0:56c5742b9e2b 76 #endif
RyoheiHagimoto 0:56c5742b9e2b 77 /*This is a trivial conversion just to check validity without extra code.*/
RyoheiHagimoto 0:56c5742b9e2b 78 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 79 utf8_cd="UTF-8"; // dummy address
RyoheiHagimoto 0:56c5742b9e2b 80 #else
RyoheiHagimoto 0:56c5742b9e2b 81 utf8_cd=iconv_open("UTF-8","UTF-8");
RyoheiHagimoto 0:56c5742b9e2b 82 #endif
RyoheiHagimoto 0:56c5742b9e2b 83 for(i=0;i<nqrdata;i++)if(!mark[i]){
RyoheiHagimoto 0:56c5742b9e2b 84 const qr_code_data *qrdataj;
RyoheiHagimoto 0:56c5742b9e2b 85 const qr_code_data_entry *entry;
RyoheiHagimoto 0:56c5742b9e2b 86 iconv_t enc_list[3];
RyoheiHagimoto 0:56c5742b9e2b 87 iconv_t eci_cd;
RyoheiHagimoto 0:56c5742b9e2b 88 int sa[16];
RyoheiHagimoto 0:56c5742b9e2b 89 int sa_size;
RyoheiHagimoto 0:56c5742b9e2b 90 char *sa_text;
RyoheiHagimoto 0:56c5742b9e2b 91 size_t sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 92 size_t sa_ctext;
RyoheiHagimoto 0:56c5742b9e2b 93 int fnc1;
RyoheiHagimoto 0:56c5742b9e2b 94 int eci;
RyoheiHagimoto 0:56c5742b9e2b 95 int err;
RyoheiHagimoto 0:56c5742b9e2b 96 int j;
RyoheiHagimoto 0:56c5742b9e2b 97 int k;
RyoheiHagimoto 0:56c5742b9e2b 98 /*Step 0: Collect the other QR codes belonging to this S-A group.*/
RyoheiHagimoto 0:56c5742b9e2b 99 if(qrdata[i].sa_size){
RyoheiHagimoto 0:56c5742b9e2b 100 unsigned sa_parity;
RyoheiHagimoto 0:56c5742b9e2b 101 sa_size=qrdata[i].sa_size;
RyoheiHagimoto 0:56c5742b9e2b 102 sa_parity=qrdata[i].sa_parity;
RyoheiHagimoto 0:56c5742b9e2b 103 for(j=0;j<sa_size;j++)sa[j]=-1;
RyoheiHagimoto 0:56c5742b9e2b 104 for(j=i;j<nqrdata;j++)if(!mark[j]){
RyoheiHagimoto 0:56c5742b9e2b 105 /*TODO: We could also match version, ECC level, etc. if size and
RyoheiHagimoto 0:56c5742b9e2b 106 parity alone are too ambiguous.*/
RyoheiHagimoto 0:56c5742b9e2b 107 if(qrdata[j].sa_size==sa_size&&qrdata[j].sa_parity==sa_parity&&
RyoheiHagimoto 0:56c5742b9e2b 108 sa[qrdata[j].sa_index]<0){
RyoheiHagimoto 0:56c5742b9e2b 109 sa[qrdata[j].sa_index]=j;
RyoheiHagimoto 0:56c5742b9e2b 110 mark[j]=1;
RyoheiHagimoto 0:56c5742b9e2b 111 }
RyoheiHagimoto 0:56c5742b9e2b 112 }
RyoheiHagimoto 0:56c5742b9e2b 113 /*TODO: If the S-A group is complete, check the parity.*/
RyoheiHagimoto 0:56c5742b9e2b 114 }
RyoheiHagimoto 0:56c5742b9e2b 115 else{
RyoheiHagimoto 0:56c5742b9e2b 116 sa[0]=i;
RyoheiHagimoto 0:56c5742b9e2b 117 sa_size=1;
RyoheiHagimoto 0:56c5742b9e2b 118 }
RyoheiHagimoto 0:56c5742b9e2b 119
RyoheiHagimoto 0:56c5742b9e2b 120 sa_ctext=0;
RyoheiHagimoto 0:56c5742b9e2b 121 fnc1=0;
RyoheiHagimoto 0:56c5742b9e2b 122 /*Step 1: Detect FNC1 markers and estimate the required buffer size.*/
RyoheiHagimoto 0:56c5742b9e2b 123 for(j=0;j<sa_size;j++)if(sa[j]>=0){
RyoheiHagimoto 0:56c5742b9e2b 124 qrdataj=qrdata+sa[j];
RyoheiHagimoto 0:56c5742b9e2b 125 for(k=0;k<qrdataj->nentries;k++){
RyoheiHagimoto 0:56c5742b9e2b 126 int shift;
RyoheiHagimoto 0:56c5742b9e2b 127 entry=qrdataj->entries+k;
RyoheiHagimoto 0:56c5742b9e2b 128 shift=0;
RyoheiHagimoto 0:56c5742b9e2b 129 switch(entry->mode){
RyoheiHagimoto 0:56c5742b9e2b 130 /*FNC1 applies to the entire code and ignores subsequent markers.*/
RyoheiHagimoto 0:56c5742b9e2b 131 case QR_MODE_FNC1_1ST:
RyoheiHagimoto 0:56c5742b9e2b 132 case QR_MODE_FNC1_2ND:fnc1=1;break;
RyoheiHagimoto 0:56c5742b9e2b 133 /*2 SJIS bytes will be at most 4 UTF-8 bytes.*/
RyoheiHagimoto 0:56c5742b9e2b 134 case QR_MODE_KANJI:shift++;
RyoheiHagimoto 0:56c5742b9e2b 135 /*We assume at most 4 UTF-8 bytes per input byte.
RyoheiHagimoto 0:56c5742b9e2b 136 I believe this is true for all the encodings we actually use.*/
RyoheiHagimoto 0:56c5742b9e2b 137 case QR_MODE_BYTE:shift++;
RyoheiHagimoto 0:56c5742b9e2b 138 default:{
RyoheiHagimoto 0:56c5742b9e2b 139 /*The remaining two modes are already valid UTF-8.*/
RyoheiHagimoto 0:56c5742b9e2b 140 if(QR_MODE_HAS_DATA(entry->mode)){
RyoheiHagimoto 0:56c5742b9e2b 141 sa_ctext+=entry->payload.data.len<<shift;
RyoheiHagimoto 0:56c5742b9e2b 142 }
RyoheiHagimoto 0:56c5742b9e2b 143 }break;
RyoheiHagimoto 0:56c5742b9e2b 144 }
RyoheiHagimoto 0:56c5742b9e2b 145 }
RyoheiHagimoto 0:56c5742b9e2b 146 }
RyoheiHagimoto 0:56c5742b9e2b 147
RyoheiHagimoto 0:56c5742b9e2b 148 /*Step 2: Convert the entries.*/
RyoheiHagimoto 0:56c5742b9e2b 149 sa_text=(char *)malloc((sa_ctext+1)*sizeof(*sa_text));
RyoheiHagimoto 0:56c5742b9e2b 150 sa_ntext=0;
RyoheiHagimoto 0:56c5742b9e2b 151 eci=-1;
RyoheiHagimoto 0:56c5742b9e2b 152 enc_list[0]=sjis_cd;
RyoheiHagimoto 0:56c5742b9e2b 153 enc_list[1]=latin1_cd;
RyoheiHagimoto 0:56c5742b9e2b 154 enc_list[2]=utf8_cd;
RyoheiHagimoto 0:56c5742b9e2b 155 eci_cd=(iconv_t)-1;
RyoheiHagimoto 0:56c5742b9e2b 156 err=0;
RyoheiHagimoto 0:56c5742b9e2b 157 zbar_symbol_t *syms = NULL, **sym = &syms;
RyoheiHagimoto 0:56c5742b9e2b 158 for(j = 0; j < sa_size && !err; j++, sym = &(*sym)->next) {
RyoheiHagimoto 0:56c5742b9e2b 159 *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0);
RyoheiHagimoto 0:56c5742b9e2b 160 (*sym)->datalen = sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 161 if(sa[j]<0){
RyoheiHagimoto 0:56c5742b9e2b 162 /* generic placeholder for unfinished results */
RyoheiHagimoto 0:56c5742b9e2b 163 (*sym)->type = ZBAR_PARTIAL;
RyoheiHagimoto 0:56c5742b9e2b 164
RyoheiHagimoto 0:56c5742b9e2b 165 /*Skip all contiguous missing segments.*/
RyoheiHagimoto 0:56c5742b9e2b 166 for(j++;j<sa_size&&sa[j]<0;j++);
RyoheiHagimoto 0:56c5742b9e2b 167 /*If there aren't any more, stop.*/
RyoheiHagimoto 0:56c5742b9e2b 168 if(j>=sa_size)break;
RyoheiHagimoto 0:56c5742b9e2b 169
RyoheiHagimoto 0:56c5742b9e2b 170 /* mark break in data */
RyoheiHagimoto 0:56c5742b9e2b 171 sa_text[sa_ntext++]='\0';
RyoheiHagimoto 0:56c5742b9e2b 172 (*sym)->datalen = sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 173
RyoheiHagimoto 0:56c5742b9e2b 174 /* advance to next symbol */
RyoheiHagimoto 0:56c5742b9e2b 175 sym = &(*sym)->next;
RyoheiHagimoto 0:56c5742b9e2b 176 *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0);
RyoheiHagimoto 0:56c5742b9e2b 177 }
RyoheiHagimoto 0:56c5742b9e2b 178
RyoheiHagimoto 0:56c5742b9e2b 179 qrdataj=qrdata+sa[j];
RyoheiHagimoto 0:56c5742b9e2b 180 /* expose bounding box */
RyoheiHagimoto 0:56c5742b9e2b 181 sym_add_point(*sym, qrdataj->bbox[0][0], qrdataj->bbox[0][1]);
RyoheiHagimoto 0:56c5742b9e2b 182 sym_add_point(*sym, qrdataj->bbox[2][0], qrdataj->bbox[2][1]);
RyoheiHagimoto 0:56c5742b9e2b 183 sym_add_point(*sym, qrdataj->bbox[3][0], qrdataj->bbox[3][1]);
RyoheiHagimoto 0:56c5742b9e2b 184 sym_add_point(*sym, qrdataj->bbox[1][0], qrdataj->bbox[1][1]);
RyoheiHagimoto 0:56c5742b9e2b 185
RyoheiHagimoto 0:56c5742b9e2b 186 for(k=0;k<qrdataj->nentries&&!err;k++){
RyoheiHagimoto 0:56c5742b9e2b 187 size_t inleft;
RyoheiHagimoto 0:56c5742b9e2b 188 size_t outleft;
RyoheiHagimoto 0:56c5742b9e2b 189 char *in;
RyoheiHagimoto 0:56c5742b9e2b 190 char *out;
RyoheiHagimoto 0:56c5742b9e2b 191 entry=qrdataj->entries+k;
RyoheiHagimoto 0:56c5742b9e2b 192 switch(entry->mode){
RyoheiHagimoto 0:56c5742b9e2b 193 case QR_MODE_NUM:{
RyoheiHagimoto 0:56c5742b9e2b 194 if(sa_ctext-sa_ntext>=(size_t)entry->payload.data.len){
RyoheiHagimoto 0:56c5742b9e2b 195 memcpy(sa_text+sa_ntext,entry->payload.data.buf,
RyoheiHagimoto 0:56c5742b9e2b 196 entry->payload.data.len*sizeof(*sa_text));
RyoheiHagimoto 0:56c5742b9e2b 197 sa_ntext+=entry->payload.data.len;
RyoheiHagimoto 0:56c5742b9e2b 198 }
RyoheiHagimoto 0:56c5742b9e2b 199 else err=1;
RyoheiHagimoto 0:56c5742b9e2b 200 }break;
RyoheiHagimoto 0:56c5742b9e2b 201 case QR_MODE_ALNUM:{
RyoheiHagimoto 0:56c5742b9e2b 202 char *p;
RyoheiHagimoto 0:56c5742b9e2b 203 in=(char *)entry->payload.data.buf;
RyoheiHagimoto 0:56c5742b9e2b 204 inleft=entry->payload.data.len;
RyoheiHagimoto 0:56c5742b9e2b 205 /*FNC1 uses '%' as an escape character.*/
RyoheiHagimoto 0:56c5742b9e2b 206 if(fnc1)for(;;){
RyoheiHagimoto 0:56c5742b9e2b 207 size_t plen;
RyoheiHagimoto 0:56c5742b9e2b 208 char c;
RyoheiHagimoto 0:56c5742b9e2b 209 p=memchr(in,'%',inleft*sizeof(*in));
RyoheiHagimoto 0:56c5742b9e2b 210 if(p==NULL)break;
RyoheiHagimoto 0:56c5742b9e2b 211 plen=p-in;
RyoheiHagimoto 0:56c5742b9e2b 212 if(sa_ctext-sa_ntext<plen+1)break;
RyoheiHagimoto 0:56c5742b9e2b 213 memcpy(sa_text+sa_ntext,in,plen*sizeof(*in));
RyoheiHagimoto 0:56c5742b9e2b 214 sa_ntext+=plen;
RyoheiHagimoto 0:56c5742b9e2b 215 /*Two '%'s is a literal '%'*/
RyoheiHagimoto 0:56c5742b9e2b 216 if(plen+1<inleft&&p[1]=='%'){
RyoheiHagimoto 0:56c5742b9e2b 217 c='%';
RyoheiHagimoto 0:56c5742b9e2b 218 plen++;
RyoheiHagimoto 0:56c5742b9e2b 219 p++;
RyoheiHagimoto 0:56c5742b9e2b 220 }
RyoheiHagimoto 0:56c5742b9e2b 221 /*One '%' is the ASCII group separator.*/
RyoheiHagimoto 0:56c5742b9e2b 222 else c=0x1D;
RyoheiHagimoto 0:56c5742b9e2b 223 sa_text[sa_ntext++]=c;
RyoheiHagimoto 0:56c5742b9e2b 224 inleft-=plen+1;
RyoheiHagimoto 0:56c5742b9e2b 225 in=p+1;
RyoheiHagimoto 0:56c5742b9e2b 226 }
RyoheiHagimoto 0:56c5742b9e2b 227 else p=NULL;
RyoheiHagimoto 0:56c5742b9e2b 228 if(p!=NULL||sa_ctext-sa_ntext<inleft)err=1;
RyoheiHagimoto 0:56c5742b9e2b 229 else{
RyoheiHagimoto 0:56c5742b9e2b 230 memcpy(sa_text+sa_ntext,in,inleft*sizeof(*sa_text));
RyoheiHagimoto 0:56c5742b9e2b 231 sa_ntext+=inleft;
RyoheiHagimoto 0:56c5742b9e2b 232 }
RyoheiHagimoto 0:56c5742b9e2b 233 }break;
RyoheiHagimoto 0:56c5742b9e2b 234 /*TODO: This will not handle a multi-byte sequence split between
RyoheiHagimoto 0:56c5742b9e2b 235 multiple data blocks.
RyoheiHagimoto 0:56c5742b9e2b 236 Does such a thing occur?
RyoheiHagimoto 0:56c5742b9e2b 237 Is it allowed?
RyoheiHagimoto 0:56c5742b9e2b 238 It requires copying buffers around to handle correctly.*/
RyoheiHagimoto 0:56c5742b9e2b 239 case QR_MODE_BYTE:{
RyoheiHagimoto 0:56c5742b9e2b 240 in=(char *)entry->payload.data.buf;
RyoheiHagimoto 0:56c5742b9e2b 241 inleft=entry->payload.data.len;
RyoheiHagimoto 0:56c5742b9e2b 242 out=sa_text+sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 243 outleft=sa_ctext-sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 244 /*If we have no specified encoding, attempt to auto-detect it.*/
RyoheiHagimoto 0:56c5742b9e2b 245 if(eci<0){
RyoheiHagimoto 0:56c5742b9e2b 246 int ei;
RyoheiHagimoto 0:56c5742b9e2b 247 /*First check for the UTF-8 BOM.*/
RyoheiHagimoto 0:56c5742b9e2b 248 if(inleft>=3&&
RyoheiHagimoto 0:56c5742b9e2b 249 in[0]==(char)0xEF&&in[1]==(char)0xBB&&in[2]==(char)0xBF){
RyoheiHagimoto 0:56c5742b9e2b 250 in+=3;
RyoheiHagimoto 0:56c5742b9e2b 251 inleft-=3;
RyoheiHagimoto 0:56c5742b9e2b 252 /*Actually try converting (to check validity).*/
RyoheiHagimoto 0:56c5742b9e2b 253 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 254 err=(in == NULL) || ( out == NULL ) || inleft > outleft;
RyoheiHagimoto 0:56c5742b9e2b 255 if (inleft > outleft) inleft = outleft;
RyoheiHagimoto 0:56c5742b9e2b 256 memcpy(out, in, inleft);
RyoheiHagimoto 0:56c5742b9e2b 257 #else
RyoheiHagimoto 0:56c5742b9e2b 258 err=utf8_cd==(iconv_t)-1||
RyoheiHagimoto 0:56c5742b9e2b 259 iconv(utf8_cd,&in,&inleft,&out,&outleft)==(size_t)-1;
RyoheiHagimoto 0:56c5742b9e2b 260 #endif
RyoheiHagimoto 0:56c5742b9e2b 261 if(!err){
RyoheiHagimoto 0:56c5742b9e2b 262 sa_ntext=out-sa_text;
RyoheiHagimoto 0:56c5742b9e2b 263 enc_list_mtf(enc_list,utf8_cd);
RyoheiHagimoto 0:56c5742b9e2b 264 continue;
RyoheiHagimoto 0:56c5742b9e2b 265 }
RyoheiHagimoto 0:56c5742b9e2b 266 in=(char *)entry->payload.data.buf;
RyoheiHagimoto 0:56c5742b9e2b 267 inleft=entry->payload.data.len;
RyoheiHagimoto 0:56c5742b9e2b 268 out=sa_text+sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 269 outleft=sa_ctext-sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 270 }
RyoheiHagimoto 0:56c5742b9e2b 271 /*If the text is 8-bit clean, prefer UTF-8 over SJIS, since SJIS
RyoheiHagimoto 0:56c5742b9e2b 272 will corrupt the backslashes used for DoCoMo formats.*/
RyoheiHagimoto 0:56c5742b9e2b 273 else if(text_is_ascii((unsigned char *)in,inleft)){
RyoheiHagimoto 0:56c5742b9e2b 274 enc_list_mtf(enc_list,utf8_cd);
RyoheiHagimoto 0:56c5742b9e2b 275 }
RyoheiHagimoto 0:56c5742b9e2b 276 /*Try our list of encodings.*/
RyoheiHagimoto 0:56c5742b9e2b 277 for(ei=0;ei<3;ei++)if(enc_list[ei]!=(iconv_t)-1){
RyoheiHagimoto 0:56c5742b9e2b 278 /*According to the standard, ISO/IEC 8859-1 (one hyphen) is
RyoheiHagimoto 0:56c5742b9e2b 279 supposed to be used, but reality is not always so.
RyoheiHagimoto 0:56c5742b9e2b 280 It's got an invalid range that is used often with SJIS
RyoheiHagimoto 0:56c5742b9e2b 281 and UTF-8, though, which makes detection easier.
RyoheiHagimoto 0:56c5742b9e2b 282 However, iconv() does not properly reject characters in
RyoheiHagimoto 0:56c5742b9e2b 283 those ranges, since ISO-8859-1 (two hyphens) defines a
RyoheiHagimoto 0:56c5742b9e2b 284 number of seldom-used control code characters there.
RyoheiHagimoto 0:56c5742b9e2b 285 So if we see any of those characters, move this
RyoheiHagimoto 0:56c5742b9e2b 286 conversion to the end of the list.*/
RyoheiHagimoto 0:56c5742b9e2b 287 if(ei<2&&enc_list[ei]==latin1_cd&&
RyoheiHagimoto 0:56c5742b9e2b 288 !text_is_latin1((unsigned char *)in,inleft)){
RyoheiHagimoto 0:56c5742b9e2b 289 int ej;
RyoheiHagimoto 0:56c5742b9e2b 290 for(ej=ei+1;ej<3;ej++)enc_list[ej-1]=enc_list[ej];
RyoheiHagimoto 0:56c5742b9e2b 291 enc_list[2]=latin1_cd;
RyoheiHagimoto 0:56c5742b9e2b 292 }
RyoheiHagimoto 0:56c5742b9e2b 293 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 294 err=(in == NULL) || ( out == NULL ) || inleft > outleft;
RyoheiHagimoto 0:56c5742b9e2b 295 if (inleft > outleft) inleft = outleft;
RyoheiHagimoto 0:56c5742b9e2b 296 memcpy(out, in, inleft);
RyoheiHagimoto 0:56c5742b9e2b 297 #else
RyoheiHagimoto 0:56c5742b9e2b 298 err=iconv(enc_list[ei],&in,&inleft,&out,&outleft)==(size_t)-1;
RyoheiHagimoto 0:56c5742b9e2b 299 #endif
RyoheiHagimoto 0:56c5742b9e2b 300 if(!err){
RyoheiHagimoto 0:56c5742b9e2b 301 sa_ntext=out-sa_text;
RyoheiHagimoto 0:56c5742b9e2b 302 enc_list_mtf(enc_list,enc_list[ei]);
RyoheiHagimoto 0:56c5742b9e2b 303 break;
RyoheiHagimoto 0:56c5742b9e2b 304 }
RyoheiHagimoto 0:56c5742b9e2b 305 in=(char *)entry->payload.data.buf;
RyoheiHagimoto 0:56c5742b9e2b 306 inleft=entry->payload.data.len;
RyoheiHagimoto 0:56c5742b9e2b 307 out=sa_text+sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 308 outleft=sa_ctext-sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 309 }
RyoheiHagimoto 0:56c5742b9e2b 310 }
RyoheiHagimoto 0:56c5742b9e2b 311 /*We were actually given a character set; use it.*/
RyoheiHagimoto 0:56c5742b9e2b 312 else{
RyoheiHagimoto 0:56c5742b9e2b 313 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 314 err=(in == NULL) || ( out == NULL ) || inleft > outleft;
RyoheiHagimoto 0:56c5742b9e2b 315 if (inleft > outleft) inleft = outleft;
RyoheiHagimoto 0:56c5742b9e2b 316 memcpy(out, in, inleft);
RyoheiHagimoto 0:56c5742b9e2b 317 #else
RyoheiHagimoto 0:56c5742b9e2b 318 err=eci_cd==(iconv_t)-1||
RyoheiHagimoto 0:56c5742b9e2b 319 iconv(eci_cd,&in,&inleft,&out,&outleft)==(size_t)-1;
RyoheiHagimoto 0:56c5742b9e2b 320 #endif
RyoheiHagimoto 0:56c5742b9e2b 321 if(!err)sa_ntext=out-sa_text;
RyoheiHagimoto 0:56c5742b9e2b 322 }
RyoheiHagimoto 0:56c5742b9e2b 323 }break;
RyoheiHagimoto 0:56c5742b9e2b 324 /*Kanji mode always uses SJIS.*/
RyoheiHagimoto 0:56c5742b9e2b 325 case QR_MODE_KANJI:{
RyoheiHagimoto 0:56c5742b9e2b 326 in=(char *)entry->payload.data.buf;
RyoheiHagimoto 0:56c5742b9e2b 327 inleft=entry->payload.data.len;
RyoheiHagimoto 0:56c5742b9e2b 328 out=sa_text+sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 329 outleft=sa_ctext-sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 330 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 331 err=(in == NULL) || ( out == NULL ) || inleft > outleft;
RyoheiHagimoto 0:56c5742b9e2b 332 if (inleft > outleft) inleft = outleft;
RyoheiHagimoto 0:56c5742b9e2b 333 memcpy(out, in, inleft);
RyoheiHagimoto 0:56c5742b9e2b 334 #else
RyoheiHagimoto 0:56c5742b9e2b 335 err=sjis_cd==(iconv_t)-1||
RyoheiHagimoto 0:56c5742b9e2b 336 iconv(sjis_cd,&in,&inleft,&out,&outleft)==(size_t)-1;
RyoheiHagimoto 0:56c5742b9e2b 337 #endif
RyoheiHagimoto 0:56c5742b9e2b 338 if(!err)sa_ntext=out-sa_text;
RyoheiHagimoto 0:56c5742b9e2b 339 }break;
RyoheiHagimoto 0:56c5742b9e2b 340 /*Check to see if a character set was specified.*/
RyoheiHagimoto 0:56c5742b9e2b 341 case QR_MODE_ECI:{
RyoheiHagimoto 0:56c5742b9e2b 342 const char *enc;
RyoheiHagimoto 0:56c5742b9e2b 343 char buf[16];
RyoheiHagimoto 0:56c5742b9e2b 344 unsigned cur_eci;
RyoheiHagimoto 0:56c5742b9e2b 345 cur_eci=entry->payload.eci;
RyoheiHagimoto 0:56c5742b9e2b 346 if(cur_eci<=QR_ECI_ISO8859_16&&cur_eci!=14){
RyoheiHagimoto 0:56c5742b9e2b 347 if(cur_eci!=QR_ECI_GLI0&&cur_eci!=QR_ECI_CP437){
RyoheiHagimoto 0:56c5742b9e2b 348 sprintf(buf,"ISO8859-%i",QR_MAXI(cur_eci,3)-2);
RyoheiHagimoto 0:56c5742b9e2b 349 enc=buf;
RyoheiHagimoto 0:56c5742b9e2b 350 }
RyoheiHagimoto 0:56c5742b9e2b 351 /*Note that CP437 requires an iconv compiled with
RyoheiHagimoto 0:56c5742b9e2b 352 --enable-extra-encodings, and thus may not be available.*/
RyoheiHagimoto 0:56c5742b9e2b 353 else enc="CP437";
RyoheiHagimoto 0:56c5742b9e2b 354 }
RyoheiHagimoto 0:56c5742b9e2b 355 else if(cur_eci==QR_ECI_SJIS)enc="SJIS";
RyoheiHagimoto 0:56c5742b9e2b 356 /*Don't know what this ECI code specifies, but not an encoding that
RyoheiHagimoto 0:56c5742b9e2b 357 we recognize.*/
RyoheiHagimoto 0:56c5742b9e2b 358 else continue;
RyoheiHagimoto 0:56c5742b9e2b 359 eci=cur_eci;
RyoheiHagimoto 0:56c5742b9e2b 360 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 361 eci_cd=enc;
RyoheiHagimoto 0:56c5742b9e2b 362 #else
RyoheiHagimoto 0:56c5742b9e2b 363 eci_cd=iconv_open("UTF-8",enc);
RyoheiHagimoto 0:56c5742b9e2b 364 #endif
RyoheiHagimoto 0:56c5742b9e2b 365 }break;
RyoheiHagimoto 0:56c5742b9e2b 366 /*Silence stupid compiler warnings.*/
RyoheiHagimoto 0:56c5742b9e2b 367 default:break;
RyoheiHagimoto 0:56c5742b9e2b 368 }
RyoheiHagimoto 0:56c5742b9e2b 369 }
RyoheiHagimoto 0:56c5742b9e2b 370 /*If eci should be reset between codes, do so.*/
RyoheiHagimoto 0:56c5742b9e2b 371 if(eci<=QR_ECI_GLI1){
RyoheiHagimoto 0:56c5742b9e2b 372 eci=-1;
RyoheiHagimoto 0:56c5742b9e2b 373 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 374 #else
RyoheiHagimoto 0:56c5742b9e2b 375 if(eci_cd!=(iconv_t)-1)iconv_close(eci_cd);
RyoheiHagimoto 0:56c5742b9e2b 376 #endif
RyoheiHagimoto 0:56c5742b9e2b 377
RyoheiHagimoto 0:56c5742b9e2b 378 }
RyoheiHagimoto 0:56c5742b9e2b 379 }
RyoheiHagimoto 0:56c5742b9e2b 380 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 381 #else
RyoheiHagimoto 0:56c5742b9e2b 382 if(eci_cd!=(iconv_t)-1)iconv_close(eci_cd);
RyoheiHagimoto 0:56c5742b9e2b 383 #endif
RyoheiHagimoto 0:56c5742b9e2b 384 if(!err){
RyoheiHagimoto 0:56c5742b9e2b 385 sa_text[sa_ntext++]='\0';
RyoheiHagimoto 0:56c5742b9e2b 386 if(sa_ctext+1>sa_ntext){
RyoheiHagimoto 0:56c5742b9e2b 387 sa_text=(char *)realloc(sa_text,sa_ntext*sizeof(*sa_text));
RyoheiHagimoto 0:56c5742b9e2b 388 }
RyoheiHagimoto 0:56c5742b9e2b 389
RyoheiHagimoto 0:56c5742b9e2b 390 zbar_symbol_t *sa_sym;
RyoheiHagimoto 0:56c5742b9e2b 391 if(sa_size == 1)
RyoheiHagimoto 0:56c5742b9e2b 392 sa_sym = syms;
RyoheiHagimoto 0:56c5742b9e2b 393 else {
RyoheiHagimoto 0:56c5742b9e2b 394 /* create "virtual" container symbol for composite result */
RyoheiHagimoto 0:56c5742b9e2b 395 sa_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0);
RyoheiHagimoto 0:56c5742b9e2b 396 sa_sym->syms = _zbar_symbol_set_create();
RyoheiHagimoto 0:56c5742b9e2b 397 sa_sym->syms->head = syms;
RyoheiHagimoto 0:56c5742b9e2b 398
RyoheiHagimoto 0:56c5742b9e2b 399 /* cheap out w/axis aligned bbox for now */
RyoheiHagimoto 0:56c5742b9e2b 400 int xmin = img->width, xmax = -2;
RyoheiHagimoto 0:56c5742b9e2b 401 int ymin = img->height, ymax = -2;
RyoheiHagimoto 0:56c5742b9e2b 402
RyoheiHagimoto 0:56c5742b9e2b 403 /* fixup data references */
RyoheiHagimoto 0:56c5742b9e2b 404 for(; syms; syms = syms->next) {
RyoheiHagimoto 0:56c5742b9e2b 405 _zbar_symbol_refcnt(syms, 1);
RyoheiHagimoto 0:56c5742b9e2b 406 if(syms->type == ZBAR_PARTIAL)
RyoheiHagimoto 0:56c5742b9e2b 407 sa_sym->type = ZBAR_PARTIAL;
RyoheiHagimoto 0:56c5742b9e2b 408 else
RyoheiHagimoto 0:56c5742b9e2b 409 for(j = 0; j < syms->npts; j++) {
RyoheiHagimoto 0:56c5742b9e2b 410 int u = syms->pts[j].x;
RyoheiHagimoto 0:56c5742b9e2b 411 if(xmin >= u) xmin = u - 1;
RyoheiHagimoto 0:56c5742b9e2b 412 if(xmax <= u) xmax = u + 1;
RyoheiHagimoto 0:56c5742b9e2b 413 u = syms->pts[j].y;
RyoheiHagimoto 0:56c5742b9e2b 414 if(ymin >= u) ymin = u - 1;
RyoheiHagimoto 0:56c5742b9e2b 415 if(ymax <= u) ymax = u + 1;
RyoheiHagimoto 0:56c5742b9e2b 416 }
RyoheiHagimoto 0:56c5742b9e2b 417 syms->data = sa_text + syms->datalen;
RyoheiHagimoto 0:56c5742b9e2b 418 int next = (syms->next) ? syms->next->datalen : sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 419 assert(next > syms->datalen);
RyoheiHagimoto 0:56c5742b9e2b 420 syms->datalen = next - syms->datalen - 1;
RyoheiHagimoto 0:56c5742b9e2b 421 }
RyoheiHagimoto 0:56c5742b9e2b 422 if(xmax >= -1) {
RyoheiHagimoto 0:56c5742b9e2b 423 sym_add_point(sa_sym, xmin, ymin);
RyoheiHagimoto 0:56c5742b9e2b 424 sym_add_point(sa_sym, xmin, ymax);
RyoheiHagimoto 0:56c5742b9e2b 425 sym_add_point(sa_sym, xmax, ymax);
RyoheiHagimoto 0:56c5742b9e2b 426 sym_add_point(sa_sym, xmax, ymin);
RyoheiHagimoto 0:56c5742b9e2b 427 }
RyoheiHagimoto 0:56c5742b9e2b 428 }
RyoheiHagimoto 0:56c5742b9e2b 429 sa_sym->data = sa_text;
RyoheiHagimoto 0:56c5742b9e2b 430 sa_sym->data_alloc = sa_ntext;
RyoheiHagimoto 0:56c5742b9e2b 431 sa_sym->datalen = sa_ntext - 1;
RyoheiHagimoto 0:56c5742b9e2b 432
RyoheiHagimoto 0:56c5742b9e2b 433 _zbar_image_scanner_add_sym(iscn, sa_sym);
RyoheiHagimoto 0:56c5742b9e2b 434 }
RyoheiHagimoto 0:56c5742b9e2b 435 else {
RyoheiHagimoto 0:56c5742b9e2b 436 _zbar_image_scanner_recycle_syms(iscn, syms);
RyoheiHagimoto 0:56c5742b9e2b 437 free(sa_text);
RyoheiHagimoto 0:56c5742b9e2b 438 }
RyoheiHagimoto 0:56c5742b9e2b 439 }
RyoheiHagimoto 0:56c5742b9e2b 440 #if (1) /* does not convert character code */
RyoheiHagimoto 0:56c5742b9e2b 441 #else
RyoheiHagimoto 0:56c5742b9e2b 442 if(utf8_cd!=(iconv_t)-1)iconv_close(utf8_cd);
RyoheiHagimoto 0:56c5742b9e2b 443 if(sjis_cd!=(iconv_t)-1)iconv_close(sjis_cd);
RyoheiHagimoto 0:56c5742b9e2b 444 if(latin1_cd!=(iconv_t)-1)iconv_close(latin1_cd);
RyoheiHagimoto 0:56c5742b9e2b 445 #endif
RyoheiHagimoto 0:56c5742b9e2b 446 free(mark);
RyoheiHagimoto 0:56c5742b9e2b 447 return ntext;
RyoheiHagimoto 0:56c5742b9e2b 448 }
RyoheiHagimoto 0:56c5742b9e2b 449