I need to scale down images coming from a Network stream without losing quality.
I am aware of this solution Strange out of memory issue while loading an image to a Bitmap object but it is too coarse - inSampleSize is an integer and does not allow finer control over the resulting dimensions. That is, I need to scale images to specific h/w dimensions (and keeping aspect ratio).
I dont mind having a DIY bicubic/lancoz algorithm in my code but I cant find any examples that would work on Android as they all rely on Java2D (JavaSE).
EDIT:
Ive attached a quick source. The original is 720x402 HD screen capture. Please ignore the top 2 thumbnails. The top large image is resized automatically by android (as part of layout) to about 130x72. It is nice and crisp. The bottom image is resized with API and has severe artifacting
I've also tried using the BitmapFactory and, as I said earlier, it has two problems - no way to scale to exact size and the scaled image is blurry.
Any ideas on how to fix the artifcating?
Thanks, S.O.!
package qp.test;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.widget.ImageView;
public class imgview extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bitmap original = BitmapFactory.decodeResource(getResources(), R.drawable.a000001570402);
Bitmap resized = getResizedBitmap(original, 130);
//Bitmap resized = getResizedBitmap2(original, 0.3f);
System.err.println(resized.getWidth() + "x" + resized.getHeight());
ImageView image = (ImageView) findViewById(R.id.ImageViewFullManual);
image.setImageBitmap(resized);
}
private Bitmap getResizedBitmap(Bitmap bm, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float aspect = (float)width / height;
float scaleWidth = newWidth;
float scaleHeight = scaleWidth / aspect; // yeah!
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth / width, scaleHeight / height);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
bm.recycle();
return resizedBitmap;
}
private Bitmap getResizedBitmap2(Bitmap bm, float scale) {
/* float aspect = bm.getWidth() / bm.getHeight();
int scaleWidth = (int) (bm.getWidth() * scale);
int scaleHeight = (int) (bm.getHeight() * scale);
*/
// original image is 720x402 and SampleSize=4 produces 180x102, which is
// still too large
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 4;
return BitmapFactory.decodeResource(getResources(), R.drawable.a000001570402, bfo);
}
}
And the layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<!-- <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hullo" android:background="#00ff00"
/>
-->
<ImageView android:id="#+id/ImageViewThumbAuto"
android:layout_width="130dip" android:layout_height="72dip"
android:src="#drawable/a000001570402" />
<ImageView android:id="#+id/ImageViewThumbManual"
android:layout_width="130dip" android:layout_height="72dip"
android:src="#drawable/a000001570402"
android:layout_toRightOf="#id/ImageViewThumbAuto"
/>
<ImageView android:id="#+id/ImageViewFullAuto" android:layout_width="300dip"
android:layout_height="169dip"
android:scaleType="fitXY"
android:src="#drawable/a000001570402"
android:layout_below="#id/ImageViewThumbAuto"
/>
<ImageView android:id="#+id/ImageViewFullManual" android:layout_width="300dip"
android:layout_height="169dip"
android:scaleType="fitXY"
android:src="#drawable/a000001570402"
android:layout_below="#id/ImageViewFullAuto"
/>
</RelativeLayout>
You can use BitmapFactory.Options with BitmapFactory.decode function(s),
using inDensity and inTargetDensity
Example: you have 1600x1200 size of image and want to resize to 640x480
then 'inDensity'=5 and 'inTargetDensity'=2 (1600x2 equal to 640x5).
Hoping this help.
The top large image is simply scaled down to 450px by the layout so no artifacts.
The artifacts of the bottom large image result from scaling it down to 130px wide and then up again to about 450px by the layout. So the artifacts are made by your scaling. Try
Bitmap resized = getResizedBitmap(original, 450);
in your code and it should be fine. However, you need to adapt that to the actuall screen width of the phone either.
Briefly, good downscaling algorithm (not nearest neighbor like) consists of 2 steps:
downscale using BitmapFactory.Options::inSampleSize->BitmapFactory.decodeResource() as close as possible to the resolution that you need but not less than it
get to the exact resolution by downscaling a little bit using Canvas::drawBitmap()
Here is detailed explanation how SonyMobile resolved this task: http://developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/
Here is the source code of SonyMobile scale utils: http://developer.sonymobile.com/downloads/code-example-module/image-scaling-code-example-for-android/
Related
I have an activity containing 4 images in total. They are all matching the resolution of a 1080x1920 device. When I run the activity with those images, which are loaded directly in my activity via the XML, it runs tremendously slow in my Genymotion emulator and lags on a real Android device.
Here is the setup:
<android.support.design.widget.AppBarLayout
...>
<android.support.design.widget.CollapsingToolbarLayout
...>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="vertical"
app:layout_collapseMode="parallax">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageView"
android:src="#drawable/shot_header"
android:scaleType="centerCrop" />
</LinearLayout>
<android.support.v7.widget.Toolbar
.../>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
The first image is in a CollapsingToolbarlayout. The resolution of the image is 1080x649 PNG.
The content_activity:
This image fills the parent width.It's resolution is 1080x772 PNG.
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/main_image"
android:layout_below="#+id/shot_error_field"
android:src="#drawable/forehand_midpng"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginTop="15dp"/>
The other 2 images are in a LinearLayout, their resolution is 500x399
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/main_image">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:id="#+id/imageView3"
android:src="#drawable/forehand_mid_wrong"
android:layout_weight="1"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" >
</View>
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:id="#+id/imageView4"
android:src="#drawable/forehand_mid_wrong"
android:layout_weight="1"/>
</LinearLayout>
To summarize, I have an activity with 4 ImageViews, populated with properly sized images, which should no problem for a modern Android device. The problem is that this activity is running extremely slow and lagging due to a high memory consumption.
Am I doing something wrong? How can I further optimize those images?
I looked into other threads- out of memory issue but none seems to propose a solution to such a problem.
Problem is resolution of the image, if you can reduce resolution of the image then work fine, here is some example for reducing image resolution and size.
If you pass bitmap width and height then use below function.
public Bitmap getResizedBitmap(Bitmap image, int bitmapWidth,
int bitmapHeight) {
return Bitmap.createScaledBitmap(image, bitmapWidth, bitmapHeight,
true);
}
if you want bitmap ratio same and reduce bitmap size. then pass your maximum size bitmap. you can use this function
public Bitmap getResizedBitmap(Bitmap image, int maxSize) {
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float)width / (float) height;
if (bitmapRatio > 0) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
return Bitmap.createScaledBitmap(image, width, height, true);
}
or if you are using drawable resources then use this method
public Drawable resizeImage(int imageResource) {// R.drawable.large_image
// Get device dimensions
Display display = getWindowManager().getDefaultDisplay();
double deviceWidth = display.getWidth();
BitmapDrawable bd = (BitmapDrawable) this.getResources().getDrawable(
imageResource);
double imageHeight = bd.getBitmap().getHeight();
double imageWidth = bd.getBitmap().getWidth();
double ratio = deviceWidth / imageWidth;
int newImageHeight = (int) (imageHeight * ratio);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), imageResource);
Drawable drawable = new BitmapDrawable(this.getResources(),
getResizedBitmap(bMap, newImageHeight, (int) deviceWidth));
return drawable;
}
/************************ Resize Bitmap *********************************/
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
Actually this should not be an issue and these images are not so big to make you phone laggy. Take a look on other stuff you have in the application, it is possible there is some heavy operations (like DB writing/readin, API requests) right in UI thread.
If there is no such operations and you see such problems with the perfomance, try to set these images via some libraries, like Picasso.
Gradle dependency:
compile 'com.squareup.picasso:picasso:2.4.0'
And code will look like this:
Picasso.with(this).load(R.drawable.my_image).into(toolbar);
TRY
Definitely reduce the size of the images.
Cache images if you can.
Download the images on a different thread. Store a HashMap would
make it easy for you
When you get the list of image urls, iterate through them:
pictures.put(id,view);
try{
FileInputStream in = openFileInput(id);
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeStream(in, null, null);
view.setImageBitmap(bitmap);
}catch(Exception e){
new Thread(new PictureGetter(this,mHandler,id)).start();
}
Code to update the image view:
if(id!=null){
ImageView iv = pictures.get(id);
if(iv!=null){
try{
FileInputStream in = openFileInput(id);
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeStream(in, null, null);
iv.setImageBitmap(bitmap);
}catch(Exception e){
}
}
Try facebook's fresco library. It can handle large images and one of my projects, reduces memory consumption about 50%.
I want to have a background image that scales to fit any screen size in Android. The image is static and doesn't need to scroll. I made the image at 4K resolution to cover what is a likely resolution to exist on tablets in the next 2-3 years (2560 x 1600 already exist). The image is a JPG with a 137KB file size. Similar resolution images seem to work fine in Android web browsers. Why am I getting a lot of slow down in Android (on Samsung Galaxy S3, which should have plenty of CPU/RAM to handle an image like this)? I don't feel like I am doing anything out of the ordinary.
This loads the image in the XML layout. The image is currently stored in drawable-nodpi.
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/logo_background"
android:scaleType="centerCrop" />
Making different size images for each category of screen resolution is difficult as I cannot find information on what the current maximum resolution for a device in each category is only a minimum.
I want to use the same background image again and again between a variety of fragments. Is there a way to have the image resized once to the width of the screen (preferably asynchronously) and then load that resized image each time? Could this be done with Picasso?
Please don't give answers like "of course larger images result in performance issues" or link me to Google's Supporting Different Densities. This is a real issue that is going to become more of an issue as screen resolutions continue to increase. I am amazed that handling and resizing large images is not already optimised in the ImageView class, which makes me think I am doing something wrong.
The problem is that what you are trying to do is not relying on the SDK. By having one image and having to change the image on runtime, you are causing more work to be done on the UI thread in onDraw().
Of course you would be able to create a Bitmap for a specific size, but why do such complicated work when you can rely on the SDK?
Currently there are a bunch of different folders that you can use in order to get what you are looking for, and then in the future you can get a 4k image put into a specific folder. Things like this might work:
drawable-xhdpi
drawable-xxhdpi
drawable-xlarge-xhdpi - May not be specific enough for what you are trying to accomplish
drawable-sw600dp - This allows you to specify a folder for an image where the screen width is greater than 600dp. This qualifier will probably be helpful for your case, in the future where you will be using 4k images.
You dont even need Picasso mate.Here you get the screen size:
LinearLayout layout = (LinearLayout)findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});
And here you resize your image with your new dimensions:
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth){
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
Using a matrix to resize is relatively fast. Although user1090347s answer would be best practice.
The problem is that android uses Bitmap to render images to canvas. It is like BMP image format for me. So, you have no gain from JPG format, cuz all information lost from jpg conversion are lost forever and you will end up will fullsize bitmap anyway. The problem with big resolution is that, you have to address few bytes for every pixel, no conversion applied! In particular, smaller devices have lower memory class as bigger ones. So, you have to handle the image resolution based on device screen size and memory class.
You can properly convert your background bitmap at runtime with these helper functions:
public void getScreenSizePixels(Resources resources, int widthHeightInPixels[/*2*/])
{
Configuration config = resources.getConfiguration();
DisplayMetrics dm = resources.getDisplayMetrics();
double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}
--
public static Bitmap getBitmap(byte[] imageAsBytes, int reqWidth, int reqHeight) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(
imageAsBytes,
0,
imageAsBytes.length,
opt);
int width = opt.outWidth;
int height = opt.outHeight;
int scale = 1;
while (reqWidth < (width / scale) || reqHeight < (height / scale)) {
scale++;
}
//bitmap.recycle();
opt.inJustDecodeBounds = false;
opt.inSampleSize = scale;
Bitmap bitmap = BitmapFactory.decodeByteArray(
imageAsBytes,
0,
imageAsBytes.length,
opt);
return bitmap;
}
I need to resize my image with custom size. The image is taken from device camera or gallery, i tired the below code, but the image is stretched, i need the image in square shape with out any stretch.
public Bitmap decodeSampledBitmapFromFile(Bitmap bm, int boundBoxInDp) {
boundBoxInDp=300;
int height = bm.getHeight();
int width = bm.getWidth();
float scaleWidth = ((float) boundBoxInDp) / width;
float scaleHeight = ((float) boundBoxInDp) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
If you already have a bitmap, you could use the following code to resize:
Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, false);
Or you can use following library for resize image
https://github.com/biokys/cropimage
This won't fit your image in a bounding box (the failure of which is presumably what you're calling "stretch"). It will not handle rectangular bitmaps in your square bounding box, nor will it handle images smaller than the bounding box particularly well. You probably want something like:
public Bitmap decodeSampledBitmapFromFile(Bitmap bm, int boundBoxInDp) {
boundSquareInPx=convertToPixels(300);
int maxDimen = Math.max(bm.getHeight(), bm.getWidth())
float scale = (maxDimen <= boundSquareInPx) ? 1 : boundSquareInPx / (float) maxDimen;
float scaleWidth = scale * bm.getWidth();
float scaleHeight = scale * bm.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, true);
return resizedBitmap;
}
Few notes: if you image is smaller than your bound it won't fit it- obvious modifications do that.
Secondly, dp != px; the Bitmap object returns px, so you're going to have to convert to px from dp (which is well documented elsewhere).
Use postTranslate(...) if you need to center the correspondingly cropped bitmap.
The documentation is here; this is allready the best library I know for resizing in Android- I've never needed anything else, and I've been in the game a while and work with this frequently.
If you need, in my opinion, the best introduction to working with the API efficiently: read the source code to ImageView and Drawable instances; a really worthwhile personal development exercise would be to use the SDK to implement a fading transition drawable that is center cropped, as that's rather annoyingly one of the only things missing from the Android library, and would involve a heck of a lot of the kind of coding you're trying to do above.
NB:
As you'll note, another answerer has pointed out the existence of createScaledBitmap, which is probably much clearer code; I just wanted to point out how what you were doing was basically right and how it could be improved.
Best.
Take a look at https://github.com/coomar2841/image-chooser-library/blob/d27b542d2487132b0150be382f39e9ef95aafe68/src/com/kbeanie/imagechooser/threads/MediaProcessorThread.java.
The method called compressAndSaveImage.
I'm trying to scale and crop image at the same time and show it from left to right screen edge. I receive image that is just little bit wider than users screen and I'm able to scale it like this (XML):
<ImageView
android:id="#+id/category_image_top"
android:layout_width="match_parent"
android:layout_height="170dp"
android:maxHeight="170dp"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:focusable="false"
/>
But this is what I get:
I would like to align image to top right like so:
Is this possible? I've tried all scaleTypes but noting works, image is either scaled to fit by X and Y (fitXY, fitStart) or image cropped but centered (centerCrop). I need something like android:scaleType="cropStart"
<ImageView
android:id="#+id/category_image_top"
android:layout_width="match_parent"
android:layout_height="170dp"
android:maxHeight="170dp"
android:scaleType="centerCrop"
android:paddingLeft="half of your screen width"
android:paddingBottom="half of your screen height"
android:adjustViewBounds="true"
android:focusable="false"
/>
You can set padding to move image left or right and also top and bottom padding to move up and down
As I didn't find a way to deal with this situation through xml (views) I turned (as #serenskye suggested) to code. Here's my code, I hope it helps (ps: I've changed my logic a little bit, I wanted to fit image by width so I've scaled it to predefined imageWidght and then cropped it to imageHeight)
//bm is received image (type = Bitmap)
Bitmap scaledImage = null;
float scaleFactor = (float) bm.getWidth() / (float) imageWidth;
//if scale factor is 1 then there is no need to scale (it will stay the same)
if (scaleFactor != 1) {
//calculate new height (with ration preserved) and scale image
int scaleHeight = (int) (bm.getHeight() / scaleFactor);
scaledImage = Bitmap.createScaledBitmap(bm, imageWidth, scaleHeight, false);
}
else {
scaledImage = bm;
}
Bitmap cropedImage = null;
//if cropped height is bigger then image height then there is no need to crop
if (scaledImage.getHeight() > imageHeight)
cropedImage = Bitmap.createBitmap(scaledImage, 0, 0, imageWidth, imageHeight);
else
cropedImage = scaledImage;
iv.setImageBitmap(cropedImage);
add
android:layout_gravity="center"
I have a 10x10 tablelayout with each cell containing an ImageView. I simulate the moving across this gamegrid by updating the pictures in each grid on a move event. I also rotate the image to align the image with the direction of travel. My problem is that as the image rotates it causes my cell rows and columns to expand to fit the rotated image.
What I would like is to have the image cropped to remain within the dimensions of the table row and columns. If that isnt possible then I would like to scale the image to remain within the dimensions of the original table cell.
Another potential issue is that the images are getting scaled initially to fit into the cells (this is done automatically as the table expands to fill the screen). I don't want to change that behavior. I just want to trim off the corners of the image as they pass the original boundaries of the table cell when they are rotated.
My rotation code is below:
Matrix matrix = new Matrix();
matrix.postRotate((float) (360 - sector.getShip().getHeading()));
Bitmap bMap = BitmapFactory.decodeResource(image.getContext().getResources(), getShip().getGridSymbol());
image.setImageBitmap(Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(), bMap.getHeight(), matrix, true));
image.setImageResource(sector.getShip().gridParams.default);
My table configuration is below:
<TableLayout android:id="#+id/quadrantGrid" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignWithParentIfMissing="true" android:stretchColumns="*" android:background="#000000">
...
<TableRow>
<TextView android:text="1" android:background="#404040" android:gravity="center"></TextView>
<ImageView android:id="#+id/grid00"></ImageView>
<ImageView android:id="#+id/grid01"></ImageView>
<ImageView android:id="#+id/grid02"></ImageView>
<ImageView android:id="#+id/grid03"></ImageView>
<ImageView android:id="#+id/grid04"></ImageView>
<ImageView android:id="#+id/grid05"></ImageView>
<ImageView android:id="#+id/grid06"></ImageView>
<ImageView android:id="#+id/grid07"></ImageView>
<ImageView android:id="#+id/grid08"></ImageView>
<ImageView android:id="#+id/grid09"></ImageView>
</TableRow>
...
UPDATE:
I found a solution, though I'm not sure its the most efficient solution.
All my images are 25x25. And so the OS figures how to scale those images to fit into the cell. The solution just performs two operations. First it rotates, and then it creates a smaller image from the rotated image. (note: When I created my image I made sure the important parts of the image would be contained within a circle with a diameter of the width of the image to allow for this type of cropping).
My code is below. I would prefer to perform both operations within one method, but Im not sure how so I just break it down into two steps.
Matrix matrix = new Matrix();
matrix.postRotate((float) (360 - sector.getShip().getHeading()));
Bitmap bMap = BitmapFactory.decodeResource(image.getContext().getResources(), getShip().getGridSymbol());
bMap = Bitmap.createBitmap(bMap, 0, 0, 25, 25, matrix, true);
int x = (bMap.getWidth() - 25) / 2;
int y = (bMap.getHeight() - 25) / 2;
image.setImageBitmap(Bitmap.createBitmap(bMap, x, y, 25, 25));
Try adding
android:scaleType="centerCrop"
to each ImageView item in your xml layout.
The final solution has to leverage the "getMeasuredHeight()" of the image. I didnt have to use the getMeasuredWidth() because for my particular layout the height is the limiting factor.
Here is the final bitmap code that works:
private Bitmap getRotatedShipBitmap(SectorGridImageView image,
Bitmap bitmap, Matrix matrix) {
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
int yHeight = (image.getMeasuredHeight() == 0) ? bitmap.getHeight()
: image.getMeasuredHeight();
int xWidth = yHeight;
int x = (bitmap.getWidth() - xWidth) / 2;
int y = (bitmap.getHeight() - yHeight) / 2;
return Bitmap.createBitmap(bitmap, x, y, xWidth, yHeight);
}