How to pass captured screenshot to iOS module and android module, respectively?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By KenHuang0917
:warning: Old Version Published before Godot 3 was released.

From demo examples, I know I can do screen capture as follows:

	get_viewport().queue_screen_capture()
	# Let two frames pass to make sure the screen was captured
	yield(get_tree(), "idle_frame")
	yield(get_tree(), "idle_frame")
	# Retrieve the captured image
	var img = get_viewport().get_screen_capture()

But how to pass this image to custom module? For iOS module, Can I do something like:

	postToModule({"image": img})

? How to retrieve it as an UIImage? And what about android module? How to pass and convert it to a Bitmap?

get_screen_capture() gives you an Image, which is nothing more than a 2D array of colors.
What are you calling a “module” here? Are you talking about a C++ Godot module?

Zylann | 2016-12-27 18:56

Yes, C++ (Objective C++) module for iOS and Java module for Android. I need both platforms to work :smiley:
I know I can retrieve it at Objective C++ or Java module by “Dictionary”, but don’t know how to convert it to UIImage (for iOS) and Bitmap (for Android). I am doing so for that I want to share the screenshots to social network like Facebook or Twitter.

KenHuang0917 | 2016-12-28 00:22

First, make your class (or whatever you are doing) have a function that accepts an Image, then… as I said, Image is really just a grid of colors. It depends on what the iOS/Android API wants you to provide, is that a PNG, JPG? I never did that before and have no idea if it’s the best idea to share screenshots, but Godot mostly provides just that, as far as I know. Image eventually has a save_png function, maybe you can refer to the produced file in your module code, as if it was a picture on the phone?

Zylann | 2016-12-28 00:28

Thank you for your help. I seem to see some light. Where does the save_png save file? If it is at “res://”, then how can I get it from C++ and Java module? i.e. How to read file of “res://” from C++ and Java module?

KenHuang0917 | 2016-12-28 00:48

The image will end up where you want it to be, there is a path argument. On mobile if you use a path like “user://screen.png” it will end up in a writable folder.
Also, I read the API wants you a Bitmap or UIImage. There is maybe a way to pass them the colors array directly instead of writing the file to disk.

Zylann | 2016-12-28 00:55

Yes, Bitmap or UIImage, that’s what I want :slight_smile: , but I don’t know how to convert these colors into them. :frowning:
As for save file to disk, what kind of path I can give? If I set path argument as “user://screen.png”, is it still the same path name: “user://screen.png” on mobile?

KenHuang0917 | 2016-12-28 01:08

Me neither.
Does the API let you create a UIImage/Bitmap and set the colors from a char* array? You should check the docs about that.
user:// is a unified path specific to Godot. It actually targets different paths depending on the OS. On Windows it’s AppData, on Android and iOS it must be somewhere else (but I can’t find it in the doc right now). The reason why is that on mobile the filesystem is more restricted.

Zylann | 2016-12-28 14:11

:bust_in_silhouette: Reply From: KenHuang0917

Thank you Zylann, I managed to find a way because of your hint. You really saved my life. :slight_smile: It’s something like the following:
GDscript:

func screen_capture():
   ......
   #Retrieve the captured image and store in the member var img
   img = get_viewport().get_screen_capture()
   #call Java singleton to get path
   JavaSingleton.askForPath()

func _on_call_back(path):
   if path != "":
    #save image to Android device path
	img.save_png(path)
    #call Java singleton to share the image
	JavaSingleton.postToShare()

Java singleton:

public void askForPath() {
     String fileName = "Screen.png";
     String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Screenshots";
     File dir = new File(dirPath);
     if(!dir.exists())
          dir.mkdirs();
     file = new File(dirPath, fileName);    
     GodotLib.calldeferred(instance_id, "_on_call_back", new Object[]{file.toString()});
}
public void postToShare(){
     ......
}

I know it’s not elegant at all, but it gets my job done. It’s not the best answer. I hope someday someone can give a smarter solution to pass the colors array directly instead of writing the file to disk as you said. Hope my answer can help someone who needs it. Thanks again! Zylann!

:bust_in_silhouette: Reply From: binogure

A good alternative for that. is using data dir returned by the OS class

const SAVE_IMAGE_FILENAME = 'godot-win-image-cache.png'
const SAVED_IMAGE_PATH = 'user://' + SAVE_IMAGE_FILENAME

var SCREENSHOT_ABSOLUTE_PATH = OS.get_data_dir() + SAVE_IMAGE_FILENAME

func pressed():
    get_viewport().queue_screen_capture()
    yield(get_tree(), 'idle_frame')
    yield(get_tree(), 'idle_frame')

    # get screen capture
    get_viewport().get_screen_capture().save_png(SAVED_IMAGE_PATH)

    postToModule({"image": SCREENSHOT_ABSOLUTE_PATH})