// Dieser Artikel
bezieht sich auf
Bitmaps animieren
oder ähnliche
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private-Deklarationen }
public
procedure vorbereitung(filename: string; bilder: word);
procedure veraenderungen(b1, b2: TBitmap);
procedure speichern(b: TBitmap);
procedure opti(bilder: word; transparent, komplett: boolean);
procedure optimiere
(filename: string; BildAnzahl: word; transparent, komplett: boolean);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type
T24 = packed array[0..2] of Byte;
const
flag: byte = $FF;
NoCode: byte = 0;
MaxCount: byte = $FE;
var
basis, hlp, bmp, sv: TBitmap;
r, g, b: Byte;
breit, fase, links, rechts, oben, unten: word;
fs: TFilestream;
procedure TForm1.FormCreate(Sender: TObject);
begin
fs := nil;
sv := TBitmap.create;
bmp := TBitmap.create;
hlp := TBitmap.create;
basis := TBitmap.create;
basis.pixelformat := pf24bit;
hlp.pixelformat := pf24bit;
sv.pixelformat := pf24bit;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
bmp.free;
basis.free;
hlp.free;
sv.free;
if fs <> nil then
fs.free;
end;
function RLEC(b: TBitmap; dst: TStream): integer;
var src: TMemorystream;
x, y, z: integer;
p: PByteArray;
function Compr24: Boolean;
var
zhln: Boolean;
Count: byte;
T24_2: packed array[0..1] of T24;
N24: T24;
begin
Result := false;
if (src.Size - src.Position < SizeOf(T24_2)) then exit;
src.ReadBuffer(T24_2, SizeOf(T24_2));
src.Position := src.Position - SizeOf(T24_2);
if not comparemem(@T24_2[0], @T24_2[1], 3) then exit;
Result := true;
src.Position := src.Position + SizeOf(T24_2);
Count := High(T24_2) - Low(T24_2) + 1;
if (src.Size - src.Position >= SizeOf(N24)) then
repeat
src.ReadBuffer(N24, SizeOf(N24));
zhln := comparemem(@T24_2[0], @N24, 3);
if zhln then Inc(Count)
else src.Position := src.Position - SizeOf(T24);
until (not zhln) or (Count >= MaxCount) or
(src.Size - src.Position < SizeOf(T24));
dst.WriteBuffer(flag, SizeOf(flag));
dst.WriteBuffer(Count, SizeOf(Count));
dst.WriteBuffer(T24_2[0], SizeOf(T24_2[0]));
end;
procedure nocmpr;
var n: byte;
begin
if (src.Size - src.Position < SizeOf(byte)) then exit;
src.ReadBuffer(n, SizeOf(n));
dst.WriteBuffer(n, SizeOf(n));
if (n = flag) then dst.WriteBuffer(NoCode, SizeOf(NoCode));
end;
begin
src := TMemorystream.create;
for y := 0 to b.height - 1 do begin
p := b.scanline[y];
for x := 0 to b.width - 1 do
for z := 0 to 2 do
src.writebuffer(p[x * 3 + z], 1);
end;
src.Position := 0;
while (src.Size - src.Position >= SizeOf(byte)) do
if not Compr24 then nocmpr;
result := dst.size;
src.free;
end;
procedure TForm1.vorbereitung(filename: string; bilder: word);
var s: string;
begin
if bmp.width * bmp.height * 3 > 1000000
then raise exception.create('Speicherbedarf zu groß');
breit := bmp.width div bilder;
// bei Bedarf evtl. so etwas:
// bmp.TransparentColor := bmp.canvas.pixels[0, 0];
r := GetRValue(bmp.TransparentColor);
g := GetGValue(bmp.TransparentColor);
b := GetBValue(bmp.TransparentColor);
basis.width := breit;
hlp.width := breit;
basis.height := bmp.height;
hlp.height := bmp.height;
basis.TransparentColor := bmp.TransparentColor;
sv.TransparentColor := bmp.TransparentColor;
hlp.TransparentColor := bmp.TransparentColor;
sv.transparent := true;
s := changefileext(filename, '.obs');
fs := TFilestream.create(s, fmcreate or fmShareExclusive);
fase := 0;
end;
procedure TForm1.speichern(b: TBitmap);
var w: word;
i, p1, p2: integer;
dst: TMemorystream;
begin
if (b.width > maxword) or (b.height > maxword)
or (b.width < 1) or (b.height < 1)
then raise exception.create('Bildmaße fehlerhaft');
dst := TMemorystream.create;
w := b.width;
fs.writebuffer(w, sizeof(w));
w := b.height;
fs.writebuffer(w, sizeof(w));
p1 := fs.position;
fs.writebuffer(i, sizeof(i));
i := RLEC(b, dst);
dst.position := 0;
fs.copyfrom(dst, i);
dst.free;
p2 := fs.position;
fs.position := p1;
fs.writebuffer(i, sizeof(i));
fs.position := p2;
end;
procedure TForm1.veraenderungen(b1, b2: TBitmap);
var x, y, b3, x3: integer;
p1, p2: PBytearray;
begin
b3 := b1.width * 3;
links := b1.width;
rechts := 0;
oben := b1.height;
unten := 0;
for y := 0 to b1.height - 1 do begin
x := 0;
p1 := b1.scanline[y];
p2 := b2.scanline[y];
while x < b3 do begin
if (p2[x] = p1[x]) and (p2[x + 1] = p1[x + 1]) and (p2[x + 2] = p1[x + 2])
then begin
p2[x] := b;
p2[x + 1] := g;
p2[x + 2] := r;
end else begin
x3 := x div 3;
if x3 < links then links := x3;
if x3 > rechts then rechts := x3;
if y < oben then oben := y;
if y > unten then unten := y;
end;
inc(x, 3);
end;
end;
end;
procedure TForm1.opti(bilder: word; transparent, komplett: boolean);
var i: integer;
begin
i := bmp.width;
fs.writebuffer(i, sizeof(i));
fs.writebuffer(bilder, sizeof(bilder));
fs.writebuffer(transparent, sizeof(transparent));
fs.writebuffer(komplett, sizeof(komplett));
fs.writebuffer(r, 1);
fs.writebuffer(g, 1);
fs.writebuffer(b, 1);
with basis.Canvas do
copyrect(cliprect, bmp.canvas,
rect(fase * breit, 0, fase * breit + breit, bmp.height));
speichern(basis);
while fase < bilder - 1 do begin
inc(fase);
with hlp.Canvas do
copyrect(cliprect, bmp.canvas,
rect(fase * breit, 0, fase * breit + breit, bmp.height));
if komplett then begin
links := 0;
oben := 0;
sv.assign(hlp);
end else begin
veraenderungen(basis, hlp);
sv.width := rechts - links - 1;
sv.height := unten - oben;
sv.canvas.copyrect(sv.canvas.cliprect, hlp.canvas,
rect(links, oben, rechts, unten));
end;
fs.writebuffer(links, sizeof(links));
fs.writebuffer(oben, sizeof(oben));
speichern(sv);
basis.canvas.draw(links, oben, sv);
end;
end;
procedure TForm1.optimiere
(filename: string; Bildanzahl: word; transparent, komplett: boolean);
begin
bmp.loadfromfile(filename);
vorbereitung(filename, Bildanzahl);
opti(BildAnzahl, transparent, komplett);
fs.free;
fs := nil;
end;
// Beispiel 1
procedure TForm1.Button1Click(Sender: TObject);
var filename: string;
Bildzahl: word;
transparent, komplett: boolean;
begin
filename := 'c:\strip.bmp';
Bildzahl := 6;
transparent := true;
komplett := false;
optimiere(filename, Bildzahl, transparent, komplett);
end;
//------------------------------------------------------------------------
// *.obs laden, decodieren und Strip erstellen type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
public
procedure aufteilen;
procedure zuweisen(s: TStream; b: TBitmap);
procedure build(filename: string);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type
T24 = packed array[0..2] of Byte;
rc = record
bm: TBitmap;
w, h, l, o: word;
end;
const
flag: byte = $FF;
var
fs: TFilestream;
bild: array of rc;
transparent, komplett: boolean;
r, g, b: byte;
bmp: TBitmap;
breit: integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
bmp := TBitmap.create;
fs := nil;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var x: integer;
begin
if fs <> nil then
fs.free;
for x := 0 to high(bild) do
bild[x].bm.free;
bild := nil;
bmp.free;
end;
procedure RLED(src, dst: TStream);
var
ccount, n: byte;
procedure DC24(Count: byte);
var
i: byte;
Mn: T24;
begin
src.ReadBuffer(Mn, SizeOf(Mn));
for i := Count downto 1 do
dst.WriteBuffer(Mn, SizeOf(Mn));
end;
begin
src.Position := 0;
while (src.Size - src.Position >= SizeOf(byte)) do
begin
src.ReadBuffer(n, SizeOf(n));
if (n = flag) then
begin
src.ReadBuffer(ccount, SizeOf(ccount));
if (ccount = 0) then dst.WriteBuffer(n, SizeOf(n))
else DC24(ccount);
end
else dst.WriteBuffer(n, SizeOf(n));
end;
end;
procedure TForm1.zuweisen(s: TStream; b: TBitmap);
var x, y, z: integer;
p: PByteArray;
begin
for y := 0 to b.height - 1 do begin
p := b.scanline[y];
for x := 0 to b.width - 1 do
for z := 0 to 2 do
s.readbuffer(p[x * 3 + z], 1);
end;
end;
procedure TForm1.aufteilen;
var w: word;
x, i: integer;
src, dst: TMemoryStream;
begin
src := TMemoryStream.create;
dst := TMemoryStream.create;
fs.readbuffer(breit, sizeof(breit));
fs.readbuffer(w, sizeof(w));
setlength(bild, w);
for x := 0 to high(bild) do begin
bild[x].bm := TBitmap.create;
bild[x].bm.pixelformat := pf24bit;
end;
bild[0].o := 0;
bild[0].l := 0;
fs.readbuffer(transparent, sizeof(transparent));
fs.readbuffer(komplett, sizeof(komplett));
fs.readbuffer(r, 1);
fs.readbuffer(g, 1);
fs.readbuffer(b, 1);
fs.readbuffer(bild[0].w, sizeof(w));
bild[0].bm.width := bild[0].w;
fs.readbuffer(bild[0].h, sizeof(w));
bild[0].bm.height := bild[0].h;
fs.readbuffer(x, sizeof(x));
src.copyfrom(fs, x);
RLED(src, dst);
dst.position := 0;
zuweisen(dst, bild[0].bm);
for x := 1 to high(bild) do begin
src.size := 0;
dst.size := 0;
fs.readbuffer(bild[x].l, sizeof(w));
fs.readbuffer(bild[x].o, sizeof(w));
fs.readbuffer(bild[x].w, sizeof(w));
fs.readbuffer(bild[x].h, sizeof(w));
fs.readbuffer(i, sizeof(i));
src.copyfrom(fs, i);
RLED(src, dst);
dst.position := 0;
bild[x].bm.width := bild[x].w;
bild[x].bm.height := bild[x].h;
zuweisen(dst, bild[x].bm);
bild[x].bm.transparentcolor := RGB(r, g, b);
bild[x].bm.transparent := not komplett;
end;
src.free;
dst.free;
end;
procedure TForm1.build(filename: string);
var x, y: integer;
begin
fs := TFilestream.create(filename, fmOpenRead or fmShareExclusive);
aufteilen;
fs.free;
fs := nil;
bmp.height := bild[0].h;
bmp.width := bild[0].w * length(bild);
if bmp.width <> breit
then raise exception.create('Abmaße oder Bilderzahl fehlerhaft');
for x := 0 to high(bild) do
bmp.canvas.draw(x * bild[0].w, 0, bild[0].bm);
for x := high(bild) downto 1 do
for y := 1 to x do
bmp.canvas.draw(x * bild[0].w + bild[y].l, bild[y].o, bild[y].bm);
bmp.transparentcolor := RGB(r, g, b);
bmp.transparent := transparent;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
build('c:\Strip.obs');
// und zur Kontrolle:
Canvas.draw(10, 10, bmp);
end;
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
Zugriffe seit 6.9.2001 auf Delphi-Ecke





