Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/viewers/projections/Equirectangular.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/viewers/projections/Equirectangular.java	(revision 18396)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/viewers/projections/Equirectangular.java	(revision 18398)
@@ -41,5 +41,5 @@
             currentOffscreenImage = this.offscreenImage;
         }
-        currentCameraPlane.mapping(image, currentOffscreenImage);
+        currentCameraPlane.mapping(image, currentOffscreenImage, visibleRect);
         if (target == null) {
             target = new Rectangle(0, 0, currentOffscreenImage.getWidth(null), currentOffscreenImage.getHeight(null));
Index: trunk/src/org/openstreetmap/josm/gui/util/imagery/CameraPlane.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/util/imagery/CameraPlane.java	(revision 18396)
+++ trunk/src/org/openstreetmap/josm/gui/util/imagery/CameraPlane.java	(revision 18398)
@@ -3,7 +3,9 @@
 
 import java.awt.Point;
+import java.awt.Rectangle;
 import java.awt.geom.Point2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
 import java.awt.image.DataBufferDouble;
 import java.awt.image.DataBufferInt;
@@ -250,13 +252,98 @@
     }
 
-    public void mapping(BufferedImage sourceImage, BufferedImage targetImage) {
+    /** Maps a panoramic view of sourceImage into targetImage based on current configuration of Camera Plane
+     * @param sourceImage The image to paint
+     * @param targetImage The target image
+     * @param visibleRect The part of target image which will be visible
+     */
+    public void mapping(BufferedImage sourceImage, BufferedImage targetImage, Rectangle visibleRect) {
         DataBuffer sourceBuffer = sourceImage.getRaster().getDataBuffer();
         DataBuffer targetBuffer = targetImage.getRaster().getDataBuffer();
         // Faster mapping
-        if (sourceBuffer.getDataType() == DataBuffer.TYPE_INT && targetBuffer.getDataType() == DataBuffer.TYPE_INT) {
+        if (sourceBuffer.getDataType() == DataBuffer.TYPE_BYTE && targetBuffer.getDataType() == DataBuffer.TYPE_BYTE) {
+            byte[] sourceImageBuffer = ((DataBufferByte) sourceImage.getRaster().getDataBuffer()).getData();
+            byte[] targetImageBuffer = ((DataBufferByte) targetImage.getRaster().getDataBuffer()).getData();
+            final boolean sourceHasAlphaChannel = sourceImage.getAlphaRaster() != null;
+            final boolean targetHasAlphaChannel = targetImage.getAlphaRaster() != null;
+            if (sourceHasAlphaChannel && targetHasAlphaChannel) {
+                final int pixelLength = 4;
+                IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                        .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).forEach(x -> {
+                            final Point2D.Double p = mapPoint(x, y);
+                            int tx = ((int) (p.x * (sourceImage.getWidth() - 1)));
+                            int ty = ((int) (p.y * (sourceImage.getHeight() - 1)));
+                            int sourceOffset = (ty * sourceImage.getWidth() + tx) * pixelLength;
+                            int targetOffset = (y * targetImage.getWidth() + x) * pixelLength;
+                            byte a = sourceImageBuffer[sourceOffset];
+                            byte b = sourceImageBuffer[sourceOffset + 1];
+                            byte g = sourceImageBuffer[sourceOffset + 2];
+                            byte r = sourceImageBuffer[sourceOffset + 3];
+                            targetImageBuffer[targetOffset] = a;
+                            targetImageBuffer[targetOffset + 1] = b;
+                            targetImageBuffer[targetOffset + 2] = g;
+                            targetImageBuffer[targetOffset + 3] = r;
+                        }));
+            } else if (sourceHasAlphaChannel) {
+                final int sourcePixelLength = 4;
+                final int targetPixelLength = 3;
+                IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                        .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).forEach(x -> {
+                            final Point2D.Double p = mapPoint(x, y);
+                            int tx = ((int) (p.x * (sourceImage.getWidth() - 1)));
+                            int ty = ((int) (p.y * (sourceImage.getHeight() - 1)));
+                            int sourceOffset = (ty * sourceImage.getWidth() + tx) * sourcePixelLength;
+                            int targetOffset = (y * targetImage.getWidth() + x) * targetPixelLength;
+                            //byte a = sourceImageBuffer[sourceOffset];
+                            byte b = sourceImageBuffer[sourceOffset + 1];
+                            byte g = sourceImageBuffer[sourceOffset + 2];
+                            byte r = sourceImageBuffer[sourceOffset + 3];
+                            targetImageBuffer[targetOffset] = b;
+                            targetImageBuffer[targetOffset + 1] = g;
+                            targetImageBuffer[targetOffset + 2] = r;
+
+                        }));
+            } else if (targetHasAlphaChannel) {
+                final int sourcePixelLength = 3;
+                final int targetPixelLength = 4;
+                IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                        .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).forEach(x -> {
+                            final Point2D.Double p = mapPoint(x, y);
+                            int tx = ((int) (p.x * (sourceImage.getWidth() - 1)));
+                            int ty = ((int) (p.y * (sourceImage.getHeight() - 1)));
+                            int sourceOffset = (ty * sourceImage.getWidth() + tx) * sourcePixelLength;
+                            int targetOffset = (y * targetImage.getWidth() + x) * targetPixelLength;
+                            byte a = (byte) 255;
+                            byte b = sourceImageBuffer[sourceOffset];
+                            byte g = sourceImageBuffer[sourceOffset + 1];
+                            byte r = sourceImageBuffer[sourceOffset + 2];
+                            targetImageBuffer[targetOffset] = a;
+                            targetImageBuffer[targetOffset + 1] = b;
+                            targetImageBuffer[targetOffset + 2] = g;
+                            targetImageBuffer[targetOffset + 3] = r;
+
+                        }));
+            } else {
+                final int pixelLength = 3;
+                IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                        .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).forEach(x -> {
+                            final Point2D.Double p = mapPoint(x, y);
+                            int tx = ((int) (p.x * (sourceImage.getWidth() - 1)));
+                            int ty = ((int) (p.y * (sourceImage.getHeight() - 1)));
+                            int sourceOffset = (ty * sourceImage.getWidth() + tx) * pixelLength;
+                            int targetOffset = (y * targetImage.getWidth() + x) * pixelLength;
+                            byte b = sourceImageBuffer[sourceOffset];
+                            byte g = sourceImageBuffer[sourceOffset + 1];
+                            byte r = sourceImageBuffer[sourceOffset + 2];
+                            targetImageBuffer[targetOffset] = b;
+                            targetImageBuffer[targetOffset + 1] = g;
+                            targetImageBuffer[targetOffset + 2] = r;
+                        }));
+            }
+        } else if (sourceBuffer.getDataType() == DataBuffer.TYPE_INT
+                && targetBuffer.getDataType() == DataBuffer.TYPE_INT) {
             int[] sourceImageBuffer = ((DataBufferInt) sourceImage.getRaster().getDataBuffer()).getData();
             int[] targetImageBuffer = ((DataBufferInt) targetImage.getRaster().getDataBuffer()).getData();
-            IntStream.range(0, targetImage.getHeight()).parallel()
-                    .forEach(y -> IntStream.range(0, targetImage.getWidth()).forEach(x -> {
+            IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                    .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).forEach(x -> {
                         final Point2D.Double p = mapPoint(x, y);
                         int tx = (int) (p.x * (sourceImage.getWidth() - 1));
@@ -268,6 +355,6 @@
             double[] sourceImageBuffer = ((DataBufferDouble) sourceImage.getRaster().getDataBuffer()).getData();
             double[] targetImageBuffer = ((DataBufferDouble) targetImage.getRaster().getDataBuffer()).getData();
-            IntStream.range(0, targetImage.getHeight()).parallel()
-                    .forEach(y -> IntStream.range(0, targetImage.getWidth()).forEach(x -> {
+            IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                    .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).forEach(x -> {
                         final Point2D.Double p = mapPoint(x, y);
                         int tx = (int) (p.x * (sourceImage.getWidth() - 1));
@@ -277,6 +364,6 @@
                     }));
         } else {
-            IntStream.range(0, targetImage.getHeight()).parallel()
-                .forEach(y -> IntStream.range(0, targetImage.getWidth()).parallel().forEach(x -> {
+            IntStream.range(visibleRect.y, visibleRect.y + visibleRect.height).parallel()
+                .forEach(y -> IntStream.range(visibleRect.x, visibleRect.x + visibleRect.width).parallel().forEach(x -> {
                     final Point2D.Double p = mapPoint(x, y);
                     targetImage.setRGB(x, y, sourceImage.getRGB((int) (p.x * (sourceImage.getWidth() - 1)),
