概述
图像的放大与缩小是图像处理中很经常碰到的问题,也是现实中经常要应用的,如一张图片太小,看不行的情况下就需要对去进行放大;在一些文档排版的时候有需要对一下大的图片进行缩小。
图像的放大与缩小在物理意义上来说是图像的像素的尺寸放大或缩小相应的比例,但像素的尺寸是不能改变的,因此我们只能通过增加(或减少)相应的像素来放大(或缩小)图片。在算法实现中最简单的是等距离采样法。
算法的实现步骤:
(1)计算采样间隔
设原图的大小为W*H,将其放大(缩小)为(k1*W)*(K2*H),则采样区间为
ii=1/k1; jj=1/k2;
当k1==k2时为等比例缩小;当k1!=k2时为不等比例放大(缩小);当k1<1 && k2<1时为图片缩小,k1>1 && k2>1时图片放大。
(2)求出放大(缩小)后的图像
设原图为F(x,y)(i=1,2, ……W; j=1,2,……H),放大(缩小)的图像为G(x,y)(x=1,2, ……M; y=1,2,……N,其中M=W*k1,N=H*k2),则有
G(x,y) = f(ii*x, jj*y)
举例说明:
原图(6*4)
f11 f12 f13 f14 f15 f16
f21 f22 f23 f24 f25 f26
f31 f32 f33 f34 f35 f36
f41 f42 f43 f44 f45 f46
缩小比例k1=0.6, k2 = 0.7
f12 f13 f15 f16
f32 f33 f35 f36
f42 f43 f45 f46
当然,使用等距采样法实现图片放大与缩小有一个缺点就是:缩小时未被选取的点的信息无法反映在缩小的图像上,放大时会出现整个小块区域像素相同,图像不清晰的,特别是缩放比例很大时。如下图
2048*1536缩小为100*80时的效果 100*80放大到600*400的效果
要解决这个问题,请看下一节“图像的放大与缩小(1)——双线性插值放大与均值缩小”
算法源代码(java)
-
-
-
-
-
- public static BufferedImage readImg(String srcPath) {
- BufferedImage img = null;
- try {
- img = ImageIO.read(new File(srcPath));
- } catch (IOException e) {
- e.printStackTrace();
- }
- return img;
- }
-
-
-
-
-
-
- public static void writeImg(BufferedImage img, String s, String distPath) {
- OutputStream out = null;
- try {
-
-
- out = new FileOutputStream(distPath);
- ImageIO.write(img, s, out);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if(out != null) {
- out.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
-
-
-
-
-
-
- public static BufferedImage flex(BufferedImage img, int m, int n) {
- float k1 = (float)m/img.getWidth();
- float k2 = (float)n/img.getHeight();
- return flex(img, k1, k2);
- }
-
-
-
-
-
-
-
- public static BufferedImage flex(BufferedImage img, float k1, float k2) {
- float ii = 1/k1;
- float jj = 1/k2;
-
- int imgType = img.getType();
- int w = img.getWidth();
- int h = img.getHeight();
- int m = (int) (k1*w);
- int n = (int) (k2*h);
- int[] pix = new int[w*h];
- pix = img.getRGB(0, 0, w, h, pix, 0, w);
- System.out.println(w + " * " + h);
- System.out.println(m + " * " + n);
- int[] newpix = new int[m*n];
-
- for(int j=0; j<n; j++) {
- for(int i=0; i<m; i++) {
- newpix[j*m + i] = pix[(int)(jj*j)*w + (int)(ii*i)];
- }
- }
- System.out.println((int)((m-1)*ii));
- System.out.println("m:" + m + " n:" + n);
-
- BufferedImage imgOut = new BufferedImage( m, n, imgType);
-
- imgOut.setRGB(0, 0, m, n, newpix, 0, m);
- return imgOut;
- }