AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Bitmap auf 8bit mittels vorhandener Palette

Bitmap auf 8bit mittels vorhandener Palette

Ein Thema von Brainstalker · begonnen am 27. Mär 2010 · letzter Beitrag vom 28. Mär 2010
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Brainstalker
Brainstalker

Registriert seit: 9. Jan 2004
Ort: Berlin
176 Beiträge
 
Delphi 2009 Professional
 
#1

Bitmap auf 8bit mittels vorhandener Palette

  Alt 27. Mär 2010, 17:35
Hallo,

ich habe eine Serie von Bitmaps, die alle die gleiche Palette benutzen, also 256 Farben. Jetzt möchte ich ein Bitmap hinzufügen, d.h. die Farben des Bitmaps sollen an die vorhandene Palette angepasst werden. Die Bitmaps die hinzugefügt werden, können jede mögliche Farbtiefe haben.
Mein erster Gedanke war, jedes Pixel des neuen Bitmaps mit den Farben der Palette zu vergleichen und mir dann ein Array des Bitmaps mit den Indizes anzulegen. Das funktioniert auch wunderbar, aber wird die Farbe in der Palette nicht gefunden werden mir die Bereiche weiß (meine default Farbe) angezeigt. Ist ja auch logisch bei einem Bitmap mit 24bit werden eher wenig Farben in der Palette gefunden.

Hat jemand einen Tipp für mich, wie ich in der Palette die Farbe finde, welche am nähsten an der zu suchenden Pixelfarbe liegt? Ich weiß wie ich Bitmaps in der Farbe reduzieren und eine Palette anlegen kann, aber eben nicht wie ich mit einer vorhandenen Palette vorgehe.

Gruß
Michael N.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.659 Beiträge
 
Delphi 2007 Enterprise
 
#2

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 27. Mär 2010, 18:21
Das einfachste ist es, Farben als 3-dimensionalen Vektor aufzufassen. Die kleinste Länge der Differenz zweier Farben gibt dann die am nächsten liegende an. Dann muss man sich nur noch für ein Farbmodell entscheiden, in dem dies die besten Ergebnisse liefert. RGB ist da meine ich schon garnicht SO schlecht, ich könnte mir aber auch gut HSV bzw. HSL für diesen Zweck vorstellen.

Edit: Ich glaube der L*a*b*-Farbraum wäre geradezu ideal dafür, allerdings auch nicht mehr ganz so trivial.
Edit2: Auch dieser Artikel dürfte für dich recht interessant sein.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Brainstalker
Brainstalker

Registriert seit: 9. Jan 2004
Ort: Berlin
176 Beiträge
 
Delphi 2009 Professional
 
#3

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 27. Mär 2010, 20:07
Ok Vektorrechnung sollte nicht das Problem sein. Hatte in der Uni erst letztes Semester Lineare Algebra.
Wie mache ich das am besten, sollte ich da dann von Nullvektor aus gehen und dann die differenz der beiden Vektoren ausrechnen? Und kann ich da einfach übers Skalarprodukt gehen?

Mir reicht auf jeden Fall erst mal der RGB Farbraum. Sicherlich wäre es besser über HSL zu gehen, da man dort die Helligkeit einbeziehen kann, aber mir erstmal nicht so wichtig. Werd ich vielleicht als zweite Implementation später hinzufügen. Dann könnte man auch beide vergleichen.
Der L*a*b*-Farbraum hört sich sehr interessant an. Den werd ich zwar hierfür nicht einsetzen, aber ich glaub da werde ich mich auf jeden Fall mal einarbeiten. Für andere Projekte.


Ich hab leider für die nächste Zeit kein Delphi, und mache das alles erstmal theoretisch. Meine erste Überlegung sieht folgendermaßen aus, wie gesagt nicht getestet.
Delphi-Quellcode:
TRGB = record
  r: byte;
  g: byte;
  b: byte;
end;

TPalette = array[0..255] of TRGB;



function Skalar(const aVector: TRGB): integer;
begin
  result := aVector.r * aVector.r
         + aVector.g * aVector.g
         + aVector.b * aVector.b;
end;


function GetNearestColor(const aColor: TRGB): integer;
var
   ind, smallest, diff: integer;
begin
  ind := 0;
  smallest := High(Palette);
  
  for i := 0 to High(Palette) do // Palette mit 256 Einträgen
  begin
    diff := Skalar(aColor) - Skalar(Palette[i]);
    if diff < 0 then diff := diff * (-1);
    
    if diff < smallest then
    begin
      ind := i;
      smallest := diff;
    end;
  end;
  
  result := ind;
end;
Michael N.
Brainstalker
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.659 Beiträge
 
Delphi 2007 Enterprise
 
#4

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 27. Mär 2010, 21:53
Das Skalarprodukt kommt mit rein beim Quadrieren, die Differenz der Skalarprodukte hat aber nicht wirklich viel aussagekraft. (255, 0, 0) würde dann zum Beispiel identisch mit (0, 0, 255) sein.
In Pseudocode eher so:
Delphi-Quellcode:
type
  TRGBColor = class
  public
    r, g, b: Integer;
    constructor Create(ar, ag, ab: Integer);
  end;
var
  color1, color2, colorDiff: TRGBColor;
  distance: Double;
begin
  colorDiff := TRGBColor.Create(color2.r-color1.r, color2.g-color1.g, color2.b-color1.b);
  distance := sqrt(colorDiff.r*colorDiff.r + colorDiff.g*colorDiff.g + colorDiff.b*colorDiff.b);
.
.
end;
Geometrisch interpretiert hast du einen Farbwürfel, und ermittelst mit der Differenz den Vektor von color1 zu color2. Je kürzer der ist, desto - wortwörtlich - näher sind die Farben beieinander.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Brainstalker
Brainstalker

Registriert seit: 9. Jan 2004
Ort: Berlin
176 Beiträge
 
Delphi 2009 Professional
 
#5

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 27. Mär 2010, 22:32
Ja logo... Macht natürlich wenig Sinn. Hab auch gerade gemerkt das ich völligen murks geschrieben hab. Natürlich müssen die Vektoren erst von einander subtrahiert werden und dann der Betrag des resultierenden Vektors gebildet werden. Also quasi die Wurzel aus dem Skalar des Resultierenden.
Kaum das Semester hinter mir, schon bring ich alles durcheinander.

Für das HSV Modell müsste man aber andere Überlegungen anstellen, denn das Modell bildet ja kein Würfel.
Mal sehen, werd ich mir mal morgen Gedanken machen.
Michael N.
Brainstalker
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.659 Beiträge
 
Delphi 2007 Enterprise
 
#6

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 27. Mär 2010, 23:33
Zitat von Brainstalker:
Für das HSV Modell müsste man aber andere Überlegungen anstellen, denn das Modell bildet ja kein Würfel.
Stimmt, da müsste man sich für Hue etwas ausdenken, da dieser Wert ja ein Winkel ist. Für Sättigung und Helligkeit müsste man mit dem 2D-Abstand ganz gut hin kommen, beim Winkel theoretisch auch, nur dass man die 360°-0°-Grenze irgendwie verhackstücken müsste.
Oder hmm, das ginge doch fast einfach:
Delphi-Quellcode:
type
  THSVColor = class
  public
    h, s, v: Integer;
    constructor Create(ah, as, av: Integer);
  end;
var
  color1, color2, colorDiff: TRGBColor;
  distance: Double;
begin
  colorDiff := TRGBColor.Create(color2.h-color1.h, color2.s-color1.s, color2.v-color1.v);
  if colorDiff.h < 0 then
    colorDiff.h := (2*pi)-colorDiff.h;
  distance := sqrt(colorDiff.h*colorDiff.h + colorDiff.s*colorDiff.s + colorDiff.v*colorDiff.v);
.
.
end;
Allerdings hat man letztlich dann keinen "kartesischen" Abstand mehr, und es könnte evtl. Sinn machen die einzelnen Komponenten zueinander zu gewichten. So dass Sättigung evtl. nur zur Hälfte eingeht, Hue aber 1,5x so stark. Fertig bestimmte optimale Werte gibt's da glaub ich nicht, aber mit ein wenig Rumprobieren sollte sich was überzeugendes anstellen lassen.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Brainstalker
Brainstalker

Registriert seit: 9. Jan 2004
Ort: Berlin
176 Beiträge
 
Delphi 2009 Professional
 
#7

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 28. Mär 2010, 19:47
Ich hab heute auch mal ein bisschen drüber nachgedacht. Und mit ein bisschen Googeln hab ich auch ne Seite gefunden wo das RGB System als Würfel und das HSV als Kegel dargestellt war. Die Farbsättigung und der Farbton sind auf dem Kreis aufgetragen. Da könnte man ja theoretisch mit 2D Vektoren arbeiten. Hab noch ein Bild angehängt, wo ich mal meine Gedanken aufgeschrieben habe. Ob das dann alles richtig ist, sei mal dahin gestellt.

Wenn wir den Einheitskreis betrachten, müsste ja folgendes gelten:

x := [0..1] Sättigung
y := [0°..360°) Farbton

Farben f1, f2 = [x*cosy, x*siny] <---- Vektor

|f1-f2| = sqrt(fx²+fy²)

Fragt sich dann nur wie man den Value Wert mit einbringt. Habs übers Dreieck versucht (siehe Zeichnung), aber naja bin da noch nicht so weit gekommen. Vielleicht ist das ja auch ein völlig falscher Ansatz.
Miniaturansicht angehängter Grafiken
ccf28032010_00000_140.jpg  
Michael N.
Brainstalker
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
39.653 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 28. Mär 2010, 20:28
Man könnte auch mal einen einfachen Weg versuchen.

- Man erstelle das 8-Bit-Bitmap, samt der Farbtabelle
- und kopiere (.Draw) einfach das gewünschte Bild da hinein.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
Benutzerbild von Brainstalker
Brainstalker

Registriert seit: 9. Jan 2004
Ort: Berlin
176 Beiträge
 
Delphi 2009 Professional
 
#9

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 28. Mär 2010, 21:18
Ok hab nicht dazu gesagt, das ich kein Bitmap benutze, mache das sozusagen on the fly mit den "raw" Daten. Aber ich könnte ja auch mal schauen wie das mit der Geschwindigkeit aussieht, wenn ich es mit einem Bitmap mache.

Ich hätte also auch gern einen Weg die Farbe zu finden ohne ein Bitmap zu benutzen. Kann ich später dann auch für andere Dinge gebrauchen. Vielleicht kannst du ja aber auch ein bisschen Beispielcode posten, für andere die sich vielleicht für das Thema interessieren. Ich hab ja im Moment kein Delphi, kann also kein produktiven Code beisteuern.

Aber schonmal soweit vielen Dank an euch beide für die Hilfe.
Michael N.
Brainstalker
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.659 Beiträge
 
Delphi 2007 Enterprise
 
#10

Re: Bitmap auf 8bit mittels vorhandener Palette

  Alt 28. Mär 2010, 21:42
Die wirklich wesentliche Frage, die es zu aller erst zu klären gälte, ist ja: Ab welchem Helligkeitsunterschied ist der wahrgenommene Fehler schlimmer als ein alternativer Farbunterschied, bzw. alle 3 Kombis aus H, S und V zueinander betrachtet.
Ich könnte mir schon vorstellen, dass eine einfache Vektorlänge auch im Kegel noch sinnvolle Ergebnisse liefert. Also H und S als Polarkoordinaten interpretieren, in Kartesische umrechnen, und dann wie auch bei RGB die Differenz bilden und Länge als Maß nehmen. Falls dabei zu oft arg falsche Farben, Helligkeiten oder Sättigungen auftreten, die entsprechende Komponente mit einem Multiplikator versehen. Dann ist das zwar keine geometrisch einwandfreie Sache mehr, aber führt ggf. zu gefälligeren Bildern. Das Ziel ist das Ziel
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 12:08 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf