001package net.gdface.image; 002 003import java.awt.Color; 004import java.awt.Graphics; 005import java.awt.Graphics2D; 006import java.awt.Image; 007import java.awt.Rectangle; 008import java.awt.Transparency; 009import java.awt.color.ColorSpace; 010import java.awt.image.BufferedImage; 011import java.awt.image.ColorConvertOp; 012import java.awt.image.ColorModel; 013import java.awt.image.ComponentColorModel; 014import java.awt.image.ComponentSampleModel; 015import java.awt.image.DataBuffer; 016import java.awt.image.DataBufferByte; 017import java.awt.image.Raster; 018import java.awt.image.RenderedImage; 019import java.awt.image.WritableRaster; 020import java.io.ByteArrayInputStream; 021import java.io.ByteArrayOutputStream; 022import java.io.IOException; 023import java.io.OutputStream; 024import java.util.Arrays; 025import java.util.Iterator; 026 027import javax.imageio.IIOException; 028import javax.imageio.IIOImage; 029import javax.imageio.ImageIO; 030import javax.imageio.ImageTypeSpecifier; 031import javax.imageio.ImageWriteParam; 032import javax.imageio.ImageWriter; 033import javax.imageio.stream.ImageOutputStream; 034 035import net.gdface.utils.Assert; 036 037/** 038 * 图åƒå·¥å…·ç±» 039 * @author guyadong 040 * 041 */ 042public class ImageUtil { 043 044 /** 045 * 对图åƒè¿›è¡Œç¼©æ”¾ 046 * @param source 原图 047 * @param targetWidth 缩放åŽå›¾åƒå®½åº¦ 048 * @param targetHeight 缩放åŽå›¾åƒé«˜åº¦ 049 * @param constrain 为trueæ—¶ç‰æ¯”例缩放,targetWidth,targetHeight为缩放图åƒçš„é™åˆ¶å°ºå¯¸ 050 * @return 051 */ 052 public static BufferedImage resize(BufferedImage source, int targetWidth, int targetHeight,boolean constrain) { 053 if(constrain){ 054 double aspectRatio = (double)source.getWidth()/source.getHeight(); 055 double sx = (double) targetWidth / source.getWidth(); 056 double sy = (double) targetHeight / source.getHeight(); 057 if (sx > sy) { 058 targetWidth = (int) Math.round(targetHeight*aspectRatio); 059 } else { 060 targetHeight = (int) Math.round(targetWidth/aspectRatio); 061 } 062 } 063 int type = source.getType(); 064 BufferedImage target = null; 065 if (type == BufferedImage.TYPE_CUSTOM) { 066 ColorModel cm = source.getColorModel(); 067 WritableRaster raster = cm.createCompatibleWritableRaster(targetWidth, targetHeight); 068 target = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); 069 } else { 070 target = new BufferedImage(targetWidth, targetHeight, type); 071 } 072 Graphics2D g = target.createGraphics(); 073 try{ 074 g.drawImage( 075 source.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH), 076 0, 0, null); 077 }finally{ 078 g.dispose(); 079 } 080 return target; 081 } 082 public static byte[] wirteJPEGBytes(BufferedImage source){ 083 return wirteJPEGBytes(source,null); 084 } 085 public static byte[] wirteBMPBytes(BufferedImage source){ 086 return wirteBytes(source,"BMP"); 087 } 088 public static byte[] wirtePNGBytes(BufferedImage source){ 089 return wirteBytes(source,"PNG"); 090 } 091 public static byte[] wirteGIFBytes(BufferedImage source){ 092 return wirteBytes(source,"GIF"); 093 } 094 /** 095 * 将原图压缩生æˆjpegæ ¼å¼çš„æ•°æ® 096 * @param source 097 * @return 098 * @see #wirteBytes(BufferedImage, String) 099 */ 100 public static byte[] wirteJPEGBytes(BufferedImage source,Float compressionQuality){ 101 return wirteBytes(source,"JPEG",compressionQuality); 102 } 103 public static byte[] wirteBytes(BufferedImage source,String formatName){ 104 return wirteBytes(source,formatName,null); 105 } 106 /** 107 * å°†{@link BufferedImage}生æˆformatNameæŒ‡å®šæ ¼å¼çš„å›¾åƒæ•°æ® 108 * @param source 109 * @param formatName å›¾åƒæ ¼å¼åï¼Œå›¾åƒæ ¼å¼å错误则抛出异常,å¯ç”¨çš„值 'BMP','PNG','GIF','JPEG' 110 * @param compressionQuality 压缩质é‡(0.0~1.0),超过æ¤èŒƒå›´æŠ›å‡ºå¼‚常,为null使用默认值 111 * @return 112 */ 113 public static byte[] wirteBytes(BufferedImage source,String formatName,Float compressionQuality){ 114 ByteArrayOutputStream output = new ByteArrayOutputStream(); 115 try { 116 wirte(source, formatName, compressionQuality, output); 117 } catch (IOException e) { 118 throw new RuntimeException(e); 119 } 120 return output.toByteArray(); 121 } 122 /** 123 * å°†{@link BufferedImage}生æˆformatNameæŒ‡å®šæ ¼å¼çš„å›¾åƒæ•°æ® 124 * @param source 125 * @param formatName å›¾åƒæ ¼å¼åï¼Œå›¾åƒæ ¼å¼å错误则抛出异常,å¯ç”¨çš„值 'BMP','PNG','GIF','JPEG' 126 * @param compressionQuality 压缩质é‡(0.0~1.0),超过æ¤èŒƒå›´æŠ›å‡ºå¼‚常,为null使用默认值 127 * @param output è¾“å‡ºæµ 128 * @throws IOException 129 */ 130 public static void wirte(BufferedImage source,String formatName,Float compressionQuality,OutputStream output) throws IOException{ 131 Assert.notNull(source, "source"); 132 Assert.notEmpty(formatName, "formatName"); 133 Assert.notNull(output, "output"); 134 135 Graphics2D g = null; 136 try { 137 // 对于æŸäº›æ ¼å¼çš„图åƒ(如png),直接调用ImageIO.write生æˆjpegå¯èƒ½ä¼šå¤±è´¥ 138 // 所以先å°è¯•直接调用ImageIO.write,如果失败则用Graphicsç”Ÿæˆæ–°çš„BufferedImageå†è°ƒç”¨ImageIO.write 139 for(BufferedImage s=source;!write(s, formatName, output,compressionQuality);){ 140 if(null!=g){ 141 throw new IllegalArgumentException(String.format("not found writer for '%s'",formatName)); 142 } 143 s = new BufferedImage(source.getWidth(), 144 source.getHeight(), BufferedImage.TYPE_INT_RGB); 145 g = s.createGraphics(); 146 g.drawImage(source, 0, 0,null); 147 } 148 } finally { 149 if (null != g){ 150 g.dispose(); 151 } 152 } 153 } 154 /** 155 * 对原图创建缩略图对象<br> 156 * 如果原图尺寸å°äºŽæŒ‡å®šçš„缩略图尺寸则直接返回原图对象的副本 157 * @param source 原图对象 158 * @param thumbnailWidth 缩略图宽度 159 * @param thumbnailHeight 缩略图高度 160 * @param ratioThreshold 最大宽高比阀值(宽高ä¸è¾ƒå¤§çš„值/较å°çš„值),<æ¤å€¼æ—¶å¯¹åŽŸå›¾ç‰æ¯”例缩放,>=æ¤å€¼æ—¶ä»ŽåŽŸå›¾åˆ‡å‡ºä¸é—´éƒ¨åˆ†å›¾åƒå†ç‰æ¯”例缩放 161 * @return 162 */ 163 public static BufferedImage createThumbnail(BufferedImage source,int thumbnailWidth,int thumbnailHeight,double ratioThreshold) { 164 int w = source.getWidth(); 165 int h = source.getHeight(); 166 if (w < thumbnailWidth && h < thumbnailHeight) { 167 // 返回原图的副本 168 return source.getSubimage(0, 0, w, h); 169 } 170 double thumAspectRatio = (double) thumbnailWidth / thumbnailHeight; 171 double wh_sca = w > h ? (double) w / h : (double) h / w; 172 if (wh_sca >= ratioThreshold) { 173 if (w > h) { 174 int fw = (int) (thumAspectRatio * h); 175 if (h <= thumbnailHeight) { 176 return source.getSubimage((w - fw) / 2, 0, fw, h); 177 } else { 178 return resize(source.getSubimage( (w - fw) / 2, 0, fw, h), thumbnailWidth, 179 thumbnailHeight,true); 180 } 181 } else { 182 int fh = (int) (thumAspectRatio * w); 183 if (w <= thumbnailWidth) { 184 return source.getSubimage( 0, (h - fh) / 2, w, fh); 185 } else { 186 return resize(source.getSubimage( 0, (h - fh) / 2, w, fh), thumbnailWidth, 187 thumbnailHeight,true); 188 } 189 } 190 } else { 191 return resize(source, thumbnailWidth, thumbnailHeight,true); 192 } 193 } 194 /** 195 * 对原图创建JPEGæ ¼å¼çš„缩略图 196 * @param imageBytes å›¾åƒæ•°æ®å—节数组 197 * @param thumbnailWidth 198 * @param thumbnailHeight 199 * @param ratioThreshold 200 * @return 返回jpegæ ¼å¼çš„å›¾åƒæ•°æ®å—节数组 201 * @see #createThumbnail(BufferedImage, int, int, double) 202 * @see #wirteJPEGBytes(BufferedImage) 203 */ 204 public static byte[] createJPEGThumbnail(byte[] imageBytes,int thumbnailWidth,int thumbnailHeight,double ratioThreshold) { 205 Assert.notEmpty(imageBytes, "imageBytes"); 206 try { 207 BufferedImage source = ImageIO.read(new ByteArrayInputStream(imageBytes)); 208 if(null==source){ 209 throw new IllegalArgumentException("unsupported image format"); 210 } 211 BufferedImage thumbnail = createThumbnail(source, thumbnailWidth, thumbnailHeight, ratioThreshold); 212 return wirteJPEGBytes(thumbnail); 213 } catch (IOException e) { 214 throw new RuntimeException(e); 215 } 216 } 217 218 /** 219 * @param image 220 * @param bandOffset 用于判æ–通é“é¡ºåº 221 * @return 222 */ 223 private static boolean equalBandOffsetWith3Byte(BufferedImage image,int[] bandOffset){ 224 if(image.getType()==BufferedImage.TYPE_3BYTE_BGR){ 225 if(image.getData().getSampleModel() instanceof ComponentSampleModel){ 226 ComponentSampleModel sampleModel = (ComponentSampleModel)image.getData().getSampleModel(); 227 if(Arrays.equals(sampleModel.getBandOffsets(), bandOffset)){ 228 return true; 229 } 230 } 231 } 232 return false; 233 } 234 public static boolean isBGRA(BufferedImage image){ 235 return image.getType()==BufferedImage.TYPE_4BYTE_ABGR 236 || image.getType()==BufferedImage.TYPE_4BYTE_ABGR_PRE; 237 } 238 public static boolean isGray(BufferedImage image){ 239 return image.getType()==BufferedImage.TYPE_BYTE_GRAY; 240 } 241 public static boolean isBGR3Byte(BufferedImage image){ 242 return equalBandOffsetWith3Byte(image,new int[]{0, 1, 2}); 243 } 244 245 public static boolean isRGB3Byte(BufferedImage image){ 246 return equalBandOffsetWith3Byte(image,new int[]{2, 1, 0}); 247 } 248 249 /** 250 * 对图åƒè§£ç 返回RGBæ ¼å¼çŸ©é˜µæ•°æ® 251 * @param image 252 * @return 253 */ 254 public static byte[] getMatrixRGB(BufferedImage image) { 255 if(null==image){ 256 throw new NullPointerException(); 257 } 258 byte[] matrixRGB; 259 if(isRGB3Byte(image)){ 260 matrixRGB= (byte[]) image.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 261 }else{ 262 // 转RGBæ ¼å¼ 263 BufferedImage rgbImage = new BufferedImage(image.getWidth(), image.getHeight(), 264 BufferedImage.TYPE_3BYTE_BGR); 265 new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null).filter(image, rgbImage); 266 matrixRGB= (byte[]) rgbImage.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 267 } 268 return matrixRGB; 269 } 270 /** 271 * 对图åƒè§£ç 返回RGBæ ¼å¼çŸ©é˜µæ•°æ® 272 * @param image 273 * @return 274 */ 275 public static byte[] getMatrixRGBA(BufferedImage image) { 276 if(null==image){ 277 throw new NullPointerException(); 278 } 279 byte[] matrixRGBA; 280 if(isBGRA(image)){ 281 matrixRGBA= (byte[]) image.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 282 }else{ 283 // 转RGBAæ ¼å¼ 284 BufferedImage rgbaImage = new BufferedImage(image.getWidth(), image.getHeight(), 285 BufferedImage.TYPE_4BYTE_ABGR); 286 new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null).filter(image, rgbaImage); 287 matrixRGBA= (byte[]) rgbaImage.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 288 } 289 return matrixRGBA; 290 } 291 292 /** 293 * 对图åƒè§£ç 返回BGRæ ¼å¼çŸ©é˜µæ•°æ® 294 * @param image 295 * @return 296 */ 297 public static byte[] getMatrixBGR(BufferedImage image){ 298 if(null==image){ 299 throw new NullPointerException(); 300 } 301 byte[] matrixBGR; 302 if(isBGR3Byte(image)){ 303 matrixBGR= (byte[]) image.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 304 }else{ 305 // ARGBæ ¼å¼å›¾åƒæ•°æ® 306 int intrgb[]=image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth()); 307 matrixBGR=new byte[image.getWidth() * image.getHeight()*3]; 308 // ARGB转BGRæ ¼å¼ 309 for(int i=0,j=0;i<intrgb.length;++i,j+=3){ 310 matrixBGR[j]=(byte) (intrgb[i]&0xff); 311 matrixBGR[j+1]=(byte) ((intrgb[i]>>8)&0xff); 312 matrixBGR[j+2]=(byte) ((intrgb[i]>>16)&0xff); 313 } 314 } 315 return matrixBGR; 316 } 317 /** 318 * 对图åƒè§£ç 返回BGRæ ¼å¼çŸ©é˜µæ•°æ® 319 * @param image 320 * @return 321 */ 322 public static byte[] getMatrixGRAY(BufferedImage image){ 323 if(null==image){ 324 throw new NullPointerException(); 325 } 326 byte[] matrixGray; 327 if(isGray(image)){ 328 matrixGray= (byte[]) image.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 329 }else{ 330 // 图åƒè½¬ç° 331 BufferedImage gray = new BufferedImage(image.getWidth(), image.getHeight(), 332 BufferedImage.TYPE_BYTE_GRAY); 333 new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(image, gray); 334 matrixGray= (byte[]) gray.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); 335 336 } 337 return matrixGray; 338 } 339 340 /** 341 * 从æº{@link BufferedImage}å¯¹è±¡åˆ›å»ºä¸€ä»½æ‹·è´ 342 * @param src 343 * @param imageType 创建的{@link BufferedImage}ç›®æ ‡å¯¹è±¡ç±»åž‹ 344 * @return 返回拷è´çš„对象 345 * @see BufferedImage#BufferedImage(int, int, int) 346 */ 347 public static BufferedImage copy(Image src,int imageType){ 348 if(null==src){ 349 throw new NullPointerException("src must not be null"); 350 } 351 BufferedImage dst = new BufferedImage(src.getWidth(null), src.getHeight(null), imageType); 352 Graphics g = dst.getGraphics(); 353 try{ 354 g.drawImage(src, 0, 0, null); 355 return dst; 356 }finally{ 357 g.dispose(); 358 } 359 } 360 /** 361 * 创建{@link BufferedImage#TYPE_3BYTE_BGR}ç±»åž‹çš„æ‹·è´ 362 * @param src 363 * @return 返回拷è´çš„对象 364 * @see #copy(Image, int) 365 */ 366 public static BufferedImage copy(BufferedImage src){ 367 return copy(src,BufferedImage.TYPE_3BYTE_BGR); 368 } 369 /** 370 * 对原图缩放,返回缩放åŽçš„æ–°å¯¹è±¡ 371 * @param src 372 * @param scale 373 * @return 返回缩放åŽçš„æ–°å¯¹è±¡ 374 */ 375 public static BufferedImage scale(BufferedImage src,double scale){ 376 if(null==src){ 377 throw new NullPointerException("src must not be null"); 378 } 379 if(0>=scale){ 380 throw new IllegalArgumentException("scale must >0"); 381 } 382 int width = src.getWidth(); // æºå›¾å®½ 383 int height = src.getHeight(); // æºå›¾é«˜ 384 Image image = src.getScaledInstance((int)Math.round(width * scale), (int)Math.round(height * scale), Image.SCALE_SMOOTH); 385 return copy(image,BufferedImage.TYPE_3BYTE_BGR); 386 } 387 /** 388 * å°†{@link Image}图åƒä¸Šä¸‹å·¦å³æ‰©å……指定的尺寸 389 * @param src 390 * @param imageType 391 * @param left 392 * @param top 393 * @param right 394 * @param bottom 395 * @return 返回扩展尺寸åŽçš„æ–°å¯¹è±¡ 396 */ 397 public static BufferedImage growCanvas(Image src,int imageType,int left,int top,int right,int bottom){ 398 if(null==src){ 399 throw new NullPointerException("src must not be null"); 400 } 401 if(left<0||top<0||right<0||bottom<0){ 402 throw new IllegalArgumentException("left,top,right,bottom must >=0"); 403 } 404 BufferedImage dst = new BufferedImage(src.getWidth(null)+left+right, src.getHeight(null)+top+bottom, imageType); 405 Graphics g = dst.getGraphics(); 406 try{ 407 g.setColor(Color.BLACK); 408 g.fillRect(0,0, dst.getWidth(), dst.getHeight()); 409 g.drawImage(src, left, top, null); 410 return dst; 411 }finally{ 412 g.dispose(); 413 } 414 } 415 /** 416 * @param src 417 * @param left 418 * @param top 419 * @param right 420 * @param bottom 421 * @return 422 * @see #growCanvas(Image, int, int, int, int, int) 423 */ 424 public static BufferedImage growCanvas(Image src,int left,int top,int right,int bottom){ 425 return growCanvas(src,BufferedImage.TYPE_3BYTE_BGR,left,top,right,bottom); 426 } 427 /** 428 * å°†{@link Image}图åƒ(å‘å³ä¸‹)æ‰©å……ä¸ºæ£æ–‡å½¢(尺寸长宽最大边) 429 * @param src 430 * @return 431 */ 432 public static BufferedImage growSquareCanvas(Image src){ 433 if(null==src){ 434 throw new NullPointerException("src must not be null"); 435 } 436 int width=src.getWidth(null); 437 int height=src.getHeight(null); 438 int size=Math.max(width, height); 439 return growCanvas(src,BufferedImage.TYPE_3BYTE_BGR,0,0,size-width,size-height); 440 } 441 /** 442 * Returns <code>ImageWriter</code> instance according to given 443 * rendered image and image format or <code>null</code> if there 444 * is no appropriate writer. 445 */ 446 private static ImageWriter getImageWriter(RenderedImage im, 447 String formatName) { 448 ImageTypeSpecifier type = 449 ImageTypeSpecifier.createFromRenderedImage(im); 450 Iterator<ImageWriter> iter = ImageIO.getImageWriters(type, formatName); 451 452 if (iter.hasNext()) { 453 return iter.next(); 454 } else { 455 return null; 456 } 457 } 458 459 /** 460 * 将原图压缩生æˆ{@code formatName}æŒ‡å®šæ ¼å¼çš„æ•°æ®<br> 461 * 除了å¯ä»¥æŒ‡å®šç”Ÿæˆçš„图åƒè´¨é‡ä¹‹å¤–, 462 * 其他行为与{@link ImageIO#write(RenderedImage, String, OutputStream)}ç›¸åŒ 463 * @param source 464 * @param formatName 465 * @param output 466 * @param compressionQuality 指定图åƒè´¨é‡,为{@code null}调用{@link ImageIO#write(RenderedImage, String, OutputStream)} 467 * @return 468 * @throws IOException 469 */ 470 public static boolean write(RenderedImage source, 471 String formatName, 472 OutputStream output, 473 Float compressionQuality) throws IOException{ 474 if(null == compressionQuality){ 475 return ImageIO.write(source, formatName, output); 476 } 477 ImageWriter writer = getImageWriter(source,formatName); 478 if(null == writer){ 479 return false; 480 } 481 ImageOutputStream stream = null; 482 try { 483 stream = ImageIO.createImageOutputStream(output); 484 } catch (IOException e) { 485 throw new IIOException("Can't create output stream!", e); 486 } 487 writer.setOutput(stream); 488 ImageWriteParam param = writer.getDefaultWriteParam(); 489 try{ 490 if(param.canWriteCompressed()){ 491 try{ 492 param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 493 param.setCompressionQuality(compressionQuality); 494 }catch(RuntimeException e){ 495 } 496 } 497 writer.write(null, new IIOImage(source, null, null), param); 498 return true; 499 } finally { 500 writer.dispose(); 501 stream.flush(); 502 } 503 } 504 /** 505 * 从RGBæ ¼å¼å›¾åƒçŸ©é˜µæ•°æ®åˆ›å»ºä¸€ä¸ªBufferedImage 506 * @param matrixRGB RGBæ ¼å¼å›¾åƒçŸ©é˜µæ•°æ®,为nullåˆ™åˆ›å»ºä¸€ä¸ªæŒ‡å®šå°ºå¯¸çš„ç©ºå›¾åƒ 507 * @param width 508 * @param height 509 * @return 510 */ 511 public static BufferedImage createRGBImage(byte[] matrixRGB,int width,int height){ 512 int bytePerPixel = 3; 513 Assert.isTrue(null==matrixRGB || matrixRGB.length==width*height*bytePerPixel,"invalid image argument"); 514 DataBufferByte dataBuffer = null==matrixRGB ? null : new DataBufferByte(matrixRGB, matrixRGB.length); 515 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 516 int[] bOffs = {0, 1, 2}; 517 ComponentColorModel colorModel = new ComponentColorModel(cs, false, false, 518 Transparency.OPAQUE, 519 DataBuffer.TYPE_BYTE); 520 WritableRaster raster = null != dataBuffer 521 ? Raster.createInterleavedRaster(dataBuffer, width, height, width*bytePerPixel, bytePerPixel, bOffs, null) 522 : Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,width*bytePerPixel, bytePerPixel, bOffs, null); 523 BufferedImage img = new BufferedImage(colorModel,raster,colorModel.isAlphaPremultiplied(),null); 524 return img; 525 } 526 /** 527 * 从RGBAæ ¼å¼å›¾åƒçŸ©é˜µæ•°æ®åˆ›å»ºä¸€ä¸ªBufferedImage<br> 528 * è¯¥æ–¹æ³•åˆ é™¤äº†alphaé€šé“ 529 * @param matrixRGBA RGBAæ ¼å¼å›¾åƒçŸ©é˜µæ•°æ®,为nullåˆ™åˆ›å»ºä¸€ä¸ªæŒ‡å®šå°ºå¯¸çš„ç©ºå›¾åƒ 530 * @param width 531 * @param height 532 * @return 533 */ 534 public static BufferedImage createRGBAImage(byte[] matrixRGBA,int width,int height){ 535 int bytePerPixel = 4; 536 Assert.isTrue(null==matrixRGBA || matrixRGBA.length==width*height*bytePerPixel,"invalid image argument"); 537 DataBufferByte dataBuffer = null==matrixRGBA ? null : new DataBufferByte(matrixRGBA, matrixRGBA.length); 538 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 539 int[] bOffs = {0, 1, 2}; 540 ComponentColorModel colorModel = new ComponentColorModel(cs, false, false, 541 Transparency.OPAQUE, 542 DataBuffer.TYPE_BYTE); 543 WritableRaster raster = null != dataBuffer 544 ? Raster.createInterleavedRaster(dataBuffer, width, height, width*bytePerPixel, bytePerPixel, bOffs, null) 545 : Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,width*bytePerPixel, bytePerPixel, bOffs, null); 546 BufferedImage img = new BufferedImage(colorModel,raster,colorModel.isAlphaPremultiplied(),null); 547 return img; 548 } 549 private static void assertContains(final Rectangle parent, String argParent, final Rectangle sub, final String argSub) 550 throws IllegalArgumentException { 551 if(!parent.contains(sub)) 552 throw new IllegalArgumentException(String.format( 553 "the %s(X%d,Y%d,W%d,H%d) not contained by %s(X%d,Y%d,W%d,H%d)", 554 argSub,sub.x, sub.y,sub.width, sub.height, argParent,parent.x,parent.y,parent.width, parent.height)); 555 } 556 /** 557 * 从matrixçŸ©é˜µä¸æˆªå–rect指定区域的å矩阵 558 * @param matrix 3byte(RGB/BGR) 图åƒçŸ©é˜µ 559 * @param matrixRect 矩阵尺寸 560 * @param rect 截å–区域 561 * @return 562 */ 563 public static byte[] cutMatrix(byte[] matrix,Rectangle matrixRect,Rectangle rect) { 564 // è§£ç 区域,为null或与图åƒå°ºå¯¸ç›¸ç‰æ—¶ç›´æŽ¥è¿”回 matrix 565 if((rect == null || rect.equals(matrixRect))) 566 return matrix; 567 else{ 568 // 如果指定的区域超出图åƒå°ºå¯¸ï¼Œåˆ™æŠ›å‡ºå¼‚常 569 ImageUtil.assertContains(matrixRect, "srcRect", rect ,"rect"); 570 byte[] dstArray=new byte[rect.width*rect.height*3]; 571 // 从 matrix ä¸å¤åˆ¶æŒ‡å®šåŒºåŸŸçš„å›¾åƒæ•°æ®è¿”回 572 for(int dstIndex=0,srcIndex=(rect.y*matrixRect.width+rect.x)*3,y=0; 573 y<rect.height; 574 ++y,srcIndex+=matrixRect.width*3,dstIndex+=rect.width*3){ 575 // 调用 System.arrayCopyæ¯æ¬¡å¤åˆ¶ä¸€è¡Œæ•°æ® 576 System.arraycopy(matrix, srcIndex, dstArray, dstIndex, rect.width*3); 577 } 578 return dstArray; 579 } 580 } 581}