BMP图片转JPG小记(使用libjpeg,RGB1555->RGB888)

  RGB1555->RGB888

  1#  生成RGB24图片水平位移

        原因:  将bmp文件信息头一并读入

      解决:  

1    /* 跳过bmp文件头,直接读取掌纹图像数据 */
2    fseek(fd, 54, SEEK_SET);  

 

  2#  生成RGB888图片颜色不对,本人遇到情况为图片有很多绿色波纹,只能看到图像轮廓。

        原因: 原始图片为RGB1555格式,我误认为是为RGB565格式。

      解决: 调整转码代码。

    /* 详见文章尾所附代码 */

  3#  生成图片部分色彩正确部分错误,本人遇到情况为带图片波纹,许多地方红颜色覆盖

      原因:  转码代码中,有位移方向错误

      解决: 调整转码代码。

    /* 错误代码 */
    static void pixel_rgb555_to_rgb24(const unsigned char *p16,unsigned char *p24) 
    {  
        *(p24+0)=(*(unsigned short*)p16 << 3) & 0xF8; /* B */
        *(p24+1)=(*(unsigned short*)p16 >> 2) & 0xF8; /* G */
        *(p24+2)=(*(unsigned short*)p16 << 7) & 0xF8; /* R */
    } 
    /* 正确代码 */
    static void pixel_rgb555_to_rgb24(const unsigned char *p16,unsigned char *p24) 
    {  
        *(p24+0)=(*(unsigned short*)p16 << 3) & 0xF8; /* B */
        *(p24+1)=(*(unsigned short*)p16 >> 2) & 0xF8; /* G */
        *(p24+2)=(*(unsigned short*)p16 >> 7) & 0xF8; /* R */
    } 

  RGB888->JPEG (使用libjpeg)

  1#  运行报错,生成图片失败

      错误:  

     [root@vm jj]# ./bmp2jpg
     Bogus input colorspace

        原因:  cinfo.in_color_spaces 与 cinfo.input_components 设置错误,

      解决:  components 为 1 对应 in_color_spaces 为 JCS_GRAYSCALE 生成灰度图,components 为 3 对应 in_color_spaces 为 JCS_RGB生成彩色图

    cinfo.input_components = 3;         /* # of color components per pixel */
   cinfo.in_color_space = JCS_RGB; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像

 

 RGB1555->RGB888

/*************************************************************************
    > File Name: RGB555ToRGB888.cpp
    > Function: convert rgb555 to rgb888 
    > update: lvc
    > Mail: lvzaina@gmail.com 
    > Created Time: 2013年02月24日 星期日 02时55分22秒
    > Quote From: http://blog.csdn.net/yinuodie/article/details/8194804
************************************************************************/

#include <stdio.h>  
#include <string.h>  
#include "bmp.h"  
  
  
#define WIDTH       (320)  
#define HEIGHT      (240)  
#define IMAGESIZE16 ((WIDTH)*(HEIGHT)*2)  
#define IMAGESIZE24 ((IMAGESIZE16/2)*3)  
  
#define _DEBUG_ printf("-----------\n");  
  
void pixel_rgb555_to_rgb24(const unsigned char *p16,unsigned char *p24) //将16bit的像素转化为24bit的像素  
{  
    unsigned char R,G,B;  
    B=(*(unsigned short*)p16 << 3) & 0xF8; 
    G=(*(unsigned short*)p16 >> 2) & 0xF8;  
    R=(*(unsigned short*)p16 >> 7) & 0xF8;  
    *(p24+0)=B;   
    *(p24+1)=G;  
    *(p24+2)=R;  
}   
void pixel_rgb565_to_rgb24(const unsigned char *p16,unsigned char *p24) //将16bit的像素转化为24bit的像素  
{  
    unsigned char R,G,B;  
    B=*(unsigned short*)p16 & 0x01F;  
    G=(*(unsigned short*)p16 & 0x7E0) >> 5;  
    R=(*(unsigned short*)p16 >> 11 ) & 0x1F;  
    *(p24+0)=B << 2;   
    *(p24+1)=G << 1;  
    *(p24+2)=R << 2;  
}   
void image16_to_image24(const unsigned char *image16, unsigned char *image24, int biWidth, int biHeight)  
{  
    const unsigned char *p16 = image16;  
    unsigned char *p24 = image24;  
    int i;  
    for(i=0; i<biWidth*biHeight; i++, p16+=2, p24+=3)  
    {  
        pixel_rgb555_to_rgb24(p16, p24);  
    }  
}  
  
int main()  
{  
    //BITMAPFILEHEADER bmp_fileheader;  
    unsigned char bmp_fileheader[14];   //位图文件头  
    BITMAPINFOHEADER bmp_infoheader;    //位图信息头  
  
    //位图文件头  
        //因为字节对齐的问题,所以位图文件头用数组来定义   
    *(WORD *)bmp_fileheader = 'B' | 'M' << 8; //bfType 文件标识'BM'  
    *(DWORD *)(bmp_fileheader + 2) = 14 + 40 + IMAGESIZE24;     //bfSize 文件的大小  
    *(DWORD *)(bmp_fileheader + 6) = 0; //bfReserved1 和 bfReserved2  
    *(DWORD *)(bmp_fileheader + 10) = 54;   //bfOffBits 图象数据RGBA的起始地址的偏移值  为54   
  
    //位图信息头  
    bmp_infoheader.biSize = 40;  
    bmp_infoheader.biWidth = WIDTH;                     //图像width  
    bmp_infoheader.biHeight = HEIGHT;                       //图像height  
    bmp_infoheader.biPlanes = 1;  
    bmp_infoheader.biBitCount = 24;                     //像素精度  
    bmp_infoheader.biCompression = 0;  
    bmp_infoheader.biSizeImage = IMAGESIZE24;               //图像大小  
    bmp_infoheader.biXPelsPerMeter = 0;  
    bmp_infoheader.biYPelsPerMeter = 0;  
    bmp_infoheader.biClrUsed = 0;  
    bmp_infoheader.biClrImportant = 0;  
  
    unsigned char *imagedata16 = new unsigned char[IMAGESIZE16];  
    unsigned char *imagedata24 = new unsigned char[IMAGESIZE24];  
  
    FILE *image = fopen("b.bmp", "rb");  
    fseek(image, 54, SEEK_SET);  
        fread(imagedata16, IMAGESIZE16, 1, image);  
    fclose(image);  
  
      
    image16_to_image24(imagedata16, imagedata24, 320, 240);  
  
    FILE *file = fopen("bmp24.bmp", "wb");  
        fwrite(bmp_fileheader, 14, 1, file);  
        fwrite(&bmp_infoheader, 40, 1, file);  
        fwrite(imagedata24, IMAGESIZE24, 1, file);  
    fclose(file);  
    delete []imagedata16;  
    delete []imagedata24;  
  return 0;
}  

RGB888->JPEG

/*************************************************************************
    > File Name: rgb555tojpg.c
    > Function: convert rgb555 to rgb888 to jpg
    > Author: lvc
    > Mail: lvzaina@gmail.com 
    > Created Time: 2013年02月24日 星期日 02时55分22秒
 ************************************************************************/

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/timeb.h>
#include <jpeglib.h>

#define JPEG_QUALITY 90

static void pixel_rgb555_to_rgb24(const unsigned char *p16,unsigned char *p24) //将16bit的像素转化为24bit的像素  
{  
    *(p24+0)=(*(unsigned short*)p16 << 3) & 0xF8; /* B */
    *(p24+1)=(*(unsigned short*)p16 >> 2) & 0xF8; /* G */
    *(p24+2)=(*(unsigned short*)p16 >> 7) & 0xF8; /* R */
} 
static void image16_to_image24(const unsigned char *image16, unsigned char *image24, int biWidth, int biHeight)  
{  
    const unsigned char *p16 = image16;  
    unsigned char *p24 = image24;  
    int i;  
    for(i=0; i<biWidth*biHeight; i++, p16+=2, p24+=3)  
    {  
        pixel_rgb555_to_rgb24(p16, p24);  
    }  
} 
int main()
{
  FILE *fd;
  int ret;
  int i,j=0;
  long rgb_index = 0;
  unsigned char *imageRGB16;
  unsigned char *imageRGB24;
  int sizeImageRGB16 = 320*240*2;
  int sizeImageRGB24 = 320*240*3;
  imageRGB16 = (unsigned char*)malloc(sizeImageRGB16);
  imageRGB24 = (unsigned char*)malloc(sizeImageRGB24);
  fd = fopen("b.bmp", "rb");
  if(!fd)
  {
    printf("ERROR1: Can not open the image.\n");
    free(imageRGB16);
    free(imageRGB24);
    return -1;
  }

  /* 跳过bmp文件头,直接读取掌纹图像数据 */
  fseek(fd, 54, SEEK_SET);  
  ret = fread(imageRGB16, sizeImageRGB16, 1, fd);
  if(ret == 0)
  {
    if(ferror(fd))
    {
      printf("\nERROR2: Can not read the pixel data.\n");
      free(imageRGB16);
      free(imageRGB24);
      fclose(fd);
      return -1;
    }
  }
  fclose(fd);
  image16_to_image24(imageRGB16,imageRGB24,320,240);
  char *filename = "jpg.jpg";
  int width = 320;
  int height = 240;
  int depth = 3;
  //unsigned char *bits = "jsdgjksdjkgjks51sd536gsgjmskjgksjgss231h1b2s123z";
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  FILE *outfile;                 /* target file */
  JSAMPROW *row_pointer;        /* pointer to JSAMPLE row[s] */
  int     row_stride;             /* physical row width in image buffer */

  cinfo.err = jpeg_std_error(&jerr);
  /* Now we can initialize the JPEG compression object. */
  jpeg_create_compress(&cinfo);

  if ((outfile = fopen(filename, "wb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    return -1;
  }
  jpeg_stdio_dest(&cinfo, outfile);

  cinfo.image_width = width;      /* image width and height, in pixels */
  cinfo.image_height = height;
  cinfo.input_components = depth;         /* # of color components per pixel */
  cinfo.in_color_space = JCS_RGB;         /* colorspace of input image */

  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, JPEG_QUALITY, TRUE ); /* limit to baseline-JPEG values */

  jpeg_start_compress(&cinfo, TRUE);

  row_pointer = malloc(height*width*3);
  char * line[height];

  for(i=0;i<height;i++)
  {    
    unsigned char * lineData = NULL;
    
    lineData = malloc(width*3);
    line[i]  = lineData;
    
    for(j=0;j<width;j++)
    {
      lineData[j*3+2] = imageRGB24[rgb_index];
      rgb_index ++;
      lineData[j*3+1] = imageRGB24[rgb_index];
      rgb_index ++;
      lineData[j*3+0] = imageRGB24[rgb_index];
      rgb_index ++;
    }
    
    row_pointer[height-i-1] = lineData;      
  }
  
  jpeg_write_scanlines(&cinfo, row_pointer, height);
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);

  for (i=0; i<height; i++)
  {
    free(line[i]);
  }
  free(row_pointer);
  free(imageRGB16);
  free(imageRGB24);
  fclose(outfile);

  return 0;
}

 

 

 

 

 

posted @ 2013-02-24 17:32  赤色  阅读(4136)  评论(0编辑  收藏  举报
知识共享许可协议本博客作品采用知识共享署名-相同方式共享 3.0 未本地化版本许可协议进行许可。