Using OpenGL for Image Processing - Setting up an OpenGL context - android

I want to do image processing on a raw image without displaying it on screen (I want to do some calculations based on the image data and display some results on screen based on these calculations.) I found an interesting answer to this question, shown here:
Do your actual processing on the GPU: Set up an OpenGL context (OpenGL
ES 2 tutorial), and create a SurfaceTexture object in that context.
Then pass that object to setPreviewTexture, and start preview. Then,
in your OpenGL code, you can call SurfaceTexture.updateTexImage, and
the texture ID associated with the SurfaceTexture will be updated to
the latest preview frame from the camera. You can also read back the
RGB texture data to the CPU for further processing using glReadPixels,
if desired.
I have a question on how to go about implementing it though.
Do I need to create a GLSurfaceView and a Renderer, I don't actually want to use OpenGL to draw anything on screen so I am not sure if I need them? From what I have read online though it seems very essential to have these in order to setup an OpenGL context? Any pointers anybody can give me on this?

You don't have to use a GLSurfaceView. GLSurfaceView is a convenience class written purely in Java. It simplifies the setup part for applications that want to use OpenGL rendering in Android, but all of its functionality is also available through lower level interfaces in the Android frameworks.
For purely offscreen rendering, you can use the EGL interfaces to create contexts, surfaces, etc. Somewhat confusingly, there are two versions in completely different parts of the Android frameworks:
EGL10 and EGL11 in the javax.microedition.khronos.egl package, available since API level 1.
EGL14 in the android.opengl package, available since API level 17.
They are fairly similar, but the newer EGL14 obviously has some more features. If you're targeting at least API level 17, I would go with the newer version.
Using the methods in the EGL14 class, you can then create contexts, surfaces, etc. For offscreen rendering, one option is to create a Pbuffer surface for rendering. To complete the setup, you will typically use functions like:
eglInitialize
eglChooseConfig
eglCreatePbufferSurface
eglCreateContext
eglMakeCurrent
The Android documentation does not really describe these functions, but you can find the actual documentation at the Khronos web site: https://www.khronos.org/registry/egl/sdk/docs/man/.

Related

What is the best tool for 3D model environment for Android Studio

I'm trying to create to create an app that will house a 3D sphere, with a surface color skin, that the user will be able to manipulate (rotate, zoom in/zoom out, be able to drop pins on coordinates, & other simple tasks like that). I was first considering using OpenGL ES, but I'm currently scared by the following comment taken from https://developer.android.com/guide/topics/graphics/opengl.html,
"However, if you want more control of what your application draws on screen, or are venturing into three dimensional graphics, you need to use a different tool."
Is 3D modeling a complete waste of time in OpenGL ES? Am I better off with a different tool?
Thanks for the help!
First, page you have linked does not have the quoted text. It´s instead in this text.
Now, about the text itself: you are taking it out of context and/or misunderstanding it. Here's a full citation:
The Android framework provides plenty of
standard tools for creating attractive, functional
graphical user interfaces. However, if you want
more control of what your application draws on
screen, or are venturing into three dimensional
graphics, you need to use a different tool. The
OpenGL ES APIs provided by the Android
framework offers a set of tools for displaying
high-end, animated graphics that are limited only
by your imagination and can also benefit from the
acceleration of graphics processing units (GPUs)
provided on many Android devices.
Which means that Android provides standard tools (Canvas or views), but for more control or 3D graphics you need to use OpenGL ES.
Is 3D modeling a complete waste of time in
OpenGL ES? Am I better off with a different tool?
OpenGL ES and the recent Vulkan API are the only tools available for Android which let you do 3D graphics and use GPU more directly.
So, OpenGL ES is what you should use (or Vulkan, if the devices you are targetting have support for it).
OpenGL ES is just a low-level accelerated rendering API - it will let your application get pretty pixels on to the screen.
All of the higher-level logic (handling rotate, zoom, pins, deciding what to draw, etc) needs to be provided by your application. OpenGL ES provides the tools to help, but it can't provide the logic for you.

Android: Is it possible to create a SurfaceTexture without a SurfaceView?

I want to create a SurfaceTexture with an OpenGL texture that I can manage, in a setup similar to this answer. (Quoted here:)
Create a texture through OpenGL
Pass this texture to the constructor of new SurfaceTexture.
Give this new SurfaceTexture to the camera.
Make sure you are using OES_External (see documentation for
details).
However, creating an OpenGL texture (as in step 1 of the answer), requires an EGL context, which requires a EGLSurface to be made current, which requires a SurfaceTexture. It seems the only way of creating the EGL context is by creating a SurfaceView (or another view that has a SurfaceTexture), and use it to initialise the EGLSurface and then make the EGLContext current.
My objective is to create an EGLContext and make it current in a background thread, to do some offscreen computation on the camera preview image (mostly using the NDK). I want to create a library, and make it as independent of the UI as possible. Two related questions:
On the Java side, is it possible to create an EGLContext without having a SurfaceTexture created beforehand?
On the NDK side, there used to be a private API call to create native windows android_createDisplaySurface(), but it doesn't work anymore, and well, it's a private API. Is there any way of creating a surface with the NDK?
I'm quite new to using EGL, and I fail to understand why you need an EGLSurface for an EGLContext to be made current. In iOS, EAGLContexts can be created first, and then framebuffers can be created as needed. Using EGL it seems you always need a native window.
You can see a number of examples that manipulate Camera output, SurfaceTexture, and EGL in Grafika. The "Continuous capture" activity is one, but it uses the technique you mentioned: to avoid having to create an EGLSurface, it just borrows the one from the nearby SurfaceView.
You do need to have an EGLSurface, but it doesn't need to be a window surface. You can create a 1x1 pbuffer surface and just use that. This is done with the eglCreatePbufferSurface() call; see the EglCore class in Grafika for an example.
These examples are in Java, but the Java implementation just wraps the native EGL/GLES calls.
android_createDisplaySurface() is an internal call that, as you discovered, doesn't work on newer devices. Search the NDK for ANativeWindow instead.
Update: for anyone who gets here by searching, android_createDisplaySurface() relied on an internal class called FramebufferNativeWindow, which was marked obsolete in Android 5.0 in this change. The internal OpenGL ES test code that used it was updated with a SurfaceFlinger-based replacement in this change. The original version of the test code required shutting down the Android app framework so it could grab the frame buffer; the newer version just asks SurfaceFlinger for a window that covers the screen and is composited on top of everything else.

How to save SurfaceTexture as bitmap

When I decode a video to a surface I want to save the frames i want as bitmap/jpeg files. I don't want to draw on the screen and just want to save the content of the SurfaceTexture as an image file.
You have to render the texture.
If it were a normal texture, and you were using GLES 2 or later, you could attach it to an FBO and read directly from that. A SurfaceTexture is backed by an "external texture", and might be in a format that the GL driver doesn't support a full set of operations on, so you can't do that. You need to render it, and read the result.
FWIW, the way you go about saving the frame can have a significant performance impact. A full example demonstrating the use of MediaExtractor, MediaCodec, glReadPixels(), and PNG file creation is now up on bigflake (ExtractMpegFramesTest).
I've been looking at this lately, on the Android platform. Summing up the various options and why they are/aren't applicable.
glReadPixels()
The only option Android Java coders currently really have. Said to be slow. Reads from a framebuffer, not a texture (so one must render the texture to an internal frame buffer first, unless one wants to record the screen itself). Okay. Got things to work.
EGL_KHR_image_base()
An extension that seems to be available on the native (NJK) level, but not in Java.
glGetTexImage()
Looked promising but not available in OpenGL 2.0 ES variant.
Pixel Buffer Objects
Probably the 'right' way to do things, but requires OpenGL 3.0 ES (i.e. selected Android 4.3+ devices).
I'm not saying this is adding any info that wouldn't be available elsewhere. But having so many seemingly similar options (that still wouldn't work) was confusing. I'm not an OpenGL expert so any mistakes above are gladly corrected.

Disadvantages of using OpenGL in Android app?

Is there any tradeoff of add some OpenGL to a "serious" (not game) Android app?
The reason why I want to use OpenGL, is to add some 3d behaviour to a few views.
According to this http://developer.android.com/guide/topics/graphics/opengl.html OpenGL 1.0 is available in every Android device and doesn't require modification of manifest file. So there will never be compatibility issues.
The only 2 things I can think about is 1. mantainability by other developers which can't OpenGL. And possible 2. Integration problems with other components / not well reusable (although, not sure).
Is there also anything else, unexpected things, overhead of some sort, complications, etc.?
Asking because it seems not to be a very popular practice, people seem to prefer to "fake" the 3d with 2d or give it up. Don't know if it's only because they don't want to learn OpenGL.
I use OpenGL for some visualization in a released app, and I have an uncaught exception handler in place to catch any exception coming from the GLThread and disable OpenGL the next time the app is run, since I had some crash reports in the internals of GLSurfaceView.java coming in from buggier devices. If the 3D rendering is not crucial to your app, this is one approach you can take so that users with these devices can continue to use the app.
From Android 3.0+ you can also preserve the EGL context by calling GLSurfaceView. setPreserveEGLContextOnPause(true);. You'll only really need to do this if your renderer is very expensive to initialize, and it only works if you're not destroying the GLSurfaceView in between (i.e. the default behavior of an activity when rotating the device). If you're not loading that many resources then initializing OpenGL is usually fast enough.
From the SurfaceView docs (emphasis mine):
The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.
The advantage is that your GL thread can update the screen independently of the UI thread (i.e. it doesn't need to render to a texture and render the texture to the screen); the disadvantage is that something needs to composite your view with the screen. If you're lucky, this can be done in the "hardware composer"; otherwise it is done on the GPU and may be a bit wasteful of GPU resources (see For Butter or Worse: Smoothing Out Performance in Android UIs at 27:32 and 40:23).
If your view is small, it may be better to use a TextureView. This will render to a texture and render the texture as part of the normal view hierarchy which might be better, but can increase latency. The downside is it's only available since API level 14.

Rendering SVG with OpenGL (and OpenGL ES)

I am currently investigating the possibility of rendering vector graphics from an SVG file using OpenGL and OpenGL ES. I intend to target Windows and Android. My ideal solution would be to have a minimal C library that generates a polygon triangulation from a given SVG file. This would then generate standard OpenGL or OpenGL ES calls, and use a display list or vbo for optimization when redrawing. I would simply draw a display list to draw the vector image after translating and rotating, allowing me to mix this with other OpenGL calls.
So far I see that the suggestions are to firstly use QT or Cairo. - This is not an option given that I wish to manage my own OpenGL context without bloated libraries (in the context of what I am trying to achieve). Nor is this suitable for Android.
Second option is to use libraries that render to a texture. While this might be ok for static vector graphics, it's not an efficient or feasible option for games where scaling and rotations occur frequently.
Thirdly there is the possibility of using OpenVG. There are some opensource implementations of the OpenVG specification (ShivaVG etc), but I am yet to find a library that is capable of generating the appropriate OpenVG calls from a given SVG file at runtime, and I can't see how to optimize this as we might wish to with a display list or vbo.
All three methods suffer limitations. I think the most promising option is using an OpenVG implementation if no other solution exists. So my question is, are there any libraries out there that do what I want, or close to what I want? If not, is there a good reason why not? And would it be better to attempt to do this from the ground up instead?
My answer is going to about displaying vector graphics wtih OpenGL in general, because all solutions for this problem can support rather trivially SVG in particular, although none support animated SVGs (SMIL). Since there was nothing said about animation, I assume the question implied static SVGs only.
First, I would not bother with anything OpenVG, not even with MonkVG, which is probably the most modern, albeit incomplete implementation. The OpenVG committee has folded in 2011 and most if not all implementations are abandonware or at best legacy software.
Since 2011, the state of the art is Mark Kilgard's baby, NV_path_rendering, which is currently only a vendor (Nvidia) extension as you might have guessed already from its name. There are a lot of materials on that:
https://developer.nvidia.com/nv-path-rendering Nvidia hub, but some material on the landing page is not the most up-to-date
http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/opengl/gpupathrender.pdf Siggraph 2012 paper
http://on-demand.gputechconf.com/gtc/2014/presentations/S4810-accelerating-vector-graphics-mobile-web.pdf GTC 2014 presentation
http://www.opengl.org/registry/specs/NV/path_rendering.txt official extension doc
You can of course load SVGs and such https://www.youtube.com/watch?v=bCrohG6PJQE. They also support the PostScript syntax for paths. You can also mix path rendering with other OpenGL (3D) stuff, as demoed at:
https://www.youtube.com/watch?v=FVYl4o1rgIs
https://www.youtube.com/watch?v=yZBXGLlmg2U
NV_path_rendering is now used by Google's Skia library behind the scenes, when available. (Nvidia contributed the code in late 2013 and 2014.) One of the cairo devs (who is an Intel employee as well) seems to like it too http://lists.cairographics.org/archives/cairo/2013-March/024134.html, although I'm not [yet] aware of any concrete efforts for cairo to use NV_path_rendering.
NV_path_rendering has some minor dependencies on the fixed pipeline, so it can a bit of nuisance to use in OpenGL ES. This issue documented in the official extension doc linked above. For a workaround see for example what Skia/Chromium has done: https://code.google.com/p/chromium/issues/detail?id=344330
An upstart having even less (or downright no) vendor support or academic glitz is NanoVG, which is currently developed and maintained. (https://github.com/memononen/nanovg) Given the number of 2D libraries over OpenGL that have come and gone over time, you're taking a big bet using something not supported by a major vendor, in my humble opinion.
Check out MonkVG an OpenVG like API implementation on top of OpenGL ES.
Also, for SVG rendering on top of OpenVG (MonkVG) checkout MonkSVG.
MonkVG has been built for iOS, OSX, and Android platforms.
I'm the author of both libraries and would be happy to answer any questions.
It needs to be said that rendering SVG or OpenVG with OpenGL or OpenGL ES is fundamentally a bad idea. There are reasons the OpenVG implementations are all so slow and largely abandoned. The process of tessellating paths (the foundation of all SVG/OpenVG rendering) into triangle lists as required by OpenGL is fundamentally slow and inefficient. It basically requires inserting a sort/search algorithm into the 3D rendering pipeline, which cripples performance. There is also the problem that a dynamic memory allocation scheme is required because the size of the data set is unknown since SVG places no limits on the complexity of the path geometry. A really poor design.
SVG and OpenVG were created by developers who had little understanding of how modern 3D graphics hardware engines actually work (triangle lists). They were created to be an open alternative to Adobe Flash, which also has the same flawed architecture that has made Flash reviled in the industry for unpredictable performance.
My advice is to rethink your design and use OpenGL triangle lists directly. You may have to write more code, but your app will perform about a thousand times better and you can more easily debug your code than someone elses.
I am currently investigating the possibility of rendering vector graphics from an SVG file > using OpenGL and OpenGL ES. I intend to target Windows and Android. My ideal solution
would be to have a minimal C library that generates a polygon triangulation from a given
SVG file. This would then generate standard OpenGL or OpenGL ES calls, and use a display
list or vbo for optimization when redrawing. I would simply draw a display list to draw
the vector image after translating and rotating, allowing me to mix this with other OpenGL > calls.
If you only want to transform SVG vector shapes into OpenGL|ES, then I suggest to do the parser and the logic yourself. Note that SVG is a huge spec, with different features like paint servers (gradients, patterns ...), references, filters, clipping, font handling, animations, scripting, linking, etc, etc.
If you want full svg support, then there's a library on http://code.google.com/p/enesim called egueb (and particularly esvg) which uses enesim (a rendering library that has software and opengl backends) for the drawing. In most cases it uses shaders and everything is rendered into a texture, the library is very flexible allowing you to adapt to your particular needs like modifying the rendered scene, transform it, etc. Because the gl drawing is done always into a texture.
So far I see that the suggestions are to firstly use QT or Cairo. - This is not an option
given that I wish to manage my own OpenGL context without bloated libraries (in the
context of what I am trying to achieve). Nor is this suitable for Android.
Second option is to use libraries that render to a texture. While this might be ok for
static vector graphics, it's not an efficient or feasible option for games where scaling
and rotations occur frequently.
In the particular case of the gl backend, enesim does not create a GLX (or any other window dependent context), you have to provide it, so it adapts perfectly to your situation as it only uses GL calls.
The only drawback is that the library is not complete yet in terms of gl support or full SVG spec support, but depending on your needs, seems to me like a good option.
From http://shivavg.svn.sourceforge.net/viewvc/shivavg/trunk/src/shPipeline.c?revision=14&view=markup :
static void shDrawVertices(SHPath *p, GLenum mode)
{
int start = 0;
int size = 0;
/* We separate vertex arrays by contours to properly
handle the fill modes */
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(SHVertex), p->vertices.items);
while (start < p->vertices.size) {
size = p->vertices.items[start].flags;
glDrawArrays(mode, start, size);
start += size;
}
glDisableClientState(GL_VERTEX_ARRAY);
}
So it does use a VBO. So I'd suggest making your own SVG parser / use a pre-made one, and forward the calls to ShivaVG.
You still have the problem that ShivaVG is in C (and not in Java) and creates an opengl context (and not opengles, if I read the code correctly). So even if you compile it using Android's NDK, you'll have to modify the code ( for instance, I've seen a few glVertex3f around, but they don't seem to be much needed... hope for the best). The other option, of course, it to port the code from C to Java. Maybe not as painful as you could imagine.
Good luck !
You can have a look at AmanithVG, they seem to have implemented a good paths -> triangles pipeline. I've tried the iOS GL tiger example, and it seems that triangulation is not a real bottleneck.

Categories

Resources