【问题标题】:flip BMP image horizontal in c在c中水平翻转BMP图像
【发布时间】:2019-10-18 07:19:17
【问题描述】:

我的函数正在获取图像,我正在尝试将其向右或向左翻转。水平翻转。我试图做类似的事情,但不知道如何前进

图像的大小是整数高度和整数宽度,函数知道像素值。

这是我的代码:

void flip_hrizntal_pixels(struct Pixel **pixels, int height, int width)
{
    //Stuck here don't know how flip those pixels 
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            //pixels[i][j].red = 
            //pixels[i][j].green = 
            //pixels[i][j].blue = 
        }
    }

}

这里是结构数据:

struct Pixel
{
    unsigned char red;
    unsigned char green;
    unsigned char blue;
};
struct RGB_Image
{
    long height;
    long width;
    long size;
    struct Pixel **pixels;
};

我是这样调用这个函数的:

struct RGB_Image image;
int status = load_image(&image); 
flip_hrizntal_pixels(image.pixels, image.height, image.width);

【问题讨论】:

  • 您的内部循环需要将第一个像素与最后一个像素交换,并在将行的前半部分与后半部分交换时停止。这有帮助吗?
  • 嗨,斯塔克,谢谢! ,对不起,我是 c 的新手,不知道该怎么做。

标签: c image-processing


【解决方案1】:

以下C代码左右翻转RGB图像:

//Flip RGB (or BGR) image Left/Right.
//P is an array of <height> pointers.
//P[0] points first pixel of first row.
//P[1] points first pixel of second row.
//P[height-1] points first pixel of last row.
static void flip_hrizntal_pixels(Pixel **P, int height, int width)
{
    //Allocate sketch buffer for storing single flipped row.
    Pixel *R = (Pixel*)malloc(width*sizeof(Pixel));

    //Stuck here don't know how flip those pixels 
    for (int i = 0; i < height; i++)
    {
        Pixel *I0 = P[i];    //Points first pixel in source image

        //j is destination index (index of rgb triple in source image I).
        for (int j = 0; j < width; j++)
        {
            //Iterate source row from end of row to beginning of row.
            R[j].red    = I0[width - j - 1].red;
            R[j].green  = I0[width - j - 1].green;
            R[j].blue   = I0[width - j - 1].blue;
        }

        //Copy flipped row back to image P.
        memcpy(I0, R, width*sizeof(Pixel));
    }

    free(R);
}

在执行flip_hrizntal_pixels之前,需要准备一个指针数组。

以字节为单位计算图像步幅:
stride 是两个连续行之间的字节数。
对于 BMP 格式,stride 必须是 4 的倍数(填充,以防宽度不是 4 的倍数)。

int stride = width*3;

//For supporting width that is not a multiple of 4, stride in bytes is padded up to nearest multiple of 4 bytes.
stride = (stride + 3) & (~3);  //http://mapw.elte.hu/elek/bmpinmemory.html

准备指向行的指针数组:
假设I 是指向输入图像的指针。

//Prepare and array of pointers to rows:
//////////////////////////////////////////////////////////////////////////
//P[0] -> Points beginning of first row.
//P[1] -> Points beginning of second row.
//...
//P[height-1] -> Points beginning of last row.    
//Allocate array of <height> pointers.
Pixel **P = (Pixel**)malloc(height*sizeof(Pixel*));

for (int i = 0; i < height; i++)
{
    P[i] = (Pixel*)((char*)I + stride*i); //Advance by <stride> bytes from row to row.
}
//////////////////////////////////////////////////////////////////////////

执行flip_hrizntal_pixels

flip_hrizntal_pixels(P,
                     height, 
                     width);

清理:

free(P);

测试(来自 MATLAB 的peppers.png 图像):

输入图片:

输出图片:

【讨论】:

  • 这是否考虑到每行末尾的潜在填充?
  • @RetiredNinja 它看起来不像,但公平地说,OPs 结构似乎也没有。正如Rotem所说,像素顺序是错误的,所以我认为这是一种自定义位图格式。
  • @RetiredNinja 谢谢!很好的解决方案,但是在我的程序中,已经有一个使用 struct Pixel **pixels 的预先声明指令。
  • 谢谢@Rotem,我想知道你是否可以帮助我实现类似的方法:void flip_hrizntal_pixels(struct Pixel **pixels, int height, int width) in parameters where am using struct Pixel **像素
  • 完成!我警告过你这会很混乱......(在准备好指针数组之后,你也可以执行 ARD 解决方案)。
【解决方案2】:

想象一下,你的图片被排列成行和列的像素,每个像素都有 R、G 和 B。每行将有“宽度”个像素,并且会有这样的“高度”行数。

因此,要水平翻转,即一行中最右边的像素转到最左边,反之亦然,然后是同一行中的第二个像素,与倒数第二个像素交换,依此类推,代码将是这样的。 (PS:这只是一个快速代码,让您了解如何继续。我还没有编译/运行我的代码)

希望对你有帮助

void flip_hrizntal_pixels(struct Pixel **pixels, int height, int width)
{
Pixel tempPixel;

for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width/2; j++)
    {
    //make a temp copy of the 'j-th' Pixel  
    tempPixel.red = pixels[i][j].red; 
    tempPixel.green = pixels[i][j].green;  
    tempPixel.blue = pixels[i][j].blue; 


    //copy the corresponding last Pixel to the j-th pixel 
    pixels[i][j].red = pixels[i][width-j].red; 
    pixels[i][j].green = pixels[i][width-j].green; 
    pixels[i][j].blue = pixels[i][width-j].blue;


    //copy the temp copy that we made earlier of j-th Pixel to the corresponding last Pixel
    pixels[i][width-j].red = tempPixel.red;
    pixels[i][width-j].green = tempPixel.green;
    pixels[i][width-j].blue = tempPixel.blue;

    }
}

}

【讨论】:

  • 最好停在width/2,否则你会把它们全部翻回去!
  • 将所有内容放在一行中会使这非常不可读。考虑将其拆分,以便无需向右滚动即可阅读。
  • 感谢韦斯顿和退休忍者的 cmets! :-) 我已经根据您的 cmets 更新了我的答案。麦克斯,如果这让你朝着正确的方向前进,那么你能接受答案吗?
  • 谢谢@ARD,我要检查一下,看起来不错的解决方案:)
猜你喜欢
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2019-11-26
  • 1970-01-01
相关资源
最近更新 更多