图像裁剪,输出的文件图像全黑

裁剪图片的程序。
输入一个BMP文件,我的是400*400大小的RGB通道图片,位深度是24位,为什么输出的图像文件是全黑色的,我确定了是最后写入输出图片文件的问题,但是不知道要怎么改


//
// Created by ztheng on 2023/9/5.
//

#ifndef CLION_BMPFILE_H
#define CLION_BMPFILE_H


#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstring>

#define FILENAME "../Dinosaur.bmp"




#pragma pack(push, 1)
struct BMP {
    uint16_t fileType;//用来标识文件类型,通常被设置为固定值 0x4D42,它表示这是一个 BMP 图像文件
    uint32_t fileSize;//表示整个 BMP 文件的大小,以字节为单位
    //下面两个参数都是保留字,没有特定的用途
    uint16_t reserved1;
    uint16_t reserved2;
    uint32_t dataOffset;//表示图像数据相对于文件起始位置的偏移量,单位是字节
}bmp,newBmp;
#pragma pack(pop)


#pragma pack(push, 1)
struct BMPInfo {
    uint32_t headerSize;//BMP 文件头的大小,通常为 40 字节
    //BMP 文件头的大小,通常为 40 字节
    int32_t width;
    int32_t height;
    //一个 16 位的整数,通常设置为 1。在现代 BMP 文件中,这个值几乎总是为 1。在早期的 BMP 文件格式中,有些图像可能会使用多个平面来表示颜色信息,但这在现代 BMP 图像中已经不再使用。
    uint16_t planes;
    //这是一个 16 位的整数,表示每个像素使用的位数,决定了图像的颜色深度。例如,24 位的图像表示每个像素由 3 个 8 位通道组成(红、绿、蓝)
    uint16_t bitsPerPixel;
    //这是一个 32 位的整数,表示图像的压缩方式。通常,不压缩的 BMP 图像文件中,这个值为 0。
    uint32_t compression;
    //这是一个 32 位的整数,表示图像数据的大小,以字节为单位。它告诉你图像数据占用了多少存储空间。
    uint32_t imageSize;
    //下面这两个参数分别是 32 位的整数,表示图像的水平和垂直像素密度,以像素每米为单位
    int32_t xPixelsPerMeter;
    int32_t yPixelsPerMeter;
    //下面这两个参数是 32 位的整数,通常不太影响非索引颜色的 BMP 图像。它们在索引颜色的 BMP 图像中用于指定调色板中的颜色数量和重要颜色数量。
    uint32_t colorsUsed;
    uint32_t colorsImportant;
}bmpInfo,newBmpInfo;
#pragma pack(pop)


void ImgInfo(const BMP& inBmp,const BMPInfo& inBmpInfo)
{
    std::cout<<"this is a BMP file"<<std::endl
    <<"BMPHeader info:"<<std::endl
    <<"---------------"<<std::endl
    <<"fileType文件类型: "<<inBmp.fileType<<std::endl
    <<"fileSize文件大小: "<<inBmp.fileSize<<std::endl
    <<"reserved1保留字段1: "<<inBmp.reserved1<<std::endl
    <<"reserved2保留字段2: "<<inBmp.reserved2<<std::endl
    <<"dataOffset数据偏移量: "<<inBmp.dataOffset<<std::endl
    <<"---------------"<<std::endl
    <<"BMPInfo:"<<std::endl
    <<"headerSize信息头大小: "<<inBmpInfo.headerSize<<std::endl
    <<"width图像宽度: "<<inBmpInfo.width<<std::endl
    <<"height图像高度: "<<inBmpInfo.height<<std::endl
    <<"planes颜色平面数: "<<inBmpInfo.planes<<std::endl
    <<"bitsPerPixel每像素位数: "<<inBmpInfo.bitsPerPixel<<std::endl
    <<"compression压缩方式: "<<inBmpInfo.compression<<std::endl
    <<"imageSize图像数据大小: "<<inBmpInfo.imageSize<<std::endl
    <<"xPixelsPerMeter水平像素每米数: "<<inBmpInfo.xPixelsPerMeter<<std::endl
    <<"yPixelsPerMeter垂直像素每米数: "<<inBmpInfo.yPixelsPerMeter<<std::endl
    <<"colorsUsed实际使用的颜色数: "<<inBmpInfo.colorsUsed<<std::endl
    <<"colorsImportant重要颜色数: "<<inBmpInfo.colorsImportant<<std::endl
    <<"-----------------"<<std::endl;

}

void CreateNewBmp()
{
    newBmp=bmp;
    newBmpInfo=bmpInfo;

}

int OutputToFile(std::vector<uint8_t>& imageData,std::string name)
{

    // open output file
    std::ofstream outputFile(name);


    if (!outputFile.is_open()) {
        std::cerr << "无法打开文件!" << std::endl;
        return 1;
    }

    // foreach imageData
    for (uint8_t byte : imageData) {
        outputFile << static_cast<int>(byte) << " ";
    }

    outputFile.close();

    std::cout << "write done!" << std::endl;
    std::cout << "-----------" << std::endl;
    std::cout << "-----------" << std::endl;
    std::cout << "-----------" << std::endl;

}




#endif //CLION_BMPFILE_H

//
// Created by ztheng on 2023/9/5.
//
#include "BMPFile.h"

int main() {

    std::ifstream inputFile(FILENAME, std::ios::binary);
    if (!inputFile.is_open()) {
        std::cout << "unable to open it!" << std::endl;
        return 1;
    }

    inputFile.read(reinterpret_cast<char*>(&bmp), sizeof(BMP));

    if (bmp.fileType != 0x4D42) { // BM ASCII
        std::cout << "file is not invalid!" << std::endl;
        return 1;
    }


    // read header
    inputFile.read(reinterpret_cast<char*>(&bmpInfo), sizeof(BMPInfo));

    // offset
    uint32_t imageDataOffset = bmp.dataOffset;
    //set imageSize imageSize=width*height*字节 480000
    uint32_t imageDataSize = bmpInfo.imageSize;

    //ImgInfo(bmp, bmpInfo);

    //move to image data
    std::vector<uint8_t> imageData(imageDataSize);


    inputFile.seekg(imageDataOffset);
    //read
    inputFile.read(reinterpret_cast<char*>(imageData.data()), imageDataSize);

    // close

    inputFile.close();

    CreateNewBmp();
    int32_t height;
    int32_t width;
    std::cout << "please input height and width" << std::endl
              << "height: " << std::endl;
    std::cin >> height;
    std::cout << "width: " << std::endl;
    std::cin >> width;
    newBmpInfo.height = height;
    newBmpInfo.width = width;
    newBmpInfo.imageSize = newBmpInfo.width * newBmpInfo.height * (newBmpInfo.bitsPerPixel / 8);
    newBmp.fileSize = sizeof(newBmp) + sizeof(newBmpInfo) + newBmpInfo.imageSize;
    //30000
    uint32_t tempImageDataSize = newBmpInfo.imageSize;
    std::vector<uint8_t> newImageData(newBmpInfo.height * newBmpInfo.width * 3);
    //480000-30000=450000
    uint32_t newImageDataSize =imageDataSize-tempImageDataSize;
    //480000-450000
    //imageData.insert(imageData.end(),newImageData.begin(),newImageData.end());
    //OutputToFile(newImageData,"newImageData");
    // fuction
    //TailorImg(height,width,imageData);
    //ImgInfo(newBmp, newBmpInfo);
    // create file
    std::ofstream outputFile("outColorTailor.bmp", std::ios::binary);
    if (!outputFile.is_open()) {
        std::cout << "unable to create this file!" << std::endl;
        return 1;
    }
    outputFile.write(reinterpret_cast<const char*>(&newBmp), sizeof(newBmp));
    outputFile.write(reinterpret_cast<const char*>(&newBmpInfo), sizeof(newBmpInfo));
    //write file
    //计算要写入文件的实际字节数,以确保只有有效的图像数据被写入文件,而不会包括任何未使用的内存。
    outputFile.write(reinterpret_cast<const char*>(newImageData.data()), newImageDataSize);
    // close file
    outputFile.close();
    std::cout << "success" << std::endl;

    return 0;

}



【相关推荐】




如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^