
Г-н Посол
   
Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.
Репутация: 16 Всего: 112
|
В былые времена как-то делал загрузку BMP, тут RLE4 и RLE8 поддерживаются. Не предусмотрен случай, когда Bmp хранится в перевёрнутом виде... Код | procedure ShowBMP (const FileName : string; bmp : TBitmap); var xSize, ySize : word; Adr_Pal, LineSize, LastBytes, MaxEDI : Cardinal; Data : Pointer;
procedure Line1bit; assembler; asm push ebx movzx ecx, [xSize] add ecx, 7 shr ecx, 3 xor edx, edx xor eax, eax dec edx @@Loop: mov bl, [esi]
@@Bit0: shl bl, 1 jc @@Set0_1 stosd jmp @@Bit1 @@Set0_1: mov [edi], edx add edi, 4
@@Bit1: shl bl, 1 jc @@Set1_1 stosd jmp @@Bit2 @@Set1_1: mov [edi], edx add edi, 4
@@Bit2: shl bl, 1 jc @@Set2_1 stosd jmp @@Bit3 @@Set2_1: mov [edi], edx add edi, 4
@@Bit3: shl bl, 1 jc @@Set3_1 stosd jmp @@Bit4 @@Set3_1: mov [edi], edx add edi, 4
@@Bit4: shl bl, 1 jc @@Set4_1 stosd jmp @@Bit5 @@Set4_1: mov [edi], edx add edi, 4
@@Bit5: shl bl, 1 jc @@Set5_1 stosd jmp @@Bit6 @@Set5_1: mov [edi], edx add edi, 4
@@Bit6: shl bl, 1 jc @@Set6_1 stosd jmp @@Bit7 @@Set6_1: mov [edi], edx add edi, 4
@@Bit7: shl bl, 1 jc @@Set7_1 stosd jmp @@End @@Set7_1: mov [edi], edx add edi, 4
@@End: inc esi loop @@Loop add esi, [LastBytes] pop ebx end;
procedure Line4bit; assembler; asm push ebx movzx ecx, [xSize] inc ecx shr ecx, 1 mov ebx, [Adr_Pal] xor edx, edx @@Loop: mov dl, [esi] and dl, $f0 mov eax, [ebx + edx] mov dl, [esi] stosd shl dl, 4 mov eax, [ebx + edx] inc esi stosd loop @@Loop add esi, [LastBytes] pop ebx end;
procedure Line8bit; assembler; asm movzx ecx, xSize mov edx, [Adr_Pal] @@Loop: xor eax, eax lodsb shl ax, 2 mov eax, [edx + eax] stosd loop @@Loop add esi, [LastBytes] ret end;
procedure Line24bit; assembler; asm movzx ecx, xSize @@Loop: movsd dec esi loop @@Loop add esi, [LastBytes] ret end;
procedure LineRLE4; assembler; asm push ebx mov eax, edi add eax, [LineSize] mov [MaxEDI], eax mov ebx, [Adr_Pal] xor ecx, ecx
@@Loop: inc esi and esi, $fffffffe lodsb test al, al jz @@CopyMode
@@RepeatMode: mov cl, al xor eax, eax xor edx, edx lodsb mov dl, al shl dl, 4 and al, $f0 cmp al, dl jne @@Different mov eax, [ebx + edx] rep stosd jmp @@End
@@Different: mov eax, [ebx + eax] mov edx, [ebx + edx] shr cl, 1 pushf test cl, cl jz @@Dif2 @@Dif: stosd mov [edi], edx add edi, 4 loop @@Dif @@Dif2: popf jnc @@End stosd jmp @@End
@@CopyMode: lodsb test al, al jz @@End mov cl, al xor edx, edx
@@Copy: xor eax, eax lodsb mov dl, al shl dl, 4 and al, $f0 mov eax, [ebx + eax] stosd loop @@Copy2 jmp @@End @@Copy2: mov eax, [ebx + edx] stosd loop @@Copy
@@End: cmp edi, [MaxEDI] jb @@Loop add esi, 2 pop ebx ret end;
procedure LineRLE8; assembler; asm push ebx mov edx, edi add edx, [LineSize] mov ebx, [Adr_Pal] xor ecx, ecx
@@Loop: inc esi and esi, $fffffffe lodsb test al, al jz @@CopyMode
@@RepeatMode: mov cl, al xor eax, eax lodsb shl ax, 2 mov eax, [ebx + eax] rep stosd jmp @@End
@@CopyMode: lodsb test al, al jz @@End mov cl, al
@@Copy: xor eax, eax lodsb shl ax, 2 mov eax, [ebx + eax] stosd loop @@Copy
@@End: cmp edi, edx jb @@Loop add esi, 2 pop ebx ret end;
type PHeaderBMP = ^THeaderBMP; THeaderBMP = record fh : TBitmapFileHeader; ih : TBitmapInfoHeader; end; TRGBQuadPalette = array [0..255] of TRGBQuad;
const BMPHeaderSize = SizeOf(THeaderBMP); var Pal_, bmpLine, LineProc : Pointer; HeaderBMP : PHeaderBMP absolute Data; y, BPL, LineLen, PalSize, Bits : word; Pal : TRGBQuadPalette; Adr, _biCompression, fSize : Cardinal; f : File;
begin Adr_Pal := Cardinal (@Pal);
AssignFile (f, FileName); Reset (f, 1); fSize := FileSize(f); GetMem (Data, fSize); BlockRead (f, Data^, fSize); CloseFile (f);
// Вычисляем, сколько цветов и размер палитры asm push esi mov esi, [HeaderBMP] mov eax, [esi + THeaderBMP.ih.biClrUsed] test ax, ax jnz @@ok1 mov cl, [esi + THeaderBMP.ih.biBitCount] cmp cl, 8 ja @@ok1 inc al shl ax, cl @@ok1: shl ax, 2 mov [PalSize], ax pop esi end;
with HeaderBMP^ do begin xSize := ih.biWidth; ySize := ih.biHeight; Bits := ih.biBitCount; _biCompression := ih.biCompression; end;
if PalSize <> 0 then begin Pal_ := Pointer (Cardinal(Data) + BMPHeaderSize); if Bits <> 4 then Move (Pal_^, Pal, PalSize) else asm push esi mov esi, [Data] add esi, BMPHeaderSize mov edx, Adr_Pal mov ecx, 16 @@Loop: lodsd mov [edx], eax add edx, 16 loop @@Loop pop esi end; end;
LineSize := xSize*4;
case Bits of 1 : begin LineProc := @Line1bit; LineLen := (xSize + 7) div 8; end; 4 : begin LineProc := @Line4bit; LineLen := (xSize + 1) div 2; end; 8 : begin LineProc := @Line8bit; LineLen := xSize; end; 24 : begin LineProc := @Line24bit; LineLen := xSize * 3; end; end; if _biCompression = BI_RLE4 then LineProc := @LineRLE4 else if _biCompression = BI_RLE8 then LineProc := @LineRLE8; BPL := ((xSize * Bits) + 31) and not 31; BPL := BPL div 8; LastBytes := BPL - LineLen;
Adr := Cardinal(Data) + BMPHeaderSize + PalSize;
bmp.PixelFormat := pf32bit; BMP.Width := xSize; BMP.Height := ySize;
for y := ySize-1 downto 0 do begin bmpLine := BMP.ScanLine[y];
asm push esi push edi
mov esi, [Adr] mov edi, [bmpLine]
call [LineProc]
mov [Adr], esi
pop edi pop esi end; end;
FreeMem (Data); end; |
(тогда у меня мания была на asm и на скорость...) Пример использования: showbmp('c:\1.bmp', image1.Picture.Bitmap);PS: а обычный TBitmap не грузит RLE-сжатые картинки ? Ты можешь выслать одну такую картиночку мне ?
--------------------
С уважением, г-н Посол.
|