RGB图像数据字符叠加,图像压缩(ijl库),YUV转RGB

jackyhwei 发布于 2010-01-01 12:02 点击:3218次 

来自:CSDN.NET

一些非常有用的图像格式转换及使用的源代码,包括RGB图像数据字符叠加,图像压缩(ijl库),YUV转RGB等等。

TAG: YUV  YUV转RGB  RGB  BMP转JPG  文字叠加  

 

/**************************************
File: yuvrgb24.h
Description: header file for yuvrgb24.c
Date: Nov. 4, 2002
*****************************************/

#ifndef YUVRGB24_H
#define YUVRGB24_H

//初始化YUV图像转化为RGB图像使用的表格 
void init_dither_tab();

//YUV图像转化为RGB图像时宽度高度都不变 
#ifdef OLD
 void ConvertYUVtoRGB(
  unsigned char *src0, 
  unsigned char *src1, 
  unsigned char *src2, 
  unsigned char *dst_ori, 
  int width, 
  int height);
#else
 void ConvertYUVtoRGB(
  unsigned char *src, 
  unsigned char *dst_ori, 
  int width, 
  int height);
#endif

//YUV图像转化为RGB图像时宽度折半高度不变 
void ConvertYUVtoRGBSample(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height);

//YUV图像转化为RGB图像时宽度折半高度不变 进行图像翻转
void ConvertYUVtoRGBSampleReverse(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height);

//YUV图像转化为RGB图像时宽度直接由720扩为768 
//隔16个点插入一列(最后一列忽略 共插44列) 两边各插2列
void ConvertYUV720toRGB768(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height);

//YUV图像转化为RGB图像时宽度直接由720扩为768,高度扩展1倍 
//隔16个点插入一列(最后一列忽略 共插44列) 两边各插2列
void ConvertYUV720toRGB768TwoHeight(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height);

//YUV图像转化为RGB图像时宽度直接由720扩为768 高度扩展1倍 进行图像翻转
//隔16个点插入一列(最后一列忽略 共插44列) 两边各插2列
void ConvertYUV720toRGB768TwoHeightReverse(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height);
#endif

/************************************************************************
 *
 *  yuvrgb24.c, colour space conversion for tmndecode (H.263 decoder)
 *  Copyright (C) 1996  Telenor R&D, Norway
 *        Karl Olav Lillevold <Karl.Lillevold@nta.no>
 ************************************************************************/

//#include "config.h"
//#include "tmndec.h"
//#include "global.h"
#include "stdafx.h"

/* Data for ConvertYUVtoRGB*/
static long int crv_tab[256];
static long int cbu_tab[256];
static long int cgu_tab[256];

static long int cgv_tab[256];
static long int tab_76309[256];

static unsigned char *clp;
static unsigned char *pclp;

void init_dither_tab()
{
 long int crv,cbu,cgu,cgv;
 int i;  

 crv = 104597; cbu = 132201;  /* fra matrise i global.h */
 cgu = 25675;  cgv = 53279;

 for (i = 0; i < 256; i++)
 {
  crv_tab[i] = (i-128) * crv;
  cbu_tab[i] = (i-128) * cbu;
  cgu_tab[i] = (i-128) * cgu;
  cgv_tab[i] = (i-128) * cgv;
  tab_76309[i] = 76309*(i-16);
 }

}

void free_clp()

 //free( pclp );
}
            
/**********************************************************************
 *
 * Name:          ConvertYUVtoRGB 
 * Description:     Converts YUV image to RGB (packed mode)
 * 
 * Input:          pointer to source luma, Cr, Cb, destination,
 *                       image width and height
 * Returns:       
 * Side effects:
 *
 * Date: 951208 Author: Karl.Lillevold@nta.no
 *
 ***********************************************************************/

inline unsigned char CharClip( int value )
{
 if( value < 0 )
 {
  return 0;
 }
 else if( value > 255 )
 {
  return 255;
 }
 else
 {
  return (unsigned char)value;
 }
}

#ifdef OLD
 void ConvertYUVtoRGB(
  unsigned char *src0,
  unsigned char *src1,
  unsigned char *src2,
  unsigned char *dst_ori, 
  int width, 
  int height)
#else
 void ConvertYUVtoRGB(
  unsigned char *src, 
  unsigned char *dst_ori, 
  int width, 
  int height)
#endif
{       
 int y11;
 int y12;
 int y13;
 int y14;
 int u, v; 
 int i, j;
 int c11, c21, c31, c41;
 int c12, c22, c32, c42;
 unsigned long DW; // 4 bytes
 unsigned long *id1; // 4 bytes
 unsigned char *py, *pu,*pv;
 unsigned char *d1;
  
 d1 = dst_ori;
  
 py = src; 
 pu = src+1; 
 pv = src+3;

 id1 = (unsigned long *)d1;

 for (j = 0; j < height; j ++ )
 { 
  for (i = 0; i < width; i += 4 )
  {
   u = *pu;
   v = *pv;
      
   c11 = crv_tab[v];   
   c21 = cgu_tab[u];
   c31 = cgv_tab[v];
   c41 = cbu_tab[u];
   pu += 4;
   pv += 4;

   u = *pu;
   v = *pv;
   c12 = crv_tab[v];
   c22 = cgu_tab[u];
   c32 = cgv_tab[v];
   c42 = cbu_tab[u];

   pu += 4;
   pv += 4;

   y11 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y12 = tab_76309[*py];
   py += 2;

   y13 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y14 = tab_76309[*py];
   py += 2;

   /* RGBR*/
   //DW = ((clp[(y11 + c41)>>16])) |
   //     ((clp[(y11 - c21 - c31)>>16])<<8) |
   //     ((clp[(y11 + c11)>>16])<<16) |  
   //     ((clp[(y12 + c41)>>16])<<24);
   DW = (( CharClip( (y11 + c41)>>16 ) )) |
    (( CharClip( (y11 - c21 - c31)>>16 ) <<8 )) |
    (( CharClip( (y11 + c11)>>16 ) <<16 )) |  
    (( CharClip( (y12 + c41)>>16 ) << 24 ));
   *id1++ = DW;

   /* GBRG*/
   //DW = ((clp[(y12 - c21 - c31)>>16])) |
   //     ((clp[(y12 + c11)>>16])<<8) |  
   //     ((clp[(y13 + c42)>>16])<<16) |
   //     ((clp[(y13 - c22 - c32)>>16])<<24);
   DW = (( CharClip( (y12 - c21 - c31)>>16 ) )) |
    (( CharClip( (y12 + c11)>>16 ) <<8 )) |  
    (( CharClip( (y13 + c42)>>16 ) <<16 )) |
    (( CharClip( (y13 - c22 - c32) >>16 ) <<24 ));
   *id1++ = DW;

   /* BRGB*/
   /*DW = ((clp[(y13 + c12)>>16])) |  
    ((clp[(y14 + c42)>>16])<<8) |
    ((clp[(y14 - c22 - c32)>>16])<<16) |
    ((clp[(y14 + c12)>>16])<<24);  
      */
   DW = (( CharClip( (y13 + c12)>>16 ) )) |  
    (( CharClip( (y14 + c42)>>16 )<<8 )) |
    (( CharClip( (y14 - c22 - c32 )>>16 )<<16)) |
    (( CharClip( (y14 + c12)>>16 )<<24));  
   *id1++ = DW;
  }

  //id1 -= (9 * width)>>2;
  //id2 -= (9 * width)>>2;
  //py += width;
  //py2 += width;
 }           

void ConvertYUVtoRGBSample(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height)
{     
 int y11;
 int y12;
 int y13;
 int y14;
 int u,v; 
 int i,j;
 int c11, c21, c31, c41;
 int c12, c22, c32, c42;
 unsigned long DW;   // 4 bytes
 unsigned long *id1; // 4 bytes
 unsigned char *py, *pu,*pv;
 unsigned char *d1;

 d1 = dst_ori;

 py = src; 
 pu = src+1; 
 pv = src+3;

 id1 = (unsigned long *)d1;

 for (j = 0; j < height; j ++ )
 { 
  for (i = 0; i < width; i += 8 )
  {
   u = *pu;
   v = *pv;
      
   c11 = crv_tab[v];   
   c21 = cgu_tab[u];
   
   pu += 4;
   pv += 4;
   u = *pu;
   v = *pv;

   c31 = cgv_tab[v];
   c41 = cbu_tab[u];
   
   pu += 4;
   pv += 4;
   u = *pu;
   v = *pv;
   c12 = crv_tab[v];
   c22 = cgu_tab[u];
   pu += 4;
   pv += 4;
   u = *pu;
   v = *pv;
   c32 = cgv_tab[v];
   c42 = cbu_tab[u];

   pu += 4;
   pv += 4;

   y11 = tab_76309[*py]; /* (255/219)*65536 */
   py += 4;
   y12 = tab_76309[*py];
   py += 4;

   y13 = tab_76309[*py]; /* (255/219)*65536 */
   py += 4;
   y14 = tab_76309[*py];
   py += 4;

   /* RGBR*/
   //DW = ((clp[(y11 + c41)>>16])) |
   //     ((clp[(y11 - c21 - c31)>>16])<<8) |
   //     ((clp[(y11 + c11)>>16])<<16) |  
   //     ((clp[(y12 + c41)>>16])<<24);
   DW = (( CharClip( (y11 + c41)>>16 ) )) |
    (( CharClip( (y11 - c21 - c31)>>16 ) <<8 )) |
    (( CharClip( (y11 + c11)>>16 ) <<16 )) |  
    (( CharClip( (y12 + c41)>>16 ) << 24 ));
   *id1++ = DW;

   /* GBRG*/
   //DW = ((clp[(y12 - c21 - c31)>>16])) |
   //     ((clp[(y12 + c11)>>16])<<8) |  
   //     ((clp[(y13 + c42)>>16])<<16) |
   //     ((clp[(y13 - c22 - c32)>>16])<<24);
   DW = (( CharClip( (y12 - c21 - c31)>>16 ) )) |
    (( CharClip( (y12 + c11)>>16 ) <<8 )) |  
      (( CharClip( (y13 + c42)>>16 ) <<16 )) |
      (( CharClip( (y13 - c22 - c32) >>16 ) <<24 ));
   *id1++ = DW;

   /* BRGB*/
   /*DW = ((clp[(y13 + c12)>>16])) |  
      ((clp[(y14 + c42)>>16])<<8) |
      ((clp[(y14 - c22 - c32)>>16])<<16) |
      ((clp[(y14 + c12)>>16])<<24);  
      */
   DW = (( CharClip( (y13 + c12)>>16 ) )) |  
      (( CharClip( (y14 + c42)>>16 )<<8 )) |
      (( CharClip( (y14 - c22 - c32 )>>16 )<<16)) |
      (( CharClip( (y14 + c12)>>16 )<<24));  
   *id1++ = DW;
  }
  //id1 -= (9 * width)>>2;
  //id2 -= (9 * width)>>2;
  //py += width;
  //py2 += width;
 }           

void ConvertYUVtoRGBSampleReverse(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height)
{     
 int y11;
 int y12;
 int y13;
 int y14;
 int u,v; 
 int i,j;
 int c11, c21, c31, c41;
 int c12, c22, c32, c42;
 unsigned long DW;   // 4 bytes
 unsigned long *id1; // 4 bytes
 unsigned char *py, *pu,*pv;
 unsigned char *d1;
 
 const int DST_LINEIMAGE_SIZE = 360 * 3; // 目标图像(RGB)1行的数据长度(BYTE)
 const int DST_END_ADDRESS = DST_LINEIMAGE_SIZE * 288; // 目标图像(RGB)末尾地址

 d1 = dst_ori + DST_END_ADDRESS;

 py = src; 
 pu = src+1; 
 pv = src+3;

 //id1 = (unsigned long *)d1;

 for (j = 0; j < height; j ++ )
 { 
  d1  -= DST_LINEIMAGE_SIZE;
  id1 = (unsigned long*)d1;

  for (i = 0; i < width; i += 8 )
  {
   u = *pu;
   v = *pv;
      
   c11 = crv_tab[v];   
   c21 = cgu_tab[u];
   
   pu += 4;
   pv += 4;
   u = *pu;
   v = *pv;

   c31 = cgv_tab[v];
   c41 = cbu_tab[u];
   
   pu += 4;
   pv += 4;
   u = *pu;
   v = *pv;
   c12 = crv_tab[v];
   c22 = cgu_tab[u];
   pu += 4;
   pv += 4;
   u = *pu;
   v = *pv;
   c32 = cgv_tab[v];
   c42 = cbu_tab[u];

   pu += 4;
   pv += 4;

   y11 = tab_76309[*py]; /* (255/219)*65536 */
   py += 4;
   y12 = tab_76309[*py];
   py += 4;

   y13 = tab_76309[*py]; /* (255/219)*65536 */
   py += 4;
   y14 = tab_76309[*py];
   py += 4;

   /* RGBR*/
   //DW = ((clp[(y11 + c41)>>16])) |
   //     ((clp[(y11 - c21 - c31)>>16])<<8) |
   //     ((clp[(y11 + c11)>>16])<<16) |  
   //     ((clp[(y12 + c41)>>16])<<24);
   DW = (( CharClip( (y11 + c41)>>16 ) )) |
    (( CharClip( (y11 - c21 - c31)>>16 ) <<8 )) |
    (( CharClip( (y11 + c11)>>16 ) <<16 )) |  
    (( CharClip( (y12 + c41)>>16 ) << 24 ));
   *id1++ = DW;

   /* GBRG*/
   //DW = ((clp[(y12 - c21 - c31)>>16])) |
   //     ((clp[(y12 + c11)>>16])<<8) |  
   //     ((clp[(y13 + c42)>>16])<<16) |
   //     ((clp[(y13 - c22 - c32)>>16])<<24);
   DW = (( CharClip( (y12 - c21 - c31)>>16 ) )) |
    (( CharClip( (y12 + c11)>>16 ) <<8 )) |  
      (( CharClip( (y13 + c42)>>16 ) <<16 )) |
      (( CharClip( (y13 - c22 - c32) >>16 ) <<24 ));
   *id1++ = DW;

   /* BRGB*/
   /*DW = ((clp[(y13 + c12)>>16])) |  
      ((clp[(y14 + c42)>>16])<<8) |
      ((clp[(y14 - c22 - c32)>>16])<<16) |
      ((clp[(y14 + c12)>>16])<<24);  
      */
   DW = (( CharClip( (y13 + c12)>>16 ) )) |  
      (( CharClip( (y14 + c42)>>16 )<<8 )) |
      (( CharClip( (y14 - c22 - c32 )>>16 )<<16)) |
      (( CharClip( (y14 + c12)>>16 )<<24));  
   *id1++ = DW;
  } // for width

  //d1 -= DST_TWOLINEIMAGE_SIZE;
  //id1 = (unsigned long*)d1;

  //id1 -= (9 * width)>>2;
  //id2 -= (9 * width)>>2;
  //py += width;
  //py2 += width;
 } // for height          

void ConvertYUV720toRGB768(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height)
{       
 int y11;
 int y12;
 int y13;
 int y14;
 int u, v; 
 int i, j;
 int c11, c21, c31, c41;
 int c12, c22, c32, c42;
 unsigned long DW; // 4 bytes
 unsigned long *id1; // 4 bytes
 unsigned char *py, *pu,*pv;
 unsigned char *d1;
  
 d1 = dst_ori+6;
  
 py = src; 
 pu = src+1; 
 pv = src+3;

 id1 = (unsigned long *)d1;

 for (j = 0; j < height; j ++ )
 { 
  for (i = 0; i < width; i += 4 )
  {
   u = *pu;
   v = *pv;
      
   c11 = crv_tab[v];   
   c21 = cgu_tab[u];
   c31 = cgv_tab[v];
   c41 = cbu_tab[u];
   pu += 4;
   pv += 4;

   u = *pu;
   v = *pv;
   c12 = crv_tab[v];
   c22 = cgu_tab[u];
   c32 = cgv_tab[v];
   c42 = cbu_tab[u];

   pu += 4;
   pv += 4;

   y11 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y12 = tab_76309[*py];
   py += 2;

   y13 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y14 = tab_76309[*py];
   py += 2;

   /* RGBR*/
   //DW = ((clp[(y11 + c41)>>16])) |
   //     ((clp[(y11 - c21 - c31)>>16])<<8) |
   //     ((clp[(y11 + c11)>>16])<<16) |  
   //     ((clp[(y12 + c41)>>16])<<24);
   DW = (( CharClip( (y11 + c41)>>16 ) )) |
    (( CharClip( (y11 - c21 - c31)>>16 ) <<8 )) |
    (( CharClip( (y11 + c11)>>16 ) <<16 )) |  
    (( CharClip( (y12 + c41)>>16 ) << 24 ));
   *id1++ = DW;

   /* GBRG*/
   //DW = ((clp[(y12 - c21 - c31)>>16])) |
   //     ((clp[(y12 + c11)>>16])<<8) |  
   //     ((clp[(y13 + c42)>>16])<<16) |
   //     ((clp[(y13 - c22 - c32)>>16])<<24);
   DW = (( CharClip( (y12 - c21 - c31)>>16 ) )) |
    (( CharClip( (y12 + c11)>>16 ) <<8 )) |  
    (( CharClip( (y13 + c42)>>16 ) <<16 )) |
    (( CharClip( (y13 - c22 - c32) >>16 ) <<24 ));
   *id1++ = DW;

   /* BRGB*/
   /*DW = ((clp[(y13 + c12)>>16])) |  
    ((clp[(y14 + c42)>>16])<<8) |
    ((clp[(y14 - c22 - c32)>>16])<<16) |
    ((clp[(y14 + c12)>>16])<<24);  
      */
   DW = (( CharClip( (y13 + c12)>>16 ) )) |  
    (( CharClip( (y14 + c42)>>16 )<<8 )) |
    (( CharClip( (y14 - c22 - c32 )>>16 )<<16)) |
    (( CharClip( (y14 + c12)>>16 )<<24));  
   *id1++ = DW;

   if ((i%16) == 0 && 
    i>0 &&
    i<width-1)
   {
    *d1 = *(d1-3);
    *(d1+1) = *(d1-2);
    *(d1+2) = *(d1-1);
    d1 += 3;
    id1 = (unsigned long*)d1;
   }
   else if (i == 0)
   {
    *(d1-6) = *d1;
    *(d1-5) = *(d1+1);
    *(d1-4) = *(d1+2);
    *(d1-3) = *(d1+3);
    *(d1-2) = *(d1+4);
    *(d1-1) = *(d1+5);
   }
   else if (i == (width-1)/16*16)
   {
    *(d1+5) = *(d1-1);
    *(d1+4) = *(d1-2);
    *(d1+3) = *(d1-3);
    *(d1+2) = *(d1-4);
    *(d1+1) = *(d1-5);
    *d1 = *(d1-6);
   }

   d1 += 12;
  }
  if (j < height-1)
  {
   d1 += 12;
   id1 = (unsigned long*)d1;
  }
  //id1 -= (9 * width)>>2;
  //id2 -= (9 * width)>>2;
  //py += width;
  //py2 += width;
 }           

void ConvertYUV720toRGB768TwoHeight(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height)
{       
 int y11;
 int y12;
 int y13;
 int y14;
 int u, v; 
 int i, j;
 int c11, c21, c31, c41;
 int c12, c22, c32, c42;
 unsigned long DW; // 4 bytes
 unsigned long *id1; // 4 bytes
 unsigned char *py, *pu,*pv;
 unsigned char *d1; // 目标图像存储区域  
 const int DST_LINEIMAGE_SIZE = 768 * 3; // 目标图像(RGB)一行的数据长度(BYTE)

 d1 = dst_ori+6;
  
 py = src; 
 pu = src+1; 
 pv = src+3;

 id1 = (unsigned long *)d1;

 for (j = 0; j < height; j ++ )
 { 
  for (i = 0; i < width; i += 4)
  {
   u = *pu;
   v = *pv;
      
   c11 = crv_tab[v];   
   c21 = cgu_tab[u];
   c31 = cgv_tab[v];
   c41 = cbu_tab[u];
   pu += 4;
   pv += 4;

   u = *pu;
   v = *pv;
   c12 = crv_tab[v];
   c22 = cgu_tab[u];
   c32 = cgv_tab[v];
   c42 = cbu_tab[u];

   pu += 4;
   pv += 4;

   y11 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y12 = tab_76309[*py];
   py += 2;

   y13 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y14 = tab_76309[*py];
   py += 2;

   /* RGBR*/
   //DW = ((clp[(y11 + c41)>>16])) |
   //     ((clp[(y11 - c21 - c31)>>16])<<8) |
   //     ((clp[(y11 + c11)>>16])<<16) |  
   //     ((clp[(y12 + c41)>>16])<<24);
   DW = (( CharClip( (y11 + c41)>>16 ) )) |
    (( CharClip( (y11 - c21 - c31)>>16 ) <<8 )) |
    (( CharClip( (y11 + c11)>>16 ) <<16 )) |  
    (( CharClip( (y12 + c41)>>16 ) << 24 ));
   *id1++ = DW;

   /* GBRG*/
   //DW = ((clp[(y12 - c21 - c31)>>16])) |
   //     ((clp[(y12 + c11)>>16])<<8) |  
   //     ((clp[(y13 + c42)>>16])<<16) |
   //     ((clp[(y13 - c22 - c32)>>16])<<24);
   DW = (( CharClip( (y12 - c21 - c31)>>16 ) )) |
    (( CharClip( (y12 + c11)>>16 ) <<8 )) |  
    (( CharClip( (y13 + c42)>>16 ) <<16 )) |
    (( CharClip( (y13 - c22 - c32) >>16 ) <<24 ));
   *id1++ = DW;

   /* BRGB*/
   /*DW = ((clp[(y13 + c12)>>16])) |  
    ((clp[(y14 + c42)>>16])<<8) |
    ((clp[(y14 - c22 - c32)>>16])<<16) |
    ((clp[(y14 + c12)>>16])<<24);  
      */
   DW = (( CharClip( (y13 + c12)>>16 ) )) |  
    (( CharClip( (y14 + c42)>>16 )<<8 )) |
    (( CharClip( (y14 - c22 - c32 )>>16 )<<16)) |
    (( CharClip( (y14 + c12)>>16 )<<24));  
   *id1++ = DW;
   
   if ((i%16) == 0 && 
    i>0 &&
    i<width-1)
   {
    d1 += 12;

    *d1 = *(d1-3);
    *(d1+1) = *(d1-2);
    *(d1+2) = *(d1-1);
    d1 += 3;
    id1 = (unsigned long*)d1;
   }
   else if (i == 0)
   {
    *(d1-6) = *d1;
    *(d1-5) = *(d1+1);
    *(d1-4) = *(d1+2);
    *(d1-3) = *d1;
    *(d1-2) = *(d1+1);
    *(d1-1) = *(d1+2);

    d1 += 12;
   }
   else if (i == (width-1)/4*4)
   {
    d1 += 12;
    
    *d1 = *(d1-3);
    *(d1+1) = *(d1-2);
    *(d1+2) = *(d1-1);
    *(d1+3) = *(d1-3);
    *(d1+4) = *(d1-2);
    *(d1+5) = *(d1-1);
   }
   else
   {
    d1 += 12;
   }
  }
  if (j < height-1)
  {
   d1 += 12;
   id1 = (unsigned long*)d1;

   memcpy(d1,(d1-DST_LINEIMAGE_SIZE),DST_LINEIMAGE_SIZE);
   d1 += DST_LINEIMAGE_SIZE;
   id1 = (unsigned long*)d1;
  }
  //id1 -= (9 * width)>>2;
  //id2 -= (9 * width)>>2;
  //py += width;
  //py2 += width;
 }           

void ConvertYUV720toRGB768TwoHeightReverse(
 unsigned char *src, 
 unsigned char *dst_ori, 
 int width, 
 int height)
{       
 int y11;
 int y12;
 int y13;
 int y14;
 int u, v; 
 int i, j;
 int c11, c21, c31, c41;
 int c12, c22, c32, c42;
 unsigned long DW; // 4 bytes
 unsigned long *id1; // 4 bytes
 unsigned char *py, *pu,*pv;
 unsigned char *d1; // 目标图像存储区域 用来运算 
 unsigned char *d2; // 目标图像存储区域 用来定位

 const int DST_LINEIMAGE_SIZE = 768 * 3; // 目标图像(RGB)1行的数据长度(BYTE)
 const int DST_TWOLINEIMAGE_SIZE = 768 * 3 * 2; // 目标图像(RGB)2行的数据长度(BYTE)
 const int DST_END_ADDRESS = DST_LINEIMAGE_SIZE * 576; // 目标图像(RGB)目标图像(RGB)末尾地址

 d2 = dst_ori + DST_END_ADDRESS;
  
 py = src; 
 pu = src+1; 
 pv = src+3;

 // id1 = (unsigned long *)d1;

 for (j = 0; j < height; j ++ )
 {
  
  d2  -= DST_TWOLINEIMAGE_SIZE;
  d1  = d2 + 6;
  id1 = (unsigned long*)d1;

  for (i = 0; i < width; i += 4 )
  {
   u = *pu;
   v = *pv;
      
   c11 = crv_tab[v];   
   c21 = cgu_tab[u];
   c31 = cgv_tab[v];
   c41 = cbu_tab[u];
   pu += 4;
   pv += 4;

   u = *pu;
   v = *pv;
   c12 = crv_tab[v];
   c22 = cgu_tab[u];
   c32 = cgv_tab[v];
   c42 = cbu_tab[u];

   pu += 4;
   pv += 4;

   y11 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y12 = tab_76309[*py];
   py += 2;

   y13 = tab_76309[*py]; /* (255/219)*65536 */
   py += 2;
   y14 = tab_76309[*py];
   py += 2;

   /* RGBR*/
   //DW = ((clp[(y11 + c41)>>16])) |
   //     ((clp[(y11 - c21 - c31)>>16])<<8) |
   //     ((clp[(y11 + c11)>>16])<<16) |  
   //     ((clp[(y12 + c41)>>16])<<24);
   DW = (( CharClip( (y11 + c41)>>16 ) )) |
    (( CharClip( (y11 - c21 - c31)>>16 ) <<8 )) |
    (( CharClip( (y11 + c11)>>16 ) <<16 )) |  
    (( CharClip( (y12 + c41)>>16 ) << 24 ));
   *id1++ = DW;

   /* GBRG*/
   //DW = ((clp[(y12 - c21 - c31)>>16])) |
   //     ((clp[(y12 + c11)>>16])<<8) |  
   //     ((clp[(y13 + c42)>>16])<<16) |
   //     ((clp[(y13 - c22 - c32)>>16])<<24);
   DW = (( CharClip( (y12 - c21 - c31)>>16 ) )) |
    (( CharClip( (y12 + c11)>>16 ) <<8 )) |  
    (( CharClip( (y13 + c42)>>16 ) <<16 )) |
    (( CharClip( (y13 - c22 - c32) >>16 ) <<24 ));
   *id1++ = DW;

   /* BRGB*/
   /*DW = ((clp[(y13 + c12)>>16])) |  
    ((clp[(y14 + c42)>>16])<<8) |
    ((clp[(y14 - c22 - c32)>>16])<<16) |
    ((clp[(y14 + c12)>>16])<<24);  
      */
   DW = (( CharClip( (y13 + c12)>>16 ) )) |  
    (( CharClip( (y14 + c42)>>16 )<<8 )) |
    (( CharClip( (y14 - c22 - c32 )>>16 )<<16)) |
    (( CharClip( (y14 + c12)>>16 )<<24));  
   *id1++ = DW;

   if ((i%16) == 0 && 
    i>0 &&
    i<width-1)
   {
    d1 += 12;

    *d1 = *(d1-3);
    *(d1+1) = *(d1-2);
    *(d1+2) = *(d1-1);
    d1 += 3;
    id1 = (unsigned long*)d1;
   }
   else if (i == 0)
   {
    *(d1-6) = *d1;
    *(d1-5) = *(d1+1);
    *(d1-4) = *(d1+2);
    *(d1-3) = *d1;
    *(d1-2) = *(d1+1);
    *(d1-1) = *(d1+2);

    d1 += 12;
   }
   else if (i == (width-1)/4*4)
   {
    d1 += 12;
    
    *d1 = *(d1-3);
    *(d1+1) = *(d1-2);
    *(d1+2) = *(d1-1);
    *(d1+3) = *(d1-3);
    *(d1+4) = *(d1-2);
    *(d1+5) = *(d1-1);
   }
   else
   {
    d1 += 12;
   }
  }
  
  d1 += 6;
  memcpy(d1,(d1-DST_LINEIMAGE_SIZE),DST_LINEIMAGE_SIZE);
  
  //id1 -= (9 * width)>>2;
  //id2 -= (9 * width)>>2;
  //py += width;
  //py2 += width;  
 }           
}  
/////////////////////////////////////////////////////////////////////////////////
// End of this file.
/////////////////////////////////////////////////////////////////////////////////

 #include "stdafx.h"
#include "PSA.h"
#include "Imageaddchar.h"
#include "ijl.h"
#include "yuvrgb24.h"
LPBITMAPINFOHEADER   m_lpVehicleBitmapHeader = NULL;
HDC                  m_hMemDC;
HBITMAP              m_hBmp;
HBITMAP              m_hBmpOld;
HFONT                m_hFont;
HFONT                m_hFontOld;
LPBYTE               m_lpMemImage = NULL;

int                  m_piBrandRatio[32];      
static bool          m_bPermitAddCharToImage;

const int            PLATE_IMAGE_SIZE = 128 * 20 * 2; 
const int            BRAND_IMAGE_SIZE = 64 * 20 * 2; 

BEGIN_MESSAGE_MAP(CPSAApp, CWinApp)
 //{{AFX_MSG_MAP(CPSAApp)
  // NOTE - the ClassWizard will add and remove mapping macros here.
  //    DO NOT EDIT what you see in these blocks of generated code!
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPSAApp construction

CPSAApp::CPSAApp()
{
 // TODO: add construction code here,
 // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CPSAApp object

CPSAApp theApp;

/************************************************************************
Function WriteToLog:
        往当前目录下日志文件写入信息
Input:
        int iErrorNumber   错误号
  TCHAR *szMsg       写入的具体信息
return:
        成功返回0值,异常返回其它整数;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/01/06        1.0      Create         
************************************************************************/
int WriteToLog(int iErrorNumber,TCHAR *szMsg)
{
 int    i = 0;
 int    iLastSperate = 0;
 TCHAR  szCurPath[272];  
 HANDLE hWndFile; 
 WIN32_FIND_DATA fileFind;
 FILE   *fp;
 SYSTEMTIME lpSystemTime;
  
 GetModuleFileName(GetModuleHandle(NULL),szCurPath,256); 

 for (i=0; i<256; i++)
 {
  if (szCurPath[i] == '\\') 
  {
   iLastSperate = i;
  }
  else if(szCurPath[i] == '\0')
  {
   break;
  }
 }
 
 if (iLastSperate > 0 && i < 256)
 {
  szCurPath[iLastSperate] = '\0'; 
 }
 else
 {
  return (-1);
 }
 
 strcat(szCurPath,"\\psaImage.evt");

 //printf("current path: %s \n",szCurPath);
 
 GetLocalTime(&lpSystemTime);
 
 printf("current time: %04d-%02d-%02d %02d:%02d:%02d:%03d\n", 
                    lpSystemTime.wYear,lpSystemTime.wMonth,lpSystemTime.wDay,
        lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,
        lpSystemTime.wMilliseconds);

 hWndFile = FindFirstFile(szCurPath,&fileFind);
 FindClose(hWndFile);

 if (INVALID_HANDLE_VALUE == hWndFile)
 {
  if ((fp = fopen(szCurPath,"w")) == NULL)
  {
   return (-2);
  }
  fprintf(fp,"%04d-%02d-%02d %02d:%02d:%02d:%03d  Event:%06d  %s\n",
          lpSystemTime.wYear,lpSystemTime.wMonth,lpSystemTime.wDay,
       lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds,
       iErrorNumber,szMsg);
  fclose(fp);
 }
 else
 {
  if (fileFind.nFileSizeLow > 61440)  // if event file size > 60K, delete, create new
  {
   if (DeleteFile(szCurPath))
   {
    if ((fp = fopen(szCurPath,"w")) == NULL)
    {
     return (-2);
    }
    fprintf(fp,"%04d-%02d-%02d %02d:%02d:%02d:%03d  Event:%06d  %s\n",
         lpSystemTime.wYear,lpSystemTime.wMonth,lpSystemTime.wDay,
         lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds,
         iErrorNumber,szMsg);
    fclose(fp);
   }
  }
  else
  {
   if ((fp = fopen(szCurPath,"a+")) == NULL)
   {
    return (-3);
   }
   else
   {
    fprintf(fp,"%04d-%02d-%02d %02d:%02d:%02d:%03d  Event:%06d  %s\n",
         lpSystemTime.wYear,lpSystemTime.wMonth,lpSystemTime.wDay,
         lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds,
         iErrorNumber,szMsg);
    fclose(fp);
   }
  }
 }

 /***********************************************
 if (SetCurrentDirectory(szCurPath) != 0)
 {
  printf("set current path ok...\n");
 }
 else
 {
  printf("set current path failure!\n");
 }
 ***********************************************/
 
 return (0);
}

/************************************************************************
Function CompressRGBToJPEG:
        RGB图像数据压缩为JPEG文件保存
Input:
        BYTE *lpImageRGB        RGB图像数据区
     int   originalWidth     原始图像宽度
  int   originalHeight    原始图像高度
  int   jpegQuality       JPEG压缩质量[1-100]
  char* jpegFileName      JPEG文件保存的名称 
  int   isNeedReversal    是否需要翻转
  int   isResizeImage     是否需要缩放图像的尺寸
return:
        成功返回0值,异常返回其它整数;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/01/06        1.0      Create         
************************************************************************/
int CompressRGBToJPEG(BYTE *lpImageRGB,  
       int originalWidth, 
       int originalHeight, 
       int   jpegQuality,
       char* jpegFileName,
       int   isNeedReversal,
       int   isResizeImage)
{
 int res = 0;
 int jpegImageWidth;
 int jpegImageHeight;
 IJLERR jerr;
 JPEG_CORE_PROPERTIES jcprops;
 
 jerr = ijlInit(&jcprops);
 if (jerr != IJL_OK)
    {
  res = 1;
  goto Exit;
    }
 
 if (isResizeImage == 0) //保持原始比例
 {
  jpegImageWidth = originalWidth;
  jpegImageHeight = originalHeight;
 }
// else if (isResizeImage == 112) //宽度变为1/2,高度不变
// {
//  jpegImageWidth = originalWidth/2;
//  jpegImageHeight = originalHeight;
// }
 else //保持原始比例
 {
  jpegImageWidth = originalWidth;
  jpegImageHeight = originalHeight;
 }

    // Setup DIB
   jcprops.DIBWidth         = originalWidth;
 if (isNeedReversal == 0) //如果不需要翻转图片
 {
  jcprops.DIBHeight        = originalHeight;
 }
 else                     //如果需要翻转图片
 {
  jcprops.DIBHeight        = -originalHeight;
 }
    jcprops.DIBBytes         = lpImageRGB;
 jcprops.DIBColor         = IJL_BGR;
 jcprops.DIBChannels      = 3;
 jcprops.DIBPadBytes      = IJL_DIB_PAD_BYTES(jcprops.DIBWidth,3);

    // Setup JPEG
    jcprops.JPGFile          = jpegFileName;
    jcprops.JPGWidth         = jpegImageWidth;
    jcprops.JPGHeight        = jpegImageHeight;
 jcprops.jquality         = jpegQuality;
 jcprops.JPGColor         = IJL_YCBCR;
 jcprops.JPGChannels      = 3;
 jcprops.JPGSubsampling   = IJL_411;

    jerr = ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
 if(IJL_OK != jerr)
 {
  //printf("ijlInit() failed - %s\n",ijlErrorStr(jerr));
  res = 2;
  goto Exit;
 }

Exit:
 jerr = ijlFree(&jcprops);
 if(IJL_OK != jerr)
 {
  //printf("ijlFree() failed - %s\n",ijlErrorStr(jerr));
  res = 3;
 }

 return res;
}

/************************************************************************
extern "C" EXPORTS Function PSAInit:
       动态库显式初始化预留函数
Input:
       无
return:
       成功返回0值;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/01/06        1.0      Create    
  Shimingjie     2006/01/13        1.1      Edit
************************************************************************/
extern "C" int PASCAL EXPORT PSAInit()
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 m_bPermitAddCharToImage = false;

 init_dither_tab();

 srand(unsigned int(time(NULL)));

 return 0;
}

/************************************************************************
extern "C" EXPORTS Function PSAFree:
       动态库显式释放资源预留函数
Input:
       无
return:
       成功返回0值;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/01/06        1.0      Create         
************************************************************************/
extern "C" int PASCAL EXPORT PSAFree()
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 m_bPermitAddCharToImage = false;

 int res = 0;

 return (res);
}

/************************************************************************
extern "C" EXPORTS Function PSAAddCharToImage:
        字符叠加在BMP图象数据上,通过字库点阵方式    
Input:
        LPBYTE lpCharImage       需要进行字符叠加的图象BMP数据指针头
  CString strLicense       需要叠加牌照号
  CString strDateTime      需要叠加的时间日期
  CString strSpeed         需要叠加的车速
  CString strLocation      需要叠加的卡口点名称描述
  CString strLimitSpeed    需要叠加的限速
  String strDirection      需要叠加的卡口点方向描述
  DWORD dwImgWidth         图象宽
  DWORD dwImgHeight        图象高
  BYTE btColorB            叠加文字的颜色RGB值中的B
  BYTE btColorG            叠加文字的颜色RGB值中的G
  BYTE btColorR            叠加文字的颜色RGB值中的R
return:
        字符叠加无错误返回>=0整数,异常返回<0整数;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/01/06        1.0      Create         
************************************************************************/
extern "C" int PASCAL EXPORT PSAAddCharToImage(LPBYTE lpImage, 
              CHAR *chLicense,
              CHAR *chDateTime,
              CHAR *chSpeed,
              CHAR *chLocation,
              CHAR *chLimitSpeed,
              CHAR *chDirection,
              WORD wImageWidth,
              WORD wImageHeight,
              BYTE btColorB,
              BYTE btColorG,
              BYTE btColorR)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 int iRetval;

 CImageaddchar cImage;

 iRetval = cImage.Imageaddchar(lpImage,
                            chLicense,
          chDateTime,
          chSpeed,
          chLocation,
          chLimitSpeed,
                                  chDirection, 
          wImageWidth,
          wImageHeight,
          btColorB,
          btColorG,
          btColorR);

 return (iRetval);
}

/************************************************************************
extern "C" EXPORTS Function PSAFreeCharToImageInit:
        初始化在内存设备场景中进行字符叠加   
Input:
        DWORD   hDC                    设备场景(根据此设备场景建立内存设备场景)
  DWORD   dwImgWidth             图象宽
  DWORD   dwImgHeight            图象高
  LPCTSTR lpszFontName           叠加字符名称
  int     iFontSize              叠加字符的大小
   DWORD   dwFontBold             是否粗体
  DWORD   dwFontItalic           是否斜体 
  DWORD   dwFontUnderline        是否加下划线
  DWORD   dwFontStrikeOut        是否加删除线 
  BYTE    btColorB               叠加文字的颜色RGB值中的B
  BYTE    btColorG               叠加文字的颜色RGB值中的G
  BYTE    btColorR               叠加文字的颜色RGB值中的R
return:
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/05/17        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAFreeCharToImageInit(DWORD   hDC,
                                                    DWORD   dwImageWidth,
             DWORD   dwImageHeight,
             LPCTSTR lpszFontName,
             int     iFontSize,
             DWORD   dwFontBold,
             DWORD   dwFontItalic,
             DWORD   dwFontUnderline, 
             DWORD   dwFontStrikeOut, 
             BYTE    btForeColorB,
             BYTE    btForeColorG,
             BYTE    btForeColorR)
              
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 DWORD        dwImageByte = 0;
 int          iRetval     = 0xFF;  
    
 dwImageByte = dwImageWidth * dwImageHeight * (DWORD)3; //计算BMP图像数据总大小
 
 m_lpMemImage = (LPBYTE) new unsigned char[dwImageByte];
 
 m_lpVehicleBitmapHeader = (LPBITMAPINFOHEADER) new char[40];

 //BITMAPINFOHEADER 结构变量初始化
    m_lpVehicleBitmapHeader->biBitCount = 24;
    m_lpVehicleBitmapHeader->biClrImportant = 0;
    m_lpVehicleBitmapHeader->biClrUsed = 0;
    m_lpVehicleBitmapHeader->biCompression = 0;
    m_lpVehicleBitmapHeader->biHeight = dwImageHeight;
    m_lpVehicleBitmapHeader->biPlanes = 1;
    m_lpVehicleBitmapHeader->biSize = 40;
    m_lpVehicleBitmapHeader->biSizeImage = dwImageByte;
    m_lpVehicleBitmapHeader->biWidth = dwImageWidth;
    m_lpVehicleBitmapHeader->biXPelsPerMeter = 0;
    m_lpVehicleBitmapHeader->biYPelsPerMeter = 0;
 
 // CreateCompatibleDC 创建一个与特定设备场景一致的内存设备场景
 // 返回值:执行成功返回新设备场景句柄,若出错则为零
 // 注意点:不再需要时,该设备场景可用DeleteDC函数删除。
    m_hMemDC = CreateCompatibleDC((HDC)hDC);           //用DeleteDC删除句柄
 if (m_hMemDC == 0)
 {
  iRetval = iRetval & 0xFE; // 1111 1110
 }

 //hMemDC = CreateDC("DISPLAY",NULL,NULL, NULL);  //用DeleteDC删除句柄
 //HDC hMemDC = GetDC(0);                         //用ReleaseDC释放句柄

 
 // CreateDIBSection 创建一个DIBSection,这是一个GDI对象,可象一幅与设备有关位图那样使用。但是,它在内部作为一幅与设备无关位图保存。
 // 返回值:执行成功返回DIBSection位图的句柄,零表示失败。
 // 注意点:一旦不再需要,记住用DeleteObject函数删除DIBSection位图。
 
 m_hBmp = CreateDIBSection(m_hMemDC, 
                      (BITMAPINFO*)m_lpVehicleBitmapHeader, 
       DIB_RGB_COLORS, 
       (LPVOID*)&m_lpMemImage, 
       NULL, 
                         0); 
 
 //hBmp = CreateCompatibleBitmap(hMemDC,lpVehicleBitmapHeader->biWidth,lpVehicleBitmapHeader->biHeight); 
 if (m_hBmp == 0)
 {
  iRetval = iRetval & 0xFD; // 1111 1101
 }
 
 //SelectObject 每个设备场景都可能有选入其中的图形对象。其中包括位图、刷子、字体、画笔以及区域等等。
 //             一次选入设备场景的只能有一个对象。选定的对象会在设备场景的绘图操作中使用。
 //             例如,当前选定的画笔决定了在设备场景中描绘的线段颜色及样式
    //返回值:与以前选入设备场景的相同hObject类型的一个对象的句柄,零表示出错。
 m_hBmpOld = (HBITMAP)SelectObject(m_hMemDC, m_hBmp);
 
 //CreateFont 用指定的属性创建一种逻辑字体 
    //返回值:执行成功则返回逻辑字体的句柄,零表示失败。
 if (dwFontBold > 0) //创建粗体的字符
 {
  m_hFont = CreateFont(iFontSize,0,0,0,FW_BOLD,dwFontItalic,dwFontUnderline,dwFontStrikeOut,DEFAULT_CHARSET,0,0,0,0,lpszFontName);
 }
 else
 {
  m_hFont = CreateFont(iFontSize,0,0,0,FW_THIN,dwFontItalic,dwFontUnderline,dwFontStrikeOut,DEFAULT_CHARSET,0,0,0,0,lpszFontName);
 }
 if (m_hFont == 0)
 {
  iRetval = iRetval & 0xFB; // 1111 1011 
 }

 m_hFontOld = (HFONT)SelectObject(m_hMemDC, m_hFont);
 
 //SetBkMode 指定阴影刷子、虚线画笔以及字符中的空隙的填充方式
    //返回值:文本色的前一个RGB颜色设定。CLR_INVALID表示失败。
    SetBkMode(m_hMemDC, TRANSPARENT); //TRANSPARENT 表示透明处理,即不作上述填充
                                 //OPAQUE 表示用当前的背景色填充虚线画笔、阴影刷子以及字符的空隙 

 //SetTextColor 设置当前文本颜色。这种颜色也称为“前景色”
    //返回值:文本色的前一个RGB颜色设定。CLR_INVALID表示失败。
 SetTextColor(m_hMemDC, RGB(btForeColorR, btForeColorG, btForeColorB));
    
 //如果初始化成功,那么返回值0
 if (iRetval == 0xFF)
 {
  iRetval = 0;
  m_bPermitAddCharToImage = true;
 }
 
 return (iRetval);
}

/************************************************************************
extern "C" EXPORTS Function PSAFreeCharToImageEnd:
        释放在内存设备场景中进行字符叠加所申请的资源   
Input:
        
Output:
        正常返回非0值,0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/05/17        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAFreeCharToImageEnd()
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 int          iRetval     = 0xFF; 

 SelectObject(m_hMemDC,m_hFontOld);
 
 SelectObject(m_hMemDC, m_hBmpOld);
 
 //DeleteObject 用这个函数删除GDI对象,比如画笔、刷子、字体、位图、区域以及调色板等等。
 //对象使用的所有系统资源都会被释放
    //返回值:非零表示成功,零表示失败。
 DeleteObject(m_hBmp);
 
 DeleteObject(m_hBmpOld);

 DeleteObject(m_hFont);

 DeleteObject(m_hFontOld);

 //DeleteObject(hMemBmp);

 DeleteDC(m_hMemDC); 
 
 if (m_lpMemImage != NULL)
 {
  delete[] m_lpMemImage;
  m_lpMemImage = NULL;
 }

 if (m_lpVehicleBitmapHeader != NULL)
 {
  delete[] m_lpVehicleBitmapHeader;
  m_lpVehicleBitmapHeader = NULL;
 }
 
 //如果终止成功,那么返回值置0
 if (iRetval == 0xFF)
 {
  iRetval = 0;
 }
 
 m_bPermitAddCharToImage = false;

 return (iRetval);
}

/************************************************************************
extern "C" EXPORTS Function PSAFreeCharToImage:
        字符叠加在BMP图象数据上,通过创建MemDC方式写入   
Input:
  LPBYTE  lpImage                需要进行字符叠加的BMP图像数据指针
        LPCTSTR lpszLineFirstString    叠加的第一行字符
  LPCTSTR lpszLineSecondString   叠加的第二行字符
  LPCTSTR lpszLineThirdString    叠加的第三行字符
  DWORD   dwLineFirstStartPosX   第一行字符的起始X坐标
  DWORD   dwLineFirstStartPosY   第一行字符的起始Y坐标
  DWORD   dwLineSecondStartPosX  第二行字符的起始X坐标
  DWORD   dwLineSecondStartPosY  第二行字符的起始Y坐标
  DWORD   dwLineThirdStartPosX   第三行字符的起始X坐标
  DWORD   dwLineThirdStartPosY   第三行字符的起始Y坐标
Output:
  LPBYTE  lpImageDst             叠加字符后的BMP图像数据指针 
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/04/06        1.0      Create  
  Shimingjie     2005/04/26        1.1      Add remark/Interface Complete
  Shimingjie     2005/05/17        1.2      Change Function Mode && Parameter 
************************************************************************/
extern "C" int PASCAL EXPORT PSAFreeCharToImage(LPBYTE  lpImage, 
                                                LPBYTE  lpImageDst, 
               LPCTSTR lpszLineFirstString,
               LPCTSTR lpszLineSecondString,
               LPCTSTR lpszLineThirdString,
            DWORD   dwLineFirstStartPosX, 
            DWORD   dwLineFirstStartPosY, 
            DWORD   dwLineSecondStartPosX, 
            DWORD   dwLineSecondStartPosY, 
            DWORD   dwLineThirdStartPosX, 
            DWORD   dwLineThirdStartPosY)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 if (!m_bPermitAddCharToImage)
 {
  return -1;
 }

 int          iTmp        = 0;
 int          iStringLen  = 0;
 int          iRetval     = 0xFF;  
 
 //SetDIBits 函数将来自与设备无关位图的二进制位复制到一幅与设备有关的位图里
    //返回值:非零表示成功,零表示失败。
 iTmp = SetDIBits(m_hMemDC, 
               m_hBmp, 
            0, 
            m_lpVehicleBitmapHeader->biHeight, 
            (LPVOID)lpImage, 
            (BITMAPINFO*)m_lpVehicleBitmapHeader, 
            DIB_RGB_COLORS);
 if (iTmp == 0)
 {
  iRetval = iRetval & 0xFE; // 1111 1110 
 }

 //TextOut 文本绘图函数。
    //返回值:非零表示成功,零表示失败。
 iStringLen = lstrlen(lpszLineFirstString); 
 if (iStringLen > 0)
 {
  TextOut(m_hMemDC, dwLineFirstStartPosX, dwLineFirstStartPosY, lpszLineFirstString, iStringLen);
 }
 
 iStringLen = lstrlen(lpszLineSecondString);
 if (iStringLen > 0)
 {
  TextOut(m_hMemDC, dwLineSecondStartPosX, dwLineSecondStartPosY, lpszLineSecondString, iStringLen);
 }

 iStringLen = lstrlen(lpszLineThirdString); 
 if (iStringLen > 0)
 {
  TextOut(m_hMemDC, dwLineThirdStartPosX, dwLineThirdStartPosY, lpszLineThirdString, iStringLen);
 }
 
 //BYTE *pTemp = new BYTE[dwImageByte];
 //ZeroMemory(pTemp, dwImageByte);

 //GetDIBits 函数将来自一幅位图的二进制位复制到一幅与设备无关的位图里
    //返回值:非零表示成功,零表示失败。
 iTmp = GetDIBits(m_hMemDC, 
               m_hBmp, 
        0, 
      m_lpVehicleBitmapHeader->biHeight, 
               (LPVOID)lpImageDst, 
      (BITMAPINFO*)m_lpVehicleBitmapHeader, 
      DIB_RGB_COLORS); 
 //iTmp = GetBitmapBits(hBmp, dwImageByte,(LPVOID)lpImageDst);
 if (iTmp == 0)
 {
  iRetval = iRetval & 0xFD; // 1111 1101 
 }
    
 //如果字符叠加成功,那么返回值置0
 if (iRetval == 0xFF)
 {
  iRetval = 0;
 }

 return (iRetval);
}

/************************************************************************
extern "C" EXPORTS Function PSACompressRawBufferToJpeg422File:
        源图 Ycrcb格式[422] 直接压缩为JPEG文件保存[深圳发现晚间图像压缩存在块状]
Input:
  BYTE* lpRawImageBuffer 源图数据区
  int   originalWidth    源图宽度
  int   originalHeight   源图高度
  int   jpegQuality      JPEG压缩质量
  char* jpegFileName     JPEG保存文件名  
  int   isNeedReversal   压缩为JPEG时是否需要翻转
  int   isResizeImage    是否需要更改图像大小 
return:
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/18        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSACompressRawBufferToJpeg422File(
        BYTE* lpRawImageBuffer,
        int   originalWidth,
        int   originalHeight,
        int   jpegQuality,
        char* jpegFileName,
        int   isNeedReversal,
        int   isResizeImage)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int res = 0;
 int jpegImageWidth;
 int jpegImageHeight;
 IJLERR jerr;
 JPEG_CORE_PROPERTIES jcprops;
 
 jerr = ijlInit(&jcprops);
 if (jerr != IJL_OK)
    {
  res = 1;
  goto Exit;
    }
 
 if (isResizeImage == 0) //保持原始比例
 {
  jpegImageWidth = originalWidth;
  jpegImageHeight = originalHeight;
 }
// else if (isResizeImage == 112) //宽度变为1/2,高度不变
// {
//  jpegImageWidth = originalWidth/2;
//  jpegImageHeight = originalHeight;
// }
 else //保持原始比例
 {
  jpegImageWidth = originalWidth;
  jpegImageHeight = originalHeight;
 }

 jcprops.DIBWidth         = originalWidth;
 if (isNeedReversal == 0) //如果不需要翻转图片
 {
  jcprops.DIBHeight        = originalHeight;
 }
 else                     //如果需要翻转图片
 {
  jcprops.DIBHeight        = -originalHeight;
 }
 jcprops.DIBChannels      = 3;
 jcprops.DIBBytes         = lpRawImageBuffer;
 jcprops.DIBPadBytes      = 0;
 jcprops.DIBColor         = IJL_YCBCR;
 jcprops.DIBSubsampling   = IJL_422;

 jcprops.JPGFile          = jpegFileName;
 jcprops.JPGWidth         = jpegImageWidth;
 jcprops.JPGHeight        = jpegImageHeight;
 jcprops.JPGChannels      = 3;
 jcprops.JPGColor         = IJL_YCBCR;
 jcprops.JPGSubsampling   = IJL_422;
 jcprops.jquality         = jpegQuality;

 jerr = ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
 if(IJL_OK != jerr)
 {
  //printf("ijlInit() failed - %s\n",ijlErrorStr(jerr));
  res = 2;
  goto Exit;
 }

Exit:
 jerr = ijlFree(&jcprops);
 if(IJL_OK != jerr)
 {
  //printf("ijlFree() failed - %s\n",ijlErrorStr(jerr));
  res = 3;
 }

 return res;
} // PSACompressRawBufferToJpeg422File

/************************************************************************
extern "C" EXPORTS Function PSARawToJpeg411Sample:
        源图 Ycrcb格式[422] 通过查表转化为RGB 转化时行长度折半
  压缩为JPEG文件保存
Input:
  BYTE* lpRawImageBuffer 源图数据区
  int   originalWidth    源图宽度
  int   originalHeight   源图高度
  int   jpegQuality      JPEG压缩质量
  char* jpegFileName     JPEG保存文件名  
  int   isNeedReversal   压缩为JPEG时是否需要翻转
  int   isResizeImage    是否需要更改图像大小 
return:
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/18        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSARawToJpeg411Sample(
        BYTE* lpRawImageBuffer,
        int   originalWidth,
        int   originalHeight,
        int   jpegQuality,
        char* jpegFileName,
        int   isNeedReversal,
        int   isResizeImage)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 int res = 0;
 BYTE* lpRGBImageBuffer;
 int rgbWidth;
 int rgbHeight;

 // 行长折半压缩为Jpeg文件
 rgbWidth = originalWidth / 2;
 rgbHeight = originalHeight;
 lpRGBImageBuffer = new BYTE[rgbWidth * rgbHeight * 3];

 ConvertYUVtoRGBSample(lpRawImageBuffer,lpRGBImageBuffer,originalWidth,originalHeight);
 
 //比例不变压缩为Jpeg文件 
 /*
 rgbWidth = originalWidth;
 rgbHeight = originalHeight;
 lpRGBImageBuffer = new BYTE[rgbWidth * rgbHeight * 3];
 ConvertYUVtoRGB(lpRawImageBuffer,lpRGBImageBuffer,originalWidth,originalHeight);
 */

 res = CompressRGBToJPEG(lpRGBImageBuffer,
                      rgbWidth,
       rgbHeight,
       jpegQuality,
       jpegFileName,
       isNeedReversal,
       isResizeImage);

 if (lpRGBImageBuffer != NULL)
 {
  delete[] lpRGBImageBuffer;
  lpRGBImageBuffer = NULL;
 }

 return (res);
}

/************************************************************************
extern "C" EXPORTS Function PSARawToJpeg411SampleAddChar:
        源图 Ycrcb格式[422] 通过查表转化为RGB 转化时行长度折半 
  叠加字符 压缩为JPEG文件保存
Input:
  BYTE* lpRawImageBuffer 源图数据区
  int   originalWidth    源图宽度
  int   originalHeight   源图高度
  int   jpegQuality      JPEG压缩质量
  char* jpegFileName     JPEG保存文件名  
  int   isNeedReversal   压缩为JPEG时是否需要翻转
  int   isResizeImage    是否需要更改图像大小 
  LPCTSTR lpszLineFirstString    叠加的第一行字符
  LPCTSTR lpszLineSecondString   叠加的第二行字符
  LPCTSTR lpszLineThirdString    叠加的第三行字符
  DWORD   dwLineFirstStartPosX   第一行字符的起始X坐标
  DWORD   dwLineFirstStartPosY   第一行字符的起始Y坐标
  DWORD   dwLineSecondStartPosX  第二行字符的起始X坐标
  DWORD   dwLineSecondStartPosY  第二行字符的起始Y坐标
  DWORD   dwLineThirdStartPosX   第三行字符的起始X坐标
  DWORD   dwLineThirdStartPosY   第三行字符的起始Y坐标
return:
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2006/01/14        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSARawToJpeg411SampleAddChar(
        BYTE* lpRawImageBuffer,
        int   originalWidth,
        int   originalHeight,
        int   jpegQuality,
        char* jpegFileName,
        int   isNeedReversal,
        int   isResizeImage,
        LPCTSTR lpszLineFirstString,
        LPCTSTR lpszLineSecondString,
        LPCTSTR lpszLineThirdString,
        DWORD   dwLineFirstStartPosX, 
        DWORD   dwLineFirstStartPosY, 
        DWORD   dwLineSecondStartPosX, 
        DWORD   dwLineSecondStartPosY, 
        DWORD   dwLineThirdStartPosX, 
        DWORD   dwLineThirdStartPosY)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int res = 0;
 BYTE* lpRGBImageBuffer;
 int rgbWidth;
 int rgbHeight;
 BYTE* lpRGBImageBufferAddChar;
 DWORD dwRGBImageSize = 0;

 // 行长折半压缩为Jpeg文件
 rgbWidth = originalWidth / 2;
 rgbHeight = originalHeight;

 dwRGBImageSize = rgbWidth * rgbHeight * 3;
 lpRGBImageBufferAddChar = new BYTE[dwRGBImageSize];
 lpRGBImageBuffer = new BYTE[dwRGBImageSize];
 
 // 图像数据格式从YUV转化为RGB,并且进行列抽样压缩(1/2)
 // ConvertYUVtoRGBSample(lpRawImageBuffer,lpRGBImageBuffer,originalWidth,originalHeight);

 ConvertYUVtoRGBSampleReverse(
  lpRawImageBuffer,
  lpRGBImageBuffer,
  originalWidth,
  originalHeight);
 
 res = PSAFreeCharToImage(lpRGBImageBuffer,
                       lpRGBImageBufferAddChar,
        lpszLineFirstString,
        lpszLineSecondString,
        lpszLineThirdString,
        dwLineFirstStartPosX, 
        dwLineFirstStartPosY, 
        dwLineSecondStartPosX, 
        dwLineSecondStartPosY, 
        dwLineThirdStartPosX, 
        dwLineThirdStartPosY);

 if (res == 0) // 如果字符叠加成功
 {
  res = CompressRGBToJPEG(lpRGBImageBufferAddChar,
        rgbWidth,
        rgbHeight,
        jpegQuality,
        jpegFileName,
        isNeedReversal,
        isResizeImage);
 }
 else
 {
  res = CompressRGBToJPEG(lpRGBImageBuffer,
        rgbWidth,
        rgbHeight,
        jpegQuality,
        jpegFileName,
        isNeedReversal,
        isResizeImage);
 }

 if (lpRGBImageBuffer != NULL) // 释放内存:无字符叠加RGB数据
 {
  delete[] lpRGBImageBuffer;
  lpRGBImageBuffer = NULL;
 }
 
 if (lpRGBImageBufferAddChar != NULL) // 释放内存:有字符叠加RGB数据
 {
  delete[] lpRGBImageBufferAddChar;
  lpRGBImageBufferAddChar = NULL;
 }

 return (res);
}

/************************************************************************
extern "C" EXPORTS Function PSARawToJpeg411Special:
        源图 Ycrcb格式[422] 通过查表转化为RGB 转化时行由720->768 高度扩1倍
  压缩为JPEG文件保存
Input:
  BYTE* lpRawImageBuffer 源图数据区
  int   originalWidth    源图宽度
  int   originalHeight   源图高度
  int   jpegQuality      JPEG压缩质量
  char* jpegFileName     JPEG保存文件名  
  int   isNeedReversal   压缩为JPEG时是否需要翻转
  int   isResizeImage    是否需要更改图像大小 
return:
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2006/01/14        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSARawToJpeg411Special(
        BYTE* lpRawImageBuffer,
        int   originalWidth,
        int   originalHeight,
        int   jpegQuality,
        char* jpegFileName,
        int   isNeedReversal,
        int   isResizeImage)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 int res = 0;
 BYTE* lpRGBImageBuffer;
 int rgbWidth;
 int rgbHeight;
 
 //宽度由720转化为768 高度不变
 rgbWidth = 768;
 rgbHeight = originalHeight * 2;
 lpRGBImageBuffer = new BYTE[rgbWidth * rgbHeight * 3];

 // ConvertYUV720toRGB768(lpRawImageBuffer,lpRGBImageBuffer,originalWidth,originalHeight);

 ConvertYUV720toRGB768TwoHeight(
  lpRawImageBuffer,
  lpRGBImageBuffer,
  originalWidth,
  originalHeight);

 res = CompressRGBToJPEG(lpRGBImageBuffer,
                      rgbWidth,
       rgbHeight,
       jpegQuality,
       jpegFileName,
       isNeedReversal,
       isResizeImage);

 if (lpRGBImageBuffer != NULL)
 {
  delete[] lpRGBImageBuffer;
  lpRGBImageBuffer = NULL;
 }

 return (res);
}

/************************************************************************
extern "C" EXPORTS Function PSARawToJpeg411SpecialAddChar:
  源图 Ycrcb格式[422] 通过查表转化为RGB 转化时行由720->768 高度扩1倍
  叠加字符 压缩为JPEG文件保存
Input:
  BYTE* lpRawImageBuffer 源图数据区
  int   originalWidth    源图宽度
  int   originalHeight   源图高度
  int   jpegQuality      JPEG压缩质量
  char* jpegFileName     JPEG保存文件名  
  int   isNeedReversal   压缩为JPEG时是否需要翻转
  int   isResizeImage    是否需要更改图像大小 
  LPCTSTR lpszLineFirstString    叠加的第一行字符
  LPCTSTR lpszLineSecondString   叠加的第二行字符
  LPCTSTR lpszLineThirdString    叠加的第三行字符
  DWORD   dwLineFirstStartPosX   第一行字符的起始X坐标
  DWORD   dwLineFirstStartPosY   第一行字符的起始Y坐标
  DWORD   dwLineSecondStartPosX  第二行字符的起始X坐标
  DWORD   dwLineSecondStartPosY  第二行字符的起始Y坐标
  DWORD   dwLineThirdStartPosX   第三行字符的起始X坐标
  DWORD   dwLineThirdStartPosY   第三行字符的起始Y坐标
return:
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2006/01/14        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSARawToJpeg411SpecialAddChar(
        BYTE* lpRawImageBuffer,
        int   originalWidth,
        int   originalHeight,
        int   jpegQuality,
        char* jpegFileName,
        int   isNeedReversal,
        int   isResizeImage,
        LPCTSTR lpszLineFirstString,
        LPCTSTR lpszLineSecondString,
        LPCTSTR lpszLineThirdString,
        DWORD   dwLineFirstStartPosX, 
        DWORD   dwLineFirstStartPosY, 
        DWORD   dwLineSecondStartPosX, 
        DWORD   dwLineSecondStartPosY, 
        DWORD   dwLineThirdStartPosX, 
        DWORD   dwLineThirdStartPosY)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 int res = 0;
 BYTE* lpRGBImageBuffer;
 int rgbWidth;
 int rgbHeight;
 BYTE* lpRGBImageBufferAddChar;
 DWORD dwRGBImageSize = 0;
 
 //宽度由720转化为768 高度不变
 rgbWidth  = 768;
 rgbHeight = originalHeight * 2;

 dwRGBImageSize = rgbWidth * rgbHeight * 3;
 lpRGBImageBufferAddChar = new BYTE[dwRGBImageSize];
 lpRGBImageBuffer = new BYTE[dwRGBImageSize];
 
 // 图像数据格式从YUV转化为RGB,并且进行列抽样压缩(1/2)
 // ConvertYUV720toRGB768(lpRawImageBuffer,lpRGBImageBuffer,originalWidth,originalHeight);
 
 // 无翻转图像保存为 768 * 576
 /*******************************************
 ConvertYUV720toRGB768TwoHeight(
  lpRawImageBuffer,
  lpRGBImageBuffer,
  originalWidth,
  originalHeight);
 *******************************************/
 
 // 翻转图像保存为 768 * 576
 ConvertYUV720toRGB768TwoHeightReverse(
  lpRawImageBuffer,
  lpRGBImageBuffer,
  originalWidth,
  originalHeight);

 // 叠加字符
 res = PSAFreeCharToImage(lpRGBImageBuffer,
                       lpRGBImageBufferAddChar,
        lpszLineFirstString,
        lpszLineSecondString,
        lpszLineThirdString,
        dwLineFirstStartPosX, 
        dwLineFirstStartPosY, 
        dwLineSecondStartPosX, 
        dwLineSecondStartPosY, 
        dwLineThirdStartPosX, 
        dwLineThirdStartPosY);

 if (res == 0) // 如果字符叠加成功 保存叠加字符后图片数据
 {
  res = CompressRGBToJPEG(lpRGBImageBufferAddChar,
        rgbWidth,
        rgbHeight,
        jpegQuality,
        jpegFileName,
        isNeedReversal,
        isResizeImage);
 }
 else // 如果字符叠加失败 保存叠加字符前图片数据
 {
  res = CompressRGBToJPEG(lpRGBImageBuffer,
        rgbWidth,
        rgbHeight,
        jpegQuality,
        jpegFileName,
        isNeedReversal,
        isResizeImage);
 }

 if (lpRGBImageBuffer != NULL) // 释放内存:无字符叠加RGB数据
 {
  delete[] lpRGBImageBuffer;
  lpRGBImageBuffer = NULL;
 }
 
 if (lpRGBImageBufferAddChar != NULL) // 释放内存:有字符叠加RGB数据
 {
  delete[] lpRGBImageBufferAddChar;
  lpRGBImageBufferAddChar = NULL;
 }

 return (res);
}

/************************************************************************
extern "C" EXPORTS Function PSAReadRawFileToBuffer:
        读取源图 Ycrcb格式[422]
Input:
  char* lpszRawFile          需要读取的文件名称(全路径完整名称)  
Output:
     int  &imageWidth           图像宽度
  int  &imageHeight          图像高度
  BYTE *lpRawImageBuffer     图像数据缓存
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/18        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAReadRawFileToBuffer(
        char* lpszRawFile, 
        int   &imageWidth, 
        int   &imageHeight, 
        BYTE *lpRawImageBuffer
        )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int res = 0;

 CFile   rawFile;
 CString strRawFile;
 CFileException e;

 short int width;
 short int height;
 int       rawImageSize;
 BYTE*     imageBuffer;
 int       fileLength;
 
 strRawFile.Format("%s",lpszRawFile);
 strRawFile.MakeLower();

 int iFind = strRawFile.ReverseFind( '.' );
 if (iFind == -1)
 {
  res = 1;
  return res;
 }
 
 iFind = strRawFile.Find("raw");
 if (iFind == -1)
 {
  res = 2;
  return res;
 }

 if (rawFile.Open(strRawFile, CFile::modeRead, &e) == NULL)
 {
  res = 3;
  return res;
 }

 rawFile.SeekToBegin();
 rawFile.Read(&width, 2);
 rawFile.Read(&height, 2);

 rawImageSize = width * height * 2 + 4;

 fileLength = rawFile.GetLength();

 if (rawImageSize != fileLength)
 {
  rawFile.Close();
  res = 4;
  return res;
 }

 imageBuffer  = new unsigned char[rawImageSize];
 imageWidth   = width;
 imageHeight  = height;
 
 rawFile.SeekToBegin();
 if (rawFile.Read(imageBuffer, rawImageSize) != (unsigned int)rawImageSize)
 {
  if (imageBuffer != NULL)
  {
   delete[] imageBuffer;
   imageBuffer = NULL;
  }
  rawFile.Close();
  res = 5;
  return res;
 }
 
 memcpy(lpRawImageBuffer, imageBuffer+4, rawImageSize-4);
 if (imageBuffer != NULL)
 {
  delete[] imageBuffer;
  imageBuffer = NULL;
 }
 rawFile.Close();

 return res;
}

/************************************************************************
extern "C" EXPORTS Function PSAReadRawFileToBuffer:
        读取源图 Ycrcb格式[422] 宽度由768更更改为720 高度不变
Input:
  char* lpszRawFile          需要读取的文件名称(全路径完整名称)  
Output:
     int  &imageWidth           图像宽度
  int  &imageHeight          图像高度
  BYTE *lpRawImageBuffer     图像数据缓存
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/18        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAReadRaw768To720(
        char* lpszRawFile, 
        int   &imageWidth, 
        int   &imageHeight, 
        BYTE *lpRawImageBuffer
        )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int res = 0;

 CFile   rawFile;
 CString strRawFile;
 CFileException e;

 short int width;
 short int height;
 int       rawImageSize;
 BYTE*     imageBuffer;
 BYTE*     imageTmp;
 BYTE*     imageDst;
 int       fileLength;
 int       nRowLength;
 
 strRawFile.Format("%s",lpszRawFile);
 strRawFile.MakeLower();

 int iFind = strRawFile.ReverseFind( '.' );
 if (iFind == -1)
 {
  res = 1;
  return res;
 }
 
 iFind = strRawFile.Find("raw");
 if (iFind == -1)
 {
  res = 2;
  return res;
 }

 if (rawFile.Open(strRawFile, CFile::modeRead, &e) == NULL)
 {
  res = 3;
  return res;
 }

 rawFile.SeekToBegin();
 rawFile.Read(&width, 2);
 rawFile.Read(&height, 2);

 rawImageSize = width * height * 2 + 4;

 fileLength = rawFile.GetLength();

 if (rawImageSize != fileLength)
 {
  rawFile.Close();
  res = 4;
  return res;
 }

 imageBuffer  = new unsigned char[rawImageSize];
 imageWidth   = width;
 imageHeight  = height;
 
 rawFile.SeekToBegin();
 if (rawFile.Read(imageBuffer, rawImageSize) != (unsigned int)rawImageSize)
 {
  if (imageBuffer != NULL)
  {
   delete[] imageBuffer;
   imageBuffer = NULL;
  }
  rawFile.Close();
  res = 5;
  return res;
 }
 
 //memcpy(lpRawImageBuffer, imageBuffer+4, rawImageSize-4);
 imageTmp = imageBuffer + 4;
 imageDst = lpRawImageBuffer;

 if (width == 768)
 { 
  imageWidth = 720;
 
  nRowLength = 0;
  for (int i=0; i< height; i++)
  {
   memcpy(imageDst, imageTmp, 1440);
   imageDst += 1440;
   imageTmp += 1536;
  }
 }
 else
 {
  memcpy(imageDst, imageTmp, rawImageSize-4); 
 }

 if (imageBuffer != NULL)
 {
  delete[] imageBuffer;
  imageBuffer = NULL;
 }
 rawFile.Close();

 return res;
}

/************************************************************************
extern "C" EXPORTS Function PSAReadRawFileToBuffer:
        读取源图 Ycrcb格式[422] 宽度由768更更改为720  高度取1/2
  取源图像数据 Height / 2 至 Height 行
Input:
  char* lpszRawFile          需要读取的文件名称(全路径完整名称)  
Output:
     int  &imageWidth           图像宽度
  int  &imageHeight          图像高度
  BYTE *lpRawImageBuffer     图像数据缓存
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2006/01/14        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAReadRaw768To720HalfHeight(
        char* lpszRawFile, 
        int   &imageWidth, 
        int   &imageHeight, 
        BYTE *lpRawImageBuffer
        )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int res = 0;

 CFile   rawFile;
 CString strRawFile;
 CFileException e;

 short int width;
 short int height;
 int       rawImageSize;
 BYTE*     imageBuffer;
 BYTE*     imageTmp;
 BYTE*     imageDst;
 int       fileLength;
 int       nRowLength;
 
 strRawFile.Format("%s",lpszRawFile);
 strRawFile.MakeLower();

 int iFind = strRawFile.ReverseFind( '.' );
 if (iFind == -1)
 {
  res = 1;
  return res;
 }
 
 iFind = strRawFile.Find("raw");
 if (iFind == -1)
 {
  res = 2;
  return res;
 }

 if (rawFile.Open(strRawFile, CFile::modeRead, &e) == NULL)
 {
  res = 3;
  return res;
 }

 rawFile.SeekToBegin();
 rawFile.Read(&width, 2);
 rawFile.Read(&height, 2);

 rawImageSize = width * height * 2 + 4;

 fileLength = rawFile.GetLength();

 if (rawImageSize != fileLength)
 {
  rawFile.Close();
  res = 4;
  return res;
 }

 imageBuffer  = new unsigned char[rawImageSize];
 imageWidth   = width;
 imageHeight  = height;
 
 rawFile.SeekToBegin();
 if (rawFile.Read(imageBuffer, rawImageSize) != (unsigned int)rawImageSize)
 {
  if (imageBuffer != NULL)
  {
   delete[] imageBuffer;
   imageBuffer = NULL;
  }
  rawFile.Close();
  res = 5;
  return res;
 }
 
 //memcpy(lpRawImageBuffer, imageBuffer+4, rawImageSize-4);
 imageTmp = imageBuffer + 4;
 imageDst = lpRawImageBuffer;

 if (width == 768)
 {
  imageWidth   = 720;
  imageHeight  = height / 2;

  nRowLength = 0;

  imageTmp += 768 * 2 * (height / 2); // 复制下半幅图,如果复制上半幅图则注释掉此句

  for (int i=0; i< (height / 2); i++)
  {
   memcpy(imageDst, imageTmp, 1440);
   imageDst += 1440;
   imageTmp += 1536;
  }
 }
 else
 {
  memcpy(imageDst, imageTmp, ((rawImageSize - 4) / 2)); 
 }

 if (imageBuffer != NULL)
 {
  delete[] imageBuffer;
  imageBuffer = NULL;
 }
 rawFile.Close();

 return res;
}

/************************************************************************
extern "C" EXPORTS Function PSAWriteRawFile:
        保存源图 Ycrcb格式[422]
Input:
  const char* lpszRawFile    需要保存的文件名称(全路径完整名称)  
     int   imageWidth           图像宽度
  int   imageHeight          图像高度
  BYTE *lpRawImageBuffer     图像缓存
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/18        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAWriteRawFile(
        const char* lpszRawFile, 
        int   imageWidth, 
        int   imageHeight, 
        BYTE *lpRawImageBuffer
        )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int res = 0;
 unsigned long ulRawImageSize;
 BYTE btHeader[4];
 WORD* lpWordHeader; 
 FILE* fileWrite;

 fileWrite = fopen(lpszRawFile,"wb");
 if (fileWrite == NULL)
 {
  res = 1;
  goto Exit;
 }
 
 lpWordHeader = (WORD *)btHeader;
 lpWordHeader[0] = (WORD)imageWidth;
 lpWordHeader[1] = (WORD)imageHeight;
 
 if (fwrite(btHeader,1,4,fileWrite) != 4)
 {
  fclose(fileWrite);
  res = 2;
  goto Exit;
 }

 ulRawImageSize = imageWidth * imageHeight * 2;

 if (fwrite(lpRawImageBuffer, 1, ulRawImageSize, fileWrite) != ulRawImageSize)
 {
  fclose(fileWrite);
  res = 3;
  goto Exit;
 }
 fclose(fileWrite);
 
Exit:
 return res;
}

/************************************************************************
extern "C" EXPORTS Function PSAWriteBMPFile:
        保存为BMP格式的图像
Input:
  LPCSTR lpszBMPFile          需要保存的文件名称(全路径完整名称)  
     int    imageWidth           图像宽度
  int    imageHeight          图像高度
  BYTE  *lpRawImageBuffer     图像缓存
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/31        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSAWriteBMPFile(
        LPCSTR lpszBMPFile, 
        int  imageWidth, 
        int  imageHeight, 
        BYTE *lpRawImageBuffer
        )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 int   res = 0;
 FILE* fileWrite;
 
 BYTE*            lpRGBImageBuffer;
 BITMAPFILEHEADER bmFileHeader;
 BITMAPINFO       bmInfo;
 DWORD            dwRGBImageSize = imageWidth * imageHeight * 3;
 BYTE             lpFileHeader[128];
 int              ibmFileHeaderSize;              
 
 bmFileHeader.bfType = 0x4D42;
 bmFileHeader.bfSize = 54 + dwRGBImageSize;
 bmFileHeader.bfOffBits = 54; 
 bmFileHeader.bfReserved1 = 0;
 bmFileHeader.bfReserved2 = 0;
 
 bmInfo.bmiHeader.biBitCount      = 24;
    bmInfo.bmiHeader.biClrImportant  = 0;
    bmInfo.bmiHeader.biClrUsed       = 0;
    bmInfo.bmiHeader.biCompression   = 0;
    bmInfo.bmiHeader.biHeight        = imageHeight;
    bmInfo.bmiHeader.biPlanes        = 1;
    bmInfo.bmiHeader.biSize          = 40;
    bmInfo.bmiHeader.biSizeImage     = dwRGBImageSize;
    bmInfo.bmiHeader.biWidth         = imageWidth;
 bmInfo.bmiHeader.biXPelsPerMeter = 0;
    bmInfo.bmiHeader.biYPelsPerMeter = 0;
 
 lpRGBImageBuffer = new BYTE[dwRGBImageSize];

 ConvertYUVtoRGB(lpRawImageBuffer,lpRGBImageBuffer,imageWidth,imageHeight);

 fileWrite = fopen(lpszBMPFile,"wb");
 if (fileWrite == NULL)
 {
  res = 1;
  goto Exit;
 }
 
 ibmFileHeaderSize = sizeof(BITMAPFILEHEADER);
 memcpy(lpFileHeader,&bmFileHeader,ibmFileHeaderSize);
 memcpy(&lpFileHeader[ibmFileHeaderSize],&bmInfo.bmiHeader,sizeof(BITMAPINFOHEADER));
 
 if (fwrite(lpFileHeader,sizeof(BYTE),54,fileWrite) != 54)
 {
  fclose(fileWrite);
  res = 5;
  goto Exit;
 }

 /*
 if (fwrite(&bmFileHeader,sizeof(BITMAPFILEHEADER),1,fileWrite) != sizeof(BITMAPFILEHEADER))
 {
  fclose(fileWrite);
  res = 2;
  goto Exit;
 }
 
 if (fwrite(&bmInfo.bmiHeader,sizeof(BITMAPINFOHEADER ),1,fileWrite) != sizeof(BITMAPINFOHEADER ))
 {
  fclose(fileWrite);
  res = 3;
  goto Exit;
 }
 */

 if (fwrite(lpRGBImageBuffer, sizeof(BYTE), dwRGBImageSize, fileWrite) != dwRGBImageSize)
 {
  fclose(fileWrite);
  res = 4;
  goto Exit;
 }

Exit:
 if (res != 1)
 {
  fclose(fileWrite);
 }
 if (lpRGBImageBuffer != NULL)
 {
  delete[] lpRGBImageBuffer;
  lpRGBImageBuffer = NULL;
 }

 return res;
}

/************************************************************************
extern "C" EXPORTS Function PSATryGetFileVersion:
        尝试获取外部文件的版本信息
  对有版本信息的文件有效[例如Exe文件/DLL文件]   
Input:
  LPCTSTR lpszFileName     需要获取的文件名称(全路径完整名称)  
     DWORD* iMajor            主版本号
  DWORD* iMinor            次版本号
  DWORD* iRelease          内部版本号
  DWORD* iBuild            修订号 
return::
        正常返回0值,非0值表示失败;
Update:
  Author         Date              Ver      Remark  
  Shimingjie     2005/08/18        1.0      Create  
************************************************************************/
extern "C" int PASCAL EXPORT PSATryGetFileVersion(
        LPTSTR lpszFileName, 
        DWORD* iMajor, 
        DWORD* iMinor, 
        DWORD* iRelease, 
        DWORD* iBuild
        )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
 int               iVersionInfoSize = 0;
 BYTE*             lpVersionDataBuffer;
 int               retval = 0;
 int               res    = -999;
 BYTE*             lplpVersion;
 VS_FIXEDFILEINFO* version;
    DWORD             dwVersionSize;
   
 if (lpszFileName == NULL)
 {
  return(res);
 }

 iVersionInfoSize = GetFileVersionInfoSize(lpszFileName,0);
 if (iVersionInfoSize > 0)
 {
  lpVersionDataBuffer = new BYTE[iVersionInfoSize];
  retval = GetFileVersionInfo(lpszFileName,0,iVersionInfoSize,lpVersionDataBuffer); 
  if (retval != 0)
  {
   retval = VerQueryValue(lpVersionDataBuffer,"\\",(void**)&lplpVersion,(unsigned int*)&dwVersionSize);
   if (retval != 0)
   {
    version = (VS_FIXEDFILEINFO*)lplpVersion; 
    *iMajor = version->dwFileVersionMS >> 16;
    *iMinor = version->dwFileVersionMS & 0xFFFF;
    *iRelease = version->dwFileVersionLS >> 16;
    *iBuild   = version->dwFileVersionLS & 0xFFFF;
    res = 0;
   }
   else
   {
    res = -3;
   }
  }
  else
  {
   res = -2;
  }
  if (lpVersionDataBuffer != NULL)
  {
   delete[] lpVersionDataBuffer;
   lpVersionDataBuffer = NULL;
  }
 }
 else
 {
  res = -1;
 }

 return(res);
}

 

(秩名)

 

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201001/8204.html]

 

 

时间: 2024-12-02 01:40:35

RGB图像数据字符叠加,图像压缩(ijl库),YUV转RGB的相关文章

vc/mfc获取rgb图像数据后动态显示及保存图片的方法

vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw32.lib  链接库 [cpp] view plaincopy   //------------------------------设置位图头结构信息----------------------------------------------------------------------      // S

YUV和RGB格式分析【转】

转自:http://www.cnblogs.com/silence-hust/p/4465354.html 做嵌入式项目的时候,涉及到YUV视频格式到RGB图像的转换,虽然之前有接触到RGB到都是基于opencv的处理,很多东西并不需要我们过多深入的去探讨,现在需要完全抛弃现有的算法程序,需要从内存中一个字节一个字节的处理,这就涉及到各个视频格式和图片格式是如何存储的.看了网上的很多资料,一下资料帮助蛮大. YUV资料整理: http://www.fourcc.org/yuv.php    YU

(DirectX系列06)DirectShow 字符叠加Filter编码分析

(DirectX系列06)DirectShow 字符叠加Filter编码分析 在很多视频播放的软件当中,字幕的处理是免不了的,有些可能本身已经加载到图像当中未做处理,但大部分都是通过字符叠加来进行处理的.DirectShow 的字符叠加Filter在这些软件中都扮演这绝佳的作用.这一节来介绍DirectShow字符叠加Filter编码的实现,如下详细介绍: 这个Filter的大概作用是在视频流指定的一段时间内进行字符叠加,字符字体.大小.颜色都进行控制,普遍支持RGB 的各种编码格式,同时实现字

MYSQL图像数据的处理

    6.8 其他主题    本节包括几个主题,这些主题不完全适合于本章从client1到client5 的开发中的任一小节的内容:    ■ 在使用结果集元数据帮助验证这些数据适合于计算之后,使用结果集数据计算结果.    ■ 如何处理很难插入到查询中的数据.    ■ 如何处理图形数据.    ■ 如何获得表结构的信息.    ■ 常见的MySQL程序设计错误及如何避免.    6.8.1在结果集上执行计算    迄今为止,我们集中而主要地使用了结果集元数据来打印行数据,但很明显,除打印之

SQL Server存储图像数据的策略与方法

server|策略|数据 目前对于图像数据的管理大都采用表+实体的方法,即图像数据以文件形式存放于指定的计算机目录下,在数据库表中只反映图像数据文件的存储路径.这种管理模式,给数据的维护增加了难度,同时,也给数据的安全带来一定的隐患.因此,要真正做到各类数据在数据库中安全管理,研究和探索直接将图像数据存储在数据库关系表中的方法是非常必要的. 笔者在Visual Basic 6.0开发环境中,采用客户机/服务器的工作方式,针对SQL Server数据库关系表中存储图像数据的问题进行了初步探讨,提出

FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

FFMPEG中的swscale提供了视频原始数据(YUV420,YUV422,YUV444,RGB24...)之间的转换,分辨率变换等操作,使用起来十分方便,在这里记录一下它的用法. swscale主要用于在2个AVFrame之间进行转换. 下面来看一个视频解码的简单例子,这个程序完成了对"北京移动开发者大会茶歇视频2.flv"(其实就是优酷上的一个普通视频)的解码工作,并将解码后的数据保存为原始数据文件(例如YUV420,YUV422,RGB24等等).其中略去了很多的代码. 注:完

《JavaScript数据可视化编程》—— 第1章 图像数据1.1 创建基础的柱状图

第1章 图像数据 JavaScript数据可视化编程在很多人的印象中,数据可视化图形是一些非常酷炫复杂.充满科幻设计感的图形.这种看法其实存在误区.实际上,建立一个有效的数据可视化模型并不需要特别深厚的设计功底和复杂的编程技巧,如果你一直牢记着数据可视化的目的是帮助人们更好地理解数据,那么你就会认同,在进行数据可视化的过程中最需要注意的,恰恰是"简单"二字.那些看似简单基础.随处可见的图表及其所传达的信息,往往最容易为人们所理解和消化. 因为用户已经熟悉了各式各样的常规图表,如柱状图.

用VB存取SQL Server中的图像数据

本文介绍MIS SQL Server对图像数据的存储机制和存取方法.针对VB开发工具,介绍了一种通过ADO Field 对象的GetChunk 方法和AppendChunk 方法来存取MIS SQL Server中的图像数据的方法. 在一个完善的医院信息MIS中,图像数据的存取是必不可少的,比如X光片.CT像片的保存.一方面,这些图像数据在远程诊疗为准确诊断病情提供了重要的依据,另一方面,也为快速查阅病人资料提供了基本条件.图像数据的存取在其它应用系统如GIS中也有广泛的应用. 1.SQL Se

SQL Server存储图像数据的机制介绍

本文介绍MIS SQL Server对图像数据的存储机制和存取方法.针对VB开发工具,介绍了一种通过ADO Field 对象的GetChunk 方法和AppendChunk 方法来存取MIS SQL Server中的图像数据的方法. 在一个完善的医院信息MIS中,图像数据的存取是必不可少的,比如X光片.CT像片的保存.一方面,这些图像数据在远程诊疗为准确诊断病情提供了重要的依据,另一方面,也为快速查阅病人资料提供了基本条件.图像数据的存取在其它应用系统如GIS中也有广泛的应用. 1.SQL Se