本程序用于在Linux下使用文件操作对bmp图片进行打马赛克,效果很不错。
对于bmp格式,只需要知道这两点:
1,偏移为18byte的地方保存了bmp图片的宽度和高度,分别占4byte。
2,偏移为54byte的地方为图片的数据区,若为24位彩色图,则一个像素占3byte空间。
程序如下:
/*===============================================
* Copyright (C) 2017 All rights reserved.
*
* 文件名称:mask.c
* 创建者:no_play
* 创建日期:2017年07月25日
* 描述:
*
* 更新日志:
*
===============================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct color
{
unsigned char B;
unsigned char G;
unsigned char R;
}COLOR;
int main(int argc,char *argv[])
{
if(8 != argc)
{
printf("Usage:%s <src file> <dst file> <xstart> <ystart> <mask_width> <mask_height> <mask_len>\n",argv[0]);
return -1;
}
int src = open(argv[1],O_RDWR);
if(-1 == src)
{
perror(argv[1]);
return -1;
}
int dst = open(argv[2],O_RDWR | O_CREAT | O_TRUNC, 0666);
if(-1 == dst)
{
perror(argv[2]);
return -1;
}
int n;
char buff[1024*1024*4]={0}; /* 定义4M大小 */
n = read(src, buff, sizeof buff); /* 将文件内容放入buff中,后面改变像素时直接在buff中改变,速度更快 */
int *pwidth = (int *)&buff[18]; /* bmp格式将宽度和高度存放在从18字节开始的地方 */
int *pheight = (int *)&buff[18+4];
int width = *pwidth;
int height = *pheight;
int xoff = atoi(argv[3]);
int yoff = atoi(argv[4]);
int mask_width = atoi(argv[5]);
int mask_height = atoi(argv[6]);
int mask_len = atoi(argv[7]);
int cnt=0,num=0;
COLOR temp[100],color;/* 保存三原色值 */
int lable = 54; /* 标签,指示当前读取位置,由于bmp格式图片前54字节为头部,所以指向54 */
lable = lable + 3*(width*(height-yoff-mask_height) + xoff);
int i,j;
for(i=0;i<mask_height;i++)
{
for(j=0;j<mask_width;j++)
{
if(j%mask_len == 0) /* 将10X10个像素点变成一个颜色 */
{
if(i%mask_len == 0)
{
color.B = buff[lable];
color.G = buff[lable + 1];
color.R = buff[lable + 2];
temp[cnt] = color; /* 保存前一行的像素值 */
cnt++;
}
else
{
color = temp[num];/* 在高度为10的像素内使用一个颜色值 */
num++;
}
}
buff[lable] = color.B;
buff[lable + 1] = color.G;
buff[lable + 2] = color.R;
lable += 3;
}
lable += 3*(width-mask_width);
cnt = 0;
num = 0;
}
write(dst, buff, n); /* 将打码后的buff写入目标文件 */
close(src);
close(dst);
return 0;
}
参数argv的含义用一张图片来解释:
如果有张bmp图片名为1.bmp,将上面的程序编译为a.out,执行下面的命令的含义就是将1.bmp的x=100,y=100像素的地方开始,长度为150,宽度为150的一个矩形区域打上马赛克,打马赛克的程度为5,即5个像素点变成一个颜色。
./a.out 1.bmp 1_mask.bmp 100 100 150 150 10
下面是两张mask_len为10和mask_len为5的图片:
mask_len=10的效果。
mask_len=5的效果。