1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.ide.eclipse.adt.internal.editors.layout.gle2; 17 18 import com.android.ide.common.api.Rect; 19 20 import org.eclipse.swt.graphics.RGB; 21 import org.eclipse.swt.graphics.Rectangle; 22 23 import java.awt.Color; 24 import java.awt.Graphics; 25 import java.awt.Graphics2D; 26 import java.awt.image.BufferedImage; 27 import java.util.Arrays; 28 import java.util.Collections; 29 import java.util.List; 30 31 import junit.framework.TestCase; 32 33 @SuppressWarnings("javadoc") 34 public class ImageUtilsTest extends TestCase { 35 public void testCropBlank() throws Exception { 36 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 37 Graphics g = image.getGraphics(); 38 g.setColor(new Color(0, true)); 39 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 40 g.dispose(); 41 42 BufferedImage crop = ImageUtils.cropBlank(image, null); 43 assertNull(crop); 44 } 45 46 public void testCropBlankPre() throws Exception { 47 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 48 Graphics g = image.getGraphics(); 49 g.setColor(new Color(0, true)); 50 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 51 g.dispose(); 52 53 BufferedImage crop = ImageUtils.cropBlank(image, new Rect(5, 5, 80, 80)); 54 assertNull(crop); 55 } 56 57 public void testCropNonblank() throws Exception { 58 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 59 Graphics g = image.getGraphics(); 60 g.setColor(new Color(0, false)); 61 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 62 g.dispose(); 63 64 BufferedImage crop = ImageUtils.cropBlank(image, null); 65 assertNotNull(crop); 66 assertEquals(image.getWidth(), crop.getWidth()); 67 assertEquals(image.getHeight(), crop.getHeight()); 68 } 69 70 public void testCropSomething() throws Exception { 71 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 72 Graphics g = image.getGraphics(); 73 g.setColor(new Color(0, true)); 74 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 75 g.setColor(new Color(0xFF00FF00, true)); 76 g.fillRect(25, 25, 50, 50); 77 g.dispose(); 78 79 BufferedImage crop = ImageUtils.cropBlank(image, null); 80 assertNotNull(crop); 81 assertEquals(50, crop.getWidth()); 82 assertEquals(50, crop.getHeight()); 83 assertEquals(0xFF00FF00, crop.getRGB(0, 0)); 84 assertEquals(0xFF00FF00, crop.getRGB(49, 49)); 85 } 86 87 public void testCropSomethingPre() throws Exception { 88 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 89 Graphics g = image.getGraphics(); 90 g.setColor(new Color(0, true)); 91 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 92 g.setColor(new Color(0xFF00FF00, true)); 93 g.fillRect(25, 25, 50, 50); 94 g.dispose(); 95 96 BufferedImage crop = ImageUtils.cropBlank(image, new Rect(0, 0, 100, 100)); 97 assertNotNull(crop); 98 assertEquals(50, crop.getWidth()); 99 assertEquals(50, crop.getHeight()); 100 assertEquals(0xFF00FF00, crop.getRGB(0, 0)); 101 assertEquals(0xFF00FF00, crop.getRGB(49, 49)); 102 } 103 104 public void testCropSomethingPre2() throws Exception { 105 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 106 Graphics g = image.getGraphics(); 107 g.setColor(new Color(0, true)); 108 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 109 g.setColor(new Color(0xFF00FF00, true)); 110 g.fillRect(25, 25, 50, 50); 111 g.dispose(); 112 113 BufferedImage crop = ImageUtils.cropBlank(image, new Rect(5, 5, 80, 80)); 114 assertNotNull(crop); 115 assertEquals(50, crop.getWidth()); 116 assertEquals(50, crop.getHeight()); 117 assertEquals(0xFF00FF00, crop.getRGB(0, 0)); 118 assertEquals(0xFF00FF00, crop.getRGB(49, 49)); 119 } 120 121 public void testCropColor() throws Exception { 122 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 123 Graphics g = image.getGraphics(); 124 g.setColor(new Color(0xFF00FF00, true)); 125 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 126 g.dispose(); 127 128 BufferedImage crop = ImageUtils.cropColor(image, 0xFF00FF00, null); 129 assertNull(crop); 130 } 131 132 public void testCropNonColor() throws Exception { 133 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 134 Graphics g = image.getGraphics(); 135 g.setColor(new Color(0xFF00FF00, true)); 136 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 137 g.dispose(); 138 139 BufferedImage crop = ImageUtils.cropColor(image, 0xFFFF0000, null); 140 assertNotNull(crop); 141 assertEquals(image.getWidth(), crop.getWidth()); 142 assertEquals(image.getHeight(), crop.getHeight()); 143 } 144 145 public void testCropColorSomething() throws Exception { 146 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 147 Graphics g = image.getGraphics(); 148 g.setColor(new Color(0xFF00FF00, true)); 149 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 150 g.setColor(new Color(0xFFFF0000, true)); 151 g.fillRect(25, 25, 50, 50); 152 g.dispose(); 153 154 BufferedImage crop = ImageUtils.cropColor(image, 0xFF00FF00, null); 155 assertEquals(50, crop.getWidth()); 156 assertEquals(50, crop.getHeight()); 157 assertEquals(0xFFFF0000, crop.getRGB(0, 0)); 158 assertEquals(0xFFFF0000, crop.getRGB(49, 49)); 159 } 160 161 public void testNothingTodo() throws Exception { 162 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 163 Graphics g = image.getGraphics(); 164 g.setColor(new Color(0xFF00FF00, true)); 165 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 166 g.dispose(); 167 168 BufferedImage crop = ImageUtils.cropColor(image, 0xFFFF0000, new Rect(40, 40, 0, 0)); 169 assertNull(crop); 170 } 171 172 public void testContainsDarkPixels() throws Exception { 173 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 174 Graphics g = image.getGraphics(); 175 g.setColor(new Color(0, true)); 176 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 177 g.dispose(); 178 179 assertFalse(ImageUtils.containsDarkPixels(image)); 180 181 image.setRGB(50, 50, 0xFFFFFFFF); 182 assertFalse(ImageUtils.containsDarkPixels(image)); 183 image.setRGB(50, 50, 0xFFAAAAAA); 184 assertFalse(ImageUtils.containsDarkPixels(image)); 185 image.setRGB(50, 50, 0xFF00FF00); 186 assertFalse(ImageUtils.containsDarkPixels(image)); 187 image.setRGB(50, 50, 0xFFFF8800); 188 assertFalse(ImageUtils.containsDarkPixels(image)); 189 image.setRGB(50, 50, 0xFF333333); 190 assertTrue(ImageUtils.containsDarkPixels(image)); 191 192 } 193 194 public void testGetBoundingRectangle() { 195 assertEquals(null, ImageUtils.getBoundingRectangle(Collections.<Rectangle> emptyList())); 196 197 assertEquals(new Rectangle(1, 2, 3, 4), ImageUtils.getBoundingRectangle(Arrays 198 .asList(new Rectangle(1, 2, 3, 4)))); 199 assertEquals(new Rectangle(1, 2, 3, 4), ImageUtils.getBoundingRectangle(Arrays 200 .asList(new Rectangle(1, 2, 3, 4), new Rectangle(1, 2, 1, 1)))); 201 assertEquals(new Rectangle(5, 5, 25, 25), ImageUtils.getBoundingRectangle(Arrays.asList( 202 new Rectangle(10, 10, 20, 20), new Rectangle(5, 5, 1, 1)))); 203 } 204 205 /** 206 * Paints a set of {@link Rectangle} object out of a rendered {@link BufferedImage} 207 * such that the resulting image is transparent except for a minimum bounding 208 * rectangle of the selected elements. 209 * 210 * @param image the source image 211 * @param rectangles the set of rectangles to copy 212 * @param boundingBox the bounding rectangle of the set of rectangles to copy, can be 213 * computed by {@link ImageUtils#getBoundingRectangle} 214 * @param scale a scale factor to apply to the result, e.g. 0.5 to shrink the 215 * destination down 50%, 1.0 to leave it alone and 2.0 to zoom in by 216 * doubling the image size 217 * @return a rendered image, or null 218 */ 219 public static BufferedImage drawRectangles(BufferedImage image, 220 List<Rectangle> rectangles, Rectangle boundingBox, double scale) { 221 222 // This code is not a test. When I implemented image cropping, I first implemented 223 // it for BufferedImages (since it's easier; easy image painting, easy scaling, 224 // easy transparency handling, etc). However, this meant that we would need to 225 // convert the SWT images from the ImageOverlay to BufferedImages, crop and convert 226 // back; not ideal, so I rewrote it in SWT (see SwtUtils). However, I 227 // don't want to throw away the code in case we start keeping BufferedImages rather 228 // than SWT images or need it for other purposes, but rather than place it in the 229 // production codebase I'm leaving this utility here in the associated ImageUtils 230 // test class. It was used like this: 231 // @formatter:off 232 // 233 // BufferedImage wholeImage = SwtUtils.convertToAwt(image); 234 // BufferedImage result = ImageUtils.cropSelection(wholeImage, 235 // rectangles, boundingBox, scale); 236 // e.image = SwtUtils.convertToSwt(image.getDevice(), result, true, 237 // DRAG_TRANSPARENCY); 238 // 239 // @formatter:on 240 241 if (boundingBox == null) { 242 return null; 243 } 244 245 int destWidth = (int) (scale * boundingBox.width); 246 int destHeight = (int) (scale * boundingBox.height); 247 BufferedImage dest = new BufferedImage(destWidth, destHeight, image.getType()); 248 249 Graphics2D g = dest.createGraphics(); 250 251 for (Rectangle bounds : rectangles) { 252 int dx1 = bounds.x - boundingBox.x; 253 int dy1 = bounds.y - boundingBox.y; 254 int dx2 = dx1 + bounds.width; 255 int dy2 = dy1 + bounds.height; 256 257 dx1 *= scale; 258 dy1 *= scale; 259 dx2 *= scale; 260 dy2 *= scale; 261 262 int sx1 = bounds.x; 263 int sy1 = bounds.y; 264 int sx2 = sx1 + bounds.width; 265 int sy2 = sy1 + bounds.height; 266 267 g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null); 268 } 269 270 g.dispose(); 271 272 return dest; 273 } 274 275 public void testSubImage() throws Exception { 276 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 277 Graphics g = image.getGraphics(); 278 g.setColor(new Color(0xFF00FF00, true)); 279 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 280 g.setColor(new Color(0xFFFF0000, true)); 281 g.fillRect(25, 25, 50, 50); 282 g.dispose(); 283 284 BufferedImage sub = ImageUtils.subImage(image, 25, 25, 35, 45); 285 assertEquals(10, sub.getWidth()); 286 assertEquals(20, sub.getHeight()); 287 assertEquals(0xFFFF0000, sub.getRGB(0, 0)); 288 assertEquals(0xFFFF0000, sub.getRGB(9, 9)); 289 290 sub = ImageUtils.subImage(image, 23, 23, 23 + 5, 23 + 5); 291 assertEquals(5, sub.getWidth()); 292 assertEquals(5, sub.getHeight()); 293 assertEquals(0xFF00FF00, sub.getRGB(0, 0)); 294 assertEquals(0xFFFF0000, sub.getRGB(4, 4)); 295 } 296 297 public void testGetColor() throws Exception { 298 assertEquals(0xFF000000, ImageUtils.getColor("#000")); 299 assertEquals(0xFF000000, ImageUtils.getColor("#000000")); 300 assertEquals(0xABCDEF91, ImageUtils.getColor("#ABCDEF91")); 301 } 302 303 public void testGetBrightness() throws Exception { 304 assertEquals(96, ImageUtils.getBrightness(0x456789)); 305 assertEquals(198, ImageUtils.getBrightness(0xABCDEF)); 306 307 assertEquals(0, ImageUtils.getBrightness(0x0)); 308 assertEquals(255, ImageUtils.getBrightness(0xFFFFFF)); 309 assertEquals(299*255/1000, ImageUtils.getBrightness(0xFF0000)); 310 assertEquals(587*255/1000, ImageUtils.getBrightness(0x00FF00)); 311 assertEquals(114*255/1000, ImageUtils.getBrightness(0x0000FF)); 312 } 313 314 public void testColorConversion() throws Exception { 315 assertEquals(0, ImageUtils.rgbToInt(ImageUtils.intToRgb(0), 0)); 316 assertEquals(0xFFFFFFFF, ImageUtils.rgbToInt(ImageUtils.intToRgb(0xFFFFFF), 0xFF)); 317 assertEquals(0x12345678, ImageUtils.rgbToInt(ImageUtils.intToRgb(0x345678), 0x12)); 318 } 319 320 public void testScaleImage() throws Exception { 321 BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB_PRE); 322 Graphics g = image.getGraphics(); 323 g.setColor(new Color(0xFF00FF00, true)); 324 g.fillRect(0, 0, image.getWidth(), image.getHeight()); 325 g.setColor(new Color(0xFFFF0000, true)); 326 g.fillRect(25, 25, 50, 50); 327 g.dispose(); 328 329 BufferedImage scaled = ImageUtils.scale(image, 0.5, 0.5); 330 assertEquals(50, scaled.getWidth()); 331 assertEquals(50, scaled.getHeight()); 332 assertEquals(0xFF00FF00, scaled.getRGB(0, 0)); 333 assertEquals(0xFF00FF00, scaled.getRGB(49, 49)); 334 assertEquals(0xFFFF0000, scaled.getRGB(25, 25)); 335 336 scaled = ImageUtils.scale(image, 2.0, 2.0); 337 assertEquals(200, scaled.getWidth()); 338 assertEquals(200, scaled.getHeight()); 339 assertEquals(0xFF00FF00, scaled.getRGB(0, 0)); 340 assertEquals(0xFF00FF00, scaled.getRGB(48, 48)); 341 assertEquals(0xFFFF0000, scaled.getRGB(100, 100)); 342 assertEquals(0xFF00FF00, scaled.getRGB(199, 199)); 343 344 scaled = ImageUtils.scale(image, 0.25, 0.25); 345 assertEquals(25, scaled.getWidth()); 346 assertEquals(25, scaled.getHeight()); 347 assertEquals(0xFF00FF00, scaled.getRGB(0, 0)); 348 assertEquals(0xFF00FF00, scaled.getRGB(24, 24)); 349 assertEquals(0xFFFF0000, scaled.getRGB(13, 13)); 350 351 scaled = ImageUtils.scale(image, 0.25, 0.25, 75, 95); 352 assertEquals(100, scaled.getWidth()); 353 assertEquals(120, scaled.getHeight()); 354 assertEquals(0xFF00FF00, scaled.getRGB(0, 0)); 355 assertEquals(0xFF00FF00, scaled.getRGB(24, 24)); 356 assertEquals(0xFFFF0000, scaled.getRGB(13, 13)); 357 358 } 359 360 public void testCreateColoredImage() throws Exception { 361 BufferedImage image = ImageUtils.createColoredImage(120, 110, new RGB(0xFE, 0xFD, 0xFC)); 362 assertEquals(120, image.getWidth()); 363 assertEquals(110, image.getHeight()); 364 assertEquals(0xFFFEFDFC, image.getRGB(0, 0)); 365 assertEquals(0xFFFEFDFC, image.getRGB(50, 50)); 366 assertEquals(0xFFFEFDFC, image.getRGB(119, 109)); 367 } 368 } 369