// pages/piano/cropper/cropper.js const { BtCmd } = require('../../../devices/bluetooth/bt_cmd'); import EventManager from '../../../utils/event_bus' import { EnumCmdEvent, CmdEvent } from '../../../devices/cmd_key_event'; import route_util from '../../../utils/route_util'; const { BtHelper } = require('../../../devices/bt_helper'); Page({ /** * 页面的初始数据 */ data: { navbarData: { showCapsule: 1, //是否显示左上角图标 1表示显示 0表示不显示 title: '壁纸设置', //导航栏 中间的标题 }, src: "", width: 320,//宽度 height: 320,//高度 showProgress: false, _chunks: [], progress: 0, _timer: null, _imgUrl: null, }, cropper: null, callback() { let that = this if (this.data._chunks.length > 0) { wx.showModal({ title: '保存图片中,确定要中断退出吗?', content: '', complete: (res) => { if (res.confirm) { that.endImage(2) wx.navigateBack({ delta: 1, }) } } }) } else { wx.navigateBack({ delta: 1, }) } }, // 图片转RGB565 convertToRGB565(imageData) { const { data, width, height } = imageData; // 原始像素数据 (RGBA 格式) const rgba = new Uint8Array(data); // 创建 RGB565 的 ArrayBuffer const pixelCount = width * height; const rgb565Buffer = new ArrayBuffer(pixelCount * 2); // 每像素 2 字节 const rgb565View = new Uint16Array(rgb565Buffer); // 转换每个像素 for (let i = 0; i < pixelCount; i++) { const r = rgba[i * 4]; // Red const g = rgba[i * 4 + 1]; // Green const b = rgba[i * 4 + 2]; // Blue // RGB565 的位运算 const r5 = (r >> 3) & 0x1F; // R 的高 5 位 const g6 = (g >> 2) & 0x3F; // G 的高 6 位 const b5 = (b >> 3) & 0x1F; // B 的高 5 位 // 组合成 RGB565 格式 const rgb565 = (r5 << 11) | (g6 << 5) | b5; // 写入到 RGB565 的 buffer 中 rgb565View[i] = rgb565; } return rgb565Buffer; }, cropperload(e) { console.log('cropper加载完成'); }, upload() { let that = this; wx.chooseMedia({ count: 1, mediaType: ['image'], sourceType: ['album'], success(res) { wx.showLoading({ title: '加载中', }) const tempFilePaths = res.tempFiles[0].tempFilePath; //重置图片角度、缩放、位置 that.cropper.imgReset(); that.setData({ src: tempFilePaths }); } }) }, loadimage(e) { wx.hideLoading(); console.log('图片', e); this.cropper.imgReset(); }, clickcut(e) { console.log("clickcut:", e.detail); //图片预览 wx.previewImage({ current: e.detail.url, urls: [e.detail.url] }) }, cancel() { wx.navigateBack({ delta: -1 }) }, submit() { let _this = this wx.showLoading({ title: '图片裁剪中', }) const fs = wx.getFileSystemManager(); this.cropper.getImg((obj) => { // app.globalData.imgSrc = obj.url; console.log("裁剪图片:", obj); _this.data._imgUrl = obj.url fs.readFile({ filePath: obj.url, encoding: '', // 不指定编码以获取原始二进制数据 success: (res) => { console.log("下载文件成功:", res) let rgbData = _this.convertToRGB565({ width: obj.width, height: obj.height, data: res.data }) console.log("下载文件成功2:", rgbData.byteLength) _this.data._imageBufferLength = rgbData.byteLength wx.hideLoading(); wx.showLoading({ title: '开始传输图片', }) _this.startImage(rgbData); // 测试 // _this.sendImage() // _this.startProgress() }, fail: (err) => { console.error('读取 .bin 文件失败:', err); }, }); }); // 651kb的 // _this.downloadAndSaveFile("https://music-play.oss-cn-shenzhen.aliyuncs.com/backOss/file/6a909799a6924e6f86a4683e6da4fad4.bin"); // 55kb的 // _this.downloadAndSaveFile("https://music-play.oss-cn-shenzhen.aliyuncs.com/backOss/file/55d2dd22bd554eb19b71536bec4ba42c.bin"); // _this.downloadAndSaveFile("https://music-play.oss-cn-shenzhen.aliyuncs.com/backOss/file/7498f0c94c5646d0a4648f313a2fa05c.bin"); }, // 下载网络文件并保存到本地 downloadAndSaveFile(url) { const fs = wx.getFileSystemManager(); let _this = this; wx.downloadFile({ url: url, // 网络文件的 URL success: (res) => { if (res.statusCode === 200) { // 下载成功,res.tempFilePath 是临时文件路径 const tempFilePath = res.tempFilePath; console.log("下载文件:", res) fs.readFile({ filePath: tempFilePath, // encoding: '', // 不指定编码以获取原始二进制数据 success: (res) => { console.log("下载文件成功:", res.data) let rgbData = res.data wx.hideLoading(); wx.showLoading({ title: '开始传输图片', }) _this.startImage(rgbData); }, fail: (err) => { console.error('读取 .bin 文件失败:', err); }, }); } else { console.error('下载文件失败:', res.statusCode); } }, fail: (err) => { console.error('下载文件失败:', err); }, }); }, checkAndRequestImagePermission: function () { const _this = this; // 检查用户是否已经授权访问相册 wx.getSetting({ success(res) { if (!res.authSetting['scope.writePhotosAlbum']) { // 用户未授权访问相册,请求用户授权 wx.authorize({ scope: 'scope.writePhotosAlbum', success() { // 用户同意授权 console.log('用户已授权访问相册'); // 可以在这里执行访问相册的操作 }, fail() { // 用户拒绝授权 console.log('用户拒绝授权访问相册'); wx.showModal({ title: '提示', content: '您拒绝了访问相册的权限,无法上传图片', showCancel: false, success(res) { if (res.confirm) { // 跳转到设置页面 wx.openSetting({ success(settingRes) { if (settingRes.authSetting['scope.writePhotosAlbum']) { console.log('用户已在设置中开启访问相册的权限'); // 可以在这里执行访问相册的操作 _this.upload(); //上传图片 } else { console.log('用户仍未授权访问相册'); } } }); } } }); } }); } else { // 用户已授权访问相册 console.log('用户已授权访问相册'); // 可以在这里执行访问相册的操作 } } }); }, async startImage(imageBuffer) { this.sliceDataIntoChunks(imageBuffer, 16); BtHelper.sendCallBack(BtCmd.wallPaper(1), function (res) { if (!res) { wx.hideLoading() wx.showToast({ title: '发送失败', icon: 'none' }) } }); }, sliceDataIntoChunks(data, chunkSize) { console.log("发送图片数据:", data.byteLength) const chunks = []; // for (let i = 0; i < data.length; i += chunkSize) { for (let i = 0; i < data.byteLength; i += chunkSize) { const chunk = data.slice(i, i + chunkSize); chunks.push(chunk); } this.data._chunks = chunks; }, async sendImage() { let _this = this wx.hideLoading() let chunks = this.data._chunks let next = 0; let total = this.data._imageBufferLength; let btHelper = BtHelper.getInstance(); let i = 0; this._timer = setInterval(async () => { const chunk = chunks[i]; i++; next += chunk.byteLength; // next += chunk.length; let uint8Array = new Uint8Array(chunk); let unit16 = uint8Array.map(item => { return item.toString(16) }); console.log("发送图片数据1:", i, next, total, unit16) _this.updateProgress(next, total); let res = await btHelper.wallPaperSyncData(chunk); // let res = true; // btHelper.wallPaperData(chunk); let nowDate = Date.now() if (i === chunks.length - 1 && res) { wx.showModal({ title: '图片上传成功' + i + " / " + nowDate, showCancel: false, success(res) { if (res.confirm) { const pages = getCurrentPages(); // 获取上一级页面实例 const prevPage = pages[pages.length - 2]; // 传递参数 prevPage.setData({ topImg: { "pic": _this.data._imgUrl, } }); wx.navigateBack({ delta: 1, }) } } }) _this.endImage(0) } else if (!res) { wx.showModal({ title: '图片上传失败', showCancel: false }) _this.endImage(2) } }, 20); }, async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, endImage(value) { let _this = this console.log("结束图片上传:", value) if (_this.data._timer) { clearInterval(_this.data._timer) _this.data._timer = null } _this.data._chunks = [] BtHelper.getInstance().wallPaper(value); if (value === 0) { } else { // 获取页面栈 } }, startProgress() { this.setData({ progress: 0, showProgress: true }) }, updateProgress(chunk, total) { let progress = parseFloat((chunk / total * 100).toFixed(2)); let _this = this if (chunk >= total) { _this.setData({ progress: 0, showProgress: false, // showCropImg: false }); wx.showToast({ title: '图片上传成功', }) } else { _this.setData({ progress: progress, }); } }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.checkAndRequestImagePermission() this.cropper = this.selectComponent("#image-cropper"); this.cropper.imgReset(); // this.setData({ // scr:json, // }) this.upload(); //上传图片 let _this = this; EventManager.addNotification(CmdEvent.eventName, function (event) { let name = event.cmdEvent; console.log("裁剪页:", EnumCmdEvent) switch (name) { case EnumCmdEvent.wallpaper: let otaCmd = event.wallpaper; let kind = event.heiJiaoKind; console.log("裁剪页:", otaCmd, kind) if (otaCmd === 1 && kind == 1) { // 开始发送 _this.sendImage() _this.startProgress() } else if (otaCmd === 0 && kind == 1) { // 发送结束 } else if (kind == 0) { wx.hideLoading() wx.showModal({ title: '图片上传失败了', showCancel: false }) if (_this.data._timer) { clearInterval(_this.data._timer) _this.data._timer = null } } break; default: break; } }, this) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, /** * 生命周期函数--监听页面显示 */ onShow() { }, /** * 生命周期函数--监听页面隐藏 */ onHide() { }, /** * 生命周期函数--监听页面卸载 */ onUnload() { EventManager.removeNotification(CmdEvent.eventName, this); }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { }, /** * 用户点击右上角分享 */ onShareAppMessage() { } })