1# 图片开发指导 2 3## 场景介绍 4 5图片开发的主要工作是将获取到的图片进行解码,将解码后的pixelmap编码成支持的格式,本文将对图片的解码、编码等场景开发进行介绍说明。 6 7## 接口说明 8 9详细API含义请参考:[图片处理API文档](../reference/apis/js-apis-image.md) 10 11## 开发步骤 12 13### 全流程场景 14 15包含流程:创建实例、读取图片信息、读写pixelmap、更新数据、打包像素、释放资源等流程。 16 17```js 18const color = new ArrayBuffer(96); // 用于存放图像像素数据 19let opts = { alphaType: 0, editable: true, pixelFormat: 4, scaleMode: 1, size: { height: 2, width: 3 } } // 图像像素数据 20 21// 创建pixelmap对象 22image.createPixelMap(color, opts, (err, pixelmap) => { 23 console.log('Succeeded in creating pixelmap.'); 24 // 创建pixelmap对象失败 25 if (err) { 26 console.info('create pixelmap failed, err' + err); 27 return 28 } 29 30 // 用于读像素 31 const area = { 32 pixels: new ArrayBuffer(8), 33 offset: 0, 34 stride: 8, 35 region: { size: { height: 1, width: 2 }, x: 0, y: 0 } 36 } 37 pixelmap.readPixels(area,() => { 38 let bufferArr = new Uint8Array(area.pixels); 39 let res = true; 40 for (let i = 0; i < bufferArr.length; i++) { 41 console.info(' buffer ' + bufferArr[i]); 42 if(res) { 43 if(bufferArr[i] == 0) { 44 res = false; 45 console.log('readPixels end.'); 46 break; 47 } 48 } 49 } 50 }) 51 52 // 用于存像素 53 const readBuffer = new ArrayBuffer(96); 54 pixelmap.readPixelsToBuffer(readBuffer,() => { 55 let bufferArr = new Uint8Array(readBuffer); 56 let res = true; 57 for (let i = 0; i < bufferArr.length; i++) { 58 if(res) { 59 if (bufferArr[i] !== 0) { 60 res = false; 61 console.log('readPixelsToBuffer end.'); 62 break; 63 } 64 } 65 } 66 }) 67 68 // 用于写像素 69 pixelmap.writePixels(area,() => { 70 const readArea = { pixels: new ArrayBuffer(20), offset: 0, stride: 8, region: { size: { height: 1, width: 2 }, x: 0, y: 0 }} 71 pixelmap.readPixels(readArea,() => { 72 let readArr = new Uint8Array(readArea.pixels); 73 let res = true; 74 for (let i = 0; i < readArr.length; i++) { 75 if(res) { 76 if (readArr[i] !== 0) { 77 res = false; 78 console.log('readPixels end.please check buffer'); 79 break; 80 } 81 } 82 } 83 }) 84 }) 85 86 const writeColor = new ArrayBuffer(96); //图像像素数据 87 // 用于写像素到缓冲区 88 pixelmap.writeBufferToPixels(writeColor).then(() => { 89 const readBuffer = new ArrayBuffer(96); 90 pixelmap.readPixelsToBuffer(readBuffer).then (() => { 91 let bufferArr = new Uint8Array(readBuffer); 92 let res = true; 93 for (let i = 0; i < bufferArr.length; i++) { 94 if(res) { 95 if (bufferArr[i] !== i) { 96 res = false; 97 console.log('readPixels end.please check buffer'); 98 break; 99 } 100 } 101 } 102 }) 103 }) 104 105 // 用于获取图片信息 106 pixelmap.getImageInfo((err, imageInfo) => { 107 // 获取图片信息失败 108 if (err || imageInfo == null) { 109 console.info('getImageInfo failed, err' + err); 110 return 111 } 112 if (imageInfo !== null) { 113 console.log('Succeeded in getting imageInfo'); 114 } 115 }) 116 117 // 用于释放pixelmap 118 pixelmap.release(()=>{ 119 console.log('Succeeded in releasing pixelmap'); 120 }) 121}) 122 123// 用于创建imagesource(uri) 124let path = '/data/local/tmp/test.jpg'; 125const imageSourceApi1 = image.createImageSource(path); 126 127// 用于创建imagesource(fd) 128let fd = 29; 129const imageSourceApi2 = image.createImageSource(fd); 130 131// 用于创建imagesource(data) 132const data = new ArrayBuffer(96); 133const imageSourceApi3 = image.createImageSource(data); 134 135// 用于释放imagesource 136imageSourceApi3.release(() => { 137 console.log('Succeeded in releasing imagesource'); 138}) 139 140// 用于编码 141const imagePackerApi = image.createImagePacker(); 142const imageSourceApi = image.createImageSource(0); 143let packOpts = { format:"image/jpeg", quality:98 }; 144imagePackerApi.packing(imageSourceApi, packOpts, (err, data) => { 145 if (err) { 146 console.info('packing from imagePackerApi failed, err' + err); 147 return 148 } 149 console.log('Succeeded in packing'); 150}) 151 152// 用于释放imagepacker 153imagePackerApi.release(); 154``` 155 156### 解码场景 157 158```js 159let path = '/data/local/tmp/test.jpg'; // 设置创建imagesource的路径 160 161// 用路径创建imagesource 162const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.jpg' 163 164// 设置参数 165let decodingOptions = { 166 sampleSize:1, // 缩略图采样大小 167 editable: true, // 是否可编辑 168 desiredSize:{ width:1, height:2}, // 期望输出大小 169 rotateDegrees:10, // 旋转角度 170 desiredPixelFormat:2, // 解码的像素格式 171 desiredRegion: { size: { height: 1, width: 2 }, x: 0, y: 0 }, // 解码的区域 172 index:0 // 图片序号 173 }; 174 175// 用于回调方式创建pixelmap 176imageSourceApi.createPixelMap(decodingOptions, (err, pixelmap) => { 177 // 创建pixelmap对象失败 178 if (err) { 179 console.info('create pixelmap failed, err' + err); 180 return 181 } 182 console.log('Succeeded in creating pixelmap.'); 183}) 184 185// 用于promise创建pixelmap 186imageSourceApi.createPixelMap().then(pixelmap => { 187 console.log('Succeeded in creating pixelmap.'); 188 189 // 用于获取像素每行字节数 190 let num = pixelmap.getBytesNumberPerRow(); 191 192 // 用于获取像素总字节数 193 let pixelSize = pixelmap.getPixelBytesNumber(); 194 195 // 用于获取pixelmap信息 196 pixelmap.getImageInfo().then( imageInfo => {}); 197 198 // 用于释放pixelmap 199 pixelmap.release(()=>{ 200 console.log('Succeeded in releasing pixelmap'); 201 }) 202}).catch(error => { 203 console.log('Failed in creating pixelmap.' + error); 204}) 205``` 206 207### 编码场景 208 209```js 210let path = '/data/local/tmp/test.png'; // 设置创建imagesource的路径 211 212// 用于设置imagesource 213const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.png' 214 215// 如果创建imagesource失败,打印错误信息 216if (imageSourceApi == null) { 217 console.log('Failed in creating imageSource.'); 218} 219 220// 如果创建imagesource成功,则创建imagepacker 221const imagePackerApi = image.createImagePacker(); 222 223// 如果创建失败,打印错误信息 224if (imagePackerApi == null) { 225 console.log('Failed in creating imagePacker.'); 226} 227 228// 如果创建imagepacker成功,则设置编码参数 229let packOpts = { format:"image/jpeg", // 支持编码的格式为jpg 230 quality:98 } // 图片质量0-100 231 232// 用于编码 233imagePackerApi.packing(imageSourceApi, packOpts) 234.then( data => { 235 console.log('Succeeded in packing'); 236}) 237 238// 编码完成,释放imagepacker 239imagePackerApi.release(); 240 241// 用于获取imagesource信息 242imageSourceApi.getImageInfo((err, imageInfo) => { 243 console.log('Succeeded in getting imageInfo'); 244}) 245 246const array = new ArrayBuffer(100); //增量数据 247// 用于更新增量数据 248imageSourceApi.updateData(array, false, 0, 10,(error, data)=> {}) 249 250``` 251 252### ImageReceiver的使用 253 254示例场景:camera作为客户端将拍照数据传给服务端 255 256```js 257public async init(surfaceId: any) { 258 259 // 服务端代码,创建ImageReceiver 260 let receiver = image.createImageReceiver(8 * 1024, 8, image.ImageFormat.JPEG, 1); 261 262 // 获取Surface ID 263 receiver.getReceivingSurfaceId((err, surfaceId) => { 264 // 获取Surface ID失败 265 if (err) { 266 console.info('getReceivingSurfaceId failed, err' + err); 267 return 268 } 269 console.info("receiver getReceivingSurfaceId success"); 270 }); 271 // 注册Surface的监听,在surface的buffer准备好后触发 272 receiver.on('imageArrival', () => { 273 // 去获取Surface中最新的buffer 274 receiver.readNextImage((err, img) => { 275 img.getComponent(4, (err, component) => { 276 // 消费component.byteBuffer,例如:将buffer内容保存成图片。 277 }) 278 }) 279 }) 280 281 // 调用Camera方法将surfaceId传递给Camera。camera会通过surfaceId获取surface,并生产出surface buffer。 282} 283``` 284 285## 相关实例 286 287针对图片开发,有以下相关实例可供参考: 288 289- [`Image`:图片处理(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/media/Image) 290- [`GamePuzzle`:拼图(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/media/GamePuzzle)