c - 双线性插值图像调整大小标记 & 'splotches'

标签 c image image-processing bitmap interpolation

我正在用 C 编写一个图像大小调整程序,目前我在使用双线性插值函数时遇到了问题(这是我正在使用的众多函数之一)。这个问题只出现在 16 位位图上,如果我使用 24 位版本,它会完美地调整它们的大小。

这是我的双线性插值代码。 n_w 和 n_h 是图像的新宽度和高度:

#define getelm(x)   (((pix+index)->x)*(1-xdiff)*(1-ydiff))+(((pix+index+1)->x)*(xdiff)*(1-ydiff))+(((pix+index+o_w)->x)*(1-xdiff)*(ydiff))+((pix+index+o_w+1)->x)*xdiff*ydiff

int pad = (2*n_w) & 3;
if (pad)
pad = 4-pad;
uint16_t *buffer;
if (buf)
buffer = malloc(2*n_w);
for (i = 0; i < n_h; i++) {
    for (j = 0; j < n_w; j++) {
        x = (int)(j*xrat);
        y = (int)(i*yrat);
        xdiff = (xrat*j)-x;
        ydiff = (yrat*i)-y;
        index = y*o_w+x;
        uint16_t container = 0;
        container |= (int)(round(getelm(b))) << 11;
        container |= (int)(round(getelm(g))) << 5;
        container |= (int)round(getelm(r));
        if (buf)
            *(buffer+j) = container;
        else
            fwrite(&container, 1, 2, dest);
    }
    if (buf)
        fwrite(buffer, 1, 2*n_w, dest);
        fwrite(&pad, 1, pad, dest);
}

我的这段代码的 24 位版本(唯一的区别是没有使用容器,而是 3 个 8 位整数保存 RGB 值)工作得很好。

然而,这段代码给出了奇怪的结果。看下图:Original image

当我调整它的大小时,它会返回给我:Resized image

我不明白为什么会发生这种情况,尤其是当它适用于 24 位位图时,而且一些其他调整大小算法(例如最近邻算法)以与这应该相同的方式适用于 16 位图。

编辑: 我不认为这是一个溢出问题,因为添加以下代码运行时没有输出:

if (MAX((int)(getelm(b)), 31) > 31)
    printf("blue overflow: %.10f\n", (getelm(b)));
if (MAX((int)(getelm(g)), 63) > 63)
    printf("green overflow: %.10f\n", (getelm(g)));
if (MAX((int)(getelm(r)), 31) > 31)
    printf("red overflow: %.10f\n", (getelm(r)));

编辑 2: 我也不认为这是一个下溢问题,这没有任何作用:

if ((getelm(b)) < 0 || (getelm(g)) < 0 || (getelm(r)) < 0)
    printf("Underflow\n");

最佳答案

假设 pix 中的数据具有类型

struct
{
    uint16_t r : 5;
    uint16_t g : 6;
    uint16_t b : 5;
};

container 的计算存在错误。使用 round 并不总能防止溢出。下一个代码将:

uint16_t container = 0;
        container |= ((int)(round(getelm(b))) & 31) << 11; // optionally
        container |= ((int)(round(getelm(g))) & 63) << 5;
        container |= ((int)round(getelm(r)) & 31);

或保留最大的丢失信息:

uint16_t container = 0;
        container |= min((int)(round(getelm(b))) , 31) << 11;
        container |= min(((int)(round(getelm(g))) , 63) << 5;
        container |= min(((int)round(getelm(r)) , 31);

编辑

由于 pix->rpix->gpix->b 来自 8 位值,相同的推理适用于它们并且需要检查它们的范围。

由于白色区域变成紫色,这意味着绿色由于溢出而被抑制,或者它首先被读取为零。在这种情况下,检查读取颜色会有所帮助。 类似地,黑色变成绿色意味着代表小值的位被移动并且颜色以某种方式反转。

为了找到错误,我建议将代码拆分为小函数并断言每个函数的输入。

关于c - 双线性插值图像调整大小标记 & 'splotches',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18283340/

相关文章:

c - 将 bash 命令 echo 和 bc 管道化到 C 程序中

java - 静态变量在Java编译时出错,在C中一次性内存分配

c - 将 char * 与 char ** 作为参数传递给 C 中的函数

我网站的 css 图片对齐

iphone - UIImageView 带有大图像。问题

image-processing - 在opencv中查找轮廓的长度

C:查找字符串中的特定字符

asp.net - 是否有推荐的方法使用 ASP.NET Web API 返回图像

java - 如何在java中处理tesserac的图像?

opencv - HAAR 分类器说明