C 在.bmp中隐藏文本

C 在.bmp中隐藏文本,c,bmp,steganography,C,Bmp,Steganography,我用C语言编写了这个函数,将文本放入bmp图像中。我试着让它只改变红色中最不重要的像素。但是,当我打开编辑过的图像时,蓝色变了。数据来自“stb_image.c”库 int-txt\u-bmp(字符*tekst,整数x,整数y,无符号字符*数据){ int i,j,k,l=0; 无符号字符t,p=0; 对于(i=0;i=(7-j); 如果(p==0) 数据[l]&=p; 数据[l]|=p; k*=2; l+=3; } } 返回0; } 你知道怎么回事吗?当使用双RGB模式(正常的未压缩D

我用C语言编写了这个函数,将文本放入bmp图像中。我试着让它只改变红色中最不重要的像素。但是,当我打开编辑过的图像时,蓝色变了。数据来自“stb_image.c”库

int-txt\u-bmp(字符*tekst,整数x,整数y,无符号字符*数据){
int i,j,k,l=0;
无符号字符t,p=0;
对于(i=0;i>=(7-j);
如果(p==0)
数据[l]&=p;
数据[l]|=p;
k*=2;
l+=3;
}
}   
返回0;
}

你知道怎么回事吗?

当使用
双RGB
模式(正常的未压缩DIB)时,24位DIB中每个三元组的顺序将是
蓝、绿、红
(即最低有效字节是蓝色分量)

通过使用
BI_位字段
模式并根据您自己的偏好指定通道掩码,可以切换组件,但据我所知,
BI_位字段
模式对24位DIB无效


因此,如果要在红色组件中存储某些内容,应使用每个三元组的最高有效字节。

这里,这将创建一个未压缩的位图。 经过一点修改,我已经让它创建了一个256x256 rgb的图像并保存到SD卡上,该图像位于arduino上,内存为2kb。(仅像素数据为192kb)

目前,代码被注释为单色图像-仅限R通道。看第155到157行

// 22nd September 2008
// 10:37pm
// Enhzflep


#include <stdio.h>              // for file I/O
#include <stdlib.h>

#ifndef WORD
 #define WORD unsigned short
#endif

#ifndef DWORD
    #define DWORD unsigned long
#endif

#ifndef BYTE
    #define BYTE unsigned char
#endif

#ifndef LONG
    #define LONG long
#endif

#define BI_RGB 0

#pragma pack(push,2)
typedef struct tagBITMAPFILEHEADER {
    WORD    bfType;
    DWORD   bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD   bfOffBits;
} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
#pragma pack(pop)

typedef struct tagBITMAPINFOHEADER{
    DWORD   biSize;
    LONG    biWidth;
    LONG    biHeight;
    WORD    biPlanes;
    WORD    biBitCount;
    DWORD   biCompression;
    DWORD   biSizeImage;
    LONG    biXPelsPerMeter;
    LONG    biYPelsPerMeter;
    DWORD   biClrUsed;
    DWORD   biClrImportant;
} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
typedef struct tagRGBQUAD {
    BYTE    rgbBlue;
    BYTE    rgbGreen;
    BYTE    rgbRed;
    BYTE    rgbReserved;
} RGBQUAD,*LPRGBQUAD;
typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD bmiColors[1];
} BITMAPINFO,*LPBITMAPINFO,*PBITMAPINFO;


bool writeBmp24(int width, int height, char *filename, char *data)
{
    BITMAPINFO myBmpInfo;
    unsigned long myInfoSize;
    BITMAPFILEHEADER myBmpFileHeader;
    FILE *outputFile;

    // different bmp file types use different headers
    // this is the one for 24 bit bitmaps
    myInfoSize = sizeof(BITMAPINFOHEADER);

    // magic signature
    myBmpFileHeader.bfType = 0x4D42; // 'BM'

    // reserved data - must be zero
    myBmpFileHeader.bfReserved1 = 0;
    myBmpFileHeader.bfReserved2 = 0;

    // offset into file of the pixel data
    myBmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + myInfoSize;

    // total file size
    myBmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER)
                         + sizeof(BITMAPINFOHEADER)
                         + myInfoSize
                         + width*height*3;

    // size in bytes of this header
    myBmpInfo.bmiHeader.biSize = sizeof(myBmpInfo.bmiHeader);

    // size in bytes of the pixel data
    myBmpInfo.bmiHeader.biSizeImage = width*height*3;

    // image dimensions
    myBmpInfo.bmiHeader.biWidth = width;
    myBmpInfo.bmiHeader.biHeight = height;

    // pixels per meter (used to help select best image for output device)
    myBmpInfo.bmiHeader.biXPelsPerMeter = 2835;
    myBmpInfo.bmiHeader.biYPelsPerMeter = 2835;

    // only 1 pixel plane. Look up X-Mode (early 90s for more info on the concept of planes)
    myBmpInfo.bmiHeader.biPlanes = 1;

    // bits per pixel
    myBmpInfo.bmiHeader.biBitCount = 24;

    // compression type
    myBmpInfo.bmiHeader.biCompression = BI_RGB;

    // only used for images with a pallette
    myBmpInfo.bmiHeader.biClrImportant = 0;
    myBmpInfo.bmiHeader.biClrUsed = 0;


    if (!(outputFile = fopen(filename, "wb")))
        return false;

    if ( fwrite(&myBmpFileHeader, sizeof(BITMAPFILEHEADER), 1, outputFile) != 1)
        goto BmpError;

    if (fwrite(&myBmpInfo, myInfoSize, 1, outputFile) != 1)
        goto BmpError;

    if (fwrite(data, 3, width*height, outputFile) != width*height)
        goto BmpError;

    if (fclose(outputFile))
        return false;

    return true;

BmpError:
           fclose(outputFile);
           return false;
}

int main()
{
    int width = 128;
    int height = 128;

    char *pixelData;//[96*96*3];       //100x100 pixels * 24 bits/pixel
    char *dest;                                  // pointer to data
    int x, y;                                        // cur pixel
    char curVal;

    pixelData = (char*)calloc(3, width * height );
    dest = pixelData;                         // get locatio in mem of raw pixel data
    for (y=0; y<height; y++)           // for all rows of the image
        for (x=0; x<width; x++)       // loop through each pixel
        {
            curVal = x^y;
            dest[0] = 0;//curVal;       // b
            dest[1] = 0;//curVal;       // g
            dest[2] = curVal;           // r
            dest += 3;                            // point to next pixel;
        }

    writeBmp24(width, height, "enhzflep.bmp", pixelData);
    free(pixelData);
}
//2008年9月22日
//晚上10:37
//Enhzflep
#包括//用于文件I/O
#包括
#ifndef字
#定义单词unsigned short
#恩迪夫
#伊夫德沃德
#定义DWORD无符号长
#恩迪夫
#ifndef字节
#定义字节无符号字符
#恩迪夫
#伊芬德夫朗
#定义长
#恩迪夫
#定义BI_RGB 0
#pragma包(推送,2)
typedef结构tagBITMAPFILEHEADER{
字型;
德沃德尺寸;
保留字1;
保留字2;
德沃德;
}BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
#布拉格语包(流行语)
typedef结构TagBitMapInfo标头{
德沃德·比西泽;
长双宽;
长双峰高度;
单词双平面;
单词双比特计数;
德沃德双压缩;
德沃德·比西泽迈格;
长双峰渗透计;
长双渗透计;
德沃德·比克尔鲁斯;
德沃德·比克勒;
}BitMapInfo头,*LPBitMapInfo头,*PBITMapInfo头;
typedef结构标记rgbquad{
字节rgbBlue;
字节rgbGreen;
字节RGR;
字节rgb;
}RGBQUAD,*LPRGBQUAD;
typedef结构tagBITMAPINFO{
位图信息头;
RGBguad颜色[1];
}BITMAPINFO、*LPBITMAPINFO、*PBITMAPINFO;
bool writeBmp24(整数宽度、整数高度、字符*文件名、字符*数据)
{
BITMAPINFO-myBmpInfo;
无符号长myInfoSize;
BITMAPFILEHEADER myBmpFileHeader;
文件*输出文件;
//不同的bmp文件类型使用不同的头
//这是一个24位位图
myInfoSize=sizeof(BitMapInfo标头);
//魔术签名
myBmpFileHeader.bfType=0x4D42;//“BM”
//保留数据-必须为零
myBmpFileHeader.bfReserved1=0;
myBmpFileHeader.bfserved2=0;
//偏移到像素数据的文件中
myBmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+myInfoSize;
//总文件大小
myBmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)
+sizeof(BitMapInfo标头)
+myInfoSize
+宽*高*3;
//此标头的大小(字节)
myBmpInfo.bmiHeader.biSize=sizeof(myBmpInfo.bmiHeader);
//像素数据的大小(以字节为单位)
myBmpInfo.bmiHeader.biSizeImage=宽度*高度*3;
//图像尺寸
myBmpInfo.bmiHeader.biWidth=宽度;
myBmpInfo.bmiHeader.biHeight=高度;
//每米像素数(用于帮助为输出设备选择最佳图像)
myBmpInfo.bmiHeader.biXPelsPerMeter=2835;
myBmpInfo.bmiHeader.biYPelsPerMeter=2835;
//仅1像素平面。查找X模式(90年代早期了解更多关于平面概念的信息)
myBmpInfo.bmiHeader.biPlanes=1;
//每像素位数
myBmpInfo.bmiHeader.biBitCount=24;
//压缩型
myBmpInfo.bmiHeader.biCompression=BI_RGB;
//仅用于带有托盘的图像
myBmpInfo.bmiHeader.biClrImportant=0;
myBmpInfo.bmiHeader.biclrued=0;
如果(!(outputFile=fopen(文件名,“wb”))
返回false;
if(fwrite(&myBmpFileHeader,sizeof(BITMAPFILEHEADER),1,outputFile)!=1)
后藤博罗尔;
if(fwrite(&myBmpInfo,myInfoSize,1,outputFile)!=1)
后藤博罗尔;
if(写入(数据,3,宽度*高度,输出文件)!=宽度*高度)
后藤博罗尔;
if(fclose(outputFile))
返回false;
返回true;
bmperor:
fclose(输出文件);
返回false;
}
int main()
{
整数宽度=128;
整数高度=128;
字符*像素数据;//[96*96*3];///100x100像素*24位/像素
char*dest;//指向数据的指针
int x,y;//cur像素
字符曲线;
pixelData=(char*)calloc(3,宽度*高度);
dest=pixelData;//获取原始像素数据在mem中的位置

对于(y=0;yPerhaps,您假定页眉的大小错误?对于bmp图像,每行的长度是4的倍数(用空字节填充)。图像加载器的返回值是一个指向像素数据的“unsigned char*”。像素数据由*x像素的*y扫描线组成,每个像素由N个交错的8位组件组成;指向的第一个像素是图像中最左上角。图像扫描线之间或像素之间没有填充。我强制3个像素components…//包含N个组件的输出映像具有
// 22nd September 2008
// 10:37pm
// Enhzflep


#include <stdio.h>              // for file I/O
#include <stdlib.h>

#ifndef WORD
 #define WORD unsigned short
#endif

#ifndef DWORD
    #define DWORD unsigned long
#endif

#ifndef BYTE
    #define BYTE unsigned char
#endif

#ifndef LONG
    #define LONG long
#endif

#define BI_RGB 0

#pragma pack(push,2)
typedef struct tagBITMAPFILEHEADER {
    WORD    bfType;
    DWORD   bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD   bfOffBits;
} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
#pragma pack(pop)

typedef struct tagBITMAPINFOHEADER{
    DWORD   biSize;
    LONG    biWidth;
    LONG    biHeight;
    WORD    biPlanes;
    WORD    biBitCount;
    DWORD   biCompression;
    DWORD   biSizeImage;
    LONG    biXPelsPerMeter;
    LONG    biYPelsPerMeter;
    DWORD   biClrUsed;
    DWORD   biClrImportant;
} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
typedef struct tagRGBQUAD {
    BYTE    rgbBlue;
    BYTE    rgbGreen;
    BYTE    rgbRed;
    BYTE    rgbReserved;
} RGBQUAD,*LPRGBQUAD;
typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD bmiColors[1];
} BITMAPINFO,*LPBITMAPINFO,*PBITMAPINFO;


bool writeBmp24(int width, int height, char *filename, char *data)
{
    BITMAPINFO myBmpInfo;
    unsigned long myInfoSize;
    BITMAPFILEHEADER myBmpFileHeader;
    FILE *outputFile;

    // different bmp file types use different headers
    // this is the one for 24 bit bitmaps
    myInfoSize = sizeof(BITMAPINFOHEADER);

    // magic signature
    myBmpFileHeader.bfType = 0x4D42; // 'BM'

    // reserved data - must be zero
    myBmpFileHeader.bfReserved1 = 0;
    myBmpFileHeader.bfReserved2 = 0;

    // offset into file of the pixel data
    myBmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + myInfoSize;

    // total file size
    myBmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER)
                         + sizeof(BITMAPINFOHEADER)
                         + myInfoSize
                         + width*height*3;

    // size in bytes of this header
    myBmpInfo.bmiHeader.biSize = sizeof(myBmpInfo.bmiHeader);

    // size in bytes of the pixel data
    myBmpInfo.bmiHeader.biSizeImage = width*height*3;

    // image dimensions
    myBmpInfo.bmiHeader.biWidth = width;
    myBmpInfo.bmiHeader.biHeight = height;

    // pixels per meter (used to help select best image for output device)
    myBmpInfo.bmiHeader.biXPelsPerMeter = 2835;
    myBmpInfo.bmiHeader.biYPelsPerMeter = 2835;

    // only 1 pixel plane. Look up X-Mode (early 90s for more info on the concept of planes)
    myBmpInfo.bmiHeader.biPlanes = 1;

    // bits per pixel
    myBmpInfo.bmiHeader.biBitCount = 24;

    // compression type
    myBmpInfo.bmiHeader.biCompression = BI_RGB;

    // only used for images with a pallette
    myBmpInfo.bmiHeader.biClrImportant = 0;
    myBmpInfo.bmiHeader.biClrUsed = 0;


    if (!(outputFile = fopen(filename, "wb")))
        return false;

    if ( fwrite(&myBmpFileHeader, sizeof(BITMAPFILEHEADER), 1, outputFile) != 1)
        goto BmpError;

    if (fwrite(&myBmpInfo, myInfoSize, 1, outputFile) != 1)
        goto BmpError;

    if (fwrite(data, 3, width*height, outputFile) != width*height)
        goto BmpError;

    if (fclose(outputFile))
        return false;

    return true;

BmpError:
           fclose(outputFile);
           return false;
}

int main()
{
    int width = 128;
    int height = 128;

    char *pixelData;//[96*96*3];       //100x100 pixels * 24 bits/pixel
    char *dest;                                  // pointer to data
    int x, y;                                        // cur pixel
    char curVal;

    pixelData = (char*)calloc(3, width * height );
    dest = pixelData;                         // get locatio in mem of raw pixel data
    for (y=0; y<height; y++)           // for all rows of the image
        for (x=0; x<width; x++)       // loop through each pixel
        {
            curVal = x^y;
            dest[0] = 0;//curVal;       // b
            dest[1] = 0;//curVal;       // g
            dest[2] = curVal;           // r
            dest += 3;                            // point to next pixel;
        }

    writeBmp24(width, height, "enhzflep.bmp", pixelData);
    free(pixelData);
}