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.