【前端】Jquery拍照,通过PHP将base64编码数据转换成PNG格式,并保存图像到本地

news2024/12/20 13:18:25

目录

一、需求

二、开发语言

三、效果

四、业务逻辑:

五、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 = 1
	c2 = 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)
	} );
	// 图片数量+1
	c = c+1
	if (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.data
				document.getElementById('results').appendChild( img );
				console.log(img)

				c2 = c2+1
				console.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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2262728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

本地摄像头视频流在html中打开

1.准备ffmpeg 和(rtsp-simple-server srs搭建流媒体服务器)视频服务器. 2.解压视频流服务器修改配置文件mediamtx.yml ,hlsAlwaysRemux: yes 3.双击运行服务器。 4&#xff0c;安装ffmpeg ,添加到环境变量。 5.查询本机设备列表 ffmpeg -list_devices true -f dshow -i d…

机器情绪及抑郁症识别算法(六)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

34. Three.js案例-创建球体与模糊阴影

34. Three.js案例-创建球体与模糊阴影 实现效果 知识点 WebGLRenderer WebGLRenderer 是 Three.js 中用于渲染 3D 场景的核心类。它负责将场景中的对象绘制到画布上。 构造器 new THREE.WebGLRenderer(parameters)参数类型描述parametersObject可选参数对象&#xff0c;包…

服务器数据恢复—RAIDZ离线硬盘数超过热备盘数导致阵列崩溃的数据恢复案例

服务器存储数据恢复环境&#xff1a; ZFS Storage 7320存储阵列中有32块硬盘。32块硬盘分为4组&#xff0c;每组8块硬盘&#xff0c;共组建了3组RAIDZ&#xff0c;每组raid都配置了热备盘。 服务器存储故障&#xff1a; 服务器存储运行过程中突然崩溃&#xff0c;排除人为误操…

108. 将有序数组转换为二叉搜索树(java)

题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,…

电子应用设计方案-60:智能床垫系统方案设计

智能床垫系统方案设计 一、引言 智能床垫作为智能家居的一部分&#xff0c;旨在为用户提供更舒适的睡眠体验和健康监测功能。本方案将详细描述智能床垫系统的设计理念、功能模块及技术实现。 二、系统概述 1. 系统目标 - 实时监测睡眠状态&#xff0c;包括心率、呼吸、体动等…

YOLOv8目标检测(六)_封装API接口

YOLOv8目标检测(一)_检测流程梳理&#xff1a;YOLOv8目标检测(一)_检测流程梳理_yolo检测流程-CSDN博客 YOLOv8目标检测(二)_准备数据集&#xff1a;YOLOv8目标检测(二)_准备数据集_yolov8 数据集准备-CSDN博客 YOLOv8目标检测(三)_训练模型&#xff1a;YOLOv8目标检测(三)_训…

CSDN数据大屏可视化【开源】

项目简介 本次基于版本3 开源 版本3开源地址&#xff1a;https://github.com/nangongchengfeng/CsdnBlogBoard.git 版本1开源地址&#xff1a;https://github.com/nangongchengfeng/CSDash.git 这是一个基于 Python 的 CSDN 博客数据可视化看板项目&#xff0c;通过爬虫采…

Moretl安全日志采集工具

永久免费: 至Gitee下载 使用教程: Moretl使用说明 使用咨询: 用途 定时全量或增量采集工控机,电脑文件或日志. 优势 开箱即用: 解压直接运行.不需额外下载.管理设备: 后台统一管理客户端.无人值守: 客户端自启动,自更新.稳定安全: 架构简单,兼容性好,通过授权控制访问. 架…

无人机航测系统技术特点!

一、无人机航测系统的设计逻辑 无人机航测系统的设计逻辑主要围绕实现高效、准确、安全的航空摄影测量展开。其设计目标是通过无人机搭载相机和传感器&#xff0c;利用先进的飞行控制系统和数据处理技术&#xff0c;实现对地表信息的全方位、高精度获取。 需求分析&#xff1…

Java学习笔记(13)——面向对象编程

面向对象基础 目录 面向对象基础 方法重载 练习&#xff1a; 继承 继承树 protected super 阻止继承 向上转型 向下转型 区分继承和组合 练习 小结&#xff1a; 方法重载 如果有一系列方法&#xff0c;功能类似&#xff0c;只是参数有所不同&#xff0c;就可以把…

Running CMake (运行 CMake)

Running CMake {运行 CMake} 1. CLion - Create a new CMake project2. Running CMake (运行 CMake)2.1. Building a project (构建项目)2.2. Picking a compiler (指定编译器)2.3. Verbose and partial builds (详细和部分的构建)2.4. Options (选项)2.4.1. Standard options …

穷举vs暴搜vs深搜vs回溯vs剪枝专题一>子集

题目&#xff1a; 两个方法本质就是决策树的画法不同 方法一解析&#xff1a; 代码&#xff1a; class Solution {private List<List<Integer>> ret;//返回结果private List<Integer> path;//记录路径&#xff0c;注意返回现场public List<List<Int…

MTU 使用使用解释

MTU (Maximum Transmission Unit&#xff0c;最大传输单元) 指的是网络链路层 (例如以太网) 能够传输的最大数据帧大小&#xff0c;以字节为单位。理解 MTU 对网络性能和可靠性至关重要&#xff0c;因为它直接影响数据包的分片 (Fragmentation) 和重组。本文档将详细解释 MTU 的…

uniapp v-tabs修改了几项功能,根据自己需求自己改

根据自己的需求都可以改 这里写自定义目录标题 1.数组中的名字过长&#xff0c;导致滑动异常2.change 事件拿不到当前点击的数据&#xff0c;通过index在原数组中查找得到所需要的id 各种字段麻烦3.添加指定下标下新加红点显示样式 1.数组中的名字过长&#xff0c;导致滑动异常…

iOS - 超好用的隐私清单修复脚本(持续更新)

文章目录 前言开发环境项目地址下载安装隐私访问报告隐私清单模板最后 前言 在早些时候&#xff0c;提交应用到App Store审核&#xff0c;大家应该都收到过类似这样的邮件&#xff1a; Although submission for App Store review was successful, you may want to correct th…

c语言-----数组

基本概念 数组是C语言中一种用于存储多个相同类型数据的数据结构。这些数据在内存中是连续存储的&#xff0c;可以通过索引&#xff08;下标&#xff09;来访问数组中的各个元素。数组的索引从0开始&#xff0c;这是C语言的规定。例如&#xff0c;一个有n个元素的数组&#xff…

社区版 IDEA 开发webapp 配置tomcat

1.安装tomcat 参考Tomcat配置_tomcat怎么配置成功-CSDN博客 2.构建webapp项目结构 新建一个普通项目 然后添加webapp的目录结构&#xff1a; main目录下新建 webapp 文件夹 webapp文件夹下新建WEB_INF文件夹 *WEB_INF目录下新建web.xml wenapp文件夹下再新建index.html …

全面解析 Kubernetes 流量负载均衡:iptables 与 IPVS 模式

目录 Kubernetes 中 Service 的流量负载均衡模式 1. iptables 模式 工作原理 数据路径 优点 缺点 适用场景 2. IPVS 模式 工作原理 数据路径 优点 缺点 适用场景 两种模式的对比 如何切换模式 启用 IPVS 模式 验证模式 总结 Kubernetes 中 Service 的流量负载…

C 语言数据类型详解

目录 一、引言 二、基本数据类型 &#xff08;一&#xff09;整型 &#xff08;二&#xff09;浮点型 &#xff08;三&#xff09;字符型 三、构造数据类型 &#xff08;一&#xff09;数组 &#xff08;二&#xff09;结构体 &#xff08;三&#xff09;联合体&#…