一个困扰很久的问题,关于c++ freeImage存储图片的使用

自己调整半天,没有弄好,关于c++ freeImage存储图片的使用存储图片的,最后生成的图片是斜的。

注意:过程稍微繁琐,如果有的前辈遇到过类似问题,可以直接看我的下文放的生成图片,看是否能直接解答,谢谢。

我现在把过程和关键代码po上来:

需求:我想读取一个大图一个小图片,然后把小图的一部分贴在大图中,然后存储图片。

我的做法:

首先读取这几个图片:

const char* sourceFile = "/Users/hh/Desktop/Possion/bear.jpg";//小图
const char* targetFile = "/Users/hh/Desktop/Possion/pool-target.jpg";//大图
const char* sourceMask = "/Users/hh/Desktop/Possion/bear-mask.jpg";//蒙版
const char* saveFile = "/Users/hh/Desktop/Possion/beatest01.jpg";//输出

    FREE_IMAGE_FORMAT fif11 = FIF_UNKNOWN;
    fif11 = FreeImage_GetFileType(sourceFile);
    if (fif11 == FIF_UNKNOWN)
        fif11 = FreeImage_GetFIFFromFilename(sourceFile);
    
    //这里省略对其他图片样式判读..
    
    //分别读取源图片三个:选择的图片,二值图片,目的图片。
    
    FIBITMAP *bitmap11 = NULL;
    FIBITMAP *bitmap12 = NULL;
    FIBITMAP *bitmap13= NULL;
    FIBITMAP *bitmap2 = NULL;
    
    if ((fif11 != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif11)){
        bitmap11 = FreeImage_Load(fif11, sourceFile, PNG_DEFAULT);
    }
    if (!bitmap11){
        fprintf(stderr, "Fail to Load Image!\n");
        exit(-1);
    }
    //这里省略对其他图片错误处理..
    
    else{
        FreeImage_Save(fif12, bitmap12, saveFile, PNG_DEFAULT);
        bitmap2 = FreeImage_Load(fif12, saveFile, PNG_DEFAULT);
        if (!bitmap2){
            fprintf(stderr, "Fail to Load saved Image!\n");
            exit(-1);
        }
    }
    
    //...
    // 获取保存图片的字节数组
    unsigned char *bits11 = FreeImage_GetBits(bitmap11);
    unsigned char *bitsSourceTarget = FreeImage_GetBits(bitmap12);

    unsigned char *bitsMaskByte = FreeImage_GetBits(bitmap13);
    
    unsigned char *bitsResult = FreeImage_GetBits(bitmap2);

然后我写了这一个函数可以把图片像素内容存储在数组中(我选的图每一个像素RGB共三个字节)

void getRGBfromBits(int pixels[][1] , unsigned char* bits, int number){
    int cur = 0;
    for (int x = 0; x < number; x++){
        // 这里对应于上述的每个像素的字节数:3
        pixels[x][0] = (int)bits[cur++];
        pixels[x][2] = (int)bits[cur++];
        pixels[x][3] = (int)bits[cur++];
    }
}

然后就是赋值和替换,因为蒙版大小和小图片是一样的,所以这里只要把蒙版>128的小图部分加上一个起始坐标偏移替换大图的像素数组即可

我认为这部分比较简单应该不会有问题,代码冗长,这里不贴图了。

最后:

    for(n=0;n<targetRows*targetCols;n++){
            bitsResult[n*3]=(char)(int)targetImgR(n/targetCols,n%250);
            bitsResult[n*3+1]=(char)(int)targetImgG(n/targetCols,n%250);
            bitsResult[n*3+2]=(char)(int)targetImgB(n/targetCols,n%250);
    }
    FreeImage_Save(fif12, bitmap2, saveFile, PNG_DEFAULT);

好的,那么问题来了:

输出:奇怪的是有一块斜掉了,可参考下文其他测试,这并不是小图的问题
图片描述

原图:
图片描述

小图:
图片描述

蒙版:
图片描述

这个时候如果我这样做:

    //targetCols是250
    for(n=0;n<targetRows*targetCols;n++){
        if(n<10){
            cout<<(int)bitsResult[cur]<<(int)targetImgR(n/targetCols,n%250)<<endl;
        }
        if((n%250)<125){
            bitsResult[n*3]=(char)(int)targetImgR(n/targetCols,n%250);
            bitsResult[n*3+1]=(char)(int)targetImgG(n/targetCols,n%250);
            bitsResult[n*3+2]=(char)(int)targetImgB(n/targetCols,n%250);
        }
        else{
            bitsResult[n*3]=255;
            bitsResult[n*3+1]=255;
            bitsResult[n*3+2]=255;
        }
        
    }
    

输出:

讲道理应该输出垂直一半白,但是它输出斜的,斜率也不是1,说明差的还不是一个像素,0.几个。
这就难办了。
图片描述

阅读 8.1k
1 个回答

看到你遍历图像数据的代码我就知道你没有考虑无压缩图像存储的一个常识问题,就是图像数据并不是按宽高依次连续存储的。为了内存对齐,我们会对图像的宽度按8或者16取整后再分配存储空间,图像数据实际占用的存储空间比你想的大,下图中【unused】的内存块就是补齐的,给你贴一个参考吧,看了就明白了:
https://msdn.microsoft.com/en...

IC420509.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏