RGB数据转bmp、jpeg格式

最近在做身份证读头读取数据,但疼的第三方只给了个so库,说可以读出RGB数据。

RGB转BMP格式:

身份证头像照片宽和高分别为102、126,所以RGB数据的大小为102 x 126 x 3个字节

要转为BMP格式,必须加上54字节的BMP头格式,然后每一行RGB数据最后加上2个0表示一行结束,所以转换出来的BMP图片大小是:102 x 126 x 3 + 54 + 126 x 3字节

函数如下:

int rgb2bmp(char *rgb_buffer,int nWidth,int nHeight,FILE*fp1)
{
    typedef unsigned char  BYTE;
    typedef unsigned short WORD;
    typedef struct
    {    long imageSize;
        long blank;
        long startPosition;
    }BmpHead;

    typedef struct
    {
        long    Length;
        long    width;
        long    height;
        WORD    colorPlane;
        WORD    bitColor;
        long    zipFormat;
        long    realSize;
        long    xPels;
        long    yPels;
        long    colorUse;
        long    colorImportant;
    }InfoHead;

    BmpHead m_BMPHeader;       
    char bfType[2]={'B','M'};
    m_BMPHeader.imageSize=3*nWidth*nHeight+54;
    m_BMPHeader.blank=0;
    m_BMPHeader.startPosition=54;

    fwrite(bfType,1,sizeof(bfType),fp1);
    fwrite(&m_BMPHeader.imageSize,1,sizeof(m_BMPHeader.imageSize),fp1);
    fwrite(&m_BMPHeader.blank,1,sizeof(m_BMPHeader.blank),fp1);
    fwrite(&m_BMPHeader.startPosition,1,sizeof(m_BMPHeader.startPosition),fp1);

    InfoHead  m_BMPInfoHeader;
    m_BMPInfoHeader.Length=40;
    m_BMPInfoHeader.width=nWidth;
    m_BMPInfoHeader.height=nHeight;
    m_BMPInfoHeader.colorPlane=1;
    m_BMPInfoHeader.bitColor=24;
    m_BMPInfoHeader.zipFormat=0;
    m_BMPInfoHeader.realSize=3*nWidth*nHeight;
    //m_BMPInfoHeader.realSize=0;
    m_BMPInfoHeader.xPels=0;
    m_BMPInfoHeader.yPels=0;
    m_BMPInfoHeader.colorUse=0;
    m_BMPInfoHeader.colorImportant=0;

    fwrite(&m_BMPInfoHeader.Length,1,sizeof(m_BMPInfoHeader.Length),fp1);
    fwrite(&m_BMPInfoHeader.width,1,sizeof(m_BMPInfoHeader.width),fp1);
    fwrite(&m_BMPInfoHeader.height,1,sizeof(m_BMPInfoHeader.height),fp1);
    fwrite(&m_BMPInfoHeader.colorPlane,1,sizeof(m_BMPInfoHeader.colorPlane),fp1);
    fwrite(&m_BMPInfoHeader.bitColor,1,sizeof(m_BMPInfoHeader.bitColor),fp1);
    fwrite(&m_BMPInfoHeader.zipFormat,1,sizeof(m_BMPInfoHeader.zipFormat),fp1);
    fwrite(&m_BMPInfoHeader.realSize,1,sizeof(m_BMPInfoHeader.realSize),fp1);
    fwrite(&m_BMPInfoHeader.xPels,1,sizeof(m_BMPInfoHeader.xPels),fp1);
    fwrite(&m_BMPInfoHeader.yPels,1,sizeof(m_BMPInfoHeader.yPels),fp1);
    fwrite(&m_BMPInfoHeader.colorUse,1,sizeof(m_BMPInfoHeader.colorUse),fp1);
    fwrite(&m_BMPInfoHeader.colorImportant,1,sizeof(m_BMPInfoHeader.colorImportant),fp1);
    fwrite(rgb_buffer,BMP_BODY,1,fp1);

    return 0;
}
刚开始的时候转换出来的数据老是不对,后来经过对比,发现原始数据的排列并不是RGB,而是BGR,对调过来后即可,


RGB转jpeg:

我是在android系统下调试,android代码external/jpeg目录下自带jpeg编解码库,在Android.mk的LOCAL_SHARED_LIBRARIES加入libjpeg链接;

由于用到jpeg的头文件,还要在Android.mk中加入:

LOCAL_C_INCLUDES := \
        external/jpeg

以下代码是两个编码函数,我用的是第一个。第二个是从jpeg代码库中的demo代码复制过来的,结果得到的图片是倒过来的;后来修改了第一个,从最后一行RGB开始压缩,得到了我想要的数据:

#include 
#include 
#include 
#include 

extern "C" {
#include "jpeglib.h"
#include "jerror.h"
}
#define IMGWIDTH 102
#define IMGHEIGHT 126
void rgb_to_jpeg (char *filename, unsigned char *img, int quality, int gray)
{
    struct jpeg_compress_struct jcoms;
    struct jpeg_error_mgr jerr;  /* More stuff */

    FILE *fp;  /* target file */

    JSAMPROW row_pointer[1];   /* pointer to JSAMPLE row[s] */

    int line_length, m;    /* physical row width in image buffer */
    unsigned char *line;


    jcoms.err = jpeg_std_error(&jerr);


    jpeg_create_compress(&jcoms);
    if ((fp = fopen(filename, "w")) == NULL)
    {
    }

    jpeg_stdio_dest(&jcoms, fp);

    jcoms.image_width = IMGWIDTH;
    jcoms.image_height = IMGHEIGHT;
    jcoms.input_components = gray ? 1 : 3;
    //3 colour
    jcoms.in_color_space = gray ? \
                           JCS_GRAYSCALE : JCS_RGB;
    /*colorspace*/

    jpeg_set_defaults(&jcoms);
    jpeg_set_quality(&jcoms, quality, TRUE);

    /* limit to baseline-JPEG values */

    jpeg_start_compress(&jcoms, TRUE);


    line_length = gray ? IMGWIDTH : IMGWIDTH * 3;

    /* JSAMPLEs per row in image_buffer */
#if 0
    for (m = 0, line = img;  m < IMGHEIGHT; \
            m++, line +=line_length)
#endif
    for (m = IMGHEIGHT, line = &img[line_length * (IMGHEIGHT - 1) - 1];  m > 0; \
            m--, line -=line_length)
        jpeg_write_scanlines(&jcoms, &line, 1);
    /* Step 6: Finish compression */
    jpeg_finish_compress(&jcoms);

    /* to read the jpg data to the image buffer*/

    /* After finish_compress, we can close the output file. */
    fclose(fp);

    jpeg_destroy_compress(&jcoms);

        ALOGE("destroy compress OK!\n");
    //return statbuf.st_size;
    /* And we're done! */
}

void
write_JPEG_file (char * filename, unsigned char *image_buffer, int image_width, int image_height, int quality)
{
  /* This struct contains the JPEG compression parameters and pointers to
   * working space (which is allocated as needed by the JPEG library).
   * It is possible to have several such structures, representing multiple
   * compression/decompression processes, in existence at once.  We refer
   * to any one struct (and its associated working data) as a "JPEG object".
   */
  struct jpeg_compress_struct cinfo;
  /* This struct represents a JPEG error handler.  It is declared separately
   * because applications often want to supply a specialized error handler
   * (see the second half of this file for an example).  But here we just
   * take the easy way out and use the standard error handler, which will
   * print a message on stderr and call exit() if compression fails.
   * Note that this struct must live as long as the main JPEG parameter
   * struct, to avoid dangling-pointer problems.
   */
  struct jpeg_error_mgr jerr;
  /* More stuff */
  FILE * outfile;		/* target file */
  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
  int row_stride;		/* physical row width in image buffer */

  /* Step 1: allocate and initialize JPEG compression object */

  /* We have to set up the error handler first, in case the initialization
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
   * This routine fills in the contents of struct jerr, and returns jerr's
   * address which we place into the link field in cinfo.
   */
  cinfo.err = jpeg_std_error(&jerr);
  /* Now we can initialize the JPEG compression object. */
  jpeg_create_compress(&cinfo);

  /* Step 2: specify data destination (eg, a file) */
  /* Note: steps 2 and 3 can be done in either order. */

  /* Here we use the library-supplied code to send compressed data to a
   * stdio stream.  You can also write your own code to do something else.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to write binary files.
   */
  if ((outfile = fopen(filename, "wb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    exit(1);
  }
  jpeg_stdio_dest(&cinfo, outfile);

  /* Step 3: set parameters for compression */

  /* First we supply a description of the input image.
   * Four fields of the cinfo struct must be filled in:
   */
  cinfo.image_width = image_width; 	/* image width and height, in pixels */
  cinfo.image_height = image_height;
  cinfo.input_components = 3;		/* # of color components per pixel */
  cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
  /* Now use the library's routine to set default compression parameters.
   * (You must set at least cinfo.in_color_space before calling this,
   * since the defaults depend on the source color space.)
   */
  jpeg_set_defaults(&cinfo);
  /* Now you can set any non-default parameters you wish to.
   * Here we just illustrate the use of quality (quantization table) scaling:
   */
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

  /* Step 4: Start compressor */

  /* TRUE ensures that we will write a complete interchange-JPEG file.
   * Pass TRUE unless you are very sure of what you're doing.
   */
  jpeg_start_compress(&cinfo, TRUE);

  /* Step 5: while (scan lines remain to be written) */
  /*           jpeg_write_scanlines(...); */

  /* Here we use the library's state variable cinfo.next_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * To keep things simple, we pass one scanline per call; you can pass
   * more if you wish, though.
   */
  row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */

  while (cinfo.next_scanline < cinfo.image_height) {
    /* jpeg_write_scanlines expects an array of pointers to scanlines.
     * Here the array is only one element long, but you could pass
     * more than one scanline at a time if that's more convenient.
     */
    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }

  /* Step 6: Finish compression */

  jpeg_finish_compress(&cinfo);
  /* After finish_compress, we can close the output file. */
  fclose(outfile);

  /* Step 7: release JPEG compression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_compress(&cinfo);

  /* And we're done! */
}




你可能感兴趣的:(framework)