image.md 9.1 KB
Newer Older
X
xiaok 已提交
1 2 3 4 5 6 7 8
# 图片开发指导

## 场景介绍

图片开发的主要工作是将获取到的图片进行解码,将解码后的pixelmap编码成支持的格式,本文将对图片的解码、编码等场景开发进行介绍说明。

## 接口说明

Z
zengyawen 已提交
9
详细API含义请参考:[图片处理API文档](../reference/apis/js-apis-image.md)
X
xiaok 已提交
10 11 12 13 14

## 开发步骤

### 全流程场景

Mr-YX's avatar
Mr-YX 已提交
15
包含流程:创建实例、读取图片信息、读写pixelmap、更新数据、打包像素、释放资源等流程。
X
xiaok 已提交
16 17

```js
18 19
const color = new ArrayBuffer(96); // 用于存放图像像素数据
let opts = { alphaType: 0, editable: true, pixelFormat: 4, scaleMode: 1, size: { height: 2, width: 3 } } // 图像像素数据
X
xiaok 已提交
20

21
// 创建pixelmap对象
22
const color = new ArrayBuffer(96);
X
xiaok 已提交
23
let opts = { alphaType: 0, editable: true, pixelFormat: 4, scaleMode: 1, size: { height: 2, width: 3 } }
24
        image.createPixelMap(color, opts, pixelmap => {
X
xiaok 已提交
25 26 27 28
            expect(pixelmap !== null).assertTrue();
            console.info('TC_001-1 success');
            done();
        })
29
// 用于读像素
Mr-YX's avatar
Mr-YX 已提交
30
pixelmap.readPixels(area,(data) => {
X
xiaok 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 	if(data !== null) {
		var bufferArr = new Uint8Array(area.pixels);
        var res = true;
        for (var i = 0; i < bufferArr.length; i++) {
			console.info('TC_021-1 buffer ' + bufferArr[i]);
				if(res) {
					if(bufferArr[i] == 0) {
						res = false;
                        console.info('TC_021-1 Success');
                        expect(true).assertTrue();
                        done();
                        break;
                        }
                    }
                }
 
47
// 用于存像素
X
xiaok 已提交
48 49 50 51 52
const readBuffer = new ArrayBuffer(96);
pixelmap.readPixelsToBuffer(readBuffer,() => {
var bufferArr = new Uint8Array(readBuffer);
var res = true;
for (var i = 0; i < bufferArr.length; i++) {
Mr-YX's avatar
Mr-YX 已提交
53 54 55 56 57 58 59 60
    if(res) {
        if (bufferArr[i] !== 0) {
            res = false;
            console.info('TC_020-1 Success');
            expect(true).assertTrue();
            done();
            break;
        }
X
xiaok 已提交
61
    }
Mr-YX's avatar
Mr-YX 已提交
62
}
X
xiaok 已提交
63
    
64
// 用于写像素
X
xiaok 已提交
65 66
pixelmap.writePixels(area,() => {
    const readArea = { pixels: new ArrayBuffer(20), offset: 0, stride: 8, region: { size: { height: 1, width: 2 }, x: 0, y: 0 }}
Mr-YX's avatar
Mr-YX 已提交
67 68 69 70 71 72 73 74 75 76 77 78
    pixelmap.readPixels(readArea,() => {
        var readArr = new Uint8Array(readArea.pixels);
        var res = true;
        for (var i = 0; i < readArr.length; i++) {
            if(res) {
                if (readArr[i] !== 0) {
                    res = false;
                    console.info('TC_022-1 Success');
                    expect(true).assertTrue();
                    done();
                    break;
                }
X
xiaok 已提交
79
            }
Mr-YX's avatar
Mr-YX 已提交
80
        }
X
xiaok 已提交
81
  
82
// 用于写像素到缓冲区
Mr-YX's avatar
Mr-YX 已提交
83 84 85
pixelmap.writeBufferToPixels(writeColor).then(() => {
    const readBuffer = new ArrayBuffer(96);
    pixelmap.readPixelsToBuffer(readBuffer).then (() => {
X
xiaok 已提交
86 87 88 89 90 91 92 93 94 95 96 97
    	var bufferArr = new Uint8Array(readBuffer);
     	var res = true;
     	for (var i = 0; i < bufferArr.length; i++) {
     		if(res) {
     			if (bufferArr[i] !== i) {
     				res = false;
                    console.info('TC_023 Success');
                    expect(true).assertTrue()
                    done();
                    break;
                }
            }
Mr-YX's avatar
Mr-YX 已提交
98
        }
X
xiaok 已提交
99

100
// 用于获取图片信息
X
xiaok 已提交
101
pixelmap.getImageInfo( imageInfo => {
Mr-YX's avatar
Mr-YX 已提交
102 103 104 105 106 107 108 109
    if (imageInfo !== null) {
        console.info('TC_024-1 imageInfo is ready');
        expect(imageInfo.size.height == 4).assertTrue();
        expect(imageInfo.size.width == 6).assertTrue();
        expect(imageInfo.pixelFormat == 4).assertTrue();
        done();
    } 
})
X
xiaok 已提交
110

111
// 用于释放pixelmap
X
xiaok 已提交
112 113 114 115 116 117
pixelmap.release(()=>{
    expect(true).assertTrue();
    console.log('TC_027-1 suc');
    done();
})

118
let path = '/data/local/tmp/test.jpg';
119 120
// 用于创建imagesource(uri)
const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.jpg'
X
xiaok 已提交
121

122
// 用于创建imagesource(fd)
X
xiaok 已提交
123 124
const imageSourceApi = image.createImageSource(29);

125
// 用于创建imagesource(data)
X
xiaok 已提交
126 127 128
const data = new ArrayBuffer(96);
const imageSourceApi = image.createImageSource(data);

129
// 用于释放imagesource
X
xiaok 已提交
130 131 132 133
imageSourceApi.release(() => {
    console.info('TC_044-1 Success');
    })
    
134
// 用于编码
X
xiaok 已提交
135 136 137 138 139
const imagePackerApi = image.createImagePacker();
imagePackerApi.packing(imageSourceApi, packOpts, data => {
    console.info('TC_062-1 finished');
    expect(data !== null).assertTrue();
    done();
Mr-YX's avatar
Mr-YX 已提交
140
})
X
xiaok 已提交
141
 
142
// 用于释放imagepacker
X
xiaok 已提交
143 144 145 146 147 148
imagePackerApi.release();
```

### 解码场景

```js
149
let path = '/data/local/tmp/test.jpg'; // 设置创建imagesource的路径
X
xiaok 已提交
150

151 152
// 用路径创建imagesource
const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.jpg'
X
xiaok 已提交
153

154
// 设置参数
X
xiaok 已提交
155
let decodingOptions = {
156 157 158 159 160 161 162
    sampleSize:1, // 缩略图采样大小
    editable: true, // 是否可编辑
    desiredSize:{ width:1, height:2}, // 期望输出大小
    rotateDegrees:10, // 旋转角度
    desiredPixelFormat:2, // 解码的像素格式
    desiredRegion: { size: { height: 1, width: 2 }, x: 0, y: 0 }, // 解码的区域
    index:0 // 图片序号
X
xiaok 已提交
163 164
    };
    
165
// 用于回调方式创建pixelmap
X
xiaok 已提交
166 167 168 169 170 171 172
imageSourceApi.createPixelMap(decodingOptions, pixelmap => {
    console.info('TC_050 createPixelMap ');
    expect(pixelmap !== null ).assertTrue();
    done();
    })
}  

173
// 用于promise创建pixelmap
X
xiaok 已提交
174
imageSourceApi.createPixelMap().then(pixelmap => {
Mr-YX's avatar
Mr-YX 已提交
175 176 177
    console.info('TC_050-11 createPixelMap ');
    expect(pixelmap !== null ).assertTrue();
    done();
X
xiaok 已提交
178 179
})

180
// 函数调用发生异常时,捕捉错误信息
X
xiaok 已提交
181 182 183 184
catch(error => {
    console.log('TC_050-11 error: ' + error);
    expect().assertFail();
    done();
Mr-YX's avatar
Mr-YX 已提交
185
})
X
xiaok 已提交
186

187
// 用于获取像素每行字节数
X
xiaok 已提交
188 189 190 191 192 193
pixelmap.getBytesNumberPerRow( num => {
	console.info('TC_025-1 num is ' + num);
	expect(num == expectNum).assertTrue();
	done();
})

194
// 用于获取像素总字节数
X
xiaok 已提交
195
pixelmap.getPixelBytesNumber(num => {
Mr-YX's avatar
Mr-YX 已提交
196 197 198 199
    console.info('TC_026-1 num is ' + num);
    expect(num == expectNum).assertTrue();
    done();
})
X
xiaok 已提交
200

201
// 用于获取pixelmap信息
Mr-YX's avatar
Mr-YX 已提交
202
pixelmap.getImageInfo( imageInfo => {})
X
xiaok 已提交
203
 
204
// 用于打印获取失败信息
X
xiaok 已提交
205 206 207
console.info('TC_024-1 imageInfo is empty');
expect(false).assertTrue()

208
// 用于释放pixelmap
X
xiaok 已提交
209
pixelmap.release(()=>{
Mr-YX's avatar
Mr-YX 已提交
210 211 212 213
    expect(true).assertTrue();
    console.log('TC_027-1 suc');
    done();
})    
X
xiaok 已提交
214

215
// 用于捕捉释放失败信息
X
xiaok 已提交
216
catch(error => {
Mr-YX's avatar
Mr-YX 已提交
217 218 219 220
    console.log('TC_027-1 error: ' + error);
    expect().assertFail();
    done();
})
X
xiaok 已提交
221 222 223 224 225
```

### 编码场景

```js
226
let path = '/data/local/tmp/test.png' // 设置创建imagesource的路径
X
xiaok 已提交
227

228 229
// 用于设置imagesource
const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.png'
X
xiaok 已提交
230
 
231
// 如果创建imagesource失败,打印错误信息
X
xiaok 已提交
232
if (imageSourceApi == null) {
Mr-YX's avatar
Mr-YX 已提交
233 234 235 236
    console.info('TC_062 create image source failed');
    expect(false).assertTrue();
    done();
}
X
xiaok 已提交
237
   
238
// 如果创建imagesource成功,则创建imagepacker
X
xiaok 已提交
239 240
const imagePackerApi = image.createImagePacker();

241
// 如果创建失败,打印错误信息
X
xiaok 已提交
242 243 244 245
if (imagePackerApi == null) {
    console.info('TC_062 create image packer failed');
    expect(false).assertTrue();
    done();
Mr-YX's avatar
Mr-YX 已提交
246
}
X
xiaok 已提交
247

248 249 250
// 如果创建imagepacker成功,则设置编码参数
let packOpts = { format:["image/jpeg"], // 支持编码的格式为jpg
                 quality:98 } // 图片质量0-100
X
xiaok 已提交
251

252
// 用于编码
X
xiaok 已提交
253 254
imagePackerApi.packing(imageSourceApi, packOpts)
.then( data => {
Mr-YX's avatar
Mr-YX 已提交
255 256 257 258
    console.info('TC_062 finished');
    expect(data !== null).assertTrue();
    done();
})
X
xiaok 已提交
259
             
260
// 编码完成,释放imagepacker
Mr-YX's avatar
Mr-YX 已提交
261
imagePackerApi.release();
Z
zhang-xiaobo1997 已提交
262

263
// 用于获取imagesource信息
X
xiaok 已提交
264
imageSourceApi.getImageInfo(imageInfo => {
Mr-YX's avatar
Mr-YX 已提交
265 266 267 268
    console.info('TC_045 imageInfo');
    expect(imageInfo !== null).assertTrue();
    done();
})
Z
zhang-xiaobo1997 已提交
269

270
// 用于更新增量数据
271
imageSourceIncrementalSApi.updateData(array, false, 0, 10,(error, data)=> {})
X
xiaok 已提交
272 273 274

```

Z
zhang-xiaobo1997 已提交
275 276 277
### ImageReceiver的使用

示例场景:camera作为客户端将拍照数据传给服务端
Z
zhang-xiaobo1997 已提交
278 279

```js
Z
zhang-xiaobo1997 已提交
280
public async init(surfaceId: any) {
Z
zhang-xiaobo1997 已提交
281

282
    // 服务端代码,创建ImageReceiver
Mr-YX's avatar
Mr-YX 已提交
283
    var receiver = image.createImageReceiver(8 * 1024, 8, image.ImageFormat.JPEG, 1);
Z
zhang-xiaobo1997 已提交
284

285
    // 获取Surface ID
Mr-YX's avatar
Mr-YX 已提交
286
    var surfaceId = await receiver.getReceivingSurfaceId();
Z
zhang-xiaobo1997 已提交
287

Z
zengyawen 已提交
288
    // 注册Surface的监听,在surface的buffer准备好后触发
Mr-YX's avatar
Mr-YX 已提交
289
    receiver.on('imageArrival', () => {
290
        // 去获取Surface中最新的buffer
Mr-YX's avatar
Mr-YX 已提交
291
        receiver.readNextImage((err, img) => {
G
gloria 已提交
292
            img.getComponent(4, (err, component) => {
293
                // 消费component.byteBuffer,例如:将buffer内容保存成图片。
Mr-YX's avatar
Mr-YX 已提交
294 295 296
		    })
	    })
    })
Z
zhang-xiaobo1997 已提交
297

298
    // 调用Camera方法将surfaceId传递给Camera。camera会通过surfaceId获取surface,并生产出surface buffer。
Z
zhang-xiaobo1997 已提交
299
}
300 301 302 303 304 305
```

## 相关实例

针对图片开发,有以下相关实例可供参考:

306 307
- [`Image`:图片处理(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/media/Image)
- [`GamePuzzle`:拼图(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/media/GamePuzzle)