Cordova iOS launch image changes while app is loading - ios

I have set up my launch images / splashscreen in the Resources/splash folder with the normal naming scheme (Default~ipad.png, Default-Portrait#2x~ipad.png, etc). I have not set any of the UILaunchImage* plist entries.
When I launch my Cordova app on an iPad2, it immediately loads one of my launch images. A few seconds later (when the org.apache.cordova.splashscreen plugin starts getting run, from what I can see in the log), the launch image will change, typically to something that's a different resolution, so the entire image shifts. After that point, the image stays as it is until I call navigator.splashscreen.hide(). This has also happened on an iPhone4.
Again, the splash screen displays immediately on app open, shifts a few seconds later, the page finishes loading (according to the console) about 5 seconds in, and then navigator.splashscreen.hide() gets calls in my ready() event.
It seems to me that maybe Xcode is choosing one of my images to be the launch image by default, and then the cordova splashscreen plugin is choosing another one when it gets loaded with the other plugins. I did initially gets a black flash and a console error of "Default.png" could not be found, so I added a "Default~ipad.png" to the splash images. I had thought it would have used either the Portrait or Landscape images for ipad, but the plugin appears to only do that if CDV_IsIPad() and isOrientationLocked.
I even tried reverting all images in Resources/splash to the default Cordova launch images. When I do that, the Cordova launch image displays immediately on app load, a few seconds later, when the Cordova splashscreen plugin loads, the launch image changes to one of MY launch images, then fades on navigator.splashscreen.hide(). When this happens, I can not find any references anywhere to my launch images that I removed from the project; not in Resources/splash or in the plist. Very odd.
Any ideas why the splash screen is getting changed by the cordova splashscreen plugin, or what I should be doing to fix this?

I ended up looking at the pull requests for the Cordova Splashscreen plugin, just to see if anyone had addressed this issue. Looks like they did!
in src/ios/CDVSplashScreen.m:
- } else if (CDV_IsIPad() && isOrientationLocked) {
- switch (orientation) {
- case UIInterfaceOrientationLandscapeLeft:
- case UIInterfaceOrientationLandscapeRight:
- imageName = [imageName stringByAppendingString:#"-Landscape"];
- break;
-
- case UIInterfaceOrientationPortrait:
- case UIInterfaceOrientationPortraitUpsideDown:
- default:
- imageName = [imageName stringByAppendingString:#"-Portrait"];
- break;
should be
+ } else if (CDV_IsIPad()) {
+ if (isOrientationLocked) {
+ imageName = [imageName stringByAppendingString:(supportsLandscape ? #"-Landscape" : #"-Portrait")];
+ } else {
+ switch (orientation) {
+ case UIInterfaceOrientationLandscapeLeft:
+ case UIInterfaceOrientationLandscapeRight:
+ imageName = [imageName stringByAppendingString:#"-Landscape"];
+ break;
+
+ case UIInterfaceOrientationPortrait:
+ case UIInterfaceOrientationPortraitUpsideDown:
+ default:
+ imageName = [imageName stringByAppendingString:#"-Portrait"];
+ break;
+ }

Related

Scaling Image Causes Crash In AS3 Flex AIR Mobile App

Problem:
Zooming in on image by scaling and moving using matrix causes the app to run out of memory and crash.
Additional Libraries used:
Gestouch - https://github.com/fljot/Gestouch
Description:
In my Flex Mobile app I have an Image inside a Group with pan/zoom enabled using the Gestouch library. The zoom works to an extent but causes the app to die (not freeze, just exit) with no error message after a certain zoom level.
This would be manageable except I can’t figure out how to implement a threshold to stop the zoom at, as it crashes at a different zoom level almost every time. I also use dynamic images so the source of the image could be any size or resolution.
They are usually JPEGS ranging from about 800x600 - 9000x6000 and are downloaded from a server so cannot be packaged with the app.
As of the AS3 docs there is no longer a limit to the size of the BitmapData object so that shouldn't be the issue.
“Starting with AIR 3 and Flash player 11, the size limits for a BitmapData object have been removed. The maximum size of a bitmap is now dependent on the operating system.”
The group is used as a marker layer for overlaying pins on.
The crash mainly happens on iPad Mini and older Android devices.
Things I have tried already tried:
1.Using Adobe Scout to pin point when the memory leak occurs.
2.Debugging to find the exact height and width of the marker layer and image at the time of crash.
3.Setting a max zoom variable based on the size of the image.
4.Cropping the image on zoom to only show the visible area. ( crashes on copyPixels function and BitmapData.draw() function )
5.Using imagemagick to make lower quality images ( small images still crash )
6.Using imagemagick to make very low res image and make a grid of smaller images . Displaying in the mobile app using a List and Tile layout.
7.Using weak references when adding event listeners.
Any suggestions would be appreciated.
Thanks
private function layoutImageResized(e: Event):void
{
markerLayer.scaleX = markerLayer.scaleY = 1;
markerLayer.x = markerLayer.y = 0;
var scale: Number = Math.min(width / image.sourceWidth , height / image.sourceHeight);
image.scaleX = image.scaleY = scale;
_imageIsWide = (image.sourceWidth / image.sourceHeight) > (width / height);
// centre image
if(_imageIsWide)
{
markerLayer.y = (height - image.sourceHeight * image.scaleY ) / 2 ;
}
else
{
markerLayer.x = (width -image.sourceWidth * image.scaleX ) / 2 ;
}
// set max scale
_maxScale = scale*_maxZoom;
}
private function onGesture(event:org.gestouch.events.GestureEvent):void
{
trace("Gesture start");
// if the user starts moving around while the add Pin option is up
// the state will be changed and the menu will disappear
if(currentState == "addPin")
{
return;
}
const gesture:TransformGesture = event.target as TransformGesture;
////trace("gesture state is ", gesture.state);
if(gesture.state == GestureState.BEGAN)
{
currentState = "zooming";
imgOldX = image.x;
imgOldY = image.y;
oldImgWidth = markerLayer.width;
oldImgHeight = markerLayer.height;
if(!_hidePins)
{
showHidePins(false);
}
}
var matrix:Matrix = markerLayer.transform.matrix;
// Pan
matrix.translate(gesture.offsetX, gesture.offsetY);
markerLayer.transform.matrix = matrix;
if ( (gesture.scale != 1 || gesture.rotation != 0) && ( (markerLayer.scaleX < _maxScale && markerLayer.scaleY < _maxScale) || gesture.scale < 1 ) && gesture.scale < 1.4 )
{
storedScale = gesture.scale;
// Zoom
var transformPoint:Point = matrix.transformPoint(markerLayer.globalToLocal(gesture.location));
matrix.translate(-transformPoint.x, -transformPoint.y);
matrix.scale(gesture.scale, gesture.scale);
/** THIS IS WHERE THE CRASH HAPPENS **/
matrix.translate(transformPoint.x, transformPoint.y);
markerLayer.transform.matrix = matrix;
}
}
I would say that's not a good idea to work with such a large image like (9000x6000) on mobile devices.
I suppose you are trying to implement some sort of map navigation so you need to zoom some areas hugely.
My solution would be to split that 9000x6000 into 2048x2048 pieces, then compress it using png2atf utility with mipmaps enabled.
Then you can use Starling to easily load these atf images and add it to stage3d and easily manage it.
In case you are dealing with 9000x6000 image - you'll get about 15 2048x2048 pieces, having them all added on the stage at one time you might think it would be heavy, but mipmaps will make it so that there are only tiny thumbnails of image are in memory until they are not zoomed - so you'll never run out of memory in case you remove invisible pieces from stage from time to time while zooming in, and return it back on zoom out

Phonegap Build iOS camera.getPicture() quality parameter not working

I have written a Phonegap application and compiled it using the Build service.
My application calls the camera in this block of code:
function capturePhoto() {
// Take picture using device camera and retrieve image
navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
quality: 20,
destinationType: destinationType.FILE_URI });
}
The resulting image is uploaded to a server via ajax.
When I review the uploaded images, some arrive with their quality reduced appropriately but some arrive with a filesize of ~4 MB. I have realized that users who are running my app on iPhone 4 and 5 (I have no testers with 6 yet) are consistently uploading the large images.
I have reduced quality to 10 and 5. Image size of Android-submitted images are appropriately reduced- but still IOS images are large. Can anyone tell me if there is a known issue here?
The API Docs say that you cannot reduce quality of images selected from gallery or camera roll- but these are not. They are loaded from camera.
This is the code the plugin uses for processing the image after taking the picture:
- (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options
{
NSData* data = nil;
switch (options.encodingType) {
case EncodingTypePNG:
data = UIImagePNGRepresentation(image);
break;
case EncodingTypeJPEG:
{
if ((options.allowsEditing == NO) && (options.targetSize.width <= 0) && (options.targetSize.height <= 0) && (options.correctOrientation == NO)){
// use image unedited as requested , don't resize
data = UIImageJPEGRepresentation(image, 1.0);
} else {
if (options.usesGeolocation) {
NSDictionary* controllerMetadata = [info objectForKey:#"UIImagePickerControllerMediaMetadata"];
if (controllerMetadata) {
self.data = data;
self.metadata = [[NSMutableDictionary alloc] init];
NSMutableDictionary* EXIFDictionary = [[controllerMetadata objectForKey:(NSString*)kCGImagePropertyExifDictionary]mutableCopy];
if (EXIFDictionary) {
[self.metadata setObject:EXIFDictionary forKey:(NSString*)kCGImagePropertyExifDictionary];
}
if (IsAtLeastiOSVersion(#"8.0")) {
[[self locationManager] performSelector:NSSelectorFromString(#"requestWhenInUseAuthorization") withObject:nil afterDelay:0];
}
[[self locationManager] startUpdatingLocation];
}
} else {
data = UIImageJPEGRepresentation(image, [options.quality floatValue] / 100.0f);
}
}
}
break;
default:
break;
};
return data;
}
So, if options.encodingType is PNG the image quality isn't change. The default value is JPG, so the problem isn't there.
But then check the
if ((options.allowsEditing == NO) && (options.targetSize.width <= 0) && (options.targetSize.height <= 0) && (options.correctOrientation == NO))
allowsEditing is NO by default
targetSize.width and targetSize.height are 0 by default
correctOrientation is NO by default
So all the conditions of the if are meet, and no change in quality is done.
It sounds like a bug as it isn't mentioned anywhere that you have to specify any other value to make the quality param work.
So, what can you do now?
You can file an issue on the cordova jira page https://issues.apache.org/jira/browse/CB
And/or you can pass any param to change the default value and make the code to skip the if and go to the else with the quality code. Changing any of this should work:
allowEdit : true,
targetWidth: 100,
targetHeight: 100,
correctOrientation: true
EDIT: there is already a bug open
https://issues.apache.org/jira/browse/CB-6190
EDIT 2: I fixed the issue, you can get the changes with cordova plugin add https://github.com/apache/cordova-plugin-camera or wait until it's released to NPM
There is no issue. iOS has larger pictures. They call it a feature.
http://lifeinlofi.com/more/iphone-photo-sizes-2007-2013/
Jesse

Strange behaviour after modifying exposure duration and going back to AVCaptureExposureModeContinuousAutoExposure

I am working on an app that exposes manual controls for the camera with the new APIs introduced in iOS 8, and I am using this sample app from WWDC 2014 as a reference.
However I noticed a strange bahaviour (on my 5s and on a 6): after setting the exposure mode to "custom" and then back to "auto" the image continues to lag as if the exposure duration was not affected by this change.
Here is the code involved in each step (from the sample app, without any modification):
- (IBAction)changeExposureMode:(id)sender
{
UISegmentedControl *control = sender;
NSError *error = nil;
AVCaptureExposureMode mode = (AVCaptureExposureMode)[self.exposureModes[control.selectedSegmentIndex] intValue];
if ([self.videoDevice lockForConfiguration:&error])
{
if ([self.videoDevice isExposureModeSupported:mode])
{
[self.videoDevice setExposureMode:mode];
}
else
{
NSLog(#"Exposure mode %# is not supported. Exposure mode is %#.", [self stringFromExposureMode:mode], [self stringFromExposureMode:self.videoDevice.exposureMode]);
}
}
else
{
NSLog(#"%#", error);
}
}
- (IBAction)changeExposureDuration:(id)sender
{
UISlider *control = sender;
NSError *error = nil;
double p = pow( control.value, EXPOSURE_DURATION_POWER ); // Apply power function to expand slider's low-end range
double minDurationSeconds = MAX(CMTimeGetSeconds(self.videoDevice.activeFormat.minExposureDuration), EXPOSURE_MINIMUM_DURATION);
double maxDurationSeconds = CMTimeGetSeconds(self.videoDevice.activeFormat.maxExposureDuration);
double newDurationSeconds = p * ( maxDurationSeconds - minDurationSeconds ) + minDurationSeconds; // Scale from 0-1 slider range to actual duration
if (self.videoDevice.exposureMode == AVCaptureExposureModeCustom)
{
if ( newDurationSeconds < 1 )
{
int digits = MAX( 0, 2 + floor( log10( newDurationSeconds ) ) );
self.exposureDurationValueLabel.text = [NSString stringWithFormat:#"1/%.*f", digits, 1/newDurationSeconds];
}
else
{
self.exposureDurationValueLabel.text = [NSString stringWithFormat:#"%.2f", newDurationSeconds];
}
}
if ([self.videoDevice lockForConfiguration:&error])
{
[self.videoDevice setExposureModeCustomWithDuration:CMTimeMakeWithSeconds(newDurationSeconds, 1000*1000*1000) ISO:AVCaptureISOCurrent completionHandler:nil];
}
else
{
NSLog(#"%#", error);
}
}
I noticed this too. It seems to be related to slow shutter speeds. Try this: Go to custom. Set a fast shutter speed. Then go back to Auto. Boom, you're right there. Now, go to custom, set a slow shutter speed (slider to the right). Go back to auto and you can watch the shutter speed gradually move back to a reasonable setting.
This is the case in the sample code and in the app that I wrote based on the sample code. It is also the same for my 4s and 5s.
I believe that this is because the sensor needs to catch a certain number of images in order to pick the right auto setting. With a very slow shutter speed (up to 1 second long max) this means it could take several seconds to find the right setting. Sort of makes sense, even if not what we'd like. Fortunately for me my app never needs a shutter speed more than quarter of second, if that.
I have found in my own code that the setExposureModeCustomWithDuration method has some issue. Though it has a completion handler which is supposed to be called AFTER the duration and ISO are set in the device, it doesn't always work.
There are times, for instance when switching from Auto expose to manual exposure, that if you grab a still from within setExposureModeCustomWithDuration's completion handler, the still is taken with an auto expose setting. If you take another still imedeately after that, it has the correct manual exposure set on it.
I found that a 1 second delay at the beginning of the completion handler works around this issue, but that can't be a proper solution.
I have also tried placing a wait/sleep loop at the beginning of the completion handler where it waits until the device is not adjusting exposure -- that does not help.
I tried the same sample app and tried to reproduce the issue but was not able to it looks like they have fixed it now.

ImageMagick API - export pixels with correct orientation

I've been using this method to export pixels using the MagickWand API:
MagickExportImagePixels
But, this doesn't appear to obey the orientation exif data in the image. Is there anyway to extract the pixels in the correct orientation, so I can write them out in a different format (Not using MagickWriteImage)? Basically, I want the behaviour of the auto-orient option for convert.
Thanks!
I am one of the developers for ImageMagick and it seems we forgot to add this method to Wand. The next release of ImageMagick (6.8.9-9) will include the following method that can be used to automatically orient an image:
MagickAutoOrientImage(magick_wand);
When 6.8.9+ release of ImageMagick with MagickAutoOrientImage() is not available I use the following code to auto-orient images:
void auto_orient_image(MagickWand* image) {
PixelWand* pwand=0;
switch(MagickGetImageOrientation(image))
{
case UndefinedOrientation:
case TopLeftOrientation:
default:
break;
case TopRightOrientation:
MagickFlopImage(image);
break;
case BottomRightOrientation:
pwand=NewPixelWand();
MagickRotateImage(image, pwand, 180.0);
case BottomLeftOrientation:
MagickFlipImage(image);
break;
case LeftTopOrientation:
MagickTransposeImage(image);
break;
case RightTopOrientation:
pwand=NewPixelWand();
MagickRotateImage(image, pwand, 90.0);
break;
case RightBottomOrientation:
MagickTransverseImage(image);
break;
case LeftBottomOrientation:
pwand=NewPixelWand();
MagickRotateImage(image, pwand, 270.0);
break;
}
if (pwand) DestroyPixelWand(pwand);
MagickSetImageOrientation(image, TopLeftOrientation);
}
Might need to add error handling.
It looks like the only way to do this is pseudo-manually by getting the image orientation and rotating the image accordingly. It's not difficult, but I was hoping a more concise solution was built into the API. An incomplete example follows:
OrientationType t = MagickGetImageOrientation(magick_wand);
if (t == RightTopOrientation) {
MagickRotateImage(mw, pw, 90);
}
...

blackberry star icon

i am developping an application that has chat&message support. I need to know weather it is applicaple on BB OS 4.5 to set a star icon on application icon as in messages application .
You can do that. You need to have four images for the icons. They are
Standard app icon
Standard roll over icon
Standard icon with a *
Standard roll over icon with a *
Once you have that use the following code
if (unReadChatMessages> 0)
{
appIcon = Bitmap.getBitmapResource("app_alert.png");
rolloverIcon = Bitmap.getBitmapResource("app_rollover_alert.png");
// turn on the LED
if(LED.isSupported(LED.LED_TYPE_STATUS))
{
LED.setState(LED.STATE_BLINKING);
LED.setConfiguration(100, 1000, LED.BRIGHTNESS_100);
}
}
else
{
// use default icons...
appIcon = Bitmap.getBitmapResource("app.png");
rolloverIcon = Bitmap.getBitmapResource("app_rollover.png");
// Turn off LED...
if(LED.isSupported(LED.LED_TYPE_STATUS))
{
LED.setState(LED.STATE_OFF);
}
}
// Try to set the icons
HomeScreen.updateIcon(appIcon, 0);
HomeScreen.setRolloverIcon(rolloverIcon, 0);

Resources