|
@@ -174,6 +174,81 @@ Model tested: iPhone 6 (iOS), Nexus 5 (Android).
|
174
|
174
|
3. Component itself lacks platform support.
|
175
|
175
|
4. But you can just use the react-native-maps snapshot function: https://github.com/airbnb/react-native-maps#take-snapshot-of-map
|
176
|
176
|
|
|
177
|
+## Performance Optimization
|
|
178
|
+
|
|
179
|
+During profiling captured several things that influence on performance:
|
|
180
|
+1) (de-)allocation of memory for bitmap
|
|
181
|
+2) (de-)allocation of memory for Base64 output buffer
|
|
182
|
+3) compression of bitmap to different image formats: PNG, JPG
|
|
183
|
+
|
|
184
|
+To solve that in code introduced several new approaches:
|
|
185
|
+- reusable images, that reduce load on GC;
|
|
186
|
+- reusable arrays/buffers that also reduce load on GC;
|
|
187
|
+- RAW image format for avoiding expensive compression;
|
|
188
|
+- ZIP deflate compression for RAW data, that works faster in compare to `Bitmap.compress`
|
|
189
|
+
|
|
190
|
+more details and code snippet are below.
|
|
191
|
+
|
|
192
|
+### RAW Images
|
|
193
|
+
|
|
194
|
+Introduced a new image format RAW. it correspond a ARGB array of pixels.
|
|
195
|
+
|
|
196
|
+Advantages:
|
|
197
|
+- no compression, so its supper quick. Screenshot taking is less than 16ms;
|
|
198
|
+
|
|
199
|
+RAW format supported for `zip-base64`, `base64` and `tmpfile` result types.
|
|
200
|
+
|
|
201
|
+RAW file on disk saved in format: `${width}:${height}|${base64}` string.
|
|
202
|
+
|
|
203
|
+### zip-base64
|
|
204
|
+
|
|
205
|
+In compare to BASE64 result string this format fast try to apply zip/deflate compression on screenshot results
|
|
206
|
+and only after that convert results to base64 string. In combination zip-base64 + raw we got a super fast
|
|
207
|
+approach for capturing screen views and deliver them to the react side.
|
|
208
|
+
|
|
209
|
+### How to work with zip-base64 and RAW format?
|
|
210
|
+
|
|
211
|
+```js
|
|
212
|
+const fs = require('fs')
|
|
213
|
+const zlib = require('zlib')
|
|
214
|
+const PNG = require('pngjs').PNG
|
|
215
|
+const Buffer = require('buffer').Buffer
|
|
216
|
+
|
|
217
|
+const format = Platform.OS === 'android' ? 'raw' : 'png'
|
|
218
|
+const result = Platform.OS === 'android' ? 'zip-base64' : 'base64'
|
|
219
|
+
|
|
220
|
+captureRef(this.ref, { result, format }).then(data => {
|
|
221
|
+ // expected pattern 'width:height|', example: '1080:1731|'
|
|
222
|
+ const resolution = /^(\d+):(\d+)\|/g.exec(data)
|
|
223
|
+ const width = (resolution || ['', 0, 0])[1]
|
|
224
|
+ const height = (resolution || ['', 0, 0])[2]
|
|
225
|
+ const base64 = data.substr((resolution || [''])[0].length || 0)
|
|
226
|
+
|
|
227
|
+ // convert from base64 to Buffer
|
|
228
|
+ const buffer = Buffer.from(base64, 'base64')
|
|
229
|
+ // un-compress data
|
|
230
|
+ const inflated = zlib.inflateSync(buffer)
|
|
231
|
+ // compose PNG
|
|
232
|
+ const png = new PNG({ width, height })
|
|
233
|
+ png.data = inflated
|
|
234
|
+ const pngData = PNG.sync.write(png)
|
|
235
|
+ // save composed PNG
|
|
236
|
+ fs.writeFileSync(output, pngData)
|
|
237
|
+})
|
|
238
|
+```
|
|
239
|
+
|
|
240
|
+Keep in mind that packaging PNG data is a CPU consuming operation as a `zlib.inflate`.
|
|
241
|
+
|
|
242
|
+Hint: use `process.fork()` approach for converting raw data into PNGs.
|
|
243
|
+
|
|
244
|
+> Note: code is tested in large commercial project.
|
|
245
|
+
|
|
246
|
+> Note #2: Don't forget to add packages into your project:
|
|
247
|
+> ```js
|
|
248
|
+> yarn add pngjs
|
|
249
|
+> yarn add zlib
|
|
250
|
+> ```
|
|
251
|
+
|
177
|
252
|
## Troubleshooting / FAQ
|
178
|
253
|
|
179
|
254
|
### Saving to a file?
|