群里的小学弟问怎么给bmp图片加水印, 我就看了一下资料, 试着弄一下
//
// main.c
// BMPtes
//
// Created by 西博尔 on 2017/9/7.
// Copyright © 2017年 西博尔. All rights reserved.
//
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#pragma pack(1) //作用:C编译器将按照1个字节对齐,很关键
#define WIDTHBYTES(bits) (((bits)+31)/32*4)
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
//位图文件头信息结构定义
//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件
unsigned int bfSize; // 文件大小
unsigned short bfReserved1; // 保留,必须设置为0
unsigned short bfReserved2; // 保留,必须设置为0
unsigned int bfOffBits; // 从文件头到像素数据的偏移
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
unsigned int biSize; // 此结构体的大小
int biWidth; // 图像的宽
int biHeight; // 图像的高
unsigned short biPlanes; // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1
unsigned short biBitCount; // 一像素所占的位数,一般为24
unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。
unsigned int biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits
int biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0
int biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0
unsigned int biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
unsigned int biClrImportant;// 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
} BITMAPINFOHEADER;
typedef struct tagRGBQUAD {
//public:
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值
} RGBQUAD;
void showBmpHead(BITMAPFILEHEADER* pBmpHead)
{
printf("位图文件头:\n");
printf("文件大小:%u\n",pBmpHead->bfSize);
printf("保留字:%d\n",pBmpHead->bfReserved1);
printf("保留字:%d\n",pBmpHead->bfReserved2);
printf("实际位图数据的偏移字节数:%u\n",pBmpHead->bfOffBits);
}
void showBmpInforHead(BITMAPINFOHEADER* pBmpInforHead)
{
printf("位图信息头:\n");
printf("结构体的长度:%u\n",pBmpInforHead->biSize);
printf("位图宽:%d\n",pBmpInforHead->biWidth);
printf("位图高:%d\n",pBmpInforHead->biHeight);
printf("biPlanes平面数:%d\n",pBmpInforHead->biPlanes);
printf("biBitCount采用颜色位数:%d\n",pBmpInforHead->biBitCount);
printf("压缩方式:%u\n",pBmpInforHead->biCompression);
printf("biSizeImage实际位图数据占用的字节数:%u\n",pBmpInforHead->biSizeImage);
printf("X方向分辨率:%d\n",pBmpInforHead->biXPelsPerMeter);
printf("Y方向分辨率:%d\n",pBmpInforHead->biYPelsPerMeter);
printf("使用的颜色数:%u\n",pBmpInforHead->biClrUsed);
printf("重要颜色数:%u\n",pBmpInforHead->biClrImportant);
}
int main(int argc, const char * argv[]) {
char * filePath = "/Users/西博尔/Desktop/bmp图片/QQ图片20170830184242.bmp"; //到时候图片路径自己更换
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
FILE* pfile;
pfile = fopen(filePath, "rb");
if(pfile == NULL){
printf("打开bmp失败!\n");
return -1;
}
int dest_fd ;
dest_fd = open("NEW.bmp" , O_RDWR | O_CREAT|O_TRUNC , 0777);
if(pfile!=NULL)
{
//从文件里读取信息
fread(&fileHeader, sizeof(fileHeader), 1, pfile);
fread(&infoHeader, sizeof(infoHeader), 1, pfile);
//解析头信息
if(fileHeader.bfType != 19778){
printf("'image.bmp'不是一个bmp格式的文件。\n");
return -1;
}
//输出文件信息
printf("大小:%dkb\n", fileHeader.bfSize);
printf("尺寸:宽%d 高%d\n", infoHeader.biWidth, infoHeader.biHeight);
printf("位数:%d\n", infoHeader.biBitCount);
printf("偏移量:%d\n", fileHeader.bfOffBits);
showBmpHead(&fileHeader);
printf("\n\n");
//读取位图信息头信息
showBmpInforHead(&infoHeader);
printf("\n");
}
else
{
printf("file open fail!\n");
return 0;
}
RGBQUAD * pRgb ;
int width = infoHeader.biWidth;
int height = infoHeader.biHeight;
//分配内存空间把源图存入内存
int l_width = WIDTHBYTES(width* infoHeader.biBitCount);//计算位图的实际宽度并确保它为32的倍数
BYTE *pColorData=(BYTE *)malloc(height*l_width);
// memset(pColorData,0,height*l_width);
long nData = height*l_width;
//
// //把位图数据信息读到数组里
fread(pColorData,1,nData,pfile);
//
// //将位图数据转化为RGB数据
RGBQUAD* dataOfBmp;
dataOfBmp = (RGBQUAD *)malloc(width*height*sizeof(RGBQUAD));//用于保存各像素对应的RGB数据
// memset(dataOfBmp,0,width*height*sizeof(RGBQUAD));
//
//
if(infoHeader.biBitCount == 24)//暂时只支持24位
{
write(dest_fd, &fileHeader, sizeof(BITMAPFILEHEADER));
write(dest_fd,&infoHeader,sizeof(BITMAPINFOHEADER));
int k;
int index = 0;
//用xcode写的, 用C编译器, 可能for循环这个位置要报错
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++)
{
k = i*l_width + j*3;
// 在这里处理像素 , 但是因为设计logo计算很麻烦, 我就不算了, 简单的加了一个横线
if (100 <i && i < 110&& j > 100 &&j< 200) {
dataOfBmp[index].rgbRed = 0x1f;
dataOfBmp[index].rgbGreen = 0x1f;
dataOfBmp[index].rgbBlue = 0x1f;
write(dest_fd , &dataOfBmp[index] , 3);
}
else
{
dataOfBmp[index].rgbRed = pColorData[k+2];
dataOfBmp[index].rgbGreen = pColorData[k+1];
dataOfBmp[index].rgbBlue = pColorData[k];
write(dest_fd , &dataOfBmp[index] , 3);
}
index++;
}
}
close(dest_fd);
}
free(dataOfBmp);
free(pColorData);
printf("\n");
printf("完成处理\n");
return 0;
}