缩放,调整 bmp 结构大小,编程 c

Posted

技术标签:

【中文标题】缩放,调整 bmp 结构大小,编程 c【英文标题】:scale, resize bmp structure, programming c 【发布时间】:2020-04-30 13:05:42 【问题描述】:

我的任务是用给定的因子缩放 bmp 图片:

流:base64 bmp 图像代码:

Qk1CAAAAAAAAADYAAAAoAAAABAAAAAEAAAABABgAAAAAAAwAAAAjLgAAIy4AAAAAAAAAAAAA/////wAAAP8AAAAA

scale.c

struct bmp_image* scale(const struct bmp_image* image, float factor)
    if(image == NULL || factor <= 0)
        return NULL;
    

    .........
    int width = bmp->header->width;
    int height = bmp->header->height;
    int widthNew = (int)round((float)width * factor);
    int heightNew = (int)round((float)height * factor);


    for (uint32_t y = 0; y < heightNew; y++)
        for(uint32_t z = 0; z< widthNew; z++)
            bmp->data[(y*widthNew)+z].red=image->data[(int)(floor((float)y/(float)factor)*width+floor((float)z/(float)factor))].red;
            bmp->data[(y*widthNew)+z].green=image->data[(int)(floor((float)y/(float)factor)*width+floor((float)z/(float)factor))].green;
            bmp->data[(y*widthNew)+z].blue=image->data[(int)(floor((float)y/(float)factor)*width+floor((float)z/(float)factor))].blue;
        
    

    return bmp;     

main.c

FILE *output_p8 = fopen("scale.bmp", "w");
    struct bmp_image* newimage8 = NULL;
    newimage8 = scale(image, 1.025656);  
    free_bmp_image(image);    
    write_bmp(output_p8,newimage8);
    free_bmp_image(newimage8);    
    fclose(output_p8);

数据输出我之后得到的:

ffffff ffffff ff0000 00ff00

我应该拥有的数据:

ffffff ff0000 00ff00 000000

有什么建议吗?

【问题讨论】:

计算新宽度时,会四舍五入到下一个整数。因此,图像的有效缩放因子不是标称因子。您必须调整您的因子或(也许更好)通过新旧宽度进行所有计算:znew = zold * wnew / wold。在您的示例中,您将 1×4 像素位图缩放 1.025656 倍。您的新尺寸基本相同,因此您不缩放图像,但第二个像素的新索引是 floor(1 / 1.025656),它是 0 而不是 1。 您的 for 循环中的索引超出范围。旧的宽度和高度更小,因此通过在循环中使用 y,z 和旧的宽度和高度,您的索引超出范围。您也永远不会增加实际的像素数 @MOehm 你能帮我解释一下znew = zold * wnew / wold是什么@ 它们是新旧z索引和宽度,可以读作z_new = z_old * w_new / w_old。我没有使用您的命名法,因为长词在 cmets 中效果不佳。无论如何,您不会使用新索引,而是使用长而重复的表达式。 【参考方案1】:

在计算新维度时,执行浮点计算,然后四舍五入到最接近的整数:

int widthNew = round(width * factor);

(您不需要强制转换:factorfloat,整数与 float 相乘的结果也是 floatwidthNew 是整数,所以float 结果必须转换为整数。)

因为你四舍五入,你的有效比例因子(我们称之为factor_eff)可能与标称的factor不同:

float factor_eff = (float) widthNew / width;

在你的情况下:

factor == 1.025656;
width == 4;
widthNew == round(1.025656 * 4) == round(4.102624) == 4;
factor_eff = 4.0 / 4 == 1.0;

但是您使用旧因子进行索引计算:

int zNew = floor(z / factor);

(同样,您不需要演员表。)对于您的四个 z 索引,这将产生:

z == 0;    zNew == floor(0 / 1.025656) == floor(0.0)       == 0;   // ok
z == 1;    zNew == floor(1 / 1.025656) ~~ floor(0.9749858) == 0;   // ! should be 1
z == 2;    zNew == floor(2 / 1.025656) ~~ floor(1.9499715) == 1;   // ! should be 2
z == 3;    zNew == floor(3 / 1.025656) ~~ floor(2.9249573) == 2;   // ! should be 3

您可以修复浮点因子,但我认为使用整数算术计算新索引会更好(并且更快):

int zNew = z * width / widthNew;
int yNew = y * height / heightNew;

确保先进行乘法运算。这种方法应该可以安全地用于大约 46,000 的尺寸。

【讨论】:

以上是关于缩放,调整 bmp 结构大小,编程 c的主要内容,如果未能解决你的问题,请参考以下文章

调整 bmp 图像大小

Android如何以编程方式调整(缩放)xml矢量图标

水平调整 BMP 图像大小的问题 (C#)

Objective c 如何根据图像大小缩放图像视图大小(高度)

根据缩放 Google 地图 v3 调整标记大小

imageresizing.net 插件允许图像调整大小/缩放/裁剪