【前端】Jquery拍照,通过PHP将base64编码数据转换成PNG格式,并保存图像到本地
目录
一、需求
二、开发语言
三、效果
四、业务逻辑:
五、web端调用摄像头
六、示例代码
1、前端
2、后端
一、需求
web端使用jquery调用摄像头拍照,并使用PHP把base64编码转换成png格式图片,下载到本地。
由于js不能指定图片存储的位置,所以需要把base64图像数据传到后台,由后台存储到指定位置。
二、开发语言
前端:JS
后端:PHP
三、效果
点击“拍摄图像”按钮,自动连续拍摄10张并上传到后台,存放到指定位置,并在前端显示预览图像
四、业务逻辑:
① 前端点击“拍摄图像”按钮,开始拍照,我这里的需求是连续拍摄10张
② 前端获取到base64编码图像数据,并发送到后端
③ 后端接收到base64编码后,转换成PNG格式并保存到指定位置
④ 图片存储成功后,返回图片路径给前端
⑤ 前端显示拍摄的图像
五、web端调用摄像头
web端调用摄像头使用“webcam.js”插件,使用webcam.js调用摄像头前提是项目是https,否则没有获取摄像头的权限。
WebcamJS:jQuery移动端调用摄像头拍照插件WebcamJS
六、示例代码
1、前端
HTML:图像采集区
<style type="text/css">#open-power{transition: transform 0.3s ease-in-out; /* 添加过渡效果,使变换更平滑 */ transform-origin: center center; /* 变换原点设置为图片中心 */ width: 100%; /* 初始尺寸设置为容器宽度 */ height: auto; /* 保持图片的宽高比 */ }#imageContainer{overflow: hidden; /* 隐藏超出容器的部分 */position: relative; /* 如果需要相对于容器定位图片,可以添加这个属性 */margin: 0 auto;background:rgba(41, 123, 255, 0.06);border-radius:18px;border:1px dashed #297BFF;cursor:pointer;box-shadow:4px 4px 18px 0px rgb(0 0 0 / 8%);padding: 10px;}.main__camera-power{background: none;border-radius: 0;border: none;cursor:none;margin: 0 auto;box-shadow:none; padding: 0px;}
</style>
<div class="layui-col-md8 layui-col-sm8 layui-col-xs12"><div class="layui-row"><div class="layui-col-md12 layui-col-sm12 layui-col-xs12"><fieldset class="layui-elem-field"><legend>图像采集区</legend><div class="layui-field-box"><!-- 图像 --><div id="imageContainer"><div id="open-power" class="main__camera-power flex-center"><span class="main__camera-power--span"><img src="/home/images/camera.png" alt="power" /></span><p class="main__camera-power--hint">请开启摄像头权限</p></div></div></div></fieldset></div></div>
</div>
HTML:拍摄图像按钮
<div class="layui-col-md6 layui-col-sm6 layui-col-xs12"><div class="paizhao" style=" width: 4.5rem; height: 4rem; margin: 0 1rem; background: #F0F0F0; text-align: center; box-shadow: 4px 4px 10px #888888; font-size: 0.9rem; border-radius: 10px; cursor: pointer; color: #000; font-size: 0.9rem;" ><i class="layui-icon layui-icon-camera-fill" style="font-size: 30px; color: #555;"></i> <br/>拍摄图像</div>
</div>
HTML:图片预览区域
<style>
/* 图像预览区域 */
#results { background:#f8f8f8; }
#results > img { width: 160px; height: 120px; margin: 3px}
</style><div class="layui-row" style="width: 98%; margin: 1% auto; "><div class="layui-col-md12 layui-col-sm12 layui-col-xs12"><div style="border: 1px solid #e6e6e6; height: 120px;overflow:auto;"><div id="results" style=""><p>Your captured images will appear here...</p></div></div></div>
</div>
JS:
<script src="/home/js/jquery-1.12.3.min.js"></script>
<script src="/home/js/webcam.js" type="text/javascript" charset="utf-8"></script>// 初始化操作 设置摄像头区域
$(function(){// 获取窗口尺寸并设置摄像头宽高为80%function setCameraSize() {var windowWidth = window.innerWidth;var windowHeight = window.innerHeight;var cameraWidth = windowWidth * 0.45;var cameraHeight = windowHeight * 0.68;$("#imageContainer").css('width',cameraWidth)$("#imageContainer").css('height',cameraHeight)// 设置摄像头宽高Webcam.set({width: cameraWidth,height: cameraHeight,jpeg_quality: 90});// 附加摄像头到容器Webcam.attach('#open-power');}// 初始设置setCameraSize();// 监听窗口大小改变事件window.addEventListener('resize', setCameraSize);});// 拍摄图像
var c = 1 // 图像张数
var c2 = 1; // 图像张数
var timer = null// 开始拍照
$(".paizhao").click(function () {c = 1c2 = 1// 拍照前先清空div里已存在的图像document.getElementById('results').innerHTML = '';var yinpian = $('#yinpian').val();if (yinpian == '') {layer.msg('请先选择饮片名称', {time: 3000, icon:2});clearTimeout( timer );return false}layer.msg('图像正在采集并处理,请稍后...', {time: 3000, icon:0});tip_html = '<br/><span style="color:green">【'+yinpian+'】</span>图像正在采集并处理,请稍后...'$("#systip").prepend(tip_html)// 开始拍照take_snapshot();// 定时 每250ms拍摄一次timer = setInterval( take_snapshot, 250 );
})function take_snapshot() {// 获取饮片名称var yinpian = $('#yinpian').val();if (yinpian == '') {layer.msg('请先选择饮片名称', {time: 3000, icon:2});clearTimeout( timer );return false}Webcam.snap( function(data_uri) {// 图片保存到本地saveJpg(data_uri,yinpian)} );// 图片数量+1c = c+1if (c > 10) {// 十张采集完成,结束采集clearTimeout( timer );timer = null;}}// Base64保存为jpg
function saveJpg(base64data,yinpian) {$.ajax({url:'/index/index/saveJpg',type:'POST',dataType:'JSON',data:{img:base64data,yinpian:yinpian},success:function (res) {console.log(res)var img_html = ''if (res.code == '200') {// 把返回的图像地址追加显示到图像预览区域var img = new Image();img.src = '/'+res.datadocument.getElementById('results').appendChild( img );console.log(img)c2 = c2+1console.log(c2)if (c2 > 10) {layer.msg('10张采集完成,请调整饮片再次采集', {time: 3000, icon:1});tip_html = '<br/><span style="color:green">【'+yinpian+'】</span>图像10张采集完成,请调整图像再次采集!'$("#systip").prepend(tip_html)}}}})
}
2、后端
接收前端传来的base64编码,把base64编码数据转存成png,并存放到指定位置
/**
* base64保存为jpg
*/
public function saveJpg()
{if (request()->isPost()) {$baseImg = trim(input('post.img')); // base64编码$yinpian = trim(input('post.yinpian')); // 饮片名称if (!empty($baseImg) && !empty($yinpian)) {//图片存放的路径$path = "uploads/images/".$yinpian.'/';if (!file_exists($path)) {mkdir($path, 0700, true); //创建目录chmod($path, 0700); //赋予权限}$uid = session('uid');//确保图片名唯一,防止重名产生覆盖$imageName = 'wx_' .$uid.'_' . rand(1000, 9000) . time(). '.jpg';//判断是否有逗号 如果有就截取后半部分if (strstr($baseImg,",")){$baseImg = explode(',',$baseImg);$baseImg = $baseImg[1];}//图片路径$imageSrc= $path . $imageName;//生成文件夹和图片$r = file_put_contents($imageSrc, base64_decode($baseImg));if($r){return apiResponse('200','图像保存成功',$imageSrc);}else{return apiResponse('110','图像保存失败');}}else{return apiResponse('110','初始化失败,请刷新页面');}}else{return apiResponse('110','非法请求');}
}
如果有控制摄像头放大缩小画面的需求,可参考另外一篇【PHP】控制摄像头缩放监控画面大小,并保存可视画面为图片_代码怎么实现监控视频怎么放大画面-CSDN博客
相关文章:

【前端】Jquery拍照,通过PHP将base64编码数据转换成PNG格式,并保存图像到本地
目录 一、需求 二、开发语言 三、效果 四、业务逻辑: 五、web端调用摄像头 六、示例代码 1、前端 2、后端 一、需求 web端使用jquery调用摄像头拍照,并使用PHP把base64编码转换成png格式图片,下载到本地。 由于js不能指定图片存储的…...
websocket再项目中的使用
WebSocket在项目中的使用主要包括以下几个方面: WebSocket的基本概念和原理: 定义:WebSocket是一种基于TCP的协议,实现了浏览器与服务器之间的全双工通信。它通过HTTP/1.1协议的101状态码进行握手,建立连接…...
ajax同步执行async:false无效的解决方法
无效的情况: function ManHourCheck() {var StartDate $("#StartDate").val();//日报日期var EndDate $("#EndDate").val();//完成日期var UserID $("#UserID").val();//员工ID$.ajax({async: false,//加了这一行也没用!!!!!!!!!!…...

基于Qt的登陆界面设计
目标 自由发挥登录界面的应用场景,实现一个登录窗口的界面。 要求:每行代码都要有注释 代码 // 设置窗口大小为600x400像素 this->resize(600,400); // 设置窗口标题为"TheWitcher 巫师3:狂猎" this->setWindowTitle(&qu…...

HarmonyOS 输入框组件:TextInput 和 TextArea 深度解析
输入框组件是移动端开发中最常见的组件之一,常用于响应用户的输入操作,比如评论区的文本输入、聊天框的消息输入、表单内容填写等场景。在 HarmonyOS 中,TextInput 和 TextArea 分别用于单行和多行输入操作。除此之外,它们还可以与…...
【Golang】 Go 语言中的 Struct、JSON 和 Map 互转:详细指南
Go 语言中的 Struct、JSON 和 Map 互转:详细指南 在 Go 语言中,处理 JSON 数据、结构体类型和映射(map)是与 API、配置或数据库交互时非常常见的任务。理解如何在这些数据类型之间无缝转换对于高效的 Go 编程至关重要。以下是如何将 Go 结构体转换为 JSON、将 JSON 转换为…...

Azure Function流式返回
最近用azure function做了一个api和llm交互,需要流式返回。但是默认不支持流返回,搜索了一下。记录。 官方文档:https://techcommunity.microsoft.com/blog/azurecompute/azure-functions-support-for-http-streams-in-python-is-now-in-prev…...

智能座舱进阶-应用框架层-Jetpack主要组件
Jetpack的分类 1. DataBinding:以声明方式将可观察数据绑定到界面元素,通常和ViewModel配合使用。 2. Lifecycle:用于管理Activity和Fragment的生命周期,可帮助开发者生成更易于维护的轻量级代码。 3. LiveData: 在底层数据库更…...
GitLab分支管理策略和最佳实践
分支管理是 Git 和 GitLab 中非常重要的部分,合理的分支管理可以帮助团队更高效地协作和开发。以下是一些细化的分支管理策略和最佳实践: 1. 分支命名规范 • 主分支:通常命名为 main 或 master,用于存放稳定版本的代码。 • …...
【Unity】【VR开发】实现VR屏幕共享应用的几个重要插件和参考资料分享
【背景】 做了一个可以在局域网远程屏幕的VR应用,如果有相同兴趣的朋友也可以参考下我用的几个插件。 【使用或相关的关键插件】 piping server:这个是最基底的插件,基于它实现的信令通信。 https://github.com/nwtgck/piping-server/blob…...

数据结构---------二叉树前序遍历中序遍历后序遍历
以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例,包括递归和非递归(借助栈实现)两种方式: 1. 二叉树节点结构体定义 #include <stdio.h> #include <stdlib.h>// 二叉树节点结构体 typedef struct…...

浏览器引入elasticsearch-head插件
elasticsearch-head插件下载: 链接: https://pan.baidu.com/s/1Dz3aU42HZCNg45iJoDOsMg?pwduvhg 提取码: uvhg 1、打开浏览器设置 2、选择拓展程序 3、选择elasticsearch-head插件下载 4、打开es-head插件 5、修改ip 6、登录...

【ELK】Filebeat采集Docker容器日志
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 介绍filebeat是如何工作的 使用部署filebeat 介绍 Filebeat 是一个用于转发和集中日志数据的轻量级传送器。 Filebeat 作为agent安装在服务器上,监视指…...

异步线程池与CountDownLatch
异步线程池 顾名思义,一个专门用来处理异步任务的线程池。可以避免线程的开销以及非阻塞的执行任务。 CountDownLatch 一个同步工具类,用于 让一个或多个线程等待一组操作完成。 业务场景 支付订单时,用户可以使用多张优惠劵,…...
在图像上显示掩码、框和点的通用函数
在图像上显示掩码、框和点的通用函数 背景介绍函数实现与用途1. 显示掩码函数:`show_mask`2. 显示边界框函数:`show_box`3. 在图像上显示点函数:`show_points`4. 综合显示框和点函数:`show_points_and_boxes_on_image`5. 显示掩码并返回图像函数:`show_mask_on_image`6. 显…...
基于Matlab的变压器仿真模型建模方法(11):三相三绕组换流变压器的建模仿真
1.概述 换流变压器是直流输电系统中的关键设备,主要负责连接交流和直流系统,并实现电能的转换与传输。换流变压器在直流输电系统中的主要用途包括:传送电力:将电能从交流系统传输到直流系统或从直流系统传输到交流系统;电压变换:把交流系统电压变换到换流器所需的换相电压…...
代码随想录算法训练营day46|动态规划part12
今天就结束动态规划章节了,以后还要多加练习。 今天的两道题都很有难度,647回文子串的思路非常巧妙,因为用一维dp数组比较难表示子串的起点和终点,所以需要用二维dp数组表示,dp[i][j]表示以i为起点,j为终点…...

【C语言】头文件
所有学习过C语言的朋友都熟悉这样一段代码: #include <stdio.h>int main(int argc, char *argv[]) {return 0; }那么,你真的了解 <stdio.h> 吗? <stdio…...

蓝桥杯——竞赛省赛国赛题分享
目录 一.[蓝桥杯 2013 省 AB] 错误票据 代码如下: 二.[蓝桥杯 2024 省 Java B] 报数游戏 代码如下: 讲解: 三.[蓝桥杯 2014 国 C] 拼接平方数 代码如下: 四.三步问题(递归,上台阶) 代码…...

企业内训|阅读行业产品运营实战训练营-某运营商数字娱乐公司
近日,TsingtaoAI公司为某运营商旗下数字娱乐公司组织的“阅读行业产品运营实战训练营”在杭州落下帷幕。此次训练营由TsingtaoAI资深互联网产品专家程靖主持。该公司的业务骨干——来自内容、市场、业务、产品与技术等跨部门核心岗位、拥有8-10年实战经验的中坚力量…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...