Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.03.25;
Скачать: CL | DM;

Вниз

32-битные изображения в Delphi   Найти похожие ветки 

 
EV   (2006-07-10 16:03) [0]

Подскажите пожалуйста как в Delphi прорисовыватьь 32-битные изображения (или иконки) с Alpha каналом? Что для этого нужно?


 
antonn ©   (2006-07-10 16:30) [1]

32-битные изображения бывают разные. Пример для TBitmap с pf32bit:
(_B_in - 32-битный битмап, _B_out - 24-битный битмап, на него выводится, _x,_y - координаты вывода)
procedure CopyBitmapAlfa32to24(_B_in,_B_out:Tbitmap; _x,_y:integer);
const
 MaxPixelCountA = MaxInt div SizeOf(TRGBQuad);
 MaxPixelCount = MaxInt div SizeOf(TRGBTriple);
type
 PRGBArray = ^TRGBArray;
 TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;
 PRGBAArray = ^TRGBAArray;
 TRGBAArray = array[0..MaxPixelCountA-1] of TRGBQuad;
var x, y: Integer; _r,_b,_g:integer;
   w_in,h_in,w_out,h_out,tmp,x_cor,y_cor,x_corS,y_corS: Integer;
   RowOut:PRGBArray; RowIn:PRGBAArray;
   _d,_dd:double;
begin
w_in:=_B_in.Width;
h_in:=_B_in.Height;
w_out:=_B_out.Width;
h_out:=_B_out.Height;
if (_x)>w_out-1 then exit; if (_x+w_out)<0 then exit;
if (_y)>h_out-1 then exit; if (_y+h_out)<0 then exit;

if _x<0 then x_corS:=abs(_x) else x_corS:=0;
if _y<0 then y_corS:=abs(_y) else y_corS:=0;
if (_x+w_in)>w_out then x_cor:=_x+w_in-w_out else x_cor:=0;
if (_y+h_in)>h_out then y_cor:=_y+h_in-h_out else y_cor:=0;

 y_cor:=h_in-1-y_cor;
 tmp:=w_in-1-x_cor; _dd:=(100/255)/100;
 for y:=y_corS to y_cor do begin
    RowOut:= _B_out.ScanLine[y+_y];
    RowIn:= _B_in.ScanLine[y];
   for x:=x_corS to tmp do begin
        _d:=RowIn[x].rgbReserved*_dd;

         _r:= trunc(RowOut[x+_x].rgbtRed+(RowIn[x].rgbRed-RowOut[x+_x].rgbtRed)*_d);
        if _r>255 then _r:=255 else if _r<0 then _r:=0;

        _g:= trunc(RowOut[x+_x].rgbtGreen+(RowIn[x].rgbGreen-RowOut[x+_x].rgbtGreen)*_d);
        if _g>255 then _g:=255 else if _g<0 then _g:=0;

        _b:= trunc(RowOut[x+_x].rgbtBlue+(RowIn[x].rgbBlue-RowOut[x+_x].rgbtBlue)*_d);
        if _b>255 then _b:=255 else if _b<0 then _b:=0;

         RowOut[x+_x].rgbtRed:=_r;
         RowOut[x+_x].rgbtGreen:=_g;
         RowOut[x+_x].rgbtBlue:=_b;

 end; end;
end;

код старый, местами "неумный", есть простор для оптимизаций и пр.


 
miek ©   (2006-07-11 08:08) [2]

Код совершенно непонятный.
Для каждого пиксела: (A-прозрачность накладываемого спрайта, X-значение цвета одного канала в исходном спрайте, Y - в накладываемом, Z - результат)
Z = (1-A)*X + A*Y
И так для всех 3-х каналов и для всех пикселов. Можно извлекать прозрачность из альфа-канала, а можно подставлять постоянную.
Естественно, оба спрайта желательно иметь 32-битные.


 
antonn ©   (2006-07-11 08:57) [3]

miek ©   (11.07.06 8:08) [2]
Естественно, оба спрайта желательно иметь 32-битные.

а если это не естественно для автора?
код, приведенный мной копирует 32 битный битмап на 24 битный (который без альфаканала).
по формуле - если копировать 32 на 32, то нужно учитывать бит альфаканала "приемника", чтобы не заменить его более светлым из иконки.
по моей формуле: Z = X+(Y-X)*(A/255)


 
EV   (2006-07-11 16:55) [4]

ОГРОМНОЕ СПАСИБО


 
EV   (2006-07-12 12:07) [5]

Вот мой доработанный код. 32-битное (либо другое) изображение накладывается на фоновое изображение.


procedure CopyBitmapAlfa32to24(SrcBitmap: TBitmap; var DestBitmap: TBitmap;
x,y: Integer; AlphaBlendValue: Byte);
const
MaxPixelCountA = MaxInt div SizeOf(TRGBQuad);
MaxPixelCount = MaxInt div SizeOf(TRGBTriple);
type
{PRGBArray = ^TRGBArray;
TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple; }
PRGBAArray = ^TRGBAArray;
TRGBAArray = array[0..MaxPixelCountA-1] of TRGBQuad;
var
i, j: integer;
r1, g1, b1, r, g, b, r2, g2, b2, alpha: byte;
a: Real;
RowIn: PRGBAArray;
c, c1: Cardinal;
//RowOut: PRGBArray;
begin
x:=Abs(x);
y:=Abs(y);

if x+SrcBitmap.Width > DestBitmap.Width then Exit;
if y+SrcBitmap.Height > DestBitmap.Height then Exit;

for j:=0 to SrcBitmap.Height-1 do
 begin
 RowIn:=SrcBitmap.ScanLine[j];
 for i:=0 to SrcBitmap.Width-1 do
 begin
  if SrcBitmap.PixelFormat = pf32bit then
  begin
   Alpha:=RowIn[i].rgbReserved;
   r1:=RowIn[i].rgbRed;
   g1:=RowIn[i].rgbGreen;
   b1:=RowIn[i].rgbBlue;
  end
   else
  begin
   Alpha:=AlphaBlendValue;
   c1:=SrcBitmap.Canvas.Pixels[i,j];
   r1:=GetRValue(c1);
   g1:=GetGValue(c1);
   b1:=GetBValue(c1);
  end;

  a:=alpha/255;

  c:=DestBitmap.Canvas.Pixels[x+i,y+j];
  r:=GetRValue(c);
  g:=GetGValue(c);
  b:=GetBValue(c);

  r2:=Round((1-a)*r + a*r1);
  g2:=Round((1-a)*g + a*g1);
  b2:=Round((1-a)*b + a*b1);

  DestBitmap.Canvas.Pixels[x+i,y+j]:=RGB(r2,g2,b2);
 end;
 end;

end;


 
Степан   (2006-07-25 23:50) [6]

Могу в помощь выложить.... может пригодиться... самопальный набор, сделано для друга... выводит битмап по маске, но можно и проапгрейдить!


function GetGradientColor(Color1, Color2: TColor; BlockCount,
 BlockIndex: Integer): TColor;
var
 DifR, DifB, DifG: Integer;
 SR, SG, SB: Integer;
begin
 SR := Color1 and $FF;
 DifR := (Color2 and $FF) - SR;
 SG := (Color1 shr 8) and $FF;
 DifG := ((Color2 shr 8) and $FF) - SG;
 SB := (Color1 shr 16) and $FF;
 difb:=((Color2 shr 16) and $FF) - SB;
 Result := RGB((BlockIndex * DifR) div (BlockCount - 1) + SR,
   (BlockIndex * DifG) div (BlockCount - 1) + SG,
   (BlockIndex * DifB) div (BlockCount - 1) + SB);
end;

function DrawAlphaBitmap(const Canvas: TCanvas; var ColorBitmap,
 MaskBitmap: TBitmap; X, Y: Integer): Boolean;

type
 TArray = array [0..0] of Integer;

 function GetBitsColor(var Bits: Pointer; Width, Height: Integer;
 X, Y: Cardinal): Integer;
 begin
   Result := 0;
   try
     Result := TArray(Bits^)[X + Y * Width];
   except
   end;
 end;
 procedure SetBitsColor(var Bits: Pointer; Width, Height: Integer;
   X, Y: Cardinal; Color: Integer);
 begin
   try
     TArray(Bits^)[X + Y * Width] := Color;
   except
   end;
 end;

var
 ColorBits: Pointer;  // Массив пикселей исходного изображения
 MaskBits: Pointer;  // Массив пикселей маски изображения
 DestBitmap: HBITMAP;   // Дескриптор полученного изображения
 DestDC: HDC;  // Контекстное устройтво полученного изображения
 DestBits: Pointer;  // Массив пикселей полученного изображения
 BitmapInfo: TBitmapInfo;  // Информация об изображении
 Color1, Color2, MaskColor: Integer;  // Цвета
 CX, CY: Integer;  // Счтечики
begin
 Result := False;
 if (MaskBitmap.Width < ColorBitmap.Width) or (MaskBitmap.Width <
 ColorBitmap.Width) then
   Exit;
 // Получение массива пикселей для ColorBitmap
 GetMem(ColorBits, ColorBitmap.Width * ColorBitmap.Height *
   GetDeviceCaps(ColorBitmap.Canvas.Handle, BITSPIXEL));
 BitmapInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 BitmapInfo.bmiHeader.biWidth := ColorBitmap.Width;
 BitmapInfo.bmiHeader.biHeight := - ColorBitmap.Height;
 BitmapInfo.bmiHeader.biPlanes := 1;
 BitmapInfo.bmiHeader.biBitCount := GetDeviceCaps(ColorBitmap.Canvas.Handle,
   BITSPIXEL);
 BitmapInfo.bmiHeader.biCompression := BI_RGB;
 if GetDIBits(ColorBitmap.Canvas.Handle, ColorBitmap.Handle, 0,
 ColorBitmap.Height, ColorBits, BitmapInfo, DIB_RGB_COLORS) = 0 then
   Exit;
 // Получение массива пикселей для MaskBitmap
 GetMem(MaskBits, MaskBitmap.Width * MaskBitmap.Height *
   GetDeviceCaps(MaskBitmap.Canvas.Handle, BITSPIXEL));
 BitmapInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 BitmapInfo.bmiHeader.biWidth := MaskBitmap.Width;
 BitmapInfo.bmiHeader.biHeight := - MaskBitmap.Height;
 BitmapInfo.bmiHeader.biPlanes := 1;
 BitmapInfo.bmiHeader.biBitCount := GetDeviceCaps(MaskBitmap.Canvas.Handle,
   BITSPIXEL);
 BitmapInfo.bmiHeader.biCompression := BI_RGB;
 if GetDIBits(MaskBitmap.Canvas.Handle, MaskBitmap.Handle, 0,
   MaskBitmap.Height, MaskBits, BitmapInfo, DIB_RGB_COLORS) = 0 then
   Exit;
 // Создание DestBitmap и копирование в него содержимого контекстного
 // устройства DC
 BitmapInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 BitmapInfo.bmiHeader.biWidth := ColorBitmap.Width;
 BitmapInfo.bmiHeader.biHeight := - ColorBitmap.Height;
 BitmapInfo.bmiHeader.biPlanes := 1;
 BitmapInfo.bmiHeader.biBitCount := 32;
 BitmapInfo.bmiHeader.biCompression := BI_RGB;
 DestBitmap := CreateDIBSection(DIB_PAL_COLORS, BitmapInfo, DIB_RGB_COLORS,
   DestBits, 0, 0);
 DestDC := CreateCompatibleDC(Canvas.Handle);
 SelectObject(DestDC, DestBitmap);
 BitBlt(DestDC, 0, 0, ColorBitmap.Width, ColorBitmap.Height, Canvas.Handle, X,
   Y, SRCCOPY);

 // КОПИРОВАНИЕ!!!
 for CY := 0 to ColorBitmap.Height - 1 do
   for CX := 0 to ColorBitmap.Width - 1 do begin
     Color1 := GetBitsColor(DestBits, ColorBitmap.Width, ColorBitmap.Height,
       CX, CY);
     Color2 := GetBitsColor(ColorBits, ColorBitmap.Width, ColorBitmap.Height,
       CX, CY);
     MaskColor := GetBitsColor(MaskBits, MaskBitmap.Width, MaskBitmap.Height,
       CX, CY);
     Color1 := GetGradientColor(Color1, Color2, 256, GetMaxIntensity(MaskColor));
     SetBitsColor(DestBits, ColorBitmap.Width, ColorBitmap.Height, CX, CY,
       Color1);
   end;
 BitBlt(Canvas.Handle, X, Y, ColorBitmap.Width, ColorBitmap.Height, DestDC, 0,
   0, SRCCOPY);

 // УДАЛЕНИЕ!
 DeleteObject(DestBitmap);
 DeleteObject(DestDC);
 Dispose(ColorBits);
 Dispose(MaskBits);
 Result := True;
end;



Страницы: 1 вся ветка

Текущий архив: 2007.03.25;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.03 c
15-1173040286
ArtemESC
2007-03-04 23:31
2007.03.25
PHP


2-1172959193
San1
2007-03-04 00:59
2007.03.25
EConvertError


15-1172460498
Slider007
2007-02-26 06:28
2007.03.25
С днем рождения ! 26 февраля


2-1173098441
Cj
2007-03-05 15:40
2007.03.25
REGISTRY


15-1171381414
Desdechado
2007-02-13 18:43
2007.03.25
Stereo и Joint Stereo - чем отличаются?