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

来源:互联网 发布:大丰娱乐软件 编辑:程序博客网 时间:2024/04/29 14:07

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

一:什么是Lanczos采样

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

二:大致算法流程


三:算法运行结果

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


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


算法源代码:

package com.gloomyfish.zoom.study;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import com.gloomyfish.filter.study.AbstractBufferedImageOp;public class LanczosScaleFilter extends AbstractBufferedImageOp {// lanczos_sizeprivate float lanczosSize;private float destWidth;public LanczosScaleFilter(){lanczosSize = 3;destWidth = 100;}public LanczosScaleFilter(float lobes, int width) {this.lanczosSize = lobes;this.destWidth = width;}public void setLanczosSize(float size) {this.lanczosSize = size;}public void setDestWidth(float destWidth) {this.destWidth = destWidth;}@Overridepublic BufferedImage filter(BufferedImage src, BufferedImage dest) {int width = src.getWidth();int height = src.getHeight();float ratio = width / this.destWidth;float rcp_ratio = 2.0f / ratio;float range2 = (float) Math.ceil(ratio * lanczosSize / 2);// destination imageint dh = (int)(height * (this.destWidth/width));int dw = (int)this.destWidth;if (dest == null) {ColorModel cMD = src.getColorModel();dest = new BufferedImage(src.getColorModel(), cMD.createCompatibleWritableRaster(dw, dh), cMD.isAlphaPremultiplied(), null);}int[] inPixels = new int[width * height];int[] outPixels = new int[dw * dh];getRGB(src, 0, 0, width, height, inPixels);int index = 0;float fcy = 0, icy = 0, fcx = 0, icx = 0;for (int row = 0; row < dh; row++) {int ta = 0, tr = 0, tg = 0, tb = 0;fcy = (row + 0.5f) * ratio;icy = (float) Math.floor(fcy);for (int col = 0; col < dw; col++) {fcx = (col + 0.5f) * ratio;icx = (float) Math.floor(fcx);float sumred = 0, sumgreen = 0, sumblue = 0;float totalWeight = 0;for (int subcol = (int) (icx - range2); subcol <= icx + range2; subcol++) {if (subcol < 0 || subcol >= width)continue;int ncol = (int) Math.floor(1000 * Math.abs(subcol - fcx));for (int subrow = (int) (icy - range2); subrow <= icy + range2; subrow++) {if (subrow < 0 || subrow >= height)continue;int nrow = (int) Math.floor(1000 * Math.abs(subrow - fcy));float weight = (float) getLanczosFactor(Math.sqrt(Math.pow(ncol * rcp_ratio, 2)+ Math.pow(nrow * rcp_ratio, 2)) / 1000);if (weight > 0) {index = (subrow * width + subcol);tr = (inPixels[index] >> 16) & 0xff;tg = (inPixels[index] >> 8) & 0xff;tb = inPixels[index] & 0xff;totalWeight += weight;sumred += weight * tr;sumgreen += weight * tg;sumblue += weight * tb;}}}index = row * dw + col;tr = (int) (sumred / totalWeight);tg = (int) (sumgreen / totalWeight);tb = (int) (sumblue / totalWeight);outPixels[index] = (255 << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);// clear for next pixelsumred = 0;sumgreen = 0;sumblue = 0;totalWeight = 0;}}setRGB(dest, 0, 0, dw, dh, outPixels);return dest;}public static int clamp(int v){return v > 255 ? 255 : (v < 0 ? 0 : v);}private double getLanczosFactor(double distance) {if (distance > lanczosSize)return 0;distance *= Math.PI;if (Math.abs(distance) < 1e-16)return 1;double xx = distance / lanczosSize;return Math.sin(distance) * Math.sin(xx) / distance / xx;}}

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

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

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

大小为8. 

3 1
原创粉丝点击