Board logo

标题: [其他] 控制台二维码生成显示qr.exe [打印本页]

作者: happy886rr    时间: 2017-5-11 21:50     标题: 控制台二维码生成显示qr.exe

【C语言版】
QR.EXE更新至1.2版, 增加二维码超窗显示,外加最小体积图片输出。代码做了高度优化,方便批量生产。
笔名由HAPPY改为LEO,以便统一不同论坛的作品笔名。
下载:http://bcn.bathome.net/s/tool/index.html?key=qr
核心代码:
  1. /*
  2. CONSOLE QRCODE, COPYRIGHT@2017~2019 BY LEO, VERSION 1.2
  3. QR.EXE
  4. LINK GDI32 GDIPLUS
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <gdiplus\gdiplus.h>
  10. #include "QR_Encode.cpp"
  11. //GDI+命名空间
  12. using namespace Gdiplus;
  13. #define BF_ZOOM 10
  14. #define BF_MARGIN 10
  15. //定义帮助说明
  16. #define HELP_INFORMATION "\
  17. QR version 1.2 - Console qrcode tool - Copyright (C) 2017-2019 by Leo\n\
  18. \n\
  19. Usage:\n\
  20.     qr [your text] [outfile name]\n\
  21. \n\
  22. Official website:\n\
  23.     http://www.bathome.net/thread-44095-1-1.html\n"
  24. //声明C函数
  25. extern "C" HWND WINAPI GetConsoleWindow();
  26. //转码款字符
  27. WCHAR* LW(const CHAR* str)
  28. {
  29. if(!str){return NULL;}
  30. int wLen=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, NULL, 0);
  31. WCHAR* wstr=(WCHAR*)malloc(sizeof(WCHAR)*wLen + 1);
  32. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, wLen);
  33. wstr[wLen]='\0';
  34. return wstr;
  35. }
  36. //获取编码器CLSID
  37. BOOL GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
  38. {
  39. UINT j, n=0, s=0;
  40. ImageCodecInfo* pInfo=NULL;
  41. GetImageEncodersSize(&n, &s);
  42. if(s==0)
  43. {
  44. return FALSE;
  45. }
  46. pInfo=(ImageCodecInfo*)(malloc(s));
  47. if(pInfo==NULL)
  48. {
  49. return FALSE;
  50. }
  51. GetImageEncoders(n, s, pInfo);
  52. for(j=0; j<n; j++)
  53. {
  54. if(wcscmp(pInfo[j].MimeType, format)==0)
  55. {
  56. *pClsid=pInfo[j].Clsid;
  57. free(pInfo);
  58. return TRUE;
  59. }
  60. }
  61. free(pInfo);
  62. return FALSE;
  63. }
  64. //主函数入口
  65. int main(int argc, char* argv[])
  66. {
  67. if(argc!=2 && argc!=3)
  68. {
  69. fprintf(stdout, HELP_INFORMATION);
  70. return 1;
  71. }
  72. //初始化GDI+
  73. GdiplusStartupInput gdiplusstartupinput;
  74. ULONG_PTR gdiplustoken;
  75. GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);
  76. {
  77. char *pCodeStr=argv[1];
  78. CQR_Encode* pQR_Encode = new CQR_Encode;
  79. //生成QR二维码数据
  80. if (! pQR_Encode->EncodeData(QR_LEVEL_H, QR_VRESION_S, TRUE, -1,  pCodeStr))
  81. {
  82. fprintf(stdout, "Encode data error\n");
  83. return 1;
  84. }
  85. //根据生成的QR二进制数据 建立图片的长宽
  86. int qwith=pQR_Encode->m_nSymbleSize*BF_ZOOM+BF_MARGIN*2, qhigh=pQR_Encode->m_nSymbleSize*BF_ZOOM+BF_MARGIN*2;
  87. //建立位图文件
  88. Rect qrect(0, 0, qwith, qhigh);
  89. Bitmap* tbmp=new Bitmap(qwith, qhigh, PixelFormat24bppRGB);
  90. BitmapData* pBitmapData = new BitmapData;
  91. //并锁定位图二进制信息
  92. tbmp->LockBits(&qrect, ImageLockModeRead, PixelFormat24bppRGB, pBitmapData);
  93. BYTE *pByte = (BYTE *)pBitmapData->Scan0;
  94. int  iOffset = pBitmapData->Stride - qwith*3;
  95. //遍历位图每个点
  96. for(int i=0; i <qwith; i++)
  97. {
  98. for(int j=0; j <qhigh; j++)
  99. {
  100. //如果位图中的点满足填充白色,则将该点像素值设为RGB(255,255,255)
  101. if(i<BF_MARGIN || i>=qwith-BF_MARGIN || j<BF_MARGIN || j>=qhigh-BF_MARGIN || !pQR_Encode->m_byModuleData[(i-BF_MARGIN)/BF_ZOOM][(j-BF_MARGIN)/BF_ZOOM])
  102. {
  103. pByte[0] = 255;
  104. pByte[1] = 255;
  105. pByte[2] = 255;
  106. }
  107. pByte+=3;
  108. }
  109. pByte += iOffset;
  110. }
  111. //解除锁定
  112. tbmp->UnlockBits(pBitmapData);
  113. //建立单值位图sbmp,并进行位图拷贝
  114. Bitmap* sbmp=tbmp->Clone(qrect, PixelFormat1bppIndexed);
  115. //在控WIN制台显示QR图片
  116. if(argc==2)
  117. {
  118. Graphics* graph=new Graphics(GetDesktopWindow());
  119. graph->DrawImage(sbmp, qrect);
  120. DeleteObject(graph);
  121. }
  122. else
  123. {
  124. //对位图sbmp进行编码,并输出为png格式
  125. CLSID clsid;
  126. if(GetEncoderClsid(L"image/png", &clsid))
  127. {
  128. if(sbmp->Save(LW(argv[2]), &clsid, NULL) != S_OK)
  129. {
  130. fprintf(stdout, "Save image failed\n");
  131. return 1;
  132. }
  133. }
  134. else
  135. {
  136. fprintf(stdout, "Encode image failed\n");
  137. return 1;
  138. }
  139. }
  140. //释放内存
  141. delete pQR_Encode;
  142. delete pBitmapData;
  143. delete tbmp;
  144. delete sbmp;
  145. }
  146. //关闭GDI+
  147. GdiplusShutdown(gdiplustoken);
  148. return 0;
  149. }
复制代码
.
.
【Python版】

脚本代码:
  1. #-*- encoding:utf-8 -*-
  2. # Made by Happy
  3. # 导入QR模块
  4. import qrcode
  5. import image
  6. import getopt,sys
  7. def QR_Encode(text):
  8. qr=qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=10, border=1)
  9. qr.add_data(text)
  10. qr.make(fit=True)
  11. return qr.make_image()
  12. def main():
  13. tv="";ov="";flag=False
  14. ops,avs = getopt.getopt(sys.argv[1:], "ht:so:r:", ["help", "text", "show", "out", "recognise"])
  15. if len(sys.argv) == 1:
  16. print("Usage: pqr [-t text] [-o outfile] [-s show image]")
  17. sys.exit(1)
  18. for op,av in ops:
  19. if op in ("-h", "--help"):
  20. print("Usage: pqr [-t text] [-o outfile] [-s show image]")
  21. sys.exit(0)
  22. elif op in ("-t","--text"):
  23. tv=av
  24. elif op in ("-o","--out"):
  25. ov=av
  26. elif op in ("-s","--show"):
  27. flag=True
  28. else:
  29. print("Unrecognise options '%s'" %av)
  30. sys.exit(1)
  31. if not tv in '':
  32. img=QR_Encode(tv)
  33. if not ov in '':
  34. img.save(ov)
  35. if flag is True:
  36. img.show()
  37. else:
  38. print("Please input text string")
  39. sys.exit(1)
  40. main()
复制代码
使用方法:
  1. Usage: pqr [-t text] [-o outfile] [-s show image]
  2. Example:
  3.     pqr -t 你好 -o 3.png
复制代码
pqr支持的二维码汉字容量惊人,生成的图片体积极小、清晰度极高、容错识别极强。且pqr.exe比C语言版qr.exe功能多,可直接显示二维码,安装响应模块,可支持多种特殊功能。安装zbar库,还能支持条码识别,py脚本请参看15楼。
作者: 老刘1号    时间: 2017-5-11 23:01

3星、QQ表示根本扫不出……
作者: 523066680    时间: 2017-5-11 23:11

本帖最后由 523066680 于 2017-5-11 23:13 编辑

回复 2# 老刘1号


    魅族,微信扫描很快扫出来。
不过手机内置的二维码扫描器有点难。
作者: 老刘1号    时间: 2017-5-11 23:19

回复 3# 523066680


    是啊……
希望作者向nro同志学习下……
这个太难扫了……
作者: happy886rr    时间: 2017-5-11 23:35

回复 3# 523066680
速度快就行,不过我觉得还可以继续优化,但是受控制台限制,样子也只能那样了。
作者: happy886rr    时间: 2017-5-11 23:36

回复 4# 老刘1号
因为是控制台上直接扫嘛,所以应该适应适应,后续将推出三维码,彻底颠覆二维码编码规则。我的编码我做主。
作者: codegay    时间: 2017-5-12 10:43

忘记是哪个软件了,特色之一就是能在发生错误的时候,同时显示一个二维码,方便用户去搜索信息以及拿给其它人咨询。
作者: codegay    时间: 2017-5-12 10:50

快弄github啊。学一学,用图形界面的软件不难的。
作者: happy886rr    时间: 2017-5-12 11:12

回复 8# codegay
图形就不要了,因为是控制塔程序啊,如何直接显示图片都不属于命令行了,就没法发到第三方里。我这个是纯命令行,字符串二维码,根正苗红。
不过我可以在程序员小工具里,补上个带窗口的版本。
作者: codegay    时间: 2017-5-12 11:37

回复 9# happy886rr


    我是说你这么多开源的代码,学学用github。放上面。
作者: happy886rr    时间: 2017-5-12 11:40

回复 10# codegay
我都是用的git的命令行,但是感觉进度条没有,我打算写个git第三方,跟github对接。
作者: codegay    时间: 2017-5-12 11:45

回复 11# happy886rr


    6666
作者: codegay    时间: 2017-5-13 10:01

放源码放源码
作者: bbaa    时间: 2017-5-13 13:41

没反色看着不顺眼....
作者: happy886rr    时间: 2017-5-13 13:44

本帖最后由 happy886rr 于 2017-5-14 13:05 编辑

回复 13# codegay
py版发布,安装个zbar库,还能支持条码识别。
使用方法:
  1. Usage: pqr [-t text] [-o outfile] [-s show image]
复制代码
pqr支持的二维码汉字容量惊人,生成的图片体积极小、清晰度极高、容错识别极强。且pqr.exe比C语言版qr.exe功能多,可直接显示二维码,安装响应模块,可支持多种特殊功能。

体积太大,就不上传了,请君编译吧。
作者: codegay    时间: 2017-5-13 17:14

python的那个叫打包。不是编译。
作者: 老刘1号    时间: 2017-5-13 17:22

回复 17# codegay


    我也是说嘛能编译成6M,不科学了




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2