C ++如何使用指针数组缩小图像? [英] C++ how to shrink an image using a pointer array?

查看:125
本文介绍了C ++如何使用指针数组缩小图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个操纵图像的c ++程序,这是缩小它的功能。有一个'像素'指针数组和一个定义了图像颜色的类。除了Visual Studio中包含的其他库之外,我不能使用任何其他库。我遇到了这个函数的问题,我需要遍历图像中的像素并将其分成块;用户将输入块宽度/高度。在创建块之后,需要从每个块中获取平均RGB值(该平均值将成为单个新像素),并且在它们全部排列后它将缩小图像。到目前为止,似乎创建了块,因为图像变小了,但我的图像变成了灰色。 RGB像素的总数正在正确添加,但在其余代码中必须关闭某些内容并且我无法确定它。这是我的代码:

I'm writing a c++ program that manipulates images, and this is the function to shrink it. There is a 'pixel' pointer array and a class that has the image colors defined. I cannot use any other library besides the ones included in Visual Studio for this image program. I'm having an issue with this function, I need to traverse the pixels in the image and split it into blocks; the user will enter the block width/height. After the blocks are created, the average RGB values need to be taken from each block (that average will become a single new pixel), and with all of them arranged it will 'shrink' the image. So far it seems the blocks are created because the image becomes smaller, but my image turns completely gray. The totals for the RGB pixels are adding correctly, but something must be off in the rest of the code and I haven't been able to pinpoint it. Here is my code:

//creates a block of average colors based on range of pixels given
pixel CreateBlock(int start, int stop, pixel** currpix, int blockHeight, int blockWidth)
{
    pixel** block;          //Problem? might have to be a single pointer pixel* block[];
    block = new pixel*[blockHeight];

    for (int i = 0; i < blockHeight; i++)
        block[i] = new pixel[blockWidth];

    pixel newPix;

    float totred = 0, totblue = 0, totgreen = 0;
    int redav = 0.0, blueav = 0.0, greenav = 0.0;

    for (int i = 0; i < blockHeight; i++)
    {
        for (int j = 0; j < blockWidth; j++)
        {
            totred = totred + block[i][j].red;
            totblue = totblue + block[i][j].blue;
            totgreen = totgreen + block[i][j].green;
        }
    }

    redav = totred / (blockHeight*blockWidth);
    blueav = totblue / (blockHeight* blockWidth);
    greenav = totgreen / (blockHeight*blockWidth);

    newPix.red = redav;
    newPix.blue = blueav;
    newPix.green = greenav;

    return newPix;
}

//make a new image that is a smaller resampling of the bigger image
void averageRegions(int blockWidth, int blockHeight)
{
    int height = displayed->getHeight(), width = displayed->getWidth();
    int i = 0, j = 0;
    pixel** currpix = displayed->getPixels();           //PROBLEM
    image* shrunk = displayed;
    //shrunk->getPixels();
    shrunk->createNewImage(width / blockWidth, height / blockHeight);
    while (i < height)
    {
        while (j < width)
        {
            int start = i, stop = i + 10;
            shrunk->getPixels()[i][j] = CreateBlock(start, stop, currpix, blockHeight, blockWidth);
            j = j + blockWidth;
        }
        i = i + blockHeight;
    }

    return;
}

以下是图片类:

class image {
    public:
        image();            //the image constructor (initializes everything)
        image(string filename);  //a image constructor that directly loads an image from disk
        ~image();           //the image destructor  (deletes the dynamically created pixel array)

        void createNewImage(int width, int height); //this function deletes any current image data and creates a new blank image
                                                //with the specified width/height and allocates the needed number of pixels
                                                //dynamically.
        bool loadImage(string filename);        //load an image from the specified file path.  Return true if it works, false if it is not a valid image.
                                            //Note that we only accept images of the RGB 8bit colorspace!
        void saveImage(string filename);       //Save an image to the specified path
        pixel** getPixels();                    //return the 2-dimensional pixels array
        int getWidth();                     //return the width of the image
        int getHeight();                    //return the height of the image

        void viewImage(CImage* myImage);  //This function is called by the windows GUI.  It returns the image in format the GUI understands.


    private:
        void pixelsToCImage(CImage* myImage);  //this function is called internally by the image class.
                                            //it converts our pixel struct array to a standard BGR uchar array with word spacing.
                                            //(Don't worry about what this does)
        pixel** pixels;             // pixel data array for image 
        int width, height;      // stores the image dimensions 
};

以下是像素类:

class pixel
{
public:
    unsigned char red;      //the red component
    unsigned char green;    //the green component
    unsigned char blue;     //the blue component
};


推荐答案

好的,减去大量内存泄漏和误导性名称,您在 CreateBlock 中有正确的想法来查找平均值。我会尝试这样的:

Ok, well minus the massive memory leak and misleading name, you have the right idea in CreateBlock for finding the average. I would try something along the lines of this:

pixel averagePixels(pixel **oldImage, int startRow, int startCol, int blockHeight, int blockWidth){
    float rTot, gTot, bTot;
    pixel avg;

    for(int i = startRow ; i < blockHeight + startRow ; i++){
        for(int j = startCol ; j < blockWidth + startCol ; j++){
            rTot += oldImage[i][j].red;
            gTot += oldImage[i][j].green;
            bTot += oldImage[i][j].blue;
        }
    }
    avg.red   = rTot / (blockHeight * blockWidth);
    avg.green = gTot / (blockHeight * blockWidth);
    avg.blue  = bTot / (blockHeight * blockWidth);
    return avg;
}

pixel **shrinkImage(pixel **oldImage, int blockHeight, int blockWidth){
    int newHeight = oldImage->getHeight() / blockHeight;
    int newWidth  = oldImage->getWidth()  / blockWidth;
    pixel **newImage = new pixel* [newHeight];
    for(int i = 0 ; i < newHeight ; i++)
        newImage[i] = new pixel[newWidth];

    for(int i = 0 ; i < newHeight){
        for(int j = 0 ; j < newWidth){
            newImage[i][j] = averagePixels(oldImage, blockHeight * i, blockWidth * j, blockWidth, blockHeight);
        }
    }
    return newImage;
}

免责声明,我实际上没有测试任何这个,它可能会明智的(至少为了测试目的)确保新的rgb值在可接受的范围内(我认为是0-255?)。当图像大小不能被块大小完全整除时,您还需要一些边界检查/特殊情况。

Disclaimer, I haven't actually tested any of this, and it would probably be wise (at least for testing purposes) to ensure that the new rgb values are within the acceptable range (0-255 I presume?). You'll also need some bounds checking/special cases for when the image size is not perfectly divisible by the block size.

这篇关于C ++如何使用指针数组缩小图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆