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对象
F
fengzewu 已提交
22
image.createPixelMap(color, opts, (err, pixelmap) => {
F
fengzewu 已提交
23
    console.log('Succeeded in creating pixelmap.');
24 25 26 27 28
    // 创建pixelmap对象失败
    if (err) {
        console.info('create pixelmap failed, err' + err);
        return
    }
F
fengzewu 已提交
29

R
renhongwei 已提交
30 31 32 33 34 35
    // 用于读像素
    const area = {
        pixels: new ArrayBuffer(8),
        offset: 0,
        stride: 8,
        region: { size: { height: 1, width: 2 }, x: 0, y: 0 }
X
xiaok 已提交
36
    }
R
renhongwei 已提交
37
    pixelmap.readPixels(area,() => {
38 39 40
        let bufferArr = new Uint8Array(area.pixels);
        let res = true;
        for (let i = 0; i < bufferArr.length; i++) {
R
renhongwei 已提交
41
            console.info(' buffer ' + bufferArr[i]);
Mr-YX's avatar
Mr-YX 已提交
42
            if(res) {
R
renhongwei 已提交
43
                if(bufferArr[i] == 0) {
Mr-YX's avatar
Mr-YX 已提交
44
                    res = false;
R
renhongwei 已提交
45
                    console.log('readPixels end.');
Mr-YX's avatar
Mr-YX 已提交
46 47
                    break;
                }
X
xiaok 已提交
48
            }
Mr-YX's avatar
Mr-YX 已提交
49
        }
F
fengzewu 已提交
50
    })
R
renhongwei 已提交
51 52
 
    // 用于存像素
Mr-YX's avatar
Mr-YX 已提交
53
    const readBuffer = new ArrayBuffer(96);
R
renhongwei 已提交
54
    pixelmap.readPixelsToBuffer(readBuffer,() => {
55 56 57
        let bufferArr = new Uint8Array(readBuffer);
        let res = true;
        for (let i = 0; i < bufferArr.length; i++) {
F
fengzewu 已提交
58
            if(res) {
R
renhongwei 已提交
59
                if (bufferArr[i] !== 0) {
F
fengzewu 已提交
60
                    res = false;
R
renhongwei 已提交
61
                    console.log('readPixelsToBuffer end.');
X
xiaok 已提交
62 63 64
                    break;
                }
            }
Mr-YX's avatar
Mr-YX 已提交
65
        }
F
fengzewu 已提交
66
    })
R
renhongwei 已提交
67 68 69 70 71
    
    // 用于写像素
    pixelmap.writePixels(area,() => {
        const readArea = { pixels: new ArrayBuffer(20), offset: 0, stride: 8, region: { size: { height: 1, width: 2 }, x: 0, y: 0 }}
        pixelmap.readPixels(readArea,() => {
72 73 74
            let readArr = new Uint8Array(readArea.pixels);
            let res = true;
            for (let i = 0; i < readArr.length; i++) {
R
renhongwei 已提交
75 76 77 78 79 80 81 82 83 84
                if(res) {
                    if (readArr[i] !== 0) {
                        res = false;
                        console.log('readPixels end.please check buffer');
                        break;
                    }
                }
            }
        })
    })
X
xiaok 已提交
85

R
renhongwei 已提交
86 87 88 89 90
    const writeColor = new ArrayBuffer(96); //图像像素数据
    // 用于写像素到缓冲区
    pixelmap.writeBufferToPixels(writeColor).then(() => {
        const readBuffer = new ArrayBuffer(96);
        pixelmap.readPixelsToBuffer(readBuffer).then (() => {
91 92 93
            let bufferArr = new Uint8Array(readBuffer);
            let res = true;
            for (let i = 0; i < bufferArr.length; i++) {
R
renhongwei 已提交
94 95 96 97 98 99 100 101 102 103 104 105
                if(res) {
                    if (bufferArr[i] !== i) {
                        res = false;
                        console.log('readPixels end.please check buffer');
                        break;
                    }
                }
            }
        })
    })

    // 用于获取图片信息
106 107 108 109 110 111
    pixelmap.getImageInfo((err, imageInfo) => {
        // 获取图片信息失败
        if (err || imageInfo == null) {
            console.info('getImageInfo failed, err' + err);
            return
        }
R
renhongwei 已提交
112 113 114 115
        if (imageInfo !== null) {
            console.log('Succeeded in getting imageInfo');
        } 
    })
X
xiaok 已提交
116

R
renhongwei 已提交
117 118 119 120
    // 用于释放pixelmap
    pixelmap.release(()=>{
        console.log('Succeeded in releasing pixelmap');
    })
X
xiaok 已提交
121 122
})

123
// 用于创建imagesource(uri)
F
fengzewu 已提交
124
let path = '/data/local/tmp/test.jpg';
R
renhongwei 已提交
125
const imageSourceApi1 = image.createImageSource(path);
X
xiaok 已提交
126

127
// 用于创建imagesource(fd)
F
fengzewu 已提交
128
let fd = 29;
R
renhongwei 已提交
129
const imageSourceApi2 = image.createImageSource(fd);
X
xiaok 已提交
130

131
// 用于创建imagesource(data)
X
xiaok 已提交
132
const data = new ArrayBuffer(96);
R
renhongwei 已提交
133
const imageSourceApi3 = image.createImageSource(data);
X
xiaok 已提交
134

135
// 用于释放imagesource
R
renhongwei 已提交
136
imageSourceApi3.release(() => {
F
fengzewu 已提交
137 138
    console.log('Succeeded in releasing imagesource');
})
X
xiaok 已提交
139
    
140
// 用于编码
X
xiaok 已提交
141
const imagePackerApi = image.createImagePacker();
F
fengzewu 已提交
142 143
const imageSourceApi = image.createImageSource(0);
let packOpts = { format:"image/jpeg", quality:98 };
F
fengzewu 已提交
144
imagePackerApi.packing(imageSourceApi, packOpts, (err, data) => {
145 146 147 148
    if (err) {
        console.info('packing from imagePackerApi failed, err' + err);
        return
    }
F
fengzewu 已提交
149
    console.log('Succeeded in packing');
Mr-YX's avatar
Mr-YX 已提交
150
})
X
xiaok 已提交
151
 
152
// 用于释放imagepacker
X
xiaok 已提交
153 154 155 156 157 158
imagePackerApi.release();
```

### 解码场景

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

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

164
// 设置参数
X
xiaok 已提交
165
let decodingOptions = {
166 167 168 169 170 171 172
    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 已提交
173 174
    };
    
175
// 用于回调方式创建pixelmap
F
fengzewu 已提交
176
imageSourceApi.createPixelMap(decodingOptions, (err, pixelmap) => {
177 178 179 180 181
    // 创建pixelmap对象失败
    if (err) {
        console.info('create pixelmap failed, err' + err);
        return
    }
F
fengzewu 已提交
182 183
    console.log('Succeeded in creating pixelmap.');
})
X
xiaok 已提交
184

185
// 用于promise创建pixelmap
X
xiaok 已提交
186
imageSourceApi.createPixelMap().then(pixelmap => {
F
fengzewu 已提交
187
    console.log('Succeeded in creating pixelmap.');
X
xiaok 已提交
188

R
renhongwei 已提交
189
    // 用于获取像素每行字节数
190
    let num = pixelmap.getBytesNumberPerRow();
X
xiaok 已提交
191

R
renhongwei 已提交
192
    // 用于获取像素总字节数
193
    let pixelSize = pixelmap.getPixelBytesNumber();
X
xiaok 已提交
194

R
renhongwei 已提交
195 196
    // 用于获取pixelmap信息
    pixelmap.getImageInfo().then( imageInfo => {});
X
xiaok 已提交
197

R
renhongwei 已提交
198 199 200 201 202 203
    // 用于释放pixelmap
    pixelmap.release(()=>{
        console.log('Succeeded in releasing pixelmap');
    })
}).catch(error => {
    console.log('Failed in creating pixelmap.' + error);
Mr-YX's avatar
Mr-YX 已提交
204
})
X
xiaok 已提交
205 206 207 208 209
```

### 编码场景

```js
F
fengzewu 已提交
210
let path = '/data/local/tmp/test.png'; // 设置创建imagesource的路径
X
xiaok 已提交
211

212 213
// 用于设置imagesource
const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.png'
X
xiaok 已提交
214
 
215
// 如果创建imagesource失败,打印错误信息
X
xiaok 已提交
216
if (imageSourceApi == null) {
F
fengzewu 已提交
217
    console.log('Failed in creating imageSource.');
Mr-YX's avatar
Mr-YX 已提交
218
}
X
xiaok 已提交
219
   
220
// 如果创建imagesource成功,则创建imagepacker
X
xiaok 已提交
221 222
const imagePackerApi = image.createImagePacker();

223
// 如果创建失败,打印错误信息
X
xiaok 已提交
224
if (imagePackerApi == null) {
F
fengzewu 已提交
225
    console.log('Failed in creating imagePacker.');
Mr-YX's avatar
Mr-YX 已提交
226
}
X
xiaok 已提交
227

228
// 如果创建imagepacker成功,则设置编码参数
R
renhongwei 已提交
229
let packOpts = { format:"image/jpeg", // 支持编码的格式为jpg
230
                 quality:98 } // 图片质量0-100
X
xiaok 已提交
231

232
// 用于编码
X
xiaok 已提交
233 234
imagePackerApi.packing(imageSourceApi, packOpts)
.then( data => {
F
fengzewu 已提交
235
    console.log('Succeeded in packing');
Mr-YX's avatar
Mr-YX 已提交
236
})
F
fengzewu 已提交
237
         
238
// 编码完成,释放imagepacker
Mr-YX's avatar
Mr-YX 已提交
239
imagePackerApi.release();
Z
zhang-xiaobo1997 已提交
240

241
// 用于获取imagesource信息
F
fengzewu 已提交
242
imageSourceApi.getImageInfo((err, imageInfo) => {
F
fengzewu 已提交
243
    console.log('Succeeded in getting imageInfo');
Mr-YX's avatar
Mr-YX 已提交
244
})
Z
zhang-xiaobo1997 已提交
245

R
renhongwei 已提交
246
const array = new ArrayBuffer(100); //增量数据
247
// 用于更新增量数据
R
renhongwei 已提交
248
imageSourceApi.updateData(array, false, 0, 10,(error, data)=> {})
X
xiaok 已提交
249 250 251

```

Z
zhang-xiaobo1997 已提交
252 253 254
### ImageReceiver的使用

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

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

259
    // 服务端代码,创建ImageReceiver
260
    let receiver = image.createImageReceiver(8 * 1024, 8, image.ImageFormat.JPEG, 1);
Z
zhang-xiaobo1997 已提交
261

262
    // 获取Surface ID
F
fengzewu 已提交
263
    receiver.getReceivingSurfaceId((err, surfaceId) => {
264 265 266 267 268
    // 获取Surface ID失败
        if (err) {
            console.info('getReceivingSurfaceId failed, err' + err);
            return
        }
F
fengzewu 已提交
269 270
        console.info("receiver getReceivingSurfaceId success");
    });
F
fengzewu 已提交
271
    // 注册Surface的监听,在surface的buffer准备好后触发
Mr-YX's avatar
Mr-YX 已提交
272
    receiver.on('imageArrival', () => {
273
        // 去获取Surface中最新的buffer
Mr-YX's avatar
Mr-YX 已提交
274
        receiver.readNextImage((err, img) => {
G
gloria 已提交
275
            img.getComponent(4, (err, component) => {
276
                // 消费component.byteBuffer,例如:将buffer内容保存成图片。
Mr-YX's avatar
Mr-YX 已提交
277 278 279
		    })
	    })
    })
Z
zhang-xiaobo1997 已提交
280

281
    // 调用Camera方法将surfaceId传递给Camera。camera会通过surfaceId获取surface,并生产出surface buffer。
Z
zhang-xiaobo1997 已提交
282
}
283 284 285 286 287 288
```

## 相关实例

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

Z
zwx1094577 已提交
289
- [`Image`:图片处理(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Media/Image)
290

Z
zwx1094577 已提交
291
- [`GamePuzzle`:拼图(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Media/GamePuzzle)