图像处理之Lanczos采样放缩算法

图像处理之Lanczos采样放缩算法

一:什么是Lanczos采样

参见这里:http://en.wikipedia.org/wiki/Lanczos_resampling

二:大致算法流程


三:算法运行结果

1.向下采样, 生成缩略图, 左边为原图,右边为缩略图


向上采样,生成放大图像时效果:


算法源代码:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.gloomyfish.zoom.study;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4. import java.awt.image.ColorModel;  
  5.   
  6. import com.gloomyfish.filter.study.AbstractBufferedImageOp;  
  7.   
  8. public class LanczosScaleFilter extends AbstractBufferedImageOp {  
  9.     // lanczos_size  
  10.     private float lanczosSize;  
  11.     private float destWidth;  
  12.       
  13.     public LanczosScaleFilter()  
  14.     {  
  15.         lanczosSize = 3;  
  16.         destWidth = 100;  
  17.     }  
  18.   
  19.     public LanczosScaleFilter(float lobes, int width) {  
  20.         this.lanczosSize = lobes;  
  21.         this.destWidth = width;  
  22.     }  
  23.   
  24.     public void setLanczosSize(float size) {  
  25.         this.lanczosSize = size;  
  26.     }  
  27.   
  28.     public void setDestWidth(float destWidth) {  
  29.         this.destWidth = destWidth;  
  30.     }  
  31.   
  32.     @Override  
  33.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  34.         int width = src.getWidth();  
  35.         int height = src.getHeight();  
  36.         float ratio = width / this.destWidth;  
  37.         float rcp_ratio = 2.0f / ratio;  
  38.         float range2 = (float) Math.ceil(ratio * lanczosSize / 2);  
  39.           
  40.         // destination image  
  41.         int dh = (int)(height * (this.destWidth/width));  
  42.         int dw = (int)this.destWidth;  
  43.   
  44.         if (dest == null) {  
  45.             ColorModel cMD = src.getColorModel();  
  46.             dest = new BufferedImage(src.getColorModel(), cMD.createCompatibleWritableRaster(dw, dh), cMD.isAlphaPremultiplied(), null);  
  47.         }  
  48.   
  49.         int[] inPixels = new int[width * height];  
  50.         int[] outPixels = new int[dw * dh];  
  51.           
  52.         getRGB(src, 00, width, height, inPixels);  
  53.         int index = 0;  
  54.         float fcy = 0, icy = 0, fcx = 0, icx = 0;  
  55.         for (int row = 0; row < dh; row++) {  
  56.             int ta = 0, tr = 0, tg = 0, tb = 0;  
  57.             fcy = (row + 0.5f) * ratio;  
  58.             icy = (float) Math.floor(fcy);  
  59.             for (int col = 0; col < dw; col++) {  
  60.                 fcx = (col + 0.5f) * ratio;  
  61.                 icx = (float) Math.floor(fcx);  
  62.   
  63.                 float sumred = 0, sumgreen = 0, sumblue = 0;  
  64.                 float totalWeight = 0;  
  65.                 for (int subcol = (int) (icx - range2); subcol <= icx + range2; subcol++) {  
  66.                     if (subcol < 0 || subcol >= width)  
  67.                         continue;  
  68.                     int ncol = (int) Math.floor(1000 * Math.abs(subcol - fcx));  
  69.   
  70.                     for (int subrow = (int) (icy - range2); subrow <= icy + range2; subrow++) {  
  71.                         if (subrow < 0 || subrow >= height)  
  72.                             continue;  
  73.                         int nrow = (int) Math.floor(1000 * Math.abs(subrow - fcy));  
  74.                         float weight = (float) getLanczosFactor(Math.sqrt(Math.pow(ncol * rcp_ratio, 2)  
  75.                                 + Math.pow(nrow * rcp_ratio, 2)) / 1000);  
  76.                         if (weight > 0) {  
  77.                             index = (subrow * width + subcol);  
  78.                             tr = (inPixels[index] >> 16) & 0xff;  
  79.                             tg = (inPixels[index] >> 8) & 0xff;  
  80.                             tb = inPixels[index] & 0xff;  
  81.                             totalWeight += weight;  
  82.                             sumred += weight * tr;  
  83.                             sumgreen += weight * tg;  
  84.                             sumblue += weight * tb;  
  85.                         }  
  86.                     }  
  87.                 }  
  88.                 index = row * dw + col;  
  89.                 tr = (int) (sumred / totalWeight);  
  90.                 tg = (int) (sumgreen / totalWeight);  
  91.                 tb = (int) (sumblue / totalWeight);  
  92.                 outPixels[index] = (255 << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  
  93.                   
  94.                 // clear for next pixel  
  95.                 sumred = 0;  
  96.                 sumgreen = 0;  
  97.                 sumblue = 0;  
  98.                 totalWeight = 0;  
  99.   
  100.             }  
  101.         }  
  102.         setRGB(dest, 00, dw, dh, outPixels);  
  103.         return dest;  
  104.     }  
  105.       
  106.     public static int clamp(int v)  
  107.     {  
  108.         return v > 255 ? 255 : (v < 0 ? 0 : v);  
  109.     }  
  110.   
  111.     private double getLanczosFactor(double distance) {  
  112.         if (distance > lanczosSize)  
  113.             return 0;  
  114.         distance *= Math.PI;  
  115.         if (Math.abs(distance) < 1e-16)  
  116.             return 1;  
  117.         double xx = distance / lanczosSize;  
  118.         return Math.sin(distance) * Math.sin(xx) / distance / xx;  
  119.     }  
  120.   
  121. }  

五:窗口大小对结果的影响

如果是向下采样生成缩略图的话, 窗口大小设置为3就已经非常清楚了

如果向上采样要放大图像的话, 窗口大小设置要大于6才能获得较好结果,推荐使用窗口

大小为8. 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值