image.md 8.2 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 } }
F
fengzewu 已提交
24 25 26 27
image.createPixelMap(color, opts, pixelmap => {
    console.log('Succeeded in creating pixelmap.');
})

28
// 用于读像素
Mr-YX's avatar
Mr-YX 已提交
29
pixelmap.readPixels(area,(data) => {
F
fengzewu 已提交
30 31
    if(data !== null) {
        var bufferArr = new Uint8Array(area.pixels);
X
xiaok 已提交
32 33
        var res = true;
        for (var i = 0; i < bufferArr.length; i++) {
F
fengzewu 已提交
34 35 36 37 38 39
            console.info(' buffer ' + bufferArr[i]);
            if(res) {
                if(bufferArr[i] == 0) {
                    res = false;
                    console.log('readPixels end.');
                    break;
X
xiaok 已提交
40
                }
F
fengzewu 已提交
41 42 43 44
            }
        }
    }
})
X
xiaok 已提交
45
 
46
// 用于存像素
X
xiaok 已提交
47 48
const readBuffer = new ArrayBuffer(96);
pixelmap.readPixelsToBuffer(readBuffer,() => {
F
fengzewu 已提交
49 50 51 52 53 54 55 56 57
    var bufferArr = new Uint8Array(readBuffer);
    var res = true;
    for (var i = 0; i < bufferArr.length; i++) {
        if(res) {
            if (bufferArr[i] !== 0) {
                res = false;
                console.log('readPixelsToBuffer end.');
                break;
            }
Mr-YX's avatar
Mr-YX 已提交
58
        }
X
xiaok 已提交
59
    }
F
fengzewu 已提交
60
})
X
xiaok 已提交
61
    
62
// 用于写像素
X
xiaok 已提交
63 64
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 已提交
65 66 67 68 69 70 71
    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;
F
fengzewu 已提交
72
                    console.log('readPixels end.please check buffer');
Mr-YX's avatar
Mr-YX 已提交
73 74
                    break;
                }
X
xiaok 已提交
75
            }
Mr-YX's avatar
Mr-YX 已提交
76
        }
F
fengzewu 已提交
77 78
    })
})
X
xiaok 已提交
79
  
80
// 用于写像素到缓冲区
Mr-YX's avatar
Mr-YX 已提交
81 82 83
pixelmap.writeBufferToPixels(writeColor).then(() => {
    const readBuffer = new ArrayBuffer(96);
    pixelmap.readPixelsToBuffer(readBuffer).then (() => {
F
fengzewu 已提交
84 85 86 87 88 89 90
        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.log('readPixels end.please check buffer');
X
xiaok 已提交
91 92 93
                    break;
                }
            }
Mr-YX's avatar
Mr-YX 已提交
94
        }
F
fengzewu 已提交
95 96
    })
})
X
xiaok 已提交
97

98
// 用于获取图片信息
F
fengzewu 已提交
99
pixelmap.getImageInfo((error, imageInfo) => {
Mr-YX's avatar
Mr-YX 已提交
100
    if (imageInfo !== null) {
F
fengzewu 已提交
101
	    console.log('Succeeded in getting imageInfo');
Mr-YX's avatar
Mr-YX 已提交
102 103
    } 
})
X
xiaok 已提交
104

105
// 用于释放pixelmap
X
xiaok 已提交
106
pixelmap.release(()=>{
F
fengzewu 已提交
107
    console.log('Succeeded in releasing pixelmap');
X
xiaok 已提交
108 109
})

110
// 用于创建imagesource(uri)
F
fengzewu 已提交
111
let path = '/data/local/tmp/test.jpg';
F
fengzewu 已提交
112
const imageSourceApi = image.createImageSource(path);
X
xiaok 已提交
113

114
// 用于创建imagesource(fd)
F
fengzewu 已提交
115
let fd = 29;
F
fengzewu 已提交
116
const imageSourceApi = image.createImageSource(fd);
X
xiaok 已提交
117

118
// 用于创建imagesource(data)
X
xiaok 已提交
119 120 121
const data = new ArrayBuffer(96);
const imageSourceApi = image.createImageSource(data);

122
// 用于释放imagesource
X
xiaok 已提交
123
imageSourceApi.release(() => {
F
fengzewu 已提交
124 125
    console.log('Succeeded in releasing imagesource');
})
X
xiaok 已提交
126
    
127
// 用于编码
X
xiaok 已提交
128
const imagePackerApi = image.createImagePacker();
F
fengzewu 已提交
129 130
const imageSourceApi = image.createImageSource(0);
let packOpts = { format:"image/jpeg", quality:98 };
X
xiaok 已提交
131
imagePackerApi.packing(imageSourceApi, packOpts, data => {
F
fengzewu 已提交
132
    console.log('Succeeded in packing');
Mr-YX's avatar
Mr-YX 已提交
133
})
X
xiaok 已提交
134
 
135
// 用于释放imagepacker
X
xiaok 已提交
136 137 138 139 140 141
imagePackerApi.release();
```

### 解码场景

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

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

147
// 设置参数
X
xiaok 已提交
148
let decodingOptions = {
149 150 151 152 153 154 155
    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 已提交
156 157
    };
    
158
// 用于回调方式创建pixelmap
X
xiaok 已提交
159
imageSourceApi.createPixelMap(decodingOptions, pixelmap => {
F
fengzewu 已提交
160 161
    console.log('Succeeded in creating pixelmap.');
})
X
xiaok 已提交
162

163
// 用于promise创建pixelmap
X
xiaok 已提交
164
imageSourceApi.createPixelMap().then(pixelmap => {
F
fengzewu 已提交
165
    console.log('Succeeded in creating pixelmap.');
X
xiaok 已提交
166 167
})

168
// 函数调用发生异常时,捕捉错误信息
X
xiaok 已提交
169
catch(error => {
F
fengzewu 已提交
170
    console.log('Failed in creating pixelmap.' + error);
Mr-YX's avatar
Mr-YX 已提交
171
})
X
xiaok 已提交
172

173
// 用于获取像素每行字节数
F
debug  
fengzewu 已提交
174
var num = pixelmap.getBytesNumberPerRow();
X
xiaok 已提交
175

176
// 用于获取像素总字节数
F
debug  
fengzewu 已提交
177
var pixelSize = pixelmap.getPixelBytesNumber();
X
xiaok 已提交
178

179
// 用于获取pixelmap信息
F
debug  
fengzewu 已提交
180
pixelmap.getImageInfo().then( imageInfo => {});
X
xiaok 已提交
181

182
// 用于释放pixelmap
X
xiaok 已提交
183
pixelmap.release(()=>{
F
fengzewu 已提交
184
    console.log('Succeeded in releasing pixelmap');
Mr-YX's avatar
Mr-YX 已提交
185
})    
X
xiaok 已提交
186

187
// 用于捕捉释放失败信息
X
xiaok 已提交
188
catch(error => {
F
fengzewu 已提交
189
    console.log('Failed in releasing pixelmap.' + error);
Mr-YX's avatar
Mr-YX 已提交
190
})
X
xiaok 已提交
191 192 193 194 195
```

### 编码场景

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

198 199
// 用于设置imagesource
const imageSourceApi = image.createImageSource(path); // '/data/local/tmp/test.png'
X
xiaok 已提交
200
 
201
// 如果创建imagesource失败,打印错误信息
X
xiaok 已提交
202
if (imageSourceApi == null) {
F
fengzewu 已提交
203
    console.log('Failed in creating imageSource.');
Mr-YX's avatar
Mr-YX 已提交
204
}
X
xiaok 已提交
205
   
206
// 如果创建imagesource成功,则创建imagepacker
X
xiaok 已提交
207 208
const imagePackerApi = image.createImagePacker();

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

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

218
// 用于编码
X
xiaok 已提交
219 220
imagePackerApi.packing(imageSourceApi, packOpts)
.then( data => {
F
fengzewu 已提交
221
    console.log('Succeeded in packing');
Mr-YX's avatar
Mr-YX 已提交
222
})
F
fengzewu 已提交
223
         
224
// 编码完成,释放imagepacker
Mr-YX's avatar
Mr-YX 已提交
225
imagePackerApi.release();
Z
zhang-xiaobo1997 已提交
226

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

232
// 用于更新增量数据
F
fengzewu 已提交
233
imageSourceIncrementalSApi.updateData(array, false, 0, 10,(error, data)=> {})
X
xiaok 已提交
234 235 236

```

Z
zhang-xiaobo1997 已提交
237 238 239
### ImageReceiver的使用

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

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

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

247
    // 获取Surface ID
F
fengzewu 已提交
248 249 250
    receiver.getReceivingSurfaceId((err, surfaceId) => {
        console.info("receiver getReceivingSurfaceId success");
    });
F
fengzewu 已提交
251
    // 注册Surface的监听,在surface的buffer准备好后触发
Mr-YX's avatar
Mr-YX 已提交
252
    receiver.on('imageArrival', () => {
253
        // 去获取Surface中最新的buffer
Mr-YX's avatar
Mr-YX 已提交
254
        receiver.readNextImage((err, img) => {
G
gloria 已提交
255
            img.getComponent(4, (err, component) => {
256
                // 消费component.byteBuffer,例如:将buffer内容保存成图片。
Mr-YX's avatar
Mr-YX 已提交
257 258 259
		    })
	    })
    })
Z
zhang-xiaobo1997 已提交
260

261
    // 调用Camera方法将surfaceId传递给Camera。camera会通过surfaceId获取surface,并生产出surface buffer。
Z
zhang-xiaobo1997 已提交
262
}
263 264 265 266 267 268
```

## 相关实例

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

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