Download image and resize to avoid OOM errors, Picasso fit() distorts image - android-image

I am trying to show images in a full screen view and using the following code:
// Target to write the image to local storage.
Target target = new Target() {
// Target implementation.
}
// (1) Download and save the image locally.
Picasso.with(context)
.load(url)
.into(target);
// (2) Use the cached version of the image and load the ImageView.
Picasso.with(context)
.load(url)
.into(imgDisplay);
This code works well on newer phones, but on phones with 32MB VMs, I get out of memory issues. So I tried changing (2) to:
Picasso.with(context)
.load(url)
.fit()
.into(imgDisplay);
This resulted in distorted images. Since I do not know the dimensions of the image until it is downloaded, I cannot set the ImageView dimensions, and hence the image is being resized without any consideration to aspect ratio in to my ImageView:
<ImageView
android:id="#+id/imgDisplay"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
What is the best way to handle this situation? My original images have max width 768, and height 1024, and I want to downsample when the screens are much smaller than this. If I try to use resize(), my code becomes complicated, as I have to wait for (1) to finish the download and then add the resize() in (2).
I am assuming Transformations do not help in this case, as the input to public Bitmap transform(Bitmap source) will already have the large bitmap which will cause me to run out of memory.

You can combine fit() with centerCrop() or centerInside(), depending on how you want the image to fit your View:
Picasso.with(context)
.load(url)
.fit()
.centerCrop()
.into(imgDisplay);
Picasso.with(context)
.load(url)
.fit()
.centerInside()
.into(imgDisplay);

Related

constructing a bitmap from stream rotates the image

I am using ASP.Net with VB and doing some file uploads. Sometimes, when a bitmap is constructed from the file input stream, the image gets rotated. It doesn't seem to happen if the image is wider than it is tall, but also doesn't seem to happen all the time if the image is taller than wide. I have provided a few screen shots where the properties of the image are show, and the created bitmap's properties are shown at run time.
Any ideas what is happening here or what we can do to prevent this rotation?
Rotated image:
Non-rotated image:
Using the rotation code found Here fixed it. The images were coming from a phone camera and had original orientation information stored in them that could be used to right them.

Meteor mobile-config.js launchScreens

I'm creating the splash images for my app but I've got some questions:
Can I create of all them at once? I've seen some repos for this but
there are not updated with new sizes (e.g 2048x1536)
Would be possible to use the same image for different sizes?
My phone is 1920x1080 but there is no splash screen size for that so it takes one and applies a disproportionate image. If I've got
text on it it looks really badly.
What happens with the rest of images when I build? Meteor removes the rest? Are located in resources/splash.
Could be possible to use a html with css page?
Thanks in advance!
Next time you should consider splitting your questions into independent posts.
Creating splash images: if your image is simple enough, indeed you have many scripts that can generate the different sizes automatically. I am sure you can customize them to fit your sizes.
Use the same image for different sizes: in general, that would mean your image will be stretched by the device to fill the screen. On Android, you can define a 9-patch PNG that will tell the device which pixels can be stretched, so that some part(s) of your image is not deformed.
Deformed image for 1920x1080 screen: depending on the pixel density, there should very probably be a placeholder for that.
Storage of image versions: by default, all versions (i.e. sizes) are packaged within your APK / APP, so that whatever the device needs will be available once user has downloaded the app.
Using an HTML+CSS page for splash screen: in general, no, but it depends on what you want to do with your splash screen. Meteor calls it "launch screen", because it is the first thing it displays while the app is loading / "launching". In particular, the WebView and local server may not be ready yet, and cannot serve any HTML/CSS. That is why you have to use a plain image, which is passed to a very simple activity while the app is loading. But some people also use a "waiting screen" between some parts of their app. In that case, your WebView and local server are already loaded, and you can simply use whatever you want.
Update:
For Android, if 9-patch PNG does not fit your need, you can also try to request Cordova's splashscreen plugin to maintain the aspect ratio of your image:
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/#preferences
<preference name="SplashMaintainAspectRatio" value="true" />
"SplashMaintainAspectRatio" preference is optional. If set to true, splash screen drawable is not stretched to fit screen, but instead simply "covers" the screen, like CSS "background-size:cover". This is very useful when splash screen images cannot be distorted in any way, for example when they contain scenery or text. This setting works best with images that have large margins (safe areas) that can be safely cropped on screens with different aspect ratios.
In Meteor, you would use App.setPreference in mobile-config.js:
App.setPreference("SplashMaintainAspectRatio", true, "android");

Minimize picture size

I have a picture into JavaFX application which is loaded +30 times into chart. I use this code to load it and shrink the size.
ImageView livePerformIcon = new ImageView(MainApp.class.getResource("/images/Untitledwdwd.png").toExternalForm());
livePerformIcon.setFitHeight(100);
livePerformIcon.setFitWidth(100);
label.setGraphic(livePerformIcon);
Can you tell em how I can optimize this code for performance and memory is there a way to save resources during work.
Maybe livePerformIcon.setCache(true); can solve this?
Load the Image once and use the same Image instance for all the ImageViews. The example in the ImageView javadocs does this.

Simulator iPhone Retina has wrong screen resolution

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.

Saving large images created in Flex

I am attempting to capture a very large image that was made dynamically within the Flash Player (the size of the image is 2400px by 12,000px) and am running into some very serious issues... Let me run down how the image get's to that size in the first place:
User adds elements to a canvas and then when the user is finished the canvas scales up to 2400px wide and ~12,000px tall. The problem arises when I attempt to save the image to the hard drive. Now, I dont know if this will affect the recommended fix, but the rendered image wont be saved on the hard drive, it will be sent to a server. I know about the ~4050px limit in Flash Player and was thinking I could get around that by clipping the images with the ImageSnapshot.captureBitmapData() method and keeping the required Rectangle variable below 4000px then repeat that down the large image until it reaches the end where the final images will be pieced together at a later time. However... As i mentioned the error comes when it reaches the 'fileReference.save(pngImage);' method... Has anyone else done something like this?
Have you tried if fileReference.save works at all (e.g. with smaller images like 100 px height)? It seems that the image data will perhaps be transformed to string data, so there might be other limits you're not aware of at the moment (your uncompressed image data will be around 86 MB, so even a PNG file with good compression might be around 10 MB in size, at the moment you're trying to save a third of this, but 3 MB still is quite large).

Resources