C# Bitmap in Graustufen umwandeln und dabei zusehen klappt nicht

@locomarco
Schon mal probiert die Bilder als Attribute der Klasse zu deklarieren und den Code von toGreyScale in einen WorkerThread zu packen?

Ich finde jedenfalls das ein Timer eine ganz schlechte Lösung ist, den du kaschierst damit ja nur und löst nicht das Problem!
 
Da muss ich erst mal suchen was Attribute einer Klasse überhaupt sind und wie ich sie benutze.
 
Ich bin jetzt einfach mal der Meinung, dass du unter Windows programmierst (sah anhand deiner bisherigen Beiträge so aus).

Dadurch bietet sich dir natürlich noch die Möglichkeit, das Umwandeln mittels GDI+ zu machen. Dann schaffst du auf einmal das ganze Bild und kannst es danach ganz bequem mit steigenden Alpha-Werten über das farbige Bild legen.

So schaust du dann zwar nicht direkt beim Umwandeln zu, hast aber eine Art Einblendeffekt, also auch was zum zugucken.

Edit:
Folgendes Beispiel ist in Delphi geschrieben, verwendet aber die Klassen und Methoden aus GDI+, wie sie auch in jeder anderen Sprache verfügbar sind:
Code:
procedure ToGreyScale(filename:string);
var
  Image:IGPBitmap;
  HSL:IGPHueSaturationLightness;
  HSLParams:TGPHueSaturationLightnessParams;
begin
  Image := TGPBitmap.Create(filename);
  HSL := TGPHueSaturationLightness.Create;
  HSLParams.SaturationLevel := -100;
  HSLParams.HueLevel := 0;
  HSLParams.LightnessLevel := 0;
  HSL.Parameters:=HSLParams;
  Image.ApplyEffect(HSL);
  Image.Save('Graustufen.jpg',TGPImageFormat.jpeg);
end;

Funktionsweise:
1. Das zu manipulierende Bild wird in das passende GDI+ Bitmap geladen. Die Vorlage muss dabei kein Bitmap sein. Statt - wie im Beispiel - mit einer Datei, kann auch mit einem Stream gearbeitet werden. Gleiches gilt beim Speichern.

2. Es wird ein Effekt angelegt, der 100% der Saturation vom Bild entfernen soll, während Hue und Lightness unverändert bleiben.

3. Der Effekt wird auf das Bitmap angewendet.

4. Das Bitmap wird (in diesem Fall als Jpeg, das Format ist natürlich auch austauschbar) gespeichert.


Wenn du aus einem Stream lädst und in einen Stream speicherst, sollte es relativ einfach sein, das ganze in dein Programm zu integrieren. Ich kenn mich mit C# aber zu wenig aus, um dir dafür entsprechende Vorlagen zu geben. Aber wenn dir Delphi nichts ausmacht:
Code:
procedure ToGreyScaleStream(Stream:IStream);
var
  Image:IGPBitmap;
  HSL:IGPHueSaturationLightness;
  HSLParams:TGPHueSaturationLightnessParams;
begin
  Image := TGPBitmap.Create(Stream);
  HSL := TGPHueSaturationLightness.Create;
  HSLParams.SaturationLevel := -100;
  HSLParams.HueLevel := 0;
  HSLParams.LightnessLevel := 0;
  HSL.Parameters:=HSLParams;
  Image.ApplyEffect(HSL);
  Image.Save(Stream,TGPImageFormat.Bmp);
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  Stream:TStream;
begin
  Stream := TMemoryStream.Create;
  Image1.Picture.Bitmap.SaveToStream(Stream);
  ToGreyScaleStream(TStreamAdapter.Create(Stream,soOwned) as IStream);
  Stream.Position:=0;
  Image2.Picture.Bitmap.LoadFromStream(Stream);
end;
 
Zuletzt bearbeitet:
Ich bin mir sicher, es gibt einige Möglichkeiten das zu tun, mir gings aber genau um diesen Effekt.
Aber trotzdem danke :)
 
Gibts keine Möglichkeit in kleineren als 1ms Schritten zu pausieren? Dann braucht man auch keine Threads etc bemühen sondern macht das einfach mit einem for y, for x als Schleife und wartet nach jedem Pixel eine angemessene Zeit?
Man kann auch einfach vorher gucken, wie viele Pixel das Bild hat und sich überlegen wie lange die Umwandlung dauern soll.
So wäre zB für 1024x768 und eine angestrebte Umwandlungszeit von 5 Sekunden die Rechnung:
1024*768 = 786432
=> 786432 / 5 Pixel = 157286,4 Pixel pro Sekunde und somit 157 pro Millisekunde oder eine Wartezeit von 0,157 Nanosekunden nach jedem Pixel.

Falls man wirklich in C# nur ganzzahlige Millisekunden warten kann wäre mein Vorschlag immer zB 100 Pixel (Zahl könnte man auch wie oben von Bildgröße abhängig machen) umzuwandeln und dann immer nach so einem Block wieder 1ms zu warten.
Mit Workerthreads etc find ichs hier einfach übertrieben.
 
locomarco schrieb:
Ich bin mir sicher, es gibt einige Möglichkeiten das zu tun, mir gings aber genau um diesen Effekt.

Du kannst doch das Bild in Graustufen zeilenweise (z.B. per Thread) über das farbige kopieren. Dann erreichst du den Effekt.

Ich hab dir den ganzen Spass mal als Beispiel angehängt: Bild laden und dann "Einblenden" drücken. Dadurch wird erst das farbige Bild komplett auf die rechte Seite übertragen und dann zeilenweise mit der schwarzweißen Version überschrieben.


Edit:
wobei du den Effekt zum umfärben natürlich auch auf einen Ausschnitt des Orginalbildes beschränken könntest, wenn du den zweiten Parameter der hier erwähnten funktion entsprechend setzt.
 

Anhänge

  • GDIpImage.zip
    355,4 KB · Aufrufe: 122
Zuletzt bearbeitet:
Zurück
Oben