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

 //printf("current path: %s ",szCurPath);
 
 GetLocalTime(&lpSystemTime);
 
 printf("current time: %04d-%02d-%02d %02d:%02d:%02d:%03d ", 
                    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 ",
          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 ",
         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 ",
         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... ");
 }
 else
 {
  printf("set current path failure! ");
 }
 ***********************************************/
 
 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 ",ijlErrorStr(jerr));
  res = 2;
  goto Exit;
 }

Exit:
 jerr = ijlFree(&jcprops);
 if(IJL_OK != jerr)
 {
  //printf("ijlFree() failed - %s ",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 ",ijlErrorStr(jerr));
  res = 2;
  goto Exit;
 }

Exit:
 jerr = ijlFree(&jcprops);
 if(IJL_OK != jerr)
 {
  //printf("ijlFree() failed - %s ",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]
 
 
原文地址:https://www.cnblogs.com/lidabo/p/3702039.html