www.pudn.com > OSD 测试程序.rar > UnitOSDFunctions.pas


{ *********************************************************************** } 
{                                                                         } 
{ 公用函数                                                                } 
{ Created: 03-18-2004                                                     } 
{ Copyright (c) 1998-2004 吉首市先凌科技                                  } 
{ Last update: 03-22-2004    by xlkjok                                    } 
{                                                                         } 
{ *********************************************************************** } 
 
unit UnitOSDFunctions; 
 
interface 
 
uses 
  Windows, SysUtils, Classes, Graphics; 
 
type 
  rgb2xFlag = (rfUseRLE, rf2Output, rf2RLE, rf7Output, rf7RLE); //默认为rf7Output 输入为8位 
 
procedure bmp8_reverse(pRgb: PBYTE; width, height: Integer); 
 
procedure bmp4_reverse(pRgb: PBYTE; width, height: Integer); 
// rgb 2 yuv: 
// Y  =  0.257r + 0.504g + 0.098b + 16 
// Cb = -0.148r - 0.291g + 0.439b + 128 
// Cr =  0.439r + 0.368g + 0.071b + 128 
function rgb2y(r, g, b: Byte): Byte; 
//------------------------ 
function rgb2u(r, g, b: Byte): Byte; 
 
function rgb2v(r, g, b: Byte): Byte; 
 
procedure rgb24_yuv420(w, h: Integer; pRgb, pYuv: PBYTE); 
// converts palette 
procedure rgb24_yuv444 (n: Integer; pRgb, pYuv: PBYTE); 
 
 
procedure ConvertTo7bit(var fsSrc: TMemoryStream; outfsDst: TMemoryStream; var bmih: BITMAPINFOHEADER); 
 
function GetPaletteFromBitmap(AmsSrc: TMemoryStream; var AmsOut: TMemoryStream): Boolean; 
 
function MakeMoreLinesWords(const ACaption: string; AWidth: Integer; AFont: TFont; var AOutStream: TMemoryStream): Boolean; 
 
function Streamrgb2x(var AmStreamSrc: TMemoryStream; var AmStreamDest: TMemoryStream): Boolean; 
 
implementation 
 
 
function Streamrgb2x(var AmStreamSrc: TMemoryStream; 
  var AmStreamDest: TMemoryStream): Boolean; 
var 
  bmfh: BITMAPFILEHEADER; 
	bmih: BITMAPINFOHEADER; 
begin 
  if AmStreamDest.Size > 0 then 
    AmStreamDest.Clear; 
  Result := False; 
  AmStreamSrc.Seek(0, soFromBeginning); 
	AmStreamSrc.ReadBuffer(bmfh, SizeOf(bmfh)); 
	AmStreamSrc.ReadBuffer(bmih, sizeof(bmih)); 
  bmih.biBitCount := 7; 
  ConvertTo7bit(AmStreamSrc, AmStreamDest, bmih); 
  Result := True; 
end; 
//------------------------------------------------------------------------------ 
 
// 
function MakeMoreLinesWords(const ACaption: string; AWidth: Integer; AFont: TFont; var AOutStream: TMemoryStream): Boolean; 
var 
  srcstr, substr: string; 
  sl: TStringList; 
  i, y,j, Len, AllLen, LineHeight, CurrentPos: Integer; 
  bmTemp: TBitmap; 
begin 
  if AOutStream.Size > 0 then 
    AOUtStream.Clear; 
 
  srcStr := ACaption; 
  AllLen := Length(srcStr); 
  bmTemp := TBitmap.Create; 
  sl := TStringList.Create; 
  try 
    bmTemp.PixelFormat := pf8bit; 
    bmTemp.Width := AWidth; 
    bmtemp.Canvas.Font := AFont; 
    if bmTemp.Canvas.TextWidth(srcStr) > AWidth then 
      Len := AWidth div (bmTemp.Canvas.TextWidth(srcStr) div AllLen) 
    else 
      Len := AllLen; 
    LineHeight := bmTemp.Canvas.TextHeight(srcStr); 
    CurrentPos := 0; 
    //bmTemp.Height := 0; 
    y := 0; 
    while True do 
    begin 
      //bmTemp.Height := bmTemp.Height + LineHeight; 
      subStr := Copy(srcStr, CurrentPos, Len); 
      Inc(CurrentPos, Len); 
      while bmTemp.Canvas.TextWidth(subStr) > AWidth do 
      begin 
        SetLength(subStr, Length(subStr) - 1); 
        Dec(CurrentPos); 
        if Ord(subStr[Length(subStr)]) > 128 then 
        begin 
          SetLength(subStr, Length(subStr) - 1); 
          Dec(CurrentPos); 
        end; 
      end; 
      sl.Add(subStr); 
      subStr := Copy(srcStr, CurrentPos, Len); 
      if subStr = '' then 
        Break; 
    end; 
 
    bmTemp.Height := sl.Count * LineHeight; 
    for i := 0 to sl.Count - 1 do 
    begin 
     bmTemp.Canvas.TextOut(0, i * LineHeight, sl.Strings[i]); 
    end; 
    bmTemp.SaveToStream(AOutStream); 
  finally 
    bmTemp.Free; 
    sl.Free; 
  end; 
end; 
//------------------------------------------------------------------------------ 
 
//从位图中取得调色板 
function GetPaletteFromBitmap(AmsSrc: TMemoryStream; var AmsOut: TMemoryStream): Boolean; 
var 
  PalEntries: LongWord; 
  bmfh: BITMAPFILEHEADER; 
	bmih: BITMAPINFOHEADER; 
  pPalRgb, pPalYuv: PBYTE; 
begin 
 
  Result := False; 
 
  if AmsSrc.Size <= 0 then Exit; 
  if AmsOut.Size > 0 then 
    AmsOut.Clear; 
 
  AmsSrc.Seek(0, soFromBeginning); 
	AmsSrc.ReadBuffer(bmfh, SizeOf(bmfh)); 
	AmsSrc.ReadBuffer(bmih, sizeof(bmih)); 
 
  if not ((bmih.biBitCount = 7) or (bmih.biBitCount = 8)) then Exit; 
 
  bmih.biBitCount := 7; 
 
  if bmih.biClrUsed > 1 then 
    PalEntries := bmih.biClrUsed 
  else 
    PalEntries := 256; 
 
  GetMem(pPalRgb, PalEntries * 4); 
  GetMem(pPalYuv, 256 * 4); 
 
  AmsSrc.ReadBuffer(pPalRgb^, PalEntries * 4); 
  rgb24_yuv444 (PalEntries, pPalRgb, pPalYuv); 
  AmsOut.WriteBuffer(pPalYuv^, 256 * 4); 
 
  FreeMem(pPalRgb); 
  FreeMem(pPalYuv); 
 
  Result := True; 
end; 
//------------------------------------------------------------------------------ 
 
 
//不知哪位高手是有OSDShell.ax的一些接口信息没有? 
// 
//-  
//-  
//   
//   
//-  1 then 
    PalEntries := bmih.biClrUsed 
  else 
    PalEntries := 256; 
		// convert to quasar 8 bit osd format and write to a file 
		GetMem(pPalRgb, PalEntries * 4); 
		GetMem(pPalYuv, 256 * 4); 
		GetMem(pRgb, bmih.biWidth * bmih.biHeight); 
		GetMem(pRgb2, bmih.biWidth * bmih.biHeight); 
 
		// read the palette 
		 fsSrc.ReadBuffer(pPalRgb^, PalEntries * 4); 
 
 
		p := pRgb; 
		align := bmih.biWidth mod 4; 
		for ii := 0 to bmih.biHeight - 1 do 
    begin 
			fsSrc.ReadBuffer(p^, bmih.biWidth); 
			p := PBYTE(DWORD(p) + bmih.biWidth); 
      fsSrc.Read(xx[0], align); 
 
		end; 
		// read the bitmap data 
		// convert the palette 
		rgb24_yuv444 (PalEntries, pPalRgb, pPalYuv); 
		// write osd file 
 
		// write header 
		//if(!rle) 
			b := $3c; 
		//else b = 0x3d; 
		outfsDst.WriteBuffer(b, 1); 
			// write size 
			size := (bmih.biWidth * bmih.biHeight) + 1024 + 8; 
			b := BYTE(size shr 16); 
      outfsDst.WriteBuffer(b, 1); 
			b := BYTE(size shr 8); 
			outfsDst.WriteBuffer(b, 1); 
			b := BYTE(size shr 0); 
			outfsDst.WriteBuffer(b, 1); 
			// write width 
			b := BYTE(bmih.biWidth shr 8); 
			outfsDst.WriteBuffer(b, 1); 
			b := BYTE(bmih.biWidth shr 0); 
			outfsDst.WriteBuffer(b, 1); 
			// write height 
			b := BYTE(bmih.biHeight shr 8); 
			outfsDst.WriteBuffer(b, 1); 
			b := BYTE(bmih.biHeight shr 0); 
			outfsDst.WriteBuffer(b, 1); 
			// write palette 
			outfsDst.WriteBuffer(pPalYuv^, 256 * 4); 
 
			// write the data 
			// for 7bit make kill the most significant bit 
     // fsSrc.Seek(576, soFromBeginning); 
     // fsSrc.Read(pRgb^, 20000); 
      pb := pRgb; 
			for ii := 0 to bmih.biWidth * bmih.biHeight - 1 do 
			begin 
			  pb^ := pb^ and $7f; 
				pb := PBYTE(DWORD(pb) + 1); 
			end; 
 
      bmp8_reverse(pRgb, bmih.biWidth, bmih.biHeight);	// reverse the data (bmp is stored upside-down) 
 
			outfsDst.WriteBuffer(pRgb^, bmih.biWidth * bmih.biHeight); 
 
		freeMem(pPalRgb); 
		FreeMem(pPalYuv); 
	 	FreeMem(pRgb); 
end; 
//------------------------------------------------------------------------------ 
 
procedure rgb24_yuv444 (n: Integer; pRgb, pYuv: PBYTE); 
var 
  i: Integer; 
  r, g, b, y, u, v, a: PBYTE; 
begin 
	r := PBYTE(DWORD(pRgb) + 2); 
	g := PBYTE(DWORD(pRgb) + 1); 
	b := PBYTE(DWORD(pRgb) + 0); 
	y := PBYTE(DWORD(pYuv) + 1); 
	u := PBYTE(DWORD(pYuv) + 2); 
	v := PBYTE(DWORD(pYuv) + 3); 
	a := PBYTE(DWORD(pYuv) + 0); 
	for i := 0 to n - 1 do 
	begin 
		y^ := rgb2y(r^, g^, b^); 
		u^ := rgb2u(r^, g^, b^); 
		v^ := rgb2v(r^, g^, b^); 
		if i = $7f then 
			a^ := 0 
		else 
			a^ := $ff; 
		r := PBYTE(DWORD(r) + 4); 
		g := PBYTE(DWORD(g) + 4); 
		b := PBYTE(DWORD(b) + 4); 
		y := PBYTE(DWORD(y) + 4); 
		u := PBYTE(DWORD(u) + 4); 
		v := PBYTE(DWORD(v) + 4); 
		a := PBYTE(DWORD(a) + 4); 
	end; 
end; 
//------------------------------------------------------------------------------ 
 
procedure bmp8_reverse(pRgb: PBYTE; width, height: Integer); 
var 
  pTemp, pDst, pSrc: PBYTE; 
  bytes_in_line: ULONG; 
  i: Integer; 
begin 
  GetMem(pTemp, (width * height)); 
	pDst := pTemp; 
	pSrc := PBYTE(DWORD(pRgb) + (width * height)); 
	bytes_in_line := width; 
	if (pDst = nil) then Exit; 
	for i := 0 to height - 1 do 
  begin 
		pSrc := PBYTE(DWORD(pSrc) - bytes_in_line); 
  //  CopyMemory(pdst, psrc, bytes_in_line); 
    StrMove(Pointer(Pdst), Pointer(pSrc), bytes_in_line); 
		pDst := PBYTE(DWORD(pDst) + bytes_in_line); 
  end; 
 
	StrMove(Pointer(pRgb), Pointer(pTemp),  width * height); 
  FreeMem(pTemp); 
end; 
//------------------------------------------------------------------------------ 
 
procedure bmp4_reverse(pRgb: PBYTE; width, height: Integer); 
var 
  bytes_in_line: ULONG; 
  num: Integer; 
  pTemp, pSrc, pDst: PBYTE; 
  i: Integer; 
begin 
	//BYTE *pTemp = (BYTE *)malloc (width * height); 
	num := (width * height) div 2; 
	if Odd(width * height) then 
    Inc(num); 
  GetMem(pTemp, num); 
	pSrc := PBYTE(DWORD(pRgb) + num); 
	pDst := pTemp; 
 
	bytes_in_line :=  width div 2; 
	if Odd(width) then 
    Inc(bytes_in_line); 
	if (pDst = nil) then Exit; 
	for i := 0 to  height - 1 do 
  begin 
		pSrc := PBYTE(DWORD(pSrc) - bytes_in_line); 
		Move(pSrc, pDst, bytes_in_line); 
		pDst := PBYTE(DWORD(pDst) + bytes_in_line); 
  end; 
	Move(pTemp, pRgb, num); 
  FreeMem(pTemp); 
end; 
//------------------------------------------------------------------------------ 
 
function rgb2y(r, g, b: Byte): Byte; 
var 
  f: Double; 
begin 
	f := 0.257*r + 0.504*g + 0.098*b + 16.0; 
	if f > 255.0 then 
		f := 255.0; 
	Result := BYTE(Trunc(f)); 
end; 
//------------------------------------------------------------------------------ 
 
function rgb2u(r, g, b: Byte): Byte; 
var 
  f: Double; 
begin 
	f := -0.148*r - 0.291*g + 0.439*b + 128; 
	if f > 255.0 then 
		f := 255.0; 
  if f < 0.0 then 
    f := 0.0; 
	Result := BYTE(Trunc(f)); 
end; 
//------------------------------------------------------------------------------ 
 
function rgb2v(r, g, b: Byte): Byte; 
var 
  f: Double; 
begin 
	f := 0.439*r - 0.368*g - 0.071*b + 128; 
	if f > 255.0 then 
		f := 255.0; 
  if f < 0.0 then 
    f := 0.0; 
	Result := BYTE(Trunc(f)); 
end; 
//------------------------------------------------------------------------------ 
 
procedure rgb24_yuv420(w, h: Integer; pRgb, pYuv: PBYTE); 
var 
  rgb, y, uv: PBYTE; 
  u0, u1, u2, u3: BYTE; 
  v0, v1, v2, v3: BYTE; 
  i, j, k: Integer; 
begin 
	rgb := PBYTE(DWORD(pRgb) + (w*(h-1)*3)); 
	y   := pYuv; 
	uv  := PBYTE(DWORD(pYuv) + (w*h)); 
  i   := 0; 
  j   := 0; 
  k   := 0; 
	for j := 0 to h - 1 do 
  begin 
		for k := 0 to  w - 1 do 
    begin 
			PBYTE(DWORD(y) + i)^  := rgb2y(PBYTE(DWORD(rgb) + 2)^, PBYTE(DWORD(rgb) + 1)^, rgb^); 
      Inc(i); 
			if (((j and 1) = 0) and ((k and 1) = 0)) then 
			begin 
				// average the uv values 
				// [2][3] 
				// [0][1] 
				u0    := rgb2u (PBYTE(DWORD(rgb) + 2)^, PBYTE(DWORD(rgb) + 1)^, rgb^); 
				v0    := rgb2v (PBYTE(DWORD(rgb) + 2)^, PBYTE(DWORD(rgb) + 1)^, rgb^); 
				u1    := rgb2u (PBYTE(DWORD(rgb) + 5)^, PBYTE(DWORD(rgb) + 4)^, PBYTE(DWORD(rgb) + 3)^); 
				v1    := rgb2v (PBYTE(DWORD(rgb) + 5)^, PBYTE(DWORD(rgb) + 4)^, PBYTE(DWORD(rgb) + 3)^); 
				u2    := rgb2u (PBYTE(DWORD(rgb) + 2 - w*3)^, PBYTE(DWORD(rgb) + 1 - w*3)^, PBYTE(DWORD(rgb) + 0 - w*3)^); 
				v2    := rgb2v (PBYTE(DWORD(rgb) + 2 - w*3)^, PBYTE(DWORD(rgb) + 1 - w*3)^, PBYTE(DWORD(rgb) + 0 - w*3)^); 
				u3    := rgb2u (PBYTE(DWORD(rgb) + 5 - w*3)^, PBYTE(DWORD(rgb) + 4 - w*3)^, PBYTE(DWORD(rgb) + 3 - w*3)^); 
				v3    := rgb2v (PBYTE(DWORD(rgb) + 5 - w*3)^, PBYTE(DWORD(rgb) + 4 - w*3)^, PBYTE(DWORD(rgb) + 3 - w*3)^); 
				uv^   := BYTE((ULONG(u0) + ULONG(u1) + ULONG(u2) + ULONG(u3) div ULONG(4))); 
        uv    := PBYTE(DWORD(uv) + 1); 
				uv^   := BYTE((ULONG(v0) + ULONG(v1) + ULONG(v2) + ULONG(v3) div ULONG(4))); 
        uv    := PBYTE(DWORD(uv) + 1); 
			end; 
			rgb := PBYTE(DWORD(rgb) + 3); 
		end; 
		rgb := PBYTE(DWORD(rgb) - w*3*2);//rgb -= (w*3*2); 
  end; 
end; 
//------------------------------------------------------------------------------ 
 
end.