AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Farbtabelle eines TBitmap bearbeiten?
Thema durchsuchen
Ansicht
Themen-Optionen

Farbtabelle eines TBitmap bearbeiten?

Ein Thema von himitsu · begonnen am 16. Jun 2020 · letzter Beitrag vom 17. Jun 2020
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.056 Beiträge
 
Delphi 12 Athens
 
#1

Farbtabelle eines TBitmap bearbeiten?

  Alt 16. Jun 2020, 15:29
Irgendwie bin ich zu doof das zu finden, wie man sowas macht.

Im Prinzip wollte ich einfach nur schnell einen 4-Bit-Stream in Bitmap.Scanline kopieren
und das als Graustufen sehen, ohne erst die Pixel einzeln umrechnen zu müssen,
aber aktuell sieht das Bild dann sehr farbenfroh aus, selbst wenn ich vorher das Monochrom-Property setze.

Inzwischen das Palette-Property entdekt, darüber mit dem Typ HPALETTE bei MSDN-Library durchsuchenSetPaletteEntries gelandet, aber hatte leider noch keine Wirkung, der erste Versuch.

[EDIT]
Grade nochmal nach "Delphi SetPaletteEntries" gesucht und
https://www.imageen.com/ieforum/topic.asp?TOPIC_ID=2673 entdeckt.
* CreatePalette, ResizePalette,
* SetPaletteEntries,
* SelectPalette, RealizePalette
Mal sehn ob dieser "nichtfunktionierende" Code nicht doch geht.
[EDIT2]
Nee, ging nicht.

Ich bekomm einen Datanstrom aus Bytes, mit 4 Bit pro Pixel in Graustufen,
und den schiebe ich direkt in ein TBitMap, aber die farbliche Datstellung ... naja

Der zweite Block ist das was aktuell als Testcode existiert.
Delphi-Quellcode:
var Bytes := FingerSensor.AcquireFingerImage;
var Width := Sqrt(Length(Bytes) * 2);
meLog.Lines.Add(' Bytes: ' + Length(Bytes).ToString);
meLog.Lines.Add(' ImageSize: ' + Width.ToString);
imFingerImage.Picture.Bitmap.PixelFormat := pf4bit;
imFingerImage.Picture.Bitmap.SetSize(Trunc(Width), Trunc(Width));
Move(Bytes[0], imFingerImage.Picture.Bitmap.ScanLine[imFingerImage.Picture.Bitmap.Height - 1]^,
  imFingerImage.Picture.Bitmap.Width * imFingerImage.Picture.Bitmap.Height div 2);

const Grays: TArray<TColor> = [$00000000, $00111111, $00222222, $00333333,
         $00444444, $00555555, $00666666, $00777777, $00888888, $00999999,
         $00AAAAAA, $00BBBBBB, $00CCCCCC, $00DDDDDD, $00EEEEEE, $00FFFFFF];
var HPalette := imFingerImage.Picture.Bitmap.Palette;
SetPaletteEntries(HPalette, 0, 16, (@Grays[0])^);
//imFinger.Picture.Bitmap.Palette := HPalette;
imFingerImage.Picture.Bitmap.Palette := SelectPalette(imFingerImage.Picture.Bitmap.Canvas.Handle, HPalette, True);
//CreateHalftonePalette(DC: HDC)

imFingerImage.Refresh;
Miniaturansicht angehängter Grafiken
formdesign-1-nach-dokumentation.png  
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (16. Jun 2020 um 19:46 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#2

AW: Farbtabelle eines TBitmap bearbeiten?

  Alt 16. Jun 2020, 16:02
Eventuell mal hier schauen: https://www.delphipraxis.net/10914-b...umwandeln.html

Die Palette in Bitmaps gilt (soweit ich mich erinnere) nur für 256-Farben-Bitmaps. (http://www.libertybasicuniversity.co...100/format.htm)

Keine Ahnung, ob dashier entsprechend Deinen Wünschen funktionieren könnte (irgendwo aus meinem Fundus):
Delphi-Quellcode:
procedure BitmapGrayscale(ABitmap: Graphics.TBitmap);
type
  PPixelRec = ^TPixelRec;
  TPixelRec = packed record
    B : Byte;
    G : Byte;
    R : Byte;
  end;

var
  X : Integer;
  Y : Integer;
  Gray : Byte;
  Pixel : PPixelRec;
begin
  for Y := 0 to ABitmap.Height - 1 do begin
    Pixel := ABitmap.ScanLine[Y];
    for X := 0 to ABitmap.Width - 1 do begin
      Gray := Round((0.299 * Pixel.R) + (0.587 * Pixel.G) + (0.114 * Pixel.B));
      Pixel.R := Gray;
      Pixel.G := Gray;
      Pixel.B := Gray;
      Inc(Pixel);
    end;
  end;
end;
Oder bei der "Konkurenz": https://www.swissdelphicenter.ch/en/showcode.php?id=437
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.056 Beiträge
 
Delphi 12 Athens
 
#3

AW: Farbtabelle eines TBitmap bearbeiten?

  Alt 16. Jun 2020, 16:09
Wie gesagt, ich hab bereits ein Graustufenbild (dessen 36864 Bits) mit 4 Bit pro Pixel.

Aber ja, die Pixel einzeln zu kopieren ginge auch, aber das wollte ich möglichst vermeiden, wenn es direkt ginge.
PixelColor = $00111111 * 4BitByte


Mit Paint kann ich ja auch ein Graustufenbild als 4-Bit abspeichern
und dann hat die Farbpalette nur noch bzw. mehr Grautöne.
Somit kann PixelFormat = pf4bit das doch scheinbar.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (16. Jun 2020 um 16:57 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.056 Beiträge
 
Delphi 12 Athens
 
#4

AW: Farbtabelle eines TBitmap bearbeiten?

  Alt 16. Jun 2020, 23:19
Och menno, TBitmap.SetPixelFormat sagt, dass bei 4 Bit immer die Palette im SystemPalette16 überschrieben wird.
Delphi-Quellcode:
Pal := FImage.FPalette;
case Value of
  // Copy Palette to prevent holding the same handle as SystemPalette16,
  // which would cause problems with the undetermined sequence of
  // finalizers in .NET
  pf4Bit: Pal := SystemPalette16;
Gut, das ist eine globale in Vcl.Graphics und ich könnte die mal kurz austauschen,
oder ich nehm erstmal den Code-Teil mit 4Bit von SetPixelFormat, zusammen dem Code der SystemPalette16 erstellt und versuch vor/statt dem PixelFormat:=pf4Bit das mit einer eigenen Palette,
denn .Net kann mich mal.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
1.051 Beiträge
 
Delphi 2009 Professional
 
#5

AW: Farbtabelle eines TBitmap bearbeiten?

  Alt 17. Jun 2020, 00:00
Mal überlegt, den Kram in ein TPNGImage zu schreiben? Die absolute Holzhammermethode wäre, bereits ein PNG der richtigen Größe mit der gewünschten Palette zu verwenden. Dann nur noch Datei (oder Ressource) öffnen und Scanline überschreiben. Beispiel ist angehängt.
Bei Problemen mit der Anzeige von Paletten-PNG siehe diesen Thread (der Vollständigkeit halber sei noch auf einen in neueren Versionen nötigen Bugfix des verlinkten Codes für 2BPP hingewiesen, der ist jedoch hier nicht relevant).
Angehängte Grafiken
 
Janni
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.056 Beiträge
 
Delphi 12 Athens
 
#6

AW: Farbtabelle eines TBitmap bearbeiten?

  Alt 17. Jun 2020, 00:39
Die Saftsäcke nutzen viele private Funktionen und die alle nachzubauen, das geht ja mal garnicht.
TBitmap.SetPixelFormat -> TBitmap.CopyImage, TBitMap.CopyPalette, TBitMap.CopyBitmap, ...

Die Palette um das PixelFormat := pf4bit; auszutauschen hat funktioniert, aber wegen dem DeleteObject (ohne ist alles Schwarz) ist das auch keine schöne Lösung.
Delphi-Quellcode:
const Grays: TArray<TColor> = [$00000000, $00111111, $00222222, $00333333, $00444444, $00555555, $00666666,
         $00777777, $00888888, $00999999, $00AAAAAA, $00BBBBBB, $00CCCCCC, $00DDDDDD, $00EEEEEE, $00FFFFFF];
var OldPal := Vcl.Graphics.SystemPalette16;
var LogPal: TMaxLogPalette;
LogPal.palVersion := $0300;
LogPal.palNumEntries := 16;
Move(Grays[0], LogPal.palPalEntry[0], 16*4);
Vcl.Graphics.SystemPalette16 := CreatePalette(PLogPalette(@LogPal)^);
try
  imFingerImage.Picture.Bitmap.PixelFormat := pf4bit;
finally
  //DeleteObject(Vcl.Graphics.SystemPalette16);
  Vcl.Graphics.SystemPalette16 := OldPal;
end;
Ich hatte versucht mir aus TBitMap.CopyBitmap den Teil rauszuschnappen, der die Palette zuweist, wo ich am Ende bei SelectPalette und RealizePalette lande, also eigentlich was ich wollte, aber das ging nicht. (vermutlich irgendwo ein Fehler gemacht)



Also rein vom Code her kommt es wohl doch einfacher nur mit zwei Zeilen Code die Pixel einzeln zu kopieren.
Dauert zwar länger, aber allein um das Bild vom Sensor abzuholen, braucht es schon 3 Sekunden, da fällt das auch nicht mehr groß auf.
(gäbe es eine API das Bild in Originalgröße abzurufen, dann würde das über 24 Sekunden dauern, mit 19200 BAUD
und der Chip da drauf dreht und verarbeitet es in knapp 100ms und vergleicht es mit seiner ganzen Fingerdatenbank)



[edit]
Delphi-Quellcode:
// verständlicher
imFingerImage.Picture.Bitmap.PixelFormat := pf32bit;
imFingerImage.Picture.Bitmap.SetSize(Width, Width);
var B: PByte := @Bytes[0];
var C: PColor := imFingerImage.Picture.Bitmap.ScanLine[Width - 1];
for var i := Width * Width div 2 - 1 downto 0 do begin
  C^ := $00111111 * (B^ shr 4);
  Inc(C);
  C^ := $00111111 * (B^ and $0F);
  Inc(C);
  Inc(B);
end;
// bzw.
for var i := Width * Width div 2 - 1 downto 0 do begin
  C^[i * 2] := $00111111 * (B[i] shr 4);
  C^[i * 2 + 1] := $00111111 * (B[i] and $0F);
end;


// holy shit
imFingerImage.Picture.Bitmap.PixelFormat := pf32bit;
imFingerImage.Picture.Bitmap.SetSize(Width, Width);
var C: PIntegerArray := imFingerImage.Picture.Bitmap.ScanLine[Width - 1];
for var i := Width * Width - 1 downto 0 do
  C[i] := $00111111 * (Bytes[i div 2] shr (4 * Byte(not Odd(i))) and $0F);
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (17. Jun 2020 um 01:23 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:28 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