Add renderer.readPixels (thank you @larsiusprime, close #666, close openfl/openfl#1003)

This commit is contained in:
Joshua Granick
2016-01-08 13:15:34 -08:00
parent 44f4de226b
commit 3e4bd31fc6
12 changed files with 183 additions and 5 deletions

View File

@@ -1,8 +1,12 @@
package lime._backend.flash; package lime._backend.flash;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.Lib; import flash.Lib;
import lime.graphics.Image;
import lime.graphics.Renderer; import lime.graphics.Renderer;
import lime.math.Rectangle;
class FlashRenderer { class FlashRenderer {
@@ -33,6 +37,39 @@ class FlashRenderer {
} }
public function readPixels (rect:Rectangle):Image {
if (rect == null) {
rect = new Rectangle (0, 0, parent.window.stage.stageWidth, parent.window.stage.stageHeight);
} else {
rect.__contract (0, 0, parent.window.stage.stageWidth, parent.window.stage.stageHeight);
}
if (rect.width > 0 && rect.height > 0) {
var bitmapData = new BitmapData (Std.int (rect.width), Std.int (rect.height));
var matrix = new Matrix ();
matrix.tx = -rect.x;
matrix.ty = -rect.y;
bitmapData.draw (parent.window.stage, matrix);
return Image.fromBitmapData (bitmapData);
} else {
return null;
}
}
public function render ():Void { public function render ():Void {

View File

@@ -48,6 +48,7 @@ class FlashWindow {
Lib.current.stage.scaleMode = StageScaleMode.NO_SCALE; Lib.current.stage.scaleMode = StageScaleMode.NO_SCALE;
parent.id = 0; parent.id = 0;
parent.stage = Lib.current.stage;
} }

View File

@@ -3,10 +3,14 @@ package lime._backend.html5;
import haxe.macro.Compiler; import haxe.macro.Compiler;
import js.html.webgl.RenderingContext; import js.html.webgl.RenderingContext;
import js.html.CanvasElement;
import js.Browser;
import lime.app.Application; import lime.app.Application;
import lime.graphics.Image;
import lime.graphics.opengl.GL; import lime.graphics.opengl.GL;
import lime.graphics.GLRenderContext; import lime.graphics.GLRenderContext;
import lime.graphics.Renderer; import lime.graphics.Renderer;
import lime.math.Rectangle;
@:access(lime.app.Application) @:access(lime.app.Application)
@:access(lime.graphics.opengl.GL) @:access(lime.graphics.opengl.GL)
@@ -130,6 +134,42 @@ class HTML5Renderer {
} }
public function readPixels (rect:Rectangle):Image {
// TODO: Handle DIV, improve 3D canvas support
if (parent.window.backend.canvas != null) {
if (rect == null) {
rect = new Rectangle (0, 0, parent.window.backend.canvas.width, parent.window.backend.canvas.height);
} else {
rect.__contract (0, 0, parent.window.backend.canvas.width, parent.window.backend.canvas.height);
}
if (rect.width > 0 && rect.height > 0) {
var canvas:CanvasElement = cast Browser.document.createElement ("canvas");
canvas.width = Std.int (rect.width);
canvas.height = Std.int (rect.height);
var context = canvas.getContext ("2d");
context.drawImage (parent.window.backend.canvas, -rect.x, -rect.y);
return Image.fromCanvas (canvas);
}
}
return null;
}
public function render ():Void { public function render ():Void {

View File

@@ -1,6 +1,7 @@
package lime._backend.native; package lime._backend.native;
import haxe.io.Bytes;
import lime.graphics.cairo.Cairo; import lime.graphics.cairo.Cairo;
import lime.graphics.cairo.CairoFormat; import lime.graphics.cairo.CairoFormat;
import lime.graphics.cairo.CairoImageSurface; import lime.graphics.cairo.CairoImageSurface;
@@ -8,7 +9,11 @@ import lime.graphics.cairo.CairoSurface;
import lime.graphics.CairoRenderContext; import lime.graphics.CairoRenderContext;
import lime.graphics.ConsoleRenderContext; import lime.graphics.ConsoleRenderContext;
import lime.graphics.GLRenderContext; import lime.graphics.GLRenderContext;
import lime.graphics.Image;
import lime.graphics.ImageBuffer;
import lime.graphics.Renderer; import lime.graphics.Renderer;
import lime.math.Rectangle;
import lime.utils.UInt8Array;
#if !macro #if !macro
@:build(lime.system.CFFI.build()) @:build(lime.system.CFFI.build())
@@ -112,6 +117,24 @@ class NativeRenderer {
} }
public function readPixels (rect:Rectangle):Image {
var data:Dynamic = lime_renderer_read_pixels (handle, rect);
if (data != null) {
var buffer = new ImageBuffer (new UInt8Array (@:privateAccess new Bytes (data.data.length, data.data.b)), data.width, data.height, data.bitsPerPixel);
buffer.format = RGBA32;
return new Image (buffer);
}
return null;
}
public function render ():Void { public function render ():Void {
#if !macro #if !macro
@@ -164,6 +187,7 @@ class NativeRenderer {
@:cffi private static function lime_renderer_get_type (handle:Dynamic):Dynamic; @:cffi private static function lime_renderer_get_type (handle:Dynamic):Dynamic;
@:cffi private static function lime_renderer_lock (handle:Dynamic):Dynamic; @:cffi private static function lime_renderer_lock (handle:Dynamic):Dynamic;
@:cffi private static function lime_renderer_make_current (handle:Dynamic):Void; @:cffi private static function lime_renderer_make_current (handle:Dynamic):Void;
@:cffi private static function lime_renderer_read_pixels (handle:Dynamic, rect:Dynamic):Dynamic;
@:cffi private static function lime_renderer_unlock (handle:Dynamic):Void; @:cffi private static function lime_renderer_unlock (handle:Dynamic):Void;
#end #end

View File

@@ -459,7 +459,11 @@ class Image {
} }
public static function fromBitmapData (bitmapData:#if flash BitmapData #else Dynamic #end):Image { #if flash
public static function fromBitmapData (bitmapData:BitmapData):Image {
#else
public static function fromBitmapData (bitmapData:Dynamic):Image {
#end
if (bitmapData == null) return null; if (bitmapData == null) return null;
#if flash #if flash
@@ -483,7 +487,11 @@ class Image {
} }
public static function fromCanvas (canvas:#if (js && html5) CanvasElement #else Dynamic #end):Image { #if (js && html5)
public static function fromCanvas (canvas:CanvasElement):Image {
#else
public static function fromCanvas (canvas:Dynamic):Image {
#end
if (canvas == null) return null; if (canvas == null) return null;
var buffer = new ImageBuffer (null, canvas.width, canvas.height); var buffer = new ImageBuffer (null, canvas.width, canvas.height);
@@ -502,7 +510,11 @@ class Image {
} }
public static function fromImageElement (image:#if (js && html5) ImageElement #else Dynamic #end):Image { #if (js && html5)
public static function fromImageElement (image:ImageElement):Image {
#else
public static function fromImageElement (image:Dynamic):Image {
#end
if (image == null) return null; if (image == null) return null;
var buffer = new ImageBuffer (null, image.width, image.height); var buffer = new ImageBuffer (null, image.width, image.height);
@@ -1563,7 +1575,6 @@ class Image {
#if ((cpp || neko || nodejs) && !macro) #if ((cpp || neko || nodejs) && !macro)
@:cffi private static function lime_image_encode (buffer:Dynamic, Type:Int, quality:Int):Dynamic;
@:cffi private static function lime_image_load (data:Dynamic):Dynamic; @:cffi private static function lime_image_load (data:Dynamic):Dynamic;
#end #end

View File

@@ -2,6 +2,7 @@ package lime.graphics;
import lime.app.Event; import lime.app.Event;
import lime.math.Rectangle;
import lime.ui.Window; import lime.ui.Window;
@@ -43,6 +44,13 @@ class Renderer {
} }
public function readPixels (rect:Rectangle = null):Image {
return backend.readPixels (rect);
}
private function render ():Void { private function render ():Void {
backend.render (); backend.render ();

View File

@@ -10,6 +10,7 @@ import lime.project.HXProject;
import sys.io.File; import sys.io.File;
import sys.FileSystem; import sys.FileSystem;
class AssetHelper { class AssetHelper {
@@ -24,7 +25,7 @@ class AssetHelper {
var data = { var data = {
id : asset.id, id : asset.id,
path : asset.resourceName, path : asset.resourceName,
type : Std.string(asset.type) type : Std.string (asset.type)
} }
manifest.push (data); manifest.push (data);

View File

@@ -10,6 +10,8 @@ import lime.system.Display;
#if openfl #if openfl
import openfl.display.Stage; import openfl.display.Stage;
#elseif flash
import flash.display.Stage;
#else #else
typedef Stage = Dynamic; typedef Stage = Dynamic;
#end #end

View File

@@ -2,6 +2,8 @@
#define LIME_GRAPHICS_RENDERER_H #define LIME_GRAPHICS_RENDERER_H
#include <graphics/ImageBuffer.h>
#include <math/Rectangle.h>
#include <ui/Window.h> #include <ui/Window.h>
#include <hx/CFFI.h> #include <hx/CFFI.h>
@@ -19,6 +21,7 @@ namespace lime {
virtual double GetScale () = 0; virtual double GetScale () = 0;
virtual value Lock () = 0; virtual value Lock () = 0;
virtual void MakeCurrent () = 0; virtual void MakeCurrent () = 0;
virtual void ReadPixels (ImageBuffer *buffer, Rectangle *rect) = 0;
virtual const char* Type () = 0; virtual const char* Type () = 0;
virtual void Unlock () = 0; virtual void Unlock () = 0;

View File

@@ -1088,6 +1088,27 @@ namespace lime {
} }
value lime_renderer_read_pixels (value renderer, value rect) {
Renderer* targetRenderer = (Renderer*)val_data (renderer);
ImageBuffer buffer;
if (!val_is_null (rect)) {
Rectangle _rect = Rectangle (rect);
targetRenderer->ReadPixels (&buffer, &_rect);
} else {
targetRenderer->ReadPixels (&buffer, NULL);
}
return buffer.Value ();
}
void lime_renderer_unlock (value renderer) { void lime_renderer_unlock (value renderer) {
((Renderer*)val_data (renderer))->Unlock (); ((Renderer*)val_data (renderer))->Unlock ();
@@ -1453,6 +1474,7 @@ namespace lime {
DEFINE_PRIME1 (lime_renderer_get_type); DEFINE_PRIME1 (lime_renderer_get_type);
DEFINE_PRIME1 (lime_renderer_lock); DEFINE_PRIME1 (lime_renderer_lock);
DEFINE_PRIME1v (lime_renderer_make_current); DEFINE_PRIME1v (lime_renderer_make_current);
DEFINE_PRIME2 (lime_renderer_read_pixels);
DEFINE_PRIME1v (lime_renderer_unlock); DEFINE_PRIME1v (lime_renderer_unlock);
DEFINE_PRIME2v (lime_render_event_manager_register); DEFINE_PRIME2v (lime_render_event_manager_register);
DEFINE_PRIME2v (lime_sensor_event_manager_register); DEFINE_PRIME2v (lime_sensor_event_manager_register);

View File

@@ -194,6 +194,34 @@ namespace lime {
} }
void SDLRenderer::ReadPixels (ImageBuffer *buffer, Rectangle *rect) {
if (sdlRenderer) {
SDL_Rect bounds = { 0, 0, 0, 0 };
if (rect) {
bounds.x = rect->x;
bounds.y = rect->y;
bounds.w = rect->width;
bounds.h = rect->height;
} else {
SDL_GetWindowSize (sdlWindow, &bounds.w, &bounds.h);
}
buffer->Resize (bounds.w, bounds.h, 32);
SDL_RenderReadPixels (sdlRenderer, &bounds, SDL_PIXELFORMAT_ABGR8888, buffer->data->Data (), buffer->Stride ());
}
}
const char* SDLRenderer::Type () { const char* SDLRenderer::Type () {
if (sdlRenderer) { if (sdlRenderer) {

View File

@@ -21,6 +21,7 @@ namespace lime {
virtual double GetScale (); virtual double GetScale ();
virtual value Lock (); virtual value Lock ();
virtual void MakeCurrent (); virtual void MakeCurrent ();
virtual void ReadPixels (ImageBuffer *buffer, Rectangle *rect);
virtual const char* Type (); virtual const char* Type ();
virtual void Unlock (); virtual void Unlock ();