两张BMP图片叠加

本文介绍了如何将两张BMP格式的图片进行叠加处理,详细阐述了图片读取、像素合并以及保存结果的步骤,包括使用RGB颜色模型进行像素级别的操作,并提供了相关代码示例。
摘要由CSDN通过智能技术生成
procedure BlendImage(BackBmp, ForeBmp: TBitmap; TransColor: TColor; Alpha: Integer);

type
  TRGBArray = array[0..32767] of TRGBTriple;
  PRGBArray = ^TRGBArray;

var
  X, Y, OffX, OffY: Integer;
  BackRect, ForeRect: TRect;
  BackRGB, ForeRGB: PRGBArray;
  BackR, BackG, BackB: Byte;
  ForeR, ForeG, ForeB: Byte;
begin
  if not Assigned(BackBmp) then exit;
  if not Assigned(ForeBmp) then exit;
  if BackBmp.PixelFormat <> pf24bit then Exit;
  if ForeBmp.PixelFormat <> pf24bit then Exit;
  if (BackBmp.Empty) or (ForeBmp.Empty) then Exit;
  BackRect := BackBmp.Canvas.ClipRect;
  ForeRect := ForeBmp.Canvas.ClipRect;
  DockRect(ForeRect, BackRect);
  OffX := ForeRect.Left - BackRect.Left;
  OffY := ForeRect.Top - BackRect.Top;
  for Y := 0 to BackBmp.Height - 1 do
  begin
    if (Y > ForeRect.Bottom - 1) or
      (Y < ForeRect.Top) then Continue;
    BackRGB := BackBmp.ScanLine[Y];
    ForeRGB := ForeBmp.ScanLine[Y 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
BMP 图片叠加的 C++ 实现可以参考以下代码: ```c++ #include <iostream> #include <fstream> #include <vector> #include <cstring> using namespace std; #pragma pack(push, 1) // BMP 文件头结构体 typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 文件类型,必须为 "BM" unsigned int bfSize; // 文件大小,单位为字节 unsigned short bfReserved1; // 保留字段 unsigned short bfReserved2; // 保留字段 unsigned int bfOffBits; // 从文件头到像素数据的偏移量,单位为字节 } BITMAPFILEHEADER; // BMP 信息头结构体 typedef struct tagBITMAPINFOHEADER { unsigned int biSize; // 信息头大小,单位为字节 int biWidth; // 图像宽度,单位为像素 int biHeight; // 图像高度,单位为像素 unsigned short biPlanes; // 位平面数,必须为 1 unsigned short biBitCount; // 每像素位数,常用的为 1、4、8、24 unsigned int biCompression; // 压缩方式,常用的为 0(不压缩) unsigned int biSizeImage; // 像素数据大小,单位为字节 int biXPelsPerMeter; // 水平分辨率,单位为像素/米 int biYPelsPerMeter; // 垂直分辨率,单位为像素/米 unsigned int biClrUsed; // 使用的颜色数,如果为 0,则使用所有颜色 unsigned int biClrImportant; // 重要的颜色数,如果为 0,则都重要 } BITMAPINFOHEADER; // BMP 调色板结构体 typedef struct tagRGBQUAD { unsigned char rgbBlue; // 蓝色分量 unsigned char rgbGreen; // 绿色分量 unsigned char rgbRed; // 红色分量 unsigned char rgbReserved; // 保留字段 } RGBQUAD; #pragma pack(pop) // 读取 BMP 文件 bool loadBmp(const char *filename, vector<unsigned char> &imageData, BITMAPFILEHEADER &bmpFileHeader, BITMAPINFOHEADER &bmpInfoHeader, vector<RGBQUAD> &bmpPalette) { // 打开 BMP 文件 ifstream file(filename, ios::binary); if (!file) { cerr << "Error: BMP file not found." << endl; return false; } // 读取 BMP 文件头 file.read(reinterpret_cast<char *>(&bmpFileHeader), sizeof(BITMAPFILEHEADER)); if (bmpFileHeader.bfType != 0x4D42) { cerr << "Error: Invalid BMP file format." << endl; return false; } // 读取 BMP 信息头 file.read(reinterpret_cast<char *>(&bmpInfoHeader), sizeof(BITMAPINFOHEADER)); if (bmpInfoHeader.biBitCount != 24 && bmpInfoHeader.biBitCount != 32) { cerr << "Error: Unsupported BMP bit count." << endl; return false; } // 读取 BMP 调色板(如果有) if (bmpInfoHeader.biClrUsed != 0) { bmpPalette.resize(bmpInfoHeader.biClrUsed); file.read(reinterpret_cast<char *>(bmpPalette.data()), bmpInfoHeader.biClrUsed * sizeof(RGBQUAD)); } // 读取 BMP 图像数据 imageData.resize(bmpInfoHeader.biSizeImage); file.read(reinterpret_cast<char *>(imageData.data()), bmpInfoHeader.biSizeImage); // 关闭 BMP 文件 file.close(); return true; } // 保存 BMP 文件 bool saveBmp(const char *filename, const vector<unsigned char> &imageData, const BITMAPFILEHEADER &bmpFileHeader, const BITMAPINFOHEADER &bmpInfoHeader, const vector<RGBQUAD> &bmpPalette) { // 创建 BMP 文件 ofstream file(filename, ios::binary); if (!file) { cerr << "Error: Failed to create BMP file." << endl; return false; } // 写入 BMP 文件头 file.write(reinterpret_cast<const char *>(&bmpFileHeader), sizeof(BITMAPFILEHEADER)); // 写入 BMP 信息头 file.write(reinterpret_cast<const char *>(&bmpInfoHeader), sizeof(BITMAPINFOHEADER)); // 写入 BMP 调色板(如果有) if (bmpInfoHeader.biClrUsed != 0) { file.write(reinterpret_cast<const char *>(bmpPalette.data()), bmpInfoHeader.biClrUsed * sizeof(RGBQUAD)); } // 写入 BMP 图像数据 file.write(reinterpret_cast<const char *>(imageData.data()), bmpInfoHeader.biSizeImage); // 关闭 BMP 文件 file.close(); return true; } // 将两张 BMP 图片叠加 bool blendBmp(const vector<unsigned char> &imageData1, const BITMAPINFOHEADER &bmpInfoHeader1, const vector<unsigned char> &imageData2, const BITMAPINFOHEADER &bmpInfoHeader2, vector<unsigned char> &imageData3, BITMAPINFOHEADER &bmpInfoHeader3) { // 检查两张 BMP 图片是否具有相同的尺寸和位深度 if (bmpInfoHeader1.biWidth != bmpInfoHeader2.biWidth || bmpInfoHeader1.biHeight != bmpInfoHeader2.biHeight || bmpInfoHeader1.biBitCount != bmpInfoHeader2.biBitCount) { cerr << "Error: BMP images have different sizes or bit depths." << endl; return false; } // 拷贝 BMP 信息头 memcpy(&bmpInfoHeader3, &bmpInfoHeader1, sizeof(BITMAPINFOHEADER)); // 计算 BMP 图像数据大小(注意,必须按 4 字节对齐) int rowSize = (bmpInfoHeader1.biWidth * bmpInfoHeader1.biBitCount + 31) / 32 * 4; bmpInfoHeader3.biSizeImage = rowSize * bmpInfoHeader1.biHeight; // 分配 BMP 图像数据内存 imageData3.resize(bmpInfoHeader3.biSizeImage); // 循环遍历 BMP 图像数据,并将两张 BMP 图片叠加 int imageSize = bmpInfoHeader1.biWidth * bmpInfoHeader1.biHeight * (bmpInfoHeader1.biBitCount / 8); for (int i = 0; i < imageSize; i += (bmpInfoHeader1.biBitCount / 8)) { int r1 = imageData1[i + 2]; int g1 = imageData1[i + 1]; int b1 = imageData1[i]; int r2 = imageData2[i + 2]; int g2 = imageData2[i + 1]; int b2 = imageData2[i]; int r3 = min(r1 + r2, 255); int g3 = min(g1 + g2, 255); int b3 = min(b1 + b2, 255); imageData3[i] = static_cast<unsigned char>(b3); imageData3[i + 1] = static_cast<unsigned char>(g3); imageData3[i + 2] = static_cast<unsigned char>(r3); } return true; } int main() { // 读取第一张 BMP 图片 BITMAPFILEHEADER bmpFileHeader1; BITMAPINFOHEADER bmpInfoHeader1; vector<unsigned char> imageData1; vector<RGBQUAD> bmpPalette1; if (!loadBmp("image1.bmp", imageData1, bmpFileHeader1, bmpInfoHeader1, bmpPalette1)) { return 1; } // 读取第二张 BMP 图片 BITMAPFILEHEADER bmpFileHeader2; BITMAPINFOHEADER bmpInfoHeader2; vector<unsigned char> imageData2; vector<RGBQUAD> bmpPalette2; if (!loadBmp("image2.bmp", imageData2, bmpFileHeader2, bmpInfoHeader2, bmpPalette2)) { return 1; } // 将两张 BMP 图片叠加 vector<unsigned char> imageData3; BITMAPINFOHEADER bmpInfoHeader3; if (!blendBmp(imageData1, bmpInfoHeader1, imageData2, bmpInfoHeader2, imageData3, bmpInfoHeader3)) { return 1; } // 保存叠加后的 BMP 图片 BITMAPFILEHEADER bmpFileHeader3; bmpFileHeader3.bfType = 0x4D42; bmpFileHeader3.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmpInfoHeader3.biSizeImage; bmpFileHeader3.bfReserved1 = 0; bmpFileHeader3.bfReserved2 = 0; bmpFileHeader3.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); if (!saveBmp("image3.bmp", imageData3, bmpFileHeader3, bmpInfoHeader3, bmpPalette1)) { return 1; } return 0; } ``` 这段代码中,loadBmp() 函数用于读取 BMP 文件,saveBmp() 函数用于保存 BMP 文件,blendBmp() 函数用于将两张 BMP 图片叠加。在主函数中,首先读取两张 BMP 图片,然后将它们叠加,并保存为新的 BMP 文件。需要注意的是,这段代码中只支持 24 位和 32 位的 BMP 图片。如果需要支持其他位深度的 BMP 图片,需要进行相应的修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值