C 缩放位图图像时出错

C 缩放位图图像时出错,c,bitmap,bitmapimage,C,Bitmap,Bitmapimage,大家好,学习C语言,做一个C语言编程作业,我要缩放给定的位图图像,我整天都在做这个。到目前为止,这是我的代码,但我遇到了一个SEGFULT,无法找出原因。我一整天都在跟踪代码,只是被卡住了。这是我的代码的功能,以规模,任何帮助将不胜感激 int enlarge(PIXEL* original, int rows, int cols, int scale, PIXEL** new, int* newrows, int* newcols) { int ncols, nrows;

大家好,学习C语言,做一个C语言编程作业,我要缩放给定的位图图像,我整天都在做这个。到目前为止,这是我的代码,但我遇到了一个SEGFULT,无法找出原因。我一整天都在跟踪代码,只是被卡住了。这是我的代码的功能,以规模,任何帮助将不胜感激

int enlarge(PIXEL* original, int rows, int cols, int scale, 
    PIXEL** new, int* newrows, int* newcols) 
{
  int ncols, nrows;
  ncols = cols * scale;
  nrows = rows * scale;
  double xratio =(double) rows / nrows;
  double yratio =(double) cols / ncols;
  int px, py;
  int auxw, cnt;
  int i, j;

 *new = (PIXEL*)malloc(nrows * ncols * sizeof(PIXEL));
  for (i = 0; i < nrows; i++){
    auxw = 0;
    cnt = 0;
    int m = i * 3;
     for (j = 0; j < ncols; j++){
         px = (int)floor( j * xratio);
         py = (int)floor( i * yratio);

         PIXEL* o1 = original + ((py*rows + px) *3);
         PIXEL* n1 = (*new) + m*ncols + j + auxw;
         *n1 = *o1;

         PIXEL* o2 = original + ((py*rows + px) *3) + 1;
         PIXEL* n2 = (*new) + m*ncols + j + 1 + auxw;
         *n2 = *o2;

         PIXEL* o3 = original + ((py*rows + px) *3) + 2;
         PIXEL* n3 = (*new) + m*ncols + j + 2 + auxw;
         *n3 = *o3;

         auxw += 2;
         cnt++;
       }
     }
 return 0;
}
然而,我不明白到底是什么问题

谢谢

编辑: 根据教授为我们提供的代码,像素的定义如下:

typedef struct {
  unsigned char r;
  unsigned char g;
  unsigned char b;
} PIXEL;
据我所知,我有一个二维数组,数组中的每个元素都包含一个3元素的像素数组。
此外,在纸上跟踪代码时,我添加了auxw逻辑,以便向下推进阵列。它的工作原理与乘以3的方式大致相同。

你的数组是一个由
像素
对象组成的
cols X rows
数组,还是实际上是一个由
像素
对象组成的
cols X rows X 3
数组,而你所说的a实际上是像素的一个组成部分?你的代码不清楚。访问
原始
阵列时,乘以3,表示一个包含3个通道的阵列:

     PIXEL* o1 = original + ((py*rows + px) *3);
但是当访问
(*new)
数组时,没有3的乘法,相反,有一些逻辑我无法使用
auxw

     PIXEL* n1 = (*new) + m*ncols + j + auxw;

     auxw += 2;
无论如何,假设您所称的像素实际上是一个通道,并且每个像素中有标准的3个RGB通道,则需要为阵列分配3倍的内存:

     *new = (PIXEL*)malloc(nrows * ncols * 3*sizeof(PIXEL));
其他一些问题:

  • int*newrows
    int*newcols
    从未初始化。您可能希望将它们初始化为
    nrows
    ncols

  • 如果
    像素
    确实是一个
    频道
    ,则将其重命名以正确表达其含义

  • 与其到处复制多维数组指针算法的逻辑,不如使用以下函数保护自己,使其不受像素/通道/任何数组索引的影响:

    #include "assert.h"
    
    PIXEL *get_channel(PIXEL *pixelArray, int nRows, int nCols, int nChannels, int iRow, int iCol, int iChannel)
    {
        if (iRow < 0 || iRow >= nRows)
        {
            assert(!(iRow < 0 || iRow >= nRows));
            return NULL;
        }
        if (iCol < 0 || iCol >= nCols)
        {
            assert(!(iRow < 0 || iRow >= nRows));
            return NULL;
        }
        if (iChannel < 0 || iChannel >= nChannels)
        {
            assert(!(iChannel < 0 || iChannel >= nChannels));
            return NULL;
        }
        return pixelArray + (iRow * nCols + iCol) * nChannels + iChannel;
    }
    
  • 使用标准的
    get\u channel()
    函数的另一个原因是指针算法不一致:

     PIXEL* o1 = original + ((py*rows + px) *3);
     PIXEL* n1 = (*new) + m*ncols + j + auxw;
    
    要访问
    原始
    像素,请执行
    阵列+iCol*nRows+iRow
    ,这看起来不错。但是要访问
    *new
    数组,您需要执行
    array+iCol*nCols+iRow
    ,这看起来是错误的。创建一个函数来访问任何像素阵列、调试它并使用它

  • 更新

    鉴于您对像素结构的定义,您无需“添加那些+1和+2值,使我能够到达像素结构的第二个和第三个元素”。因为像素结构是一个结构,如果您有一个指向该结构的指针,您可以使用操作符访问其字段:

                PIXEL *p_oldPixel = get_pixel(old, nRowsOld, nColsOld, iRowOld, iColOld);
                PIXEL *p_newPixel = get_pixel(*p_new, nRowsNew, nColsNew, iRowNew, iColNew);
    
                p_newPixel->r = p_oldPixel->r;
                p_newPixel->g = p_oldPixel->g;
                p_newPixel->b = p_oldPixel->b;
    
    或者,在这种情况下,您可以使用:

    至于通过
    PIXEL
    数组进行索引,由于指针被正确声明为
    PIXEL*
    ,因此C编译器的算法将被调用

    此外,我建议您使用清晰一致的命名约定来澄清代码:

  • 对循环迭代器和边界使用一致的描述性名称。
    i
    是行还是列?为什么在一个地方使用
    i
    ,而在另一个地方使用
    py
    ?一致的命名约定有助于确保您永远不会混淆行和列

  • 通过在“p_”前面加上“p_ptr”将指针与变量或结构区分开来。明确区分指针的命名约定可以使按引用传递的实例更加清晰,因此(例如)您不会忘记初始化输出参数

  • 对与新旧位图对应的所有变量使用相同的音节。例如,如果有名为
    old
    nRowsOld
    nColsOld
    的参数,则不太可能在新位图中意外使用
    nColsOld

  • 因此,您的代码变成:

    #include "assert.h"
    
    typedef struct _pixel {
        unsigned char r;
        unsigned char g;
        unsigned char b;
    } PIXEL;
    
    PIXEL *get_pixel(PIXEL *pixelArray, int nRows, int nCols, int iRow, int iCol)
    {
        if (iRow < 0 || iRow >= nRows)
        {
            assert(!(iRow < 0 || iRow >= nRows));
            return NULL;
        }
        if (iCol < 0 || iCol >= nCols)
        {
            assert(!(iRow < 0 || iRow >= nRows));
            return NULL;
        }
        return pixelArray + iRow * nCols + iCol;
    }
    
    int enlarge(PIXEL* old, int nRowsOld, int nColsOld, int scale, 
        PIXEL **p_new, int *p_nRowsNew, int *p_nColsNew) 
    {
        int nColsNew = nColsOld * scale;
        int nRowsNew = nRowsOld * scale;
        double xratio =(double) nRowsOld / nRowsNew;
        double yratio =(double) nColsOld / nColsNew;
        int iRowNew, iColNew;
    
        *p_new = malloc(nRowsNew * nColsNew * sizeof(PIXEL));
        *p_nRowsNew = nRowsNew;
        *p_nColsNew = nColsNew;
        for (iRowNew = 0; iRowNew < nRowsNew; iRowNew++){
            for (iColNew = 0; iColNew < nColsNew; iColNew++){
                int iColOld = (int)floor( iColNew * xratio);
                int iRowOld = (int)floor( iRowNew * yratio);
    
                PIXEL *p_oldPixel = get_pixel(old, nRowsOld, nColsOld, iRowOld, iColOld);
                PIXEL *p_newPixel = get_pixel(*p_new, nRowsNew, nColsNew, iRowNew, iColNew);
    
                *p_newPixel = *p_oldPixel;
            }
        }
    
        return 0;
    }
    
    #包括“assert.h”
    typedef结构像素{
    无符号字符r;
    无符号字符g;
    无符号字符b;
    }像素;
    像素*获取像素(像素*像素阵列,int nRows,int nCols,int iRow,int iCol)
    {
    如果(iRow<0 | | iRow>=nRows)
    {
    断言(!(iRow<0 | | iRow>=nRows));
    返回NULL;
    }
    如果(iCol<0 | | iCol>=nCols)
    {
    断言(!(iRow<0 | | iRow>=nRows));
    返回NULL;
    }
    返回像素数组+iRow*nCols+iCol;
    }
    整数放大(像素*old,整数nRowsOld,整数nColsOld,整数比例,
    像素**p_新建,int*p_nRowsNew,int*p_nColsNew)
    {
    int nColsNew=nColsOld*刻度;
    int nRowsNew=nRowsOld*刻度;
    双X比率=(双)nRowsOld/nRowsNew;
    双yratio=(双)nColsOld/NCOLSONEW;
    int iRowNew、iColNew;
    *p_new=malloc(nRowsNew*nColsNew*sizeof(像素));
    *p_nRowsNew=nRowsNew;
    *p_nColsNew=nColsNew;
    对于(iRowNew=0;iRowNew

    我还没有测试过这段代码,但是通过使用一致的命名约定,人们可以清楚地看到它在做什么以及为什么它应该工作。

    您已经分配了相当于
    ncols
    的内存,但是您正在使用
    ncols+2
    ?这条线
    PIXEL*n3=(*new)+m*ncols+j+2+auxw
    当我在纸上跟踪代码时,添加+1和+2值允许我到达像素结构的第二个和第三个元素。关于像素的定义,请参考我在原始帖子上的编辑。谢谢你的回复。我正在努力
                PIXEL *p_oldPixel = get_pixel(old, nRowsOld, nColsOld, iRowOld, iColOld);
                PIXEL *p_newPixel = get_pixel(*p_new, nRowsNew, nColsNew, iRowNew, iColNew);
    
                p_newPixel->r = p_oldPixel->r;
                p_newPixel->g = p_oldPixel->g;
                p_newPixel->b = p_oldPixel->b;
    
                *p_newPixel = *p_oldPixel;
    
    #include "assert.h"
    
    typedef struct _pixel {
        unsigned char r;
        unsigned char g;
        unsigned char b;
    } PIXEL;
    
    PIXEL *get_pixel(PIXEL *pixelArray, int nRows, int nCols, int iRow, int iCol)
    {
        if (iRow < 0 || iRow >= nRows)
        {
            assert(!(iRow < 0 || iRow >= nRows));
            return NULL;
        }
        if (iCol < 0 || iCol >= nCols)
        {
            assert(!(iRow < 0 || iRow >= nRows));
            return NULL;
        }
        return pixelArray + iRow * nCols + iCol;
    }
    
    int enlarge(PIXEL* old, int nRowsOld, int nColsOld, int scale, 
        PIXEL **p_new, int *p_nRowsNew, int *p_nColsNew) 
    {
        int nColsNew = nColsOld * scale;
        int nRowsNew = nRowsOld * scale;
        double xratio =(double) nRowsOld / nRowsNew;
        double yratio =(double) nColsOld / nColsNew;
        int iRowNew, iColNew;
    
        *p_new = malloc(nRowsNew * nColsNew * sizeof(PIXEL));
        *p_nRowsNew = nRowsNew;
        *p_nColsNew = nColsNew;
        for (iRowNew = 0; iRowNew < nRowsNew; iRowNew++){
            for (iColNew = 0; iColNew < nColsNew; iColNew++){
                int iColOld = (int)floor( iColNew * xratio);
                int iRowOld = (int)floor( iRowNew * yratio);
    
                PIXEL *p_oldPixel = get_pixel(old, nRowsOld, nColsOld, iRowOld, iColOld);
                PIXEL *p_newPixel = get_pixel(*p_new, nRowsNew, nColsNew, iRowNew, iColNew);
    
                *p_newPixel = *p_oldPixel;
            }
        }
    
        return 0;
    }