【问题标题】:Hide text in .bmp隐藏 .bmp 中的文本
【发布时间】:2013-05-05 22:51:33
【问题描述】:

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

int txt_bmp(char *tekst, int x, int y, unsigned char *data){
    int i, j, k, l = 0;
    unsigned char t,p = 0;
    for (i = 0; i < strlen(tekst); i++){    
        for (j = 0; j < 8; j++){
            t = 0x80;
            k = 1;
            p = tekst[i] & (t/k);
            p >>= (7-j);
            if (p == 0)
               data[l] &= p;
            data[l] |= p;
            k *= 2;
            l += 3;
        }
    }   
    return 0;
}

你知道哪里出了问题吗?

【问题讨论】:

  • 也许您认为标题的大小有误?
  • 对于 bmp 图像,每行的长度是 4 的倍数(用空字节填充)。
  • 图像加载器的返回值是一个指向像素数据的“unsigned char *”。像素数据由*x个像素的*y个扫描线组成,每个像素由N个交错的8位分量组成;指向的第一个像素位于图像的最左上角。图像扫描线之间或像素之间没有填充。我强制了 3 个组件...

标签: c bmp steganography


【解决方案1】:

当使用BI_RGB 模式(普通的未压缩 DIB)时,24 位 DIB 中每个三元组的顺序将是 blue, green, red(即最低有效字节是蓝色分量)。

可以通过使用BI_BITFIELDS 模式并根据自己的喜好指定通道掩码来切换组件,但据我所知BI_BITFIELDS 模式不适用于 24 位 DIB。

所以如果你想在红色组件中存储一些东西,你应该使用每个三元组的最高有效字节。

【讨论】:

  • // 具有 N 个分量的输出图像具有交错的以下分量 // 在每个像素中按此顺序: // // N=#comp 分量 // 1 灰度 // 2 灰度,alpha / / 3 红色,绿色,蓝色 // 4 红色,绿色,蓝色,alpha
  • 好的,但这不是它们在原始图像内部的存储方式。保存修改后图像的代码是否采用相同的相反顺序(即是否将其切换回蓝色、绿色、红色)?
  • @magnums - 就像迈克尔说的那样,只需更改每个 3 字节像素中第三个字节的值,而不是第一个......
  • 我使用 stb_image.c 和 stb_image_write.h 来导入和导出 .bmp 文件。这些库使我能够像这样操作 picsel 数据:图像是从左到右、从上到下存储的像素矩形。每个像素包含以每通道 8 位交错存储的“comp”数据通道,顺序如下:1=Y、2=YA、3=RGB、4=RGBA。而且我总是在插入文本之前强制将输入图像的comp转换为itno 3(RGB)。输出的comp也是3。
【解决方案2】:

在这里,这将创建一个未压缩的位图。 稍加修改后,我已经在 arduino 上创建了一个 256x256 rgb 图像并将其保存到 SD 卡,内存为 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多