Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Bitmap manuel als icon speichern (https://www.delphipraxis.net/168933-bitmap-manuel-als-icon-speichern.html)

Memnarch 19. Jun 2012 14:11

Bitmap manuel als icon speichern
 
Nabend,
Also wenn ich die struktur eines Icons richtig verstanden habe, liegen in einem icon einfach nur mehrere bmaps. Vorangestellt ist eine TIconDir struktur mit einer TIconDirEntry-Liste(array)

Ok, diese strukturen sagen wieviele, welche und wo die bitmaps in der Ico datei liegen.
Nach diesen strukturen kommen dann die eigentlichen Bildinformationen.

In der MSDN steht das im falle von BMP bildern einfach die komplette BMP ohne BMPFILEHEADER geschrieben wird.
In diesem falle also eine TBitmap als stream speichern, den offset auf die stelle nach dem header setzen und diese daten hinten anhängen?

Irgendwo habe ich zumindest nen knicks, den das resultat ist eine kaputte datei -.-

MFG
Memnarch

Bummi 19. Jun 2012 15:20

AW: Bitmap manuel als icon speichern
 
sowas nützt Dir wahrscheinlich nichts?

Delphi-Quellcode:
function BitmapToIcon(Bitmap: TBitmap;Size:Integer): TIcon;
var

  IconInfo: TIconInfo;
  IconBitmap, MaskBitmap: TBitmap;
  x, y: Integer;
  TransparentColor: TColor;
begin
  Result:= TIcon.Create;
  IconBitmap:= TBitmap.Create;
  MaskBitmap:= TBitmap.Create;
  try
  IconBitmap.Width:= Size;
  IconBitmap.Height:= Size;
  IconBitmap.Canvas.StretchDraw(Rect(0, 0, Size, Size), Bitmap);
  IconBitmap.TransparentColor:= Bitmap.TransparentColor;
  TransparentColor:= IconBitmap.TransparentColor and $FFFFFF;
 
  MaskBitmap.Assign(IconBitmap);
  for y:= 0 to Size - 1 do
    for x:= 0 to Size - 1 do
      if IconBitmap.Canvas.Pixels[x, y] = TransparentColor then
        IconBitmap.Canvas.Pixels[x, y]:= clBlack;
  IconInfo.fIcon:= True;
  IconInfo.hbmMask:= MaskBitmap.MaskHandle;
  IconInfo.hbmColor:= IconBitmap.Handle;
  Result.Handle:= CreateIconIndirect(IconInfo);
  finally
  MaskBitmap.Free;
  IconBitmap.Free;
  end;
end;

DeddyH 19. Jun 2012 15:28

AW: Bitmap manuel als icon speichern
 
Sollte man nicht besser die Icon-Instanz als Parameter entgegennehmen und ein paar Ressourcenschutzblöcke einbauen?

Memnarch 19. Jun 2012 16:00

AW: Bitmap manuel als icon speichern
 
Verzeiht meine vergesslichkeit :(
Hatte es schon hinbekommen.
Der trick war:
Nach schreiben der dir und entry strukturen, manuel den header aufsetzen und schreiben und danach einfach die pixel reinschreiben.

Jetzt klappts und ich kann aus bmps icons generieren(multiframe inklusive) :D

edit: auf die Idee mit dem header selbstschreiben bin ich hierdurchgekommen:

http://www.pjhayward.net/ico.php

Hier ist mir dan auch aufgefallen wo ich den fehler in meinen entry strukturen hatte^^"

NickelM 19. Jun 2012 17:10

AW: Bitmap manuel als icon speichern
 
Naja mit Bummis Funktion habe ich es so hinbekommen:
Delphi-Quellcode:
var Icon : TIcon;
    Bitmap,TmpBitmap : TBitmap;
    IconInfo : TCursorOrIcon;
    IconRec : TIconRec;
    FileStream : TFileStream;
    BmfInfo : TBitmapInfoHeader;
    MemStream : TMemoryStream;
    X,Y : Integer;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.LoadFromFile('C:\Users\Mario\Desktop\test_ico.bmp');
    Bitmap.PixelFormat := pf8bit;
    Icon := BitmapToIcon(Bitmap,32);
  finally
    Bitmap.Free;
  end;
    try
      MemStream := TMemoryStream.Create;
      try
        Icon.SaveToStream(MemStream); //In dem Stream ist aber eine Komplette Ico-Datei inklusive Header
Wenn du, was ich ja vermute, eine Ico-Datei mit mehreren Bitmaps machen willst musst du beide Header überschreiben
        FileStream := TFileStream.Create('C:\Users\Mario\Desktop\test_create.ico',fmCreate);
        try
          FillChar(IconInfo,SizeOf(IconInfo),0);
          IconInfo.wType := RC3_ICON;
          IconInfo.Count := 1;
          FileStream.WriteBuffer(IconInfo,SizeOf(IconInfo));
          FillChar(IconRec,SizeOf(IconRec),0);
          IconRec.Width := 32; //Header Manuel schreiben
          IconRec.Height := 32;
          IconRec.Reserved1 := 1; //Immer 1
          IconRec.Reserved2 := 8; //Pixelformat in Bits
          IconRec.DIBSize := MemStream.Size - SizeOf(IconRec) - SizeOf(IconInfo); //Größe anpassen
          IconRec.DIBOffset := FileStream.Position + SizeOf(IconRec); //Sowie Pos neusetzen
          FileStream.WriteBuffer(IconRec,SizeOf(IconRec)); //Schreiben
          FileStream.Position := IconRec.DIBOffset; //Zur Pos des Bild begins
          FileStream.WriteBuffer(Pointer(Integer(MemStream.Memory) + SizeOf(IconRec) + SizeOf(IconInfo))^,IconRec.DIBSize);
        finally
          FileStream.free;
        end;
      finally
        MemStream.free;
      end;
    finally
      Icon.free;
    end;
end;
EDIT:Sehe schon du hast es, naja aber für die Leute die es "einfacher" haben wollen.
Mann muss natürlich ein bischen umschreiben, wenn man mehrer Header reinschreiben will, aber das denk ich wäre möglich.
EDIT2: @DeddyH : So der Schönheit und der RAM-Memory-Sicherung zuliebe.

DeddyH 19. Jun 2012 17:30

AW: Bitmap manuel als icon speichern
 
Holla die Waldfee. Hast Du mal ReportMemoryLeaksOnShutdown auf true gesetzt?

NickelM 19. Jun 2012 17:47

AW: Bitmap manuel als icon speichern
 
Ne, hab jetzt die try...finallys vergessen gehabt :-D Passiert mal :-D
Die könnte man noch nachtragen, falls wirklich jemand diesen Code benötigt.

DeddyH 19. Jun 2012 17:50

AW: Bitmap manuel als icon speichern
 
Zitat:

Zitat von NickelM (Beitrag 1171631)
Die könnte man noch nachtragen, falls wirklich jemand diesen Code benötigt.

Jo, das wäre nett. Hinterher meinen die Leser noch, wir schweinsen hier mit dem RAM herum :zwinker:

Memnarch 21. Jun 2012 10:04

AW: Bitmap manuel als icon speichern
 
Ich muss übrigens noch einen Fehler korrigieren, der im von mir verlinkten quellcode vorkommt.
Der author dieses quelltextes lässt am ende für ein 32bit icon die 1bit alpha mask weg. Das ist aber falsch. Bei jedem DirEntry muss zur imagegröße die 1bitmask größe hinzugerechnet werden UND natürlich auch eine geschrieben werden(in diesem fall reicht einfach 0 für alles sichtbar).

Warum? Macht mal bei einer datei die mit obigem fehler kreiert wurde nen rechtsklick->show properties
oder drück entf damit der entfernen dialog mit bildvorschau aufpoppt. Dort werdet ihr hässliche schwarze punkte entdecken.

Wieso den das?
Nur weil ein icon 32bit ist und einen eigenen alphachannel hat, heißt dass nicht dass er auch von allen loadern genutzt wird. In diesem fall wird einfach die 1bit alphamask abgefragt

Memnarch 22. Jun 2012 08:33

AW: Bitmap manuel als icon speichern
 
Guten Morgen allereits,
Ich bin es nochmal. Ich habe ein Problem.
WIE berechne ich die Größe der 1bit alphamask?

Soweit ich weiß wird in dieser Maske für jeden pixel ein bit angekreuzt repräsentativ für sichtbar/unsichtbar.

Also dachte ich ich brauche (width*height)/8 bytes an bitmaske

Aber irgendwas stimmt nicht.

32*32/8 = 128
Gimp = 128

ok ABER:

16*16/8 = 32
Gimp = 64

24*24/8 = 72
Gimp = 96

Meine größen passen zwar exakt, resultieren aber je nach viewer(icon thumbnail preview/ bildvorschau) in einer fehlerhaften darstellung. Die Größen von Gimp erzeugen ein sauberes bild.

Ja wie komm ich den jetzt mathem,atisch auf diese Größen?


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz