暂无公开图库照片
是不是努力Coding 就可以买大House

暂无公开图库照片
是不是努力Coding 就可以买大House
开源了。
让 AI 整理了下之前写的一个小工具
顺着教我怎么用Github Actions 自动化发布
于是 npm 仓库上 又留下了我的一个脚印
客户那边有一套用了很多年的 ERP 系统,导出的二维码用手机扫一扫,呈现出来的是一串看不懂的乱码。用 Java 或者 Python 去读图片底层的字节数据,再做一次编码转换,是可以还原成正常中文的。但我们的场景是纯前端——用户在浏览器里上传图片或者打开摄像头,就要直接得到正确的结果,不能依赖后端服务。
前端这边折腾了挺久,最后用 zxing-wasm 配合一套自定义的解码逻辑,总算把这个问题解决了。
zxing-wasm 是 ZXing C++ 库的 WebAssembly 版本,编译后可以直接在浏览器里运行。调用时把图像数据传进去,通过配置参数来启用各种内置的预处理能力:
const results = await readBarcodes(imageData, {
formats: ['QRCode'],
tryRotate: true, // 自动旋转 0/90/180/270 度
tryInvert: true, // 尝试反色(黑底白字)
tryHarder: true, // 启用更精细的搜索
tryDownscale: true, // 大图自动缩小以加速
tryDenoise: true, // 形态学降噪
maxNumberOfSymbols: 4,
});
灰度化、二值化、旋转修正、反色判断、降噪这些步骤,全部在 C++ 层内部完成,前端不需要额外处理,代码更简洁,识别率也有保障。
引擎虽然能识别出二维码的内容,但遇到不带 ECI 字符集声明的中文二维码时,会默认按 UTF-8 解码。GBK 编码的中文在这种情况下就会显示成 æ±‰å— 这样的乱码——这是字符集探测本身的局限,不是引擎的 Bug。
readBarcodes 返回的结果里,除了 text(引擎自动解码后的文本),还有一个 bytes 字段,存放的是原始字节数组。问题就转化成了:拿到原始字节后,如何判断它到底应该用什么编码来解读。
思路很简单:把常见的几种中文编码都试一遍,然后挑一个最像“正常文本”的结果。
function decodeBytesSmart(bytes: Uint8Array) {
const encodings = ['gbk', 'gb18030', 'gb2312', 'utf-8', 'big5'];
const attempts = encodings.map(enc => {
try {
const text = new TextDecoder(enc).decode(bytes);
return { encoding: enc, text, score: scoreText(text) };
} catch { return null; }
}).filter(Boolean);
attempts.sort((a, b) => b.score - a.score);
return attempts[0];
}
关键是这个评分函数——怎么判断一段文本是“正常的”还是“乱码”?
function scoreText(t: string): number {
if (!t) return -1e9;
let s = 0;
// 中文字符越多,得分越高
const cn = t.match(/[\u4e00-\u9fff]/g);
if (cn) s += cn.length * 5;
// 以 { 或 [ 开头,可能是 JSON,加分
if (t.trim().startsWith('{') || t.trim().startsWith('[')) s += 20;
// 包含典型的 UTF-8 误读乱码字符,减分
if (/Ã.|Â./.test(t)) s -= 30;
// 高字节西欧符号,减分
const garbage = (t.match(/[€‚ƒ…†‡ˆ‰Š‹ŒŽ'""•–—˜™š›œžŸ]/g) || []).length;
s -= garbage * 10;
return s;
}
中文字符多、有 JSON 结构,说明这段文本很大概率是正常的;出现 Ã、Â 这类 Latin-1 误读字符,或者大量高字节符号,基本就是乱码。用这个规则给每个编码尝试结果打分,分数最高的那个就是最可能的正确文本。
最后一步,把引擎自带的解码结果和暴力探测的最高分结果放在一起比较,谁分高就用谁:
const smart = decodeBytesSmart(target.bytes);
let text = target.text;
if (!text || scoreText(smart.text) > scoreText(text)) {
text = smart.text;
}
这套方案上线之后,无论是标准的 UTF-8 二维码,还是老 ERP 导出的 GBK 编码二维码,都能在浏览器里直接还原成正确的中文内容。整个过程不依赖后端,用户上传图片或打开摄像头扫码,得到的就是可读的文本。
网站恢复上线了。
微信又收到了打赏通知。
22年开始做的这个工具网站,最开始就寝室里用。
再后来开了源,上了在线版,修bug、优化性能,小白一个,跌跌撞撞弄了几年。
用户过了万,挺意外的。
今年五月,接口被攻击,上游把服务拉黑了。
只能暂时停掉,仓库也藏起来了,怕被人顺着逻辑继续搞。
原来攒的star也全没了。
那段时间在群里教大家怎么本地部署,能用的接着用。
最近工作没那么忙,把代码重构了,重新开源。
之前用的朋友也陆续回来了。
重新上线之后,开始有人打赏了。
感谢每一位。
深圳连着下了好几天雨,今天一天都没停过。
下班出来,雨还在飘着,不大不小,烦得很。
换了地方租房,也不能骑小电驴,扫了辆共享单车去地铁站。
自行车道跟人行道混在一起,电动车在旁边窜来窜去,得让着点。
路面坑坑洼洼的,雨天路滑,一手撑伞一手扶把,不安全。
就这么骑了一路,总算到地铁站。
收伞,甩了甩水,进站,刷卡,等车。
一天又过完了。
周末休息,跟女朋友去中医医院看脸上的痘痘。
反反复复长了好一阵,心情也不太好。
深圳还在下雨,打不到车,在路边拦了辆摩托车,小雨,让师傅慢点开。
预约时间快到了,但安全要紧。
医院有好几栋楼,约的是一位甘肃名医,独立的大办公室,挺气派。
把了脉,问了诊,开了药方,还有祛痘面膜和痛经的药。
下楼去药房办了快递,中药要熬,直接寄回去方便。
又上七楼,医生做了火针,一颗颗挑破,又用紫光灯照了十来分钟。
灯光太刺眼,没敢一直看。
灯停了,问医生可以走了。女朋友脸上大大小小的红点,看着有点心疼。
希望这次能好,别再受这番困扰了。
出来还在下雨,还是打不到车。
沿着坡往下走了一段,到了大公路才叫到车。
等车的时候,雨伞遮不住雨点,我们俩蹲在门庭下躲雨。
司机到了,车里空调开得足,一上车打了个寒颤。
没一会儿开始晕车,红灯多,走走停停,胃里翻得难受。
女朋友也累,靠着眯了一会儿。
总算到了,下车吸了口新鲜空气,缓过来了。
周五了。
一天也没什么事,和同事各自对着电脑。
到了下班点,关掉屏幕,收拾东西。
出了园区,夕阳泛着红。
周五晚上,路上人多,车也多。
明天不用早起,可以睡到自然醒。
地铁到了,上去,找个角落站好。
周五了,挺好。
快下班了,瞄了一眼日期。
突然想起来,今天是好朋友生日。
发了条消息过去,约了晚上碰头。
女朋友今天没上班,提前过去点了菜和蛋糕。
我也提前撤了,在地铁口接上他。
商场就在旁边,坐下来边吃边聊,聊了些有的没的。
吃完饭在商场里逛了一圈,新开了家零食店,人挺多。
女朋友已经逛过买过了,我们也就没再买。
可惜是周一,不能痛痛快快玩一宿。
聚少离多,但感情没变过。
生日快乐。
几个周末都在看房,这周总算搬了。
下班回去就开始收拾,之前零零散散拾掇过一些,但最后一天还是得抓紧,东西比想象中多,堆了一地,一直收拾到八点半。
约的小厢车,九点司机准时到了。
车快开走的时候,女朋友想起来说电动车还没拉,我本来打算自己下班骑过去,差点忘了。
司机人挺好,没多说什么,帮忙一起把电动车抬上车。
我给他们买了瓶水,自己也喝了一瓶。
公寓管家来验房,转了一圈,没什么问题,第二天顺利退了押金。
关上门那一刻,住了一年的地方,说不清什么感觉,有点累,也有点不舍。
车开到新住处,又把东西一件件搬上去,电动车也安安稳稳拉过来了。
女朋友在家还有几天才上班,我第二天还得早起。
屋里东西摊了一地,也没力气细整了,把床铺出来,被子一裹就躺下了。
明天再说吧。
新地方,从今晚开始住。

周四了,要放假了😭
周四了,要放假了😭
周四了,要放假了😭
做了一个梦。
公司转型升级了。
我的工作是去高中当一个学生。
梦里坐在教室里,好几个同学也在,但看不清。
下课铃响的时候醒了一下,又睡过去,继续梦。
梦到课间趴在桌上补觉。
醒来的时候人在床上,周一了。
躺着想了想,上班要是改成去当学生,也不是不行。
看了一眼手机,没有通知说公司转型的事。
起床上班。
一不小心两点半了,睡了睡了。
建议不要在520发誓啊喂,大暴雨天让牛马怎么上班 😭
@我是柚子:我爸叫鄢水平,用我妈的话讲,他这辈子混得挺没水平的。
他初中辍学跟人学了半年屠宰,之后二十多年在外做工地建筑工人了,也没混到过个包工头当当,最后一笔工钱还被跟了几年的包工头抹了五十多块钱的零头,五十岁刚过,还完家里最后一笔债,人就没了。
他排行第六,是七个姊妹兄弟里面唯二的男丁,听家里人讲,小时候有什么都是先紧着大的,他从小也因为家里穷没过上啥好日子。
后面有了我和姐姐,要自建房、要供我们读书,他就更省了:没有买过一件羽绒服,作为家里最怕冷的,每年冬天也只是一件又一件叠穿不防寒的毛衣,永远穿着我初高中的鞋子,一把铁锤用了十几年,柄要脱落了也没换过,为了省五十块钱选通宵的硬座火车票而不是硬卧…
其实我和他感情本来不太深的,从我出生到他死的二十来年里,他基本都只会过年会回家,小小的我自作聪明地以为他就是不爱我,所以我也不用多对他好。
我的童年也好像一直缺失着父亲的角色,我遇事也从来不会跟他打电话,不会和他说我的事,我们的交流固定在过年的几天在家一起吃饭,以及每年过年和生日的分别一个200块红包。
23年过年,因为我22年复读高考完,成了全家也是全村第一个考上985的,他一定拉着我和他去姑姑们家走亲戚,以前的我都因为和他们不亲,不愿意去他也不会强求,可这次他一定坚持要我陪他去,我想他是想弯了一辈子的腰板,可以挺直一次。
但面对的是姑父们的各种挖苦和瞧不起,他们说我们家一直都没起色没出息,会读书也没什么用,我很愤懑,为什么他都不会回嘴,为什么要受这种窝囊气,回家后我就对他发脾气说,我再也不会跟他一起去走亲戚去受气了!
24年初过年,他这一年没有喊我一起去走亲戚了,不想我跟着受气受委屈吧,他自己去的时候,我不瞥见他脑后的错落的白发,才意识到这个一米六几、不到一百斤的男人慢慢老了。我突然意识到我得多爱他一点的,我发了个私密朋友圈说等我大二结束要拿好多奖学金,明年过年的时候要给他买最暖最厚的羽绒服,要提前给他买好卧铺票。
那年三月,你出去打工不久就从二楼工地摔下来了,右脚被划破真菌感染,全部紫红的鼓肿起来了,当然这些都是在你死了之后,我才通过你手机相册知道的,毕竟我基本从来不会主动找你了解你的近况。
五月底你身体疼得受不了,和舅舅一起去医院检查,医生说你还有本事干工地啊?肝癌晚期,随时都可能不行了,叫你赶紧回家里和亲人告别吧。你打通妈妈的电话,第一句说的是对不起,出门几个月,没给家里带来什么好消息还得了恶病。
六月初是我生日,你不同以往的,一次性给我发了两个红包,现在想来,是提前把过年的压岁钱给我了,你估计自己挺不到那个时候了。因为我在期末考试,你和妈妈商量了,让所有亲戚都只对我隐瞒了,发完生日红包之后到你死的一个月里,你一句话也没和我说过了。
六月底你实在疼得受不了了,才跟家里人说要让姐姐知道,要让姐姐回家,你总是怕耽误我们,怕耽误姐姐工作,怕耽误我读书,可我们耽误你的一生,你怎么不怨我呢?
七月三号,我结束完期末考试,姐姐偷偷试探我的考试结束与否,说了爸爸的病情。刚刚爸爸跟她讲恐怕要守夜了,可能挺不过这两天了,不知道能不能等到我回来了,这也是他留给我的最后一句话。当晚我凌晨三点搜索着肝癌晚期的症状,心疼地哭着睡不着觉,在我第二天第一次登上飞机,收拾了很多拍立得相纸要和他拍,拍下了飞机上很好看的云和晚霞。
等我回去了,才知道你在姐姐跟我说完消息的四个小时之后就走了。你是在凌晨十二点多走的,长辈说,咱那边人如果在晚上十二点前走就可能会把后辈以后的福气,早午晚饭都带走,你硬生生不愿意咽气,挨到的凌晨十二点后,你还是怕耽误我和姐姐。
第二天回家的我能做的就只有在你走的那个房间外磕了三个头,再见你,是在火葬场从冷冻柜推出来的,穿着寿衣,被病痛折磨的只剩皮包骨,我不敢认你,跪着哭着给你磕头,我不信,半年不见的人就再也不能见了。
火化了捧着你的骨灰盒我们回了家,把你安葬在家不远的山头,风水先生说那一块很适合你,前有水后有路,在地下会住得很舒坦。你是不是住得太舒服都不舍得给我托梦,还是在怪我没有好好关心你呢?
面对购物车那件没来得下单的羽绒服,面对没来得及拆封和你拍的相纸,面对相册拍下的那么好看的天上的云和天,我该和谁说呢?
你那么怕冷,是因为担心我给你买羽绒服费钱,所以才永远留在最热的夏天吗
你儿子在你死了的一年里,一直都努力奔前程,一直努力赚学费。在你的一周年忌日当天,结束了北大的面试,后面还顺利通过了,但是学费有点贵,我一边实习赚钱一边哭,我付不起。
后来我也去了清华面试,但是发挥的不好,面试的前一个晚上哭到两点睡不着,结果是没过,面对着十几万的北大学费,我自责地哭得停不下来,是不是我哭得太大声你心疼地受不了,后面才会破天荒地被清华候补录取,垫底倒数着进去了,不用太担心学费问题了。今年暑假我借了朋友的北大录取封壳,把北大优营邮件打印出来烧给你你有没有收到?
又要过年了,你能回来看看我吗?
鄢水平,其实你当爸爸很有水平
#爸爸 #我爱你 #亲人的离世不是一场暴雨而是一生的潮湿 #争气 #清华大学
降温了😴
留言加载中…