From 093704f9cfe726ff44eb6cee81241349211efd2d Mon Sep 17 00:00:00 2001 From: Paco Date: Sun, 17 May 2020 17:40:22 -0300 Subject: [PATCH] [gl] Add WebP format as an option when taking GL snapshots (Android only) (#7490) # Why At some point (API 14), Android added native WebP support ([Bitmap.CompressFormat.WEBP](https://developer.android.com/reference/android/graphics/Bitmap.CompressFormat#WEBP)), so adding the option to export the render to WebP is trivial. Creating a new module just for converting from PNG to WebP is silly since you can get the GL render as WebP directly. Also converting from PNG to WebP could create quality loss. # How In GLContext.java, I extended the block that specifies using png (instead of jpeg, the default) to recognize webp as another posible format. # Test Plan Sadly, a combination of living in Windows OS and lack of experience in some aspects of software development, I was not able to test this change using the proper methods (unit test, and that). But I did tried the change in the App I'm building and it worked fine Thanks for your attention, sorry for any mistake in the PR, this is the second time I do a PR --- docs/pages/versions/unversioned/sdk/gl-view.md | 4 +++- .../src/main/java/expo/modules/gl/GLContext.java | 11 ++++++++--- packages/expo-gl/ios/EXGL/EXGLContext.m | 7 ++++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/docs/pages/versions/unversioned/sdk/gl-view.md b/docs/pages/versions/unversioned/sdk/gl-view.md index d096e3a6e546f..dc6953e8f4291 100644 --- a/docs/pages/versions/unversioned/sdk/gl-view.md +++ b/docs/pages/versions/unversioned/sdk/gl-view.md @@ -80,9 +80,11 @@ Takes a snapshot of the framebuffer and saves it as a file to app's cache direct - **framebuffer (_WebGLFramebuffer_)** -- Specify the framebuffer that we will be reading from. Defaults to underlying framebuffer that is presented in the view or the current framebuffer if context is headless. - **rect (`{ x: number, y: number, width: number, height: number }`)** -- Rect to crop the snapshot. It's passed directly to `glReadPixels`. - **flip (_boolean_)** -- Whether to flip the snapshot vertically. Defaults to `false`. - - **format (_string_)** -- Either `'jpeg'` or `'png'`. Specifies what type of compression should be used and what is the result file extension. PNG compression is lossless but slower, JPEG is faster but the image has visible artifacts. Defaults to `'jpeg'`. + - **format (_string_)** -- Either `'jpeg'`, `'png'` or `'webp'` (_Android only_ for the latter). Specifies what type of compression should be used and what is the result file extension. PNG compression is lossless but slower, JPEG is faster but the image has visible artifacts. Defaults to `'jpeg'`. - **compress (_number_)** -- A value in range 0 - 1 specifying compression level of the result image. 1 means no compression and 0 the highest compression. Defaults to `1.0`. +> **Note:** When using WebP format, the iOS version will print a warning, and generate a `'png'` file instead. It is recommendable to use platform dependant code in this case. You can refer to the [documentation on platform specifi code](https://docs.expo.io/versions/latest/react-native/platform-specific-code/). + #### Returns Returns `{ uri, localUri, width, height }` where `uri` is a URI to the snapshot. `localUri` is a synonym for `uri` that makes this object compatible with `texImage2D`. `width, height` specify the dimensions of the snapshot. diff --git a/packages/expo-gl/android/src/main/java/expo/modules/gl/GLContext.java b/packages/expo-gl/android/src/main/java/expo/modules/gl/GLContext.java index a97f812373785..872b7da4fab8d 100644 --- a/packages/expo-gl/android/src/main/java/expo/modules/gl/GLContext.java +++ b/packages/expo-gl/android/src/main/java/expo/modules/gl/GLContext.java @@ -278,9 +278,14 @@ protected Void doInBackground(Void... params) { FileOutputStream output = null; Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.JPEG; - if (mFormat != null && mFormat.equals("png")) { - compressFormat = Bitmap.CompressFormat.PNG; - extension = ".png"; + if (mFormat != null) { + if (mFormat.equals("png")) { + compressFormat = Bitmap.CompressFormat.PNG; + extension = ".png"; + } else if (mFormat.equals("webp")) { + compressFormat = Bitmap.CompressFormat.WEBP; + extension = ".webp"; + } } Context context = mContext.get(); diff --git a/packages/expo-gl/ios/EXGL/EXGLContext.m b/packages/expo-gl/ios/EXGL/EXGLContext.m index 7b70eeaa9f67d..88dcbb250b185 100644 --- a/packages/expo-gl/ios/EXGL/EXGLContext.m +++ b/packages/expo-gl/ios/EXGL/EXGLContext.m @@ -230,7 +230,12 @@ - (void)takeSnapshotWithOptions:(nonnull NSDictionary *)options NSData *imageData; NSString *extension; - if ([format isEqualToString:@"png"]) { + if ([format isEqualToString:@"webp"]) { + UMLogWarn(@"iOS doesn't support 'webp' representation, so 'takeSnapshot' won't work with that format. The image is going to be exported as 'png', but consider using a different code for iOS. Check this docs to learn how to do platform specific code (https://reactnative.dev/docs/platform-specific-code)"); + imageData = UIImagePNGRepresentation(image); + extension = @".png"; + } + else if ([format isEqualToString:@"png"]) { imageData = UIImagePNGRepresentation(image); extension = @".png"; } else {