I've built an AIR application with flash/as3 that has a webcam display on the stage. While building the app, and in all my tests everything looks and works just dandy, but when I publish for AIR the image gets stretched. The bounds of the image seem to stay the same, but the actual cam output is what's distorted. Has anyone come into this problem before?
I should add, this is a desktop app, which is permanently installed on one machine, so device compatibility should not be an issue.
this is the camera setup:
var cam:Camera = Camera.getCamera();
cam.setMode(280,380,20);
var video:Video = new Video(380,380);
this is where i first call the camera...
video.attachCamera(cam);
video.x = 355;
video.scaleX = -1;
video.y = -100;
addChildAt(video, 0);
the reason for the odd sizing, is that it sits behind a frame, that changes positions throughout the interactive.
Not necessarily the answer you are looking for, but you should keep this in mind:
You are asking the camera to capture at the resolution of 280 x 380, which is not a standard 4:3 aspect ratio.
When you call cam.setMode(280,380,20); the docs say that Flash will try to set the cameras resolution to your specifications, and if the camera does not support that resolution it will try to find one that matches. So you may or may not be getting this actual resolution.
setMode() has a fourth parameter, which can disable this functionality. Read the docs on that so you understand the implications :)
Then you display the video in a Video object that is 380x380. So I would expect the image to be stretched in the horizontal direction (b/c the original source is only 280).
It's not clear why this behaves differently: are you saying that running the debug version of the app works, but when you export the release build and run that it looks funky?
Finally, what is scaleX = -1 doing? I recall this as some sort of nifty trick I used in the past... but it's purpose here is escaping me :)
Yep, source code would be cool. Btw, i suggest you, as soon as you get the video streaming running, to set by hand the video.width and video.height property.
This will force the cam to display at the correct size.
Related
I have a project that needs to be made in Animate CC using ActionScript3.
The situation is that I have to make resolution options, meaning that if I select a button it will change the resolution of my project to said resolution like 800x600 etc. Like video games you know.
i've tried using
res1.addEventListener(MouseEvent.CLICK, setRes1);
function setRes1(event:MouseEvent):void
{
stage.fullScreenSourceRect = new Rectangle(0, 0, 800, 600);
stage.displayState = StageDisplayState.FULL_SCREEN;
}
But it doesn't seem to work, is there even a way to do this?
Not using the Flash Player, but If you target AIR yes you can do it accessing the properties of NativeWindow. Stage.fullScreenSourceRect is read-only. But you can modify application size accessing NativeApplication.nativeApplication.nativeWindow.width = ...; This will not modify your pc screen resolution, but only resize the application window. You can change resolution in AIR though using the ScreenMode class. Detailed working is described here: https://helpx.adobe.com/flash-player/release-note/fp_31_air_31_release_notes.html#ScreenModeConfigurationforAIRDesktop
Under certain conditions, picking a resolution with Camera.setMode() adds black bars to the camera input, "letterboxing" it. I understand that setMode() uses some kind of hidden algorithm that picks a resolution from one of your camera's available resolutions and then crops it to fit your desired dimensions, but apparently sometimes it would rather add black bars than crop it.
This behavior is dependent on what camera I'm using. Some cameras seem to always crop and never letterbox. This may be related to what available resolutions they have. But what's really strange is that the letterboxing only ever happens when I try it in a Flash Player ActiveX control, like in Internet Explorer. It doesn't happen when I try the exact same SWF in Flash Player Projector or Google Chrome. This seems to imply that different Flash Player versions use a different algorithm to select and fit a resolution to the desired dimensions.
Here's a very simple example of code that's been creating this problem for me. In this case I'm providing a 4x3 resolution to setMode(), which means it must be selecting a 16x9 resolution even though 640x480 is one of the camera's available resolutions.
public class Flashcam extends Sprite
{
private var _camera:Camera = Camera.getCamera("0");
public var _video:Video;
private var _width:int = 640;
private var _height:int = 480;
public function Flashcam()
{
_camera.setMode(_width, _height, 15);
_video = new Video(_camera.width, _camera.height);
addChild(_video);
_video.attachCamera(_camera);
}
}
Is there any way to stop Camera from letterboxing its input? If not, is there some way to tell whether or not it's being letterboxed and which camera resolution has been automatically selected so that I can write my own code to account for it?
In my Adobe Air application, I have a room and my player that can walk around it. I set it so it automatically opens in fullscreen, however, when you exit fullscreen it doesn't scale anything, so it just shows you the edge of the room, where you can't see the player or anything else. How do I make it so that when you exit fullscreen, everything will scale down to the windowed version, and back again? This is in Adobe Flash Builder 4.7.
I tried scaling everything down by putting an If statement in an update function, that constantly checks if the window is full screened or not, and if not, it'll scale the x and y down by .5, and if full screened again, it'll scale it back up by 1. The player however changes position, and if I try to make the X equal it it just does it again if I move the player, so it doesn't work. I've also tried verticleCenter and horizontalCenter on both the player and room, it also doesn't work.
What I'm wondering is if there is a stage.autoScale line that can solve everything, or if I have to do it manually another way like I've tried.
So you got 2 options here.
Check for fullscreen event and then in the listener function scale everything according to your logics. This will give you more control over the scaling and visual display of your components and graphics. You can find a working example for fullscreen event handling at http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS2E9C7F3B-6A7C-4c5d-8ADD-5B23446FBEEB.html
Allow FP to scale the stage according to the window size. This can be achieved by setting up stage.scale mode. There are couple options which you can find at http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/StageScaleMode.html. Use the one best suit for your application.
I would prefer using first method. Hope that make sense.
I'm building a simple eBook for tablets in Flash Pro. All the pages are images (Bitmaps in library) and there's about 80 of them. To maintain good quality for large tablets, bitmaps are quite big (3999x2999).
This eBook has vertical and horizontal scrolling and these are working fine, but; due to huge amount and size of these images, I can't add all of them to stage when app starts, so I ended up adding only the closest pages to current page always after scrolling tween.
This works ok, but causes always a delay after page scroll (even several seconds with older tablet, and with new iMac it's almost 1s, so it's notable). This is basicly what I do per image/page:
var bitmapdata:BitmapData = new bitmapArray[i](); //linkage name
var hRatio:Number = stage.stageHeight / bitmapdata.height;
var bitmap:Bitmap = BitmapScaled(bitmapdata, bitmapdata.width * hRatio, bitmapData.height * hRatio);
target.addChild(bitmap); //target is a MovieClip (I have one Mc for each vertical pile of pages)
And BitmapScaled function:
function BitmapScaled(source0:BitmapData, width0:Number, height0:Number):Bitmap{
var mat:Matrix = new Matrix();
mat.scale(width0/source0.width, height0/source0.height);
var bmpd_draw:BitmapData = new BitmapData(width0,height0,false);
bmpd_draw.drawWithQuality(source0,mat,null,null,null,true,StageQuality.BEST);
return new Bitmap(bmpd_draw);
}
Also, after scrolling I clean up the ones that aren't next to new current page:
function clear(targetArray:Array):void{
for(var i:int = 0; i<targetArray.length; i++){
targetArray[i].bitmapData.dispose();
targetArray[i].bitmapData = null;
targetArray[i].parent.removeChild(targetArray[i]);
targetArray[i] = null;
}
if(targetArrays[targetArrays.indexOf(targetArray)] = new Array();
}
How often:
After horizontal scroll I add one new horizontal page and one new vertical page, and remove one horizontal and at least one vertical page.
After vertical scroll I add only one new vertical page (if next vertical page is one that I already haven't added), so vertical pages I keep in stage untill next horizontal scroll happens. This takes a smaller delay, but also notable.
I know Flash/AIR is not the best way for this, but it's all I have now. How could I get rid of the addChild-delay? Yeah you can't, so any better ways to do all this?
I'm pretty sure I'm using the hard way with something here, but just can't figure out what and how I should do it.
BitmapData drawing on mobile device is too slow to be used on the fly, if you must use it do your drawing on app start (still slow though). BitmapData blitting is a little bit faster but still too slow to be used on mobile device.
With large amount of assets like in your case, Stage3D frameworks like Starling might not be the best solution either as texture uploading is also slow and limited in memory amount (when limit is reached the app crashes).
Best might just be to copy what typical Android/Ios development use: Few different resolutions for all assets with a minimum of 1x and 2x.
I personally use 0.5x, 1x, 2x, 3x and developed a framework that switches resolution according to different settings (very much like XCode does). But still you can keep things simple without a framework and just set at app start the asset resolution you'll use for the app. I would also make sure to remove and add those assets on screen as they are needed.
don't use that "new BitmapData" in conjunction with the "dispose". when you load your bytes load it directly into the already existing bitmaps on the stage. try to have as little modification of the allocated memory as possible through your load-resize-display pipe.
removing and dumping pixels onto the renderer is far slower than changing already existing ones.
I need to take thumbnail from Video playing with MediaElement
For this i learn there is RenderTargetBitmap in windows 8.1 API
RenderTargetBitmap a = new RenderTargetBitmap();
await a.RenderAsync(myMedia);
thumb.Source = a;
and second way i got with help of WinRTXamlToolkit.Composition toolkit which do rendring with WriteableBitmapRenderExtensions class
WriteableBitmap w = await WriteableBitmapRenderExtensions.Render(myMedia);
thumb.Source = w;
Both these methods are working with all UIElement but not with MediaElement
only black screen is visible when source this to Image object.
Can any one tell me why? and how can i take thumbnail from video?
It seems like the methods you mentioned might be limited in that regard. I'd still try RenderTargetBitmap but with something overlaid on top of the MediaElement. I believe if you place anything on top of a MediaElement, like a 0.01 opacity, 1x1 sized, black rectangle - it will switch to run in some different rendering mode where it is possible RenderTargetBitmap would be able to render it. Otherwise I think someone discussed here a while back a question of capturing a frame from a video stream. IIRC it is a pretty involved process though, involving using DirectX or Media Foundation and quite a bit of native code.