I'm trying to write a Universal Application. The display should be slightly different for different screen resolutions. But when I code like this:
- (void)viewDidLoad {
SCREEN_WIDTH=[[UIScreen mainScreen] applicationFrame].size.width;
SCREEN_HEIGHT=[[UIScreen mainScreen] applicationFrame].size.height;
NSLog(#"w:%f h:%f",SCREEN_WIDTH,SCREEN_HEIGHT);
...
}
I get output: w:320.000000 h:480.000000 even when the simulator is set to
Hardware->Device->iPhone (Retina)
Furthermore, images with this resolution display as full-screen images in the simulator.
I understand I should be getting w:640.000000 h:960.000000.
Is it like this for anyone else? And any ideas why/how to fix?
See the related thread: here
UIScreen will always report the resolution of a Retina Display device as that of a non-Retina Display device. This allows old code to run transparently on such screens. However, UIScreen exposes a scale property which, when combined with the bounds of the screen, can be used to determine the physical pixel resolution of a device:
CGSize PhysicalPixelSizeOfScreen(UIScreen *s) {
CGSize result = s.bounds.size;
if ([s respondsToSelector: #selector(scale)]) {
CGFloat scale = s.scale;
result = CGSizeMake(result.width * scale, result.height * scale);
}
return result;
}
The resulting value on an iPhone 4 would be { 640.0, 960.0 }.
Here is what I've found out. Since iOS4,
[[UIScreen mainScreen] applicationFrame].size.width;
and
[[UIScreen mainScreen] applicationFrame].size.height;
give measurements in "points", not "pixels". For everything else, pixels=points, but for the iPhone4, each point has 4 pixels. Normal images are scaled in the iPhone4, so each pixel in the image is mapped onto a point. This means that the iPhone4 can run iPhone apps without a noticeable change.
The "apple" way to add "hi-res" images that take advantage of the iPhone's greater resolution is to replace ".png" with "#2x.png" in the image file name, and double the pixel density (effectively, just the width&height) in the image. Importantly, don't change the way the image is referred to in your code.
So if you have "img.png" in your code, iPhone4 will load the "img#2x.png" image if it is available.
The problem with this is that, if you are trying to develop a Universal app, and include separate images for all the different possible screen resolutions/pixel densities, your app will get bloated pretty quick.
A common solution to this problem is to pull all the required images of the 'net. This will make your binary nice and small. On the negative side, this will eat into your user's internet quota, and it will really annoy users who don't have wifi--especially if your app has no other reason to use the 'net (and you don't say your app needs the 'net in your app store description).
Fortunately, I have found another way. Often, when you scale down an image, the iPhone4 is clever enough to utilise the increased pixel density of the scaled image. For example, you might have:
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100.0, 50.0)];
[indicatorButton setBackgroundImage:
[UIImage imageNamed:#"buttonImage.png"] forState:UIControlStateNormal];
Now if buttonImage.png is 200x100, it will be perfectly well behaved on everything. Similarly, if you start with a nice 640x960 (pixel) image that displays quite nicely on the iPad and you scale it down to a 320x480 image for smaller screens, using something like:
+ (UIImage*)imageWithImage:(UIImage*)image newX:(float)newX newY:(float)newY{
CGSize newSize=CGSizeMake((CGFloat)newX, (CGFloat)newY);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newX,newY)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
It should display quite nicely on the iPhone4. The trick is not to double-up on your scaling. For example, if you do something like:
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100.0, 50.0)];
[indicatorButton setBackgroundImage:
[Utilities imageWithImage:[UIImage imageNamed:#"buttonImage.png"] newX:100 newY:50] forState:UIControlStateNormal];
Then you'll have lost your pixel density and your image will look all "pixely" on the iPhone4.
Finally, if you want to detect if you are an iPhone4 (not really necessary if you use the above technique), the following code may be useful:
+(bool)imAnIphone4{
return([[UIScreen mainScreen]respondsToSelector:#selector(scale)] && [UIScreen mainScreen].scale==2);
}
Did you rename the images as img.png#2x? And you should enable retina display in your code.
Even if you set simulator to retina display BUT the code is not retina display enabled, the graphics displayed out would be 320x480.
Related
I'm drawing a bitmap with SkiaSharp in Xamarin Forms. The antialiasing is poor and I would like to know how I can improve it.
The source bitmap has antialiasing, shown in the left of the attached image. The right half shows a part of a screen capture on an Android device.
On the left part, notice that the aliasing is regular - a bit of dark feathering going upward and a bit of light feathering going downward, all uniform. On the right part we still see both feathering but it alternates between double wide pixels and single wide pixels.
When drawing the bitmap
canvas.DrawBitmap(bmpSrc, rectSrcRight, rectDest, paint);
I've tried setting the paint IsAntialiasing() true and false. No significant difference.
In this example, the source image is 61 pixels tall and the Android image is 102.
Am I expecting too much ?
You could have a try with the following code:
SKPaint paint = new SKPaint
{
IsAntialias = true,
FilterQuality = SKFilterQuality.High
};
canvas.DrawBitmap(bmpSrc, rectSrcRight, rectDest, paint);
Although IsAntialias will not work for bitmap, I also add it. If you want to draw bitmap continually, it will use more memory.
If you have a better way to make it work and not using more memory, please share here to discuss.
I have a Qt Widgets application using Qt styleSheet for the app look and feel. We want to add support for high-DPI displays, as on these, the app looks very small. The first step was thus to call:
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
This does most of the job and the app window is big enough. The only remaining issue is the resolution of the images used in style sheet.
Say that we have:
QCheckBox::indicator::unchecked {
image: url(:/res/checkbox_off.png);
}
MainWindow QFrame {
background-image: url(:/res/background.png);
}
When using high DPI scaling, these images get upscaled accordingly which is a problem. For high DPI, I would prefer to use higher resolution images to make them look as crisp as possible.
As expected, a naive approach of simply providing the images in higher resolution does not work - it makes images and controls twice as large (on both low and high DPI screens).
Qt documentation on QImageReader states that
The high resolution version is marked by the suffix #2x on the base name. The image read will have its device pixel ratio set to a value of 2.
However, I have provided these resources with twice the resolution, added them to qrc file, but the images displayed are still the same on device with pixel_ratio of 3.
Are there any other steps needed to make this automatic image loading work with stylesheets?
I am instantiating a QImage from an image file like below and subsequently rendering it on a QWidget.
QImage ( const QString & fileName, const char * format = 0 )
For most images, everything works fine. But for a few images, the QImage gets loaded with a 90-degree rotated image.
It seems this happens only with pictures taken earlier on my phone in portrait mode. Those taken in landscape are fine
You might need to use a library like libexif to determine the photo orientation and then rotate the QImage accordingly
Since Qt 5.5 set Image.autoTransform : true because the default is false!
QT Image QML Type reference
With C++ Qt-class QImageReader:
QImageReader imgReader( imagePath );
imgReader.setAutoTransform( true );
QImage img = imgReader.read();
https://discussions.apple.com/thread/2541504?start=0&tstart=0
It sounds like it is a pretty common issue, where there is some flag or tag added on the image that says how to rotate it, instead of actually reordering the pixels in the image. For the image you are trying to render, you could go and take the format you are trying to use, and see if there are any extra flags you could check and have Qt do the rotation.
Sounds like cppguy knows of a library that can let you check these flags.
EDIT Found a better description for it:
johninsj - Re: iPhone 4 Photo's & Video Rotating Sideways In Email
Nov 2, 2010 1:45 PM (in response to VibrantRedGT)
Apple sets the jpeg meta tag for orientation when you shoot a photo,
so if you hold the iphone upside down, or sideways, etc, the image
(which is shot upside down or sideways, since the camera is upside
down/sideways) knows it needs to flip/rotate the image when you look
at it.
Not all software honors the rotation settings. Gimp (which runs on
everything, and is free) does.
You can rotate images and save them, or learn to shoot photos with the
iPhone in the correct orientation for non-rotated images. That would
be with the home button to the right as you look at the screen.
Hope that helps.
I'm really new with flex. I want to develop an app for multiscreen resolutions. I can't figure out exactly what i need to do.
I read this article here but it still it's not that clear what i have to do.
Can anyone explain how can i keep the same size and design across multiple resolutions?
How can i achieve Density independence ?
Do i need to have 3 different resolutions for a background picture for example?
What screen resolutions does my background image needs to be ?
Thank you!
To achieve density independence and hit multiple screen resolutions, you need to be prepared for any and every screen possible. From the low-res iPhone 3/GS to the super hi-res Nexus 10. There is no specific screen resolution your background image needs to be because, well, there are hundreds of resolutions it will need to be.
Instead of making the background a set resolution, consider constructing it with code. Either through a repeatable tile or by using multiple images and putting them together to form your background.
You definitely will want to use one image for each Adobe resolution (160dpi, 240dpi, and 320dpi). You can do that by using this:
<s:Image>
<s:source>
<s:MultiDPIBitmapSource
source160dpi="#Embed('assets/ui/images/phone/info-image-160.png')"
source240dpi="#Embed('assets/ui/images/phone/info-image-240.png')"
source320dpi="#Embed('assets/ui/images/phone/info-image-320.png')" />
</s:source>
</s:Image>
Assuming you created everything in vector, this is relatively simple. Just take the image you designed for 160 (which is what most people seem to design for) and enlarge it to 150% for 240dpi and 200% for 320dpi.
For true density independence, you also need to make sure you are not using applicationDPI in your application tags as that will force a specific resolution.
For CSS, you should follow this format (taken directly from the first link below)
#media (application-dpi: 160) {
s|Button {
fontSize: 10;
}
}
/* IOS only # 240dpi */
#media (application-dpi: 240) and (os-platform: "IOS") {
s|Button {
fontSize: 11;
}
}
/* IOS at 160dpi or Android # 160dpi */
#media (os-platform: "IOS") and (application-dpi:160), (os-platform: "ANDROID") and (application-dpi: 160) {
s|Button {
fontSize: 13;
}
}
You need to consider everything. Images, fonts/font sizes, component sizing, hardcoded component placemenets, etc. You can take a look at the Capabilities class for any idea of what kind of data is available to you at run time as well. If you end up getting incorrect values using things like stage.stageHeight, consider using FlexGlobals.topApplication.sys(tem?)Manager.screen.height instead. That accounts for DPI whereas stageHeight does not.
Also Read:
Support multiple screen sizes and DPI values in a mobile
application
I am developing a flash based website using mxml. My monitor's resolution is 1280x768 and is widescreen. The problem is while it appears properly in my screen it doesn't appear properly in others. Which is the best approach to solve the problem ?
I have 2 in mind.
Let scrollbars take care of it : If the screen is 14 inch screen with
800x600 resolution it appears zoomed
in. So thats a problem
Get screen resolution and resize using scaleX and scaleY : The graphic
components will get resized but fonts
give problem.
Which is the best approach among these ? If there is a better approach please mention.
Thanks
The BEST approach for this is to create a fluent UI based on percentage and constraints.
This way, the UI will feel the same on all computers not just yours.
I would recommend to also use the flow container that comes as a part of flexLib because that way is the easiest to create a fluent design.
Not long ago I created an application for a forex company that was perfectly fit to all screens larger then 1280X800 (design definition).
It's not that hard to do once you get the hang of it.
Good luck.
You can add an event listener to the stage to this effect:
this.stage.addEventListener(Event.RESIZE, resizeHandler);
private function resizeHandler(e:Event):void {
var newWidth:Number = this.stage.stageWidth;
var newHeight:Number = this.stage.stageHeight;
// etc, roll from here to do your manual positioning logic.
}
Note that this should also work on any DisplayObject - so you can use constraints and percentages on your containers, but then intercept their auto-resizing with a setup like this which will let you fine-tune the appearance of their contents.
Personally I would develop the screen for 800x600 and then dynamically resize the screen for higher resolutions.
You can use vertical scrollbars but horizontal scrolling is a big no-no in my books. It takes away from the whole experience of your site and gets rather irritating.