Orientation detection for camera capture - camera

I've been searching for a solution to this for some time and believe that it, at it's core, isn't possible.
I'm wondering if anybody has found a decent hack or bypass.
My issue is this:
I have an app that captures a photo, then that photo is used as a canvas that the user can tap on to place tags.
After the tags are placed the user uploads the photos and the tags get submitted to a client service for parsing.
If the photo is taken in landscape I need to detect if it's landscape left or landscape right so that I can display it at the proper orientation when it gets to the canvas, and flip it the proper direction if the user changes to the opposite landscape mode.
How could I capture the orientation that the photo was taken in?

Simply look at the height and width of event.media to at least determine portrait vs. landscape. This will not help you with which direction to flip, though I'm not sure why you need to figure that out from the capture. The image is saved as a landscape photo in the correct natural orientation, such that you would simply rotate it to the current orientation of the phone
Titanium.Media.showCamera({
success: function(event) {
var isLandscape = event.media.width > event.media.height;
}
}

function getOrientation(o) {
switch (o){
case Titanium.UI.PORTRAIT:
return 'portrait';
case Titanium.UI.UPSIDE_PORTRAIT:
return 'upside portrait';
case Titanium.UI.LANDSCAPE_LEFT:
return 'landscape left';
case Titanium.UI.LANDSCAPE_RIGHT:
return 'landscape right';
case Titanium.UI.FACE_UP:
return 'face up';
case Titanium.UI.FACE_DOWN:
return 'face down';
case Titanium.UI.UNKNOWN:
return 'unknown';
}
}
}
Ti.Gesture.addEventListener('orientationchange',function(e){
Ti.API.info('Current Orientation: ' + getOrientation(Titanium.Gesture.orientation));
var orientation = getOrientation(e.orientation);
Titanium.API.info(
"orientation changed = "+orientation+", is portrait?"+e.source.isPortrait()+", orientation = "+Ti.Gesture.orientation + "is landscape?"+e.source.isLandscape()
);
});
modified a bit from the KS but should do the trick.
this should do what the above doesn't
Titanium.Media.showCamera({
success:function(event) {
var orientationWhilePictureTaken = Ti.Gesture.orientation;
// all other camera code...
}
});

Related

ExoPlayer in Android TV plays video in portrait mode instead of landscape

We are using ExoPlayer to play m3u8 files (stream) on Android TV. The streaming is working fine, but the video plays in portrait mode (even if the video is shot in landscape).
Looks like some issue with orientation of the android TV instead of aspect ratio.
private fun initializePlayer() {
if(mPlayer == null) {
playerView = activity!!.findViewById<SimpleExoPlayerView>(R.id.texture_view)
// playerView!!.setControllerVisibilityListener(this)
playerView!!.requestFocus()
val bandwidthMeter = DefaultBandwidthMeter()
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(bandwidthMeter)
mTrackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
mPlayer = ExoPlayerFactory.newSimpleInstance(activity, mTrackSelector)
playerView!!.player= mPlayer
mPlayerAdapter = LeanbackPlayerAdapter(activity, mPlayer, UPDATE_DELAY)
mPlayerGlue = VideoPlayerGlue(activity!!, mPlayerAdapter!!)
mPlayerGlue!!.host = VideoSupportFragmentGlueHost(this)
mPlayerGlue!!.playWhenPrepared()
play(s1)
}
}
Commenting these lines :
mPlayerAdapter = LeanbackPlayerAdapter(activity, mPlayer, UPDATE_DELAY)
mPlayerGlue = VideoPlayerGlue(activity!!, mPlayerAdapter!!)
mPlayerGlue!!.host = VideoSupportFragmentGlueHost(this)
mPlayerGlue!!.playWhenPrepared()
Plays the video in landscape but the player controls are hidden and it only plays the lowest quality of the video. Please help us with this.
Metadata of the MP4 video contains a property called Rotation=90° but it's ignored by the ExoPlayer. To fix it you need to inject this Java function into your code:
void onVideoSizeChanged(int width,
int height,
int unappliedRotationDegrees, // 90° or 270°
float pixelWidthHeightRatio);
This allows an application using TextureView to easily apply the rotation by making the appropriate call to TextureView.setTransform. Note that on Lollypop+ unappliedRotationDegrees will always be equal to 0.
You can find this function on a line #74 at MediaCodecVideoTrackRenderer page of GitHub.
If the above-mentioned method doesn't work for you, you may find another remedy in Rotation Issue #91 post on a GitHub.
As far i know, exoplayer will generate its size based on texture view size. So try to programmatically resize your texture view by
playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL);
and also try to resize your player programmatically
mPlayer.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
Hope this will help.

How do find out if there is a full-screen app running on a specific NSScreen

In Cocoa/AppKit, given a screen from [NSScreen screens], how can I find out if there's a full-screen app running on that specific screen? I'm mostly interested in apps that use the Cocoa APIs for full-screen, but if there's a solution that also encompasses other types of full-screen apps, even better. The solution needs be able to pass Mac App Store approval.
My specific use case involves a menu bar app (NSStatusItem) and figuring out whether or not a menubar is shown at all on [NSScreen mainScreen] in order to allow a global keyboard shortcut to show either a popover positioning on the status item (if it's visible) or a floating window if there's no visible status item.
NSScreens themselves don't seem to expose any information about windows/apps, and NSRunningApplication doesn't expose this information either.
Are there perhaps Carbon APIs for finding this out? For example, if I have a list of windows, I could iterate through them and see if any window frames match the screens' frame exactly. On the other hand, there might be apps that have a frame like that but run underneath other apps (like the Backdrop app, https://itunes.apple.com/us/app/backdrop/id411461952?mt=12), so an approach like this would need to look at window levels.
You can try the CGWindowList API, such as CGWindowListCopyWindowInfo().
If you just want to know if the menu bar is showing, you should be able to check -[NSApplication currentSystemPresentationOptions] for NSApplicationPresentationAutoHideMenuBar or NSApplicationPresentationHideMenuBar. That method can also tell you if the active app is in Cocoa full-screen mode (NSApplicationPresentationFullScreen).
Here's a solution based on CGWindowListCopyWindowInfo in Swift.
func fullScreenWindows(fullScreen: Bool) -> [CGWindowID] {
var winList: [CGWindowID] = []
// if you want to get the windows in full screen, you MUST make sure the option excluding 'optionOnScreenOnly'
let option: CGWindowListOption = fullScreen ? .excludeDesktopElements : [.excludeDesktopElements, .optionOnScreenOnly]
guard let winArray: CFArray = CGWindowListCopyWindowInfo(option, kCGNullWindowID) else {
return winList
}
for i in 0..<CFArrayGetCount(winArray) {
// current window's info
let winInfo = unsafeBitCast(CFArrayGetValueAtIndex(winArray, i), to: CFDictionary.self)
// current window's bounds
guard let boundsDict = (winInfo as NSDictionary)[kCGWindowBounds],
let bounds = CGRect.init(dictionaryRepresentation: boundsDict as! CFDictionary) else {
continue
}
// to check the window is in full screen or not
guard __CGSizeEqualToSize(NSScreen.main!.frame.size, bounds.size) else {
continue
}
// current window's id
guard let winId = (winInfo as NSDictionary)[kCGWindowNumber] as? CGWindowID,
winId == kCGNullWindowID else {
continue
}
winList.append(winId)
}
return winList
}
Here's a solution based on CGWindowListCopyWindowInfo, as Ken Thomases suggested in his answer:
- (BOOL)fullScreenAppPresentOn:(NSScreen *)screen
{
// Get all of the visible windows (across all running applications)
NSArray<NSDictionary*> *windowInfoList = (__bridge_transfer id)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
// For each window, see if the bounds are the same size as the screen's frame
for (int windowInfoListIndex = 0; windowInfoListIndex < (int)windowsInfoList.count; windowInfoListIndex++)
{
NSDictionary *windowInfo = windowInfoList[windowInfoListIndex];
CFDictionaryRef windowInfoRef = (__bridge CFDictionaryRef) windowInfo[(__bridge NSString *)kCGWindowBounds];
CGRect windowBounds;
CGRectMakeWithDictionaryRepresentation(windowInfoRef, &windowBounds);
if (CGRectEqualToRect([screen frame], windowBounds))
{
return YES;
}
}
return NO;
}

How to handle various view states in Windows 8.1 store app

I have windows 8.0 code and I had handled the UI for ViewStates like Portrait,Landscape, filled and Snapped. But with windows 8.1 a Viewer can move the app into any size. how do i handle the UI in this case. Currently i am doing it like this.
private void QuestionPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
ApplicationViewState currentState = Windows.UI.ViewManagement.ApplicationView.Value;
if (currentState.Equals(ApplicationViewState.Snapped))
{
VisualStateManager.GoToState(this, "Snapped", false);
}
else if (currentState.Equals(ApplicationViewState.FullScreenLandscape))
{
VisualStateManager.GoToState(this, "FullScreenLandscape", false);
}
else if (currentState.Equals(ApplicationViewState.Filled))
{
VisualStateManager.GoToState(this, "Filled", false);
}
else if (currentState.Equals(ApplicationViewState.FullScreenPortrait))
{
VisualStateManager.GoToState(this, "FullScreenPortrait", false);
}
}
Firstly, you need to decide how to categorize your sizes. We decided to go with the following:
Default - landscape full screen.
Portrait - portrait full screen.
Small - snapped/resized to 500 - 683 wide, vertical orientation
Medium - snapped/resized to 684 wide and above, vertical orientation
So basically, the small and medium sizes are a vertical layout, as the height is bigger than the width. When the Medium width becomes larger than its height, then it would be the default landscape size.
We use:DisplayOrientations CurrentOrientation = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().CurrentOrientation; instead of ApplicationViewState for SizeChangedEventArgs.
Then define the sizes as follows:
//Small Size
if (e.NewSize.Width <= 683
&& (CurrentOrientation == DisplayOrientations.Landscape || CurrentOrientation == DisplayOrientations.LandscapeFlipped || CurrentOrientation == DisplayOrientations.None))
You can then play and define which ever sizes you would like.
Instead of basing your layout on ApplicationViewState - make it depend on size and aspect ratio of the window. Think how users would use your app and what layout would work best in these cases. Maybe one layout would be fine or maybe you might want to switch a GridView layout into a ListView one when the window width is smaller than some value - e.g. 500px. Think what's most comfortable to use in these cases. At the very least - test that the layout doesn't fall apart when you resize the app.

Thumbnail of previous image instead of cancel button while camera is open

i want to show the thumbnail of the previous image taken by camera instead of the cancel button while camera is running ...
Is that possible ?? Need help ..
Yep. Just capture the last image, keep it in memory (or save it to disk), then use it as one of the controls. We can do this using the overlay property of the Titanium.Media.showCamera function. Here is a quick example:
First we need an overlay view to show the image.
var overlayView = Ti.UI.createView();
var imageView = Ti.UI.createImageView({
width:44,
height:44,
left : 5
});
overlayView.add(imageView);
Now this is the function we use to open the camera with the overlay view. Note that we don't have controls so you need to add those (for closing etc). All we do right now is set the overlays image.
Titanium.Media.showCamera({
success:function(event) {
// called when media returned from the camera
imageView.image = event.media;
},
cancel:function() {},
error:function(error) {},
saveToPhotoGallery:true,
allowEditing:true,
mediaTypes:[Ti.Media.MEDIA_TYPE_PHOTO],
overlay : overlayView,
showControls: false // This is important!
});
To really make this work, you may need to save the event.media in a global variable, or use a similiar technique make sure overlayView will not be nulled out / garbage collected.
Also this is a barebones solution, not very robust, but this is the basic method I would use!

UIScrollView contentOffset CoreMotion Bug

I'm having a problem when I try to move the content of a UIScrollView with CoreMotion.
The thing is, I have a background with approximately 5000px, inside a container, which is inside my scrollView (is a landscape app); I already set the self.scrollView.bounces = FALSE;, my value for motion is attitude.pitch * 10.0; and when I move the content inside and it reaches the edge of the pointZero or the self.scrollView.contentSize.width it doesn't respect the bounds and keep moving in a white screen like it has no limit.
So, I set a verification (the code below), but when it reaches the pointZero it was supposed to stop but still give me a little white border. I set a NSLog and I saw that the contentOffset was still going till x =-14, like the bounce was active. The pitch value is controlling that because when the pitch value is zero the content stays at pointZero, when I raise the value of the pitch ir keep going till -14.
I think that is something wrong with my verification, if anyone can help I will be really grateful!!
self.accel = attitude.pitch *10.0;
//"pointZERO"----------------
if (self.gameArea.contentOffset.x <= self.gameArea.frame.origin.x) {
NSLog(#"%2.f",self.gameArea.contentOffset.x);
self.gameArea.contentOffset = CGPointZero;
} else {
self.gameArea.contentOffset = CGPointMake(self.gameArea.contentOffset.x + self.accel,0.0);
}
//"END OF SCREEN"------------------------
if (self.gameArea.contentOffset.x + self.gameArea.frame.size.width >= self.gameArea.contentSize.width) {
NSLog(#"%2.f",self.gameArea.contentOffset.x);
self.gameArea.contentOffset = CGPointMake(self.gameArea.contentSize.width - self.gameArea.frame.size.width ,0.0);
} else {
self.gameArea.contentOffset = CGPointMake(self.gameArea.contentOffset.x + self.accel,0.0);
}