Index: AndroidManifest.xml
===================================================================
--- AndroidManifest.xml	(revision 9)
+++ AndroidManifest.xml	(working copy)
@@ -21,6 +21,7 @@
 	android:installLocation="internalOnly">
 
 	<application android:icon="@drawable/app_icon"
+		android:largeHeap="true"
 		android:label="@string/app_name">
 
 		<service android:name=".WallpaperSlideshow"
Index: src/com/birbeck/wallpaperslideshow/BitmapUtil.java
===================================================================
--- src/com/birbeck/wallpaperslideshow/BitmapUtil.java	(revision 9)
+++ src/com/birbeck/wallpaperslideshow/BitmapUtil.java	(working copy)
@@ -105,7 +105,7 @@
         double h = options.outHeight;
 
         int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
-                (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
+                (int) Math.floor(Math.sqrt(w * h / maxNumOfPixels));
         int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
                 (int) Math.min(Math.floor(w / minSideLength),
                 Math.floor(h / minSideLength));
@@ -130,60 +130,51 @@
                                    int targetWidth,
                                    int targetHeight,
                                    boolean scaleUp,
+                                   boolean crop,
                                    boolean recycle) {
-        int deltaX = source.getWidth() - targetWidth;
-        int deltaY = source.getHeight() - targetHeight;
-        if (!scaleUp && (deltaX < 0 || deltaY < 0)) {
+        if (!scaleUp && (source.getWidth() < targetWidth ||
+                         source.getHeight() < targetHeight)) {
             /*
              * In this case the bitmap is smaller, at least in one dimension,
              * than the target.  Transform it by placing as much of the image
              * as possible into the target and leaving the top/bottom or
              * left/right (or both) black.
              */
-            Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight,
-                    Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(b2);
-
-            int deltaXHalf = Math.max(0, deltaX / 2);
-            int deltaYHalf = Math.max(0, deltaY / 2);
-            Rect src = new Rect(
-                    deltaXHalf,
-                    deltaYHalf,
-                    deltaXHalf + Math.min(targetWidth, source.getWidth()),
-                    deltaYHalf + Math.min(targetHeight, source.getHeight()));
-            int dstX = (targetWidth  - src.width())  / 2;
-            int dstY = (targetHeight - src.height()) / 2;
-            Rect dst = new Rect(
-                    dstX,
-                    dstY,
-                    targetWidth - dstX,
-                    targetHeight - dstY);
-            c.drawBitmap(source, src, dst, null);
+            Bitmap b2 = drawBitmapInBlackRectangle(targetWidth,
+                                                   targetHeight, 
+                                                   source);
             if (recycle) {
                 source.recycle();
             }
             return b2;
         }
+
         float bitmapWidthF = source.getWidth();
         float bitmapHeightF = source.getHeight();
 
         float bitmapAspect = bitmapWidthF / bitmapHeightF;
         float viewAspect   = (float) targetWidth / targetHeight;
 
-        if (bitmapAspect > viewAspect) {
-            float scale = targetHeight / bitmapHeightF;
-            if (scale < .9F || scale > 1F) {
-                scaler.setScale(scale, scale);
+        if (crop) {
+            if (bitmapAspect > viewAspect) {
+                float scale = targetHeight / bitmapHeightF;
+                if (scale < .9F || scale > 1F) {
+                    scaler.setScale(scale, scale);
+                } else {
+                    scaler = null;
+                }
             } else {
-                scaler = null;
+                float scale = targetWidth / bitmapWidthF;
+                if (scale < .9F || scale > 1F) {
+                    scaler.setScale(scale, scale);
+                } else {
+                    scaler = null;
+                }
             }
         } else {
-            float scale = targetWidth / bitmapWidthF;
-            if (scale < .9F || scale > 1F) {
-                scaler.setScale(scale, scale);
-            } else {
-                scaler = null;
-            }
+            float scale = (bitmapAspect > viewAspect) ?
+                targetWidth / bitmapWidthF : targetHeight / bitmapHeightF;
+            scaler.setScale(scale, scale);
         }
 
         Bitmap b1;
@@ -199,16 +190,21 @@
             source.recycle();
         }
 
-        int dx1 = Math.max(0, b1.getWidth() - targetWidth);
-        int dy1 = Math.max(0, b1.getHeight() - targetHeight);
+        Bitmap b2;
+        if (crop) {
+            int dx1 = Math.max(0, b1.getWidth() - targetWidth);
+            int dy1 = Math.max(0, b1.getHeight() - targetHeight);
+            b2 = Bitmap.createBitmap(b1,
+                                     dx1 / 2,
+                                     dy1 / 2,
+                                     targetWidth,
+                                     targetHeight);
+        } else {
+            b2 = drawBitmapInBlackRectangle(targetWidth,
+                                            targetHeight, 
+                                            b1);
+        }
 
-        Bitmap b2 = Bitmap.createBitmap(
-                b1,
-                dx1 / 2,
-                dy1 / 2,
-                targetWidth,
-                targetHeight);
-
         if (b2 != b1) {
             if (recycle || b1 != source) {
                 b1.recycle();
@@ -218,6 +214,32 @@
         return b2;
     }
 
+    private static Bitmap drawBitmapInBlackRectangle(int targetWidth,
+                                                     int targetHeight, 
+                                                     Bitmap bitmap) {
+        Bitmap res = Bitmap.createBitmap(targetWidth, targetHeight,
+                                         Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(res);
+
+        int deltaX = bitmap.getWidth() - targetWidth;
+        int deltaY = bitmap.getHeight() - targetHeight;
+        int deltaXHalf = Math.max(0, deltaX / 2);
+        int deltaYHalf = Math.max(0, deltaY / 2);
+        Rect src = new Rect(deltaXHalf,
+                        deltaYHalf,
+                        deltaXHalf + Math.min(targetWidth, bitmap.getWidth()),
+                        deltaYHalf + Math.min(targetHeight, bitmap.getHeight()));
+        int dstX = (targetWidth  - src.width())  / 2;
+        int dstY = (targetHeight - src.height()) / 2;
+        Rect dst = new Rect(
+                        dstX,
+                        dstY,
+                        targetWidth - dstX,
+                        targetHeight - dstY);
+        c.drawBitmap(bitmap, src, dst, null);
+        return res;
+    }
+
     /**
      * Make a bitmap from a given Uri.
      *
@@ -235,8 +257,9 @@
                 return null;
             }
             
-            options.inSampleSize = computeSampleSize(
-                    options, minSideLength, maxNumOfPixels);
+            options.inSampleSize = computeSampleSize(options,
+                                                     minSideLength,
+                                                     maxNumOfPixels);
             options.inJustDecodeBounds = false;
             //options.inDither = false;
             //options.inPreferredConfig = Bitmap.Config.ARGB_8888;
@@ -285,4 +308,4 @@
         }
     }
     
-}
\ No newline at end of file
+}
Index: src/com/birbeck/wallpaperslideshow/WallpaperSlideshow.java
===================================================================
--- src/com/birbeck/wallpaperslideshow/WallpaperSlideshow.java	(revision 9)
+++ src/com/birbeck/wallpaperslideshow/WallpaperSlideshow.java	(working copy)
@@ -92,6 +92,7 @@
         private String mFolder = null;
         private int mDuration = 0;
         private boolean mRandom = false;
+        private boolean mCrop = false;
         private boolean mRotate = false;
         private boolean mScroll = false;
         private boolean mRecurse = false;
@@ -255,6 +256,9 @@
     			mRandom = sharedPreferences.getBoolean(
     					res.getString(R.string.preferences_random_key),
     					Boolean.valueOf(res.getString(R.string.preferences_random_default)));
+    			mCrop = sharedPreferences.getBoolean(
+    					res.getString(R.string.preferences_crop_key),
+    					Boolean.valueOf(res.getString(R.string.preferences_crop_default)));
     			mRotate = sharedPreferences.getBoolean(
     					res.getString(R.string.preferences_rotate_key), 
     					Boolean.valueOf(res.getString(R.string.preferences_rotate_default)));
@@ -282,6 +286,9 @@
     		} else if (key.equals(res.getString(R.string.preferences_random_key))) {
     			mRandom = sharedPreferences.getBoolean(key,
     					Boolean.valueOf(res.getString(R.string.preferences_random_default)));
+    		} else if (key.equals(res.getString(R.string.preferences_crop_key))) {
+    			mCrop = sharedPreferences.getBoolean(key,
+    					Boolean.valueOf(res.getString(R.string.preferences_crop_default)));
     		} else if (key.equals(res.getString(R.string.preferences_rotate_key))) {
     			mRotate = sharedPreferences.getBoolean(key,
     					Boolean.valueOf(res.getString(R.string.preferences_rotate_default)));
@@ -408,8 +415,8 @@
         	int targetWidth = (mScroll)? mMinWidth: mWidth;
         	int targetHeight = (mScroll)? mMinHeight: mHeight;
 
-	        Bitmap bitmap = BitmapUtil.makeBitmap(Math.max(mMinWidth, mMinHeight),
-	        			mMinWidth * mMinHeight, file, null);
+	        Bitmap bitmap = BitmapUtil.makeBitmap(Math.max(mWidth, mHeight),
+	        			mWidth * mHeight, file, null);
 
         	if (bitmap == null) {
         		return Bitmap.createBitmap(targetWidth, targetHeight,
@@ -435,7 +442,7 @@
         	// Scale bitmap
 			if (width != targetWidth || height != targetHeight) {
         		bitmap = BitmapUtil.transform(mScaler, bitmap,
-        				targetWidth, targetHeight, true, true);
+        				targetWidth, targetHeight, true, mCrop, true);
         	}
 
         	return bitmap;
@@ -469,4 +476,4 @@
 		private static final long serialVersionUID = 1L;
 	}
 
-}
\ No newline at end of file
+}
Index: res/values/preferences.xml
===================================================================
--- res/values/preferences.xml	(revision 9)
+++ res/values/preferences.xml	(working copy)
@@ -59,6 +59,11 @@
 	<string name="preferences_random_summary">Display photos in random order instead of sequentially</string>
     <string name="preferences_random_default">false</string>
 
+    <string name="preferences_crop_key">crop</string>
+    <string name="preferences_crop_title">Crop</string>
+	<string name="preferences_crop_summary">Crop photos to make them fill whole screen</string>
+    <string name="preferences_crop_default">true</string>
+
     <string name="preferences_rotate_key">rotate</string>
     <string name="preferences_rotate_title">Do not rotate</string>
 	<string name="preferences_rotate_summary">Keep original screen orientation of photos</string>
Index: res/xml/preferences.xml
===================================================================
--- res/xml/preferences.xml	(revision 9)
+++ res/xml/preferences.xml	(working copy)
@@ -47,6 +47,12 @@
 		android:summary="@string/preferences_random_summary"
 		android:defaultValue="@string/preferences_random_default" />
 
+	<CheckBoxPreference android:id="@+id/prefs_crop"
+		android:key="@string/preferences_crop_key"
+		android:title="@string/preferences_crop_title"
+		android:summary="@string/preferences_crop_summary"
+		android:defaultValue="@string/preferences_crop_default" />
+
 	<CheckBoxPreference android:id="@+id/prefs_rotate"
 		android:key="@string/preferences_rotate_key"
 		android:title="@string/preferences_rotate_title"
@@ -72,4 +78,4 @@
 	<Preference android:key="@string/preferences_about_key"
 		android:title="@string/preferences_about_title" />
 
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
