#ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #ifdef __cplusplus } #endif #include "imext.h" #include "imperl.h" #include "qrencode.h" QRcode *encode(const char *text, int version, QRecLevel level, QRencodeMode mode, int casesensitive) { QRcode *code; if(casesensitive) { code = QRcode_encodeStringCase(text, version, level); } else { code = QRcode_encodeString(text, version, level, mode); } return code; } void generate(i_img *im, QRcode *qrcode, int size, int margin, i_color *lightcolor, i_color *darkcolor) { unsigned char *p, *q; int x, y; int base_y; /* top margin */ base_y = 0; for(y=base_y; ywidth + margin * 2; x++) { i_box_filled(im, x*size, y*size, x*size + size, y*size + size, lightcolor); } } /* data */ p = qrcode->data; q = p; base_y = margin; for(y=base_y; ywidth; y++) { for (x=0; xwidth; x++) { i_box_filled(im, x*size, y*size, x*size + size, y*size + size, (*q & 1) ? darkcolor : lightcolor); q++; } for (x=margin + qrcode->width; x< qrcode->width + margin * 2; x++) { i_box_filled(im, x*size, y*size, x*size + size, y*size + size, lightcolor); } } /* bottom margin */ base_y = qrcode->width + margin; for(y=base_y; ywidth + margin * 2; x++) { i_box_filled(im, x*size, y*size, x*size + size, y*size + size - 1, lightcolor); } } } DEFINE_IMAGER_CALLBACKS; i_img *_plot(char* text, HV *hv) { i_img* im; QRcode *qrcode; SV** svp; STRLEN len; char* ptr; int size = 3; int margin = 4; int version = 0; int casesensitive = 0; QRencodeMode mode = QR_MODE_8; QRecLevel level = QR_ECLEVEL_L; i_color lightcolor, darkcolor; if ((svp = hv_fetch(hv, "size", 4, 0)) && *svp && SvOK(*svp)) { ptr = SvPV(*svp, len); if (ptr >= 0) size = atoi(ptr); } if ((svp = hv_fetch(hv, "margin", 6, 0)) && *svp && SvOK(*svp)) { ptr = SvPV(*svp, len); if (ptr >= 0) margin = atoi(ptr); } if ((svp = hv_fetch(hv, "level", 5, 0)) && *svp && SvOK(*svp)) { ptr = SvPV(*svp, len); switch (*ptr) { case 'l': case 'L': level = QR_ECLEVEL_L; break; case 'm': case 'M': level = QR_ECLEVEL_M; break; case 'q': case 'Q': level = QR_ECLEVEL_Q; break; case 'h': case 'H': level = QR_ECLEVEL_H; break; default: level = QR_ECLEVEL_L; } } if ((svp = hv_fetch(hv, "version", 7, 0)) && *svp && SvOK(*svp)) { ptr = SvPV(*svp, len); if (ptr >= 0) version = atoi(ptr); } if ((svp = hv_fetch(hv, "mode", 4, 0)) && *svp && SvOK(*svp)) { ptr = SvPV(*svp, len); if (strcmp(ptr, "numerical") == 0) { mode = QR_MODE_NUM; } else if (strcmp(ptr, "alpha-numerical") == 0) { mode = QR_MODE_AN; } else if (strcmp(ptr, "8-bit") == 0) { mode = QR_MODE_8; } else if (strcmp(ptr, "kanji") == 0) { mode = QR_MODE_KANJI; } else { mode = QR_MODE_8; } } if ((svp = hv_fetch(hv, "casesensitive", 13, 0)) && *svp) { casesensitive = SvTRUE(*svp); } if ((svp = hv_fetch(hv, "lightcolor", 10, 0)) && *svp && SvOK(*svp) && sv_derived_from(*svp, "Imager::Color")) { lightcolor = *INT2PTR(i_color *, SvIV((SV *)SvRV(*svp))); } else { /* white */ lightcolor.rgba.r = 255; lightcolor.rgba.g = 255; lightcolor.rgba.b = 255; lightcolor.rgba.a = 255; } if ((svp = hv_fetch(hv, "darkcolor", 9, 0)) && *svp && SvOK(*svp) && SvOK(*svp) && sv_derived_from(*svp, "Imager::Color")) { darkcolor = *INT2PTR(i_color *, SvIV((SV *)SvRV(*svp))); } else { /* black */ darkcolor.rgba.r = 0; darkcolor.rgba.g = 0; darkcolor.rgba.b = 0; darkcolor.rgba.a = 255; } qrcode = encode(text, version, level, mode, casesensitive); if(qrcode == NULL) { croak("Failed to encode the input data: XS error"); } im = i_img_16_new( (qrcode->width + margin * 2) * size, (qrcode->width + margin * 2) * size, 4 ); generate(im, qrcode, size, margin, &lightcolor, &darkcolor); QRcode_free(qrcode); return im; } MODULE = Imager::QRCode PACKAGE = Imager::QRCode PROTOTYPES: ENABLE Imager::ImgRaw _plot(text, hv) char *text HV *hv BOOT: PERL_INITIALIZE_IMAGER_CALLBACKS;