因此,改变图像大小的一种方案是对其进行重新采样(从技术上讲,这实际上是唯一的方法,每种变化实际上只是一种不同类型的重新采样函数)。
将图像切成两半非常容易,您想要读取每个方向上的每隔一个像素,然后将该像素加载到新的一半大小的数组中。困难的部分是确保你的簿记能力强。
static int[][] halfImage(int[][] orig){
int[][] hi = new int[orig.length/2][orig[0].length/2];
for(int r = 0, newr = 0; r < orig.length; r += 2, newr++){
for(int c = 0, newc = 0; c < orig[0].length; c += 2, newc++){
hi[newr][newc] = orig[r][c];
}
}
return hi;
}
在上面的代码中,我对原始图像进行索引,从第 0 行和第 0 列开始读取每隔一行中的每隔一个像素(此处假设图像是行主)。因此,r
告诉我们我们正在查看原始图像中的哪一行,以及c
告诉我们我们正在查看原始图像中的哪一列。orig[r][c]
给我们“当前”像素。
相似地,newr
and newc
索引到指定的“半图像”矩阵hi
。对于每个增量newr
or newc
我们增加r
and c
分别增加了 2。通过这样做,我们在迭代图像时会跳过所有其他像素。
编写一个不对小数部分(如 1/2、1/4、1/8 等)进行操作的通用调整大小例程确实非常困难。对于更复杂的因素,例如 0.13243,您需要定义一种方法来确定子像素(像素之间的点)的值。当然,这很容易做到,您可以开发一种非常简单的线性插值原理,当您需要两个像素之间的值时,您只需获取周围的像素,在它们的值之间构造一条线,然后读取子像素点距线。更复杂的插值版本可能是sinc
基于插值......或广泛出版的文献中的许多其他插值之一。
放大图像的大小涉及到的事情与我们在这里所做的略有不同(如果您实际上必须编写通用的调整大小函数,您可能会考虑拆分您的函数以以不同的方式处理放大和缩小)。您需要以某种方式创建比原来更多的值——这些插值函数也适用于此。一个简单的方法可能只是在点之间重复一个值,直到有足够的值为止,并且对此也有一些细微的变化,对于特定位置,您可能会从左侧获取如此多的值,从右侧获取如此多的值。
我鼓励您考虑的是——由于这是家庭作业,我将远离实现——将缩放因子视为导致您在一张图像上进行观察并在新图像上写入的东西。当缩放因子小于 1 时,您通常会从原始图像中采样以填充新图像并忽略原始图像的一些像素。当缩放因子大于 1 时,您通常会更频繁地写入新图像,并且可能需要从旧图像中多次读取相同的值。 (我在强调差异方面做得很差,希望你能看到我所说的二元论。)