前两天,组长给了一个小任务,就是前端会传一个url和两个坐标点给你,如果没有传两个坐标点的话,就返回整张 图片,如果有穿的话,就根据这两个坐标,截图返回.
首先根据url得到这个图片的inputStream
public InputStreamdownloadPicByUrl(String picUrl)throws IOException {
URL url =new URL(picUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(1000);//超时提示1秒=1000毫秒
InputStream inStream = conn.getInputStream();//获取输出流
return inStream;
}
然后呢,根据这个inputStream就可以做图片处理.
下面是两种处理方式
1: @GetMapping("/pic-preview")
@ApiOperation(value = "根据图片url返回图片接口", notes = "根据图片url返回图片接口")
public ResponseEntity> showPicByUrl(HttpServletResponse res, @ApiParam("媒体url") @RequestParam(name = "picUrl", required = true) String picUrl,
@ApiParam("媒体截取的第一个x坐标") @RequestParam(name = "x", required = false) Integer x,
@ApiParam("媒体截取的第一个y坐标") @RequestParam(name = "y", required = false) Integer y,
@ApiParam("媒体截取的第二个x坐标") @RequestParam(name = "z", required = false) Integer z,
@ApiParam("媒体截取的第二个y坐标") @RequestParam(name = "v", required = false) Integer v) throws GlobalException {
FileInputStream is = null;
ImageInputStream iis = null;
InputStream inputStream = null;
String[] split = picUrl.split("\\.");
String mediaFormat = split[(split.length - 1)];
try {
// 读取图片文件
inputStream = infoCaseService.downloadPicByUrl(picUrl);
/*
* 返回包含所有当前已注册 ImageReader 的 Iterator,这些 ImageReader
* 声称能够解码指定格式。 参数:formatName - 包含非正式格式名称 .
*(例如 "jpeg" 或 "tiff")等 。
*/
Iterator
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(inputStream);
/*
*
iis:读取源.true:只向前搜索
.将它标记为 ‘只向前搜索'。* 此设置意味着包含在输入源中的图像将只按顺序读取,可能允许 reader
* 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
*/
reader.setInput(iis, true);
/*
*
描述如何对流进行解码的类
.用于指定如何在输入时从 Java Image I/O
* 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
* 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回
* ImageReadParam 的实例。
*/
ImageReadParam param = reader.getDefaultReadParam();
// inputStream
//判断是否需要截取图片
if (x != null && y != null & z != null && v != null) {
/*
* 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象
* 的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。
*/
int width = Math.abs(x - z);
int height = Math.abs(y - v);
Rectangle rect = new Rectangle(x, y, width, height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
/*
* 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将
* 它作为一个完整的 BufferedImage 返回。
*/
BufferedImage bi = reader.read(0, param);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bi, mediaFormat, imOut);
inputStream = new ByteArrayInputStream(bs.toByteArray());
}
res.setContentType("image/" + mediaFormat); // 如果是 jpg 则为 image/jpeg,svg 为 image/svg+xml 等
OutputStream out = res.getOutputStream();
IOUtils.copy(inputStream, out);
//吧截取后的图片返回前端
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
throw new GlobalException(String.format("/preview"), e.getMessage());
}
}
if (iis != null) {
try {
iis.close();
} catch (IOException e) {
throw new GlobalException(String.format("/preview"), e.getMessage());
}
}
}
return new ResponseEntity<>(HttpStatus.OK);
}
第一种方式的话,在短时间内可以找的到,网上也比较多,然后第二种方案是根据Thumbnails来做,这是一个处理图片的优秀框架,大家喜欢的可以去了解一下(各种图片的缩放,放大,处理基本都有)
@GetMapping("/pic-preview")
@ApiOperation(value ="根据图片url返回图片接口", notes ="根据图片url返回图片接口")
public ResponseEntityshowPicByUr(HttpServletResponse res, @ApiParam("媒体url")@RequestParam(name ="picUrl", required =true) String picUrl,
@ApiParam("媒体截取的第一个x坐标")@RequestParam(name ="x", required =false) Integer x,
@ApiParam("媒体截取的第一个y坐标")@RequestParam(name ="y", required =false) Integer y,
@ApiParam("媒体截取的第二个x坐标")@RequestParam(name ="z", required =false) Integer z,
@ApiParam("媒体截取的第二个y坐标")@RequestParam(name ="v", required =false) Integer v)throws GlobalException {
InputStream inputStream =null;
String[] split = picUrl.split("\\.");
String mediaFormat = split[(split.length -1)];
try {
inputStream =infoCaseService.downloadPicByUrl(picUrl);
OutputStream out = res.getOutputStream();
if (x !=null && y !=null & z !=null && v !=null) {
//这个如果没有指定这个图片的缩放比例或指定大小,这个方法是会报错的
BufferedImage bufferedImage = Thumbnails.of(inputStream).sourceRegion(x, y, z, v).scale(1.0f).asBufferedImage();
ByteArrayOutputStream bs =new ByteArrayOutputStream();
ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bufferedImage, mediaFormat, imOut);
inputStream =new ByteArrayInputStream(bs.toByteArray());
}
res.setContentType("image/" + mediaFormat);
IOUtils.copy(inputStream, out);
}catch (Exception e) {
throw new GlobalException(String.format("/pic-preview"), e.getMessage());
}
return new ResponseEntity<>(HttpStatus.OK);
}
其实这里面还有一个问题,就是res.setContentType("image/" + mediaFormat);
这个方法,各个图片格式对应的contentType不一定是image/图片格式.原本是想要把所有的对应关系放在一个map中,在从中取,经过试验,只要前缀是image/,谷歌浏览器都会自动识别正确的格式然后处理显示出来.