Anfänger - Bild öffnen



  • Hi,

    ich hoffe ich bin hier im richtigen Unterforum.

    Folgende Situation:
    Ich hab zwar immer mal wieder kleine Konsolenprogramme geschrieben (in C) oder mal was in Javascript rumgefummelt aber nie großartig was dran gemacht.
    Jetzt hatte ich vor ein paar Wochen mal ne Idee für ein Programm was ich schreiben könnte und weil ich noch ein Buch für C++ hab, hab ich halt in C++ angefangen.

    Gearbeitet wird in Visual Studio.

    Ich hab zur Übung auch schon ein bisschen was gemacht und diverse Vectoren erzeugt, verschoben, ausgegeben etc.

    Mein Problem jetzt:

    Ich möchte auf möglichst einfache Weise ein Bild (Format ist egal) öffnen und die RGB-Werte für jeden Pixel auslesen eventuell verändern und nach der Änderung wieder als Bild speichern.

    Aber irgendwie komme ich da auf keinen grünen Zweig.

    Ich hab mir z.B. das hier http://msdn.microsoft.com/de-de/library/vstudio/3135s427.aspx und das hier http://msdn.microsoft.com/de-de/library/vstudio/system.drawing.bitmap.getpixel.aspx angesehen.
    Versteh aber schon mal nicht wie ich System.Drawing einbinde.

    Und bin grade irgendwie allgemein Überfordert, dachte nicht, dass da so ein Rattenschwanz dranhängt.

    Danke für jede Hilfe schon mal.



  • Was du hier hast, ist das .NET Framework. Wenn du eine Bitmap öffnen willst mit C++ und .NET, dann kannst du das wie gewohnt tun:

    System::Drawing::Bitmap meinBild(L"C:\\abc\\def.jpg"); // Kannst auch using namespace System::Drawing; schreiben
    
    // Pixel lesen:
    auto p42_57 = meinBild.GetPixel(42, 57);
    
    // Pixel schreiben:
    meinBild.SetPixel(39, 11, Color::FromArgb(1234567));
    
    // Speichern:
    meinBild.Save(L"C:\\abc123.jpg");
    

    Was du aber verstehen musst ist, dass dies mit normalem C++ wenig bis gar nichts zu tun hat. Und nur mit Visual C++ 2005 oder neuer geht, wenn man für .NET kompiliert.

    Wie auch immer, wenn es das ist, was du willst, kannst gerne weitere Fragen stellen. Viel Spass.

    FG



  • Thx für die fixe Antwort und sry für meine späte ^^

    /rant/ schrieb:

    Was du hier hast, ist das .NET Framework. Wenn du eine Bitmap öffnen willst mit C++ und .NET, dann kannst du das wie gewohnt tun:

    System::Drawing::Bitmap meinBild(L"C:\\abc\\def.jpg"); // Kannst auch using namespace System::Drawing; schreiben
    
    // Pixel lesen:
    auto p42_57 = meinBild.GetPixel(42, 57);
    
    // Pixel schreiben:
    meinBild.SetPixel(39, 11, Color::FromArgb(1234567));
    
    // Speichern:
    meinBild.Save(L"C:\\abc123.jpg");
    

    Was du aber verstehen musst ist, dass dies mit normalem C++ wenig bis gar nichts zu tun hat. Und nur mit Visual C++ 2005 oder neuer geht, wenn man für .NET kompiliert.

    Wie auch immer, wenn es das ist, was du willst, kannst gerne weitere Fragen stellen. Viel Spass.

    FG

    Er sagt bei mir:

    Fehler 1 error C2653: 'System': Keine Klasse oder Namespace

    Liegt das irgendwie daran, dass ich als Projekt ein Konsolenprogramm gewählt habe?



  • Lampe schrieb:

    Liegt das irgendwie daran, dass ich als Projekt ein Konsolenprogramm gewählt habe?

    Ja, das kann gut sein. Ich denke, als erstes musst du entscheiden ob C++ oder C++/CLI (=.NET). Dann bist du nähmlich entweder im falschen Forum oder aber du hast ein Projekt der falschen Art erstellt.



  • Hab mir das nochmal angeschaut was ich da erstellt hatte.

    Es ist sowohl .NET 4.5 als Framework, als auch Visual C++ abgewählt. Und Visual C++ ist doch C++/CLI, oder?



  • Lampe schrieb:

    Hab mir das nochmal angeschaut was ich da erstellt hatte.

    Es ist sowohl .NET 4.5 als Framework, als auch Visual C++ aNgewählt. Und Visual C++ ist doch C++/CLI, oder?

    Es sollte natürlich aNgewählt heißen.



  • Du musst das Template "CLR Console Application" anwählen und die Referenz auf System.Drawing.dll hinzufügen. Danach kompiliert folgendes problemlos:

    using namespace System;
    using namespace System::Drawing;
    
    int main(array<String ^> ^)
    {
        Console::WriteLine(L"Hello World");
    
        Bitmap meinBild(L"C:\\abc\\def.jpg");
        // Pixel lesen: 
        auto p42_57 = meinBild.GetPixel(42, 57); 
        // Pixel schreiben: 
        meinBild.SetPixel(39, 11, Color::FromArgb(1234567)); 
        // Speichern: 
        meinBild.Save(L"C:\\abc123.jpg");
    
        return 0;
    }
    


  • Aaaaah 🙂

    Jetzt kommt kein Fehler mehr.

    Danke! 🙂



  • Hi,

    habe wieder ein Problem. 😉

    Und zwar war mein Plan jetzt erst mal ein ganzes Bild einzulesen und Pixel für Pixel als ein neues auszugeben bevor ich die eigentlichen Veränderungen vornehme.

    Der Code kompiliert ich bekomme aber einen MSVCP110D.dll Fehler. "Vector subscript out of range".

    #include "stdafx.h"
    #include <fstream>
    #include <iostream>
    #include <windows.h>
    #include <vector>
    #include <math.h>
    
    using namespace System;
    using namespace System::Drawing; 
    using namespace std;
    
    int main(array<String ^> ^) 
    { 
       vector<double> Rot; 
       vector<double> Gruen;
       vector<double> Blau;
    
    	Bitmap meinBild(L"D:\\Comp1.jpg"); 
        // Pixel mit 2 Schleifen einlesen, Zeile für Zeile. Und Farben in entsprechende Vectoren packen: 
    
    	for(int y=0; y < 200; y++)
    	{
    		for(int x=0; x < 200; x++)
    		{
        auto Farbe =  meinBild.GetPixel(x, y); 
    
    	Byte g = Farbe.G;
    	Byte b = Farbe.B;
    	Byte r = Farbe.R;
    	Byte a = Farbe.A;
    
    	Rot.push_back(r);
    	Gruen.push_back(g);
    	Blau.push_back(b);
    		}
    	}
    
    	int L=0;
    	int Ro;
    	int Gr;
    	int Bl;
        // Pixel Zeile für Zeile schreiben. L ist so gedacht, dass es von 0 bis 200*200 (so viele Slots müssten die Vectoren ja haben) durchläuft.
    
    	for(int y=0; y < 200; y++)
    	{
    		for(int x=0; x < 200; x++)
    		{
    
    	Ro=Rot[L];
    	Gr=Gruen[L];
    	Bl=Blau[L];
    
    	meinBild.SetPixel(x, y, Color::FromArgb(Ro,Gr,Bl));
    		L++;
    		}
         L++;
    	}
    
        // Speichern: 
        meinBild.Save(L"D:\\Test.jpg"); 
    
        return 0; 
    }
    


  • Zeile 61 "L++;" ist zu viel und daher erhältst du den Overflow.

    Und noch viele andere Fehler:
    Warum verwendest du double als vector-Elemente (anstatt byte)?
    Warum erstellst du drei unterschiedliche Vektoren anstatt einen (mit jeweils der Farbe (int) als Element)?
    Die Höhe und Breite des Bildes solltest du aus den Bitmap-Daten lesen (und nicht fix als 200 annehmen).

    P.S. Für Bitmapmanipulationen ist GetPixel und SetPixel viel zu langsam - dafür gibt es bessere Implementationen, z.B.
    GetPixel und SetPixel um Längen geschlagen. 800 mal schneller
    Bitmap-Manipulation (MemBitmap)
    (ist zwar C#, aber dies ist sowieso die bessere Sprache für .NET!)



  • Thx für die Antwort!

    Th69 schrieb:

    Zeile 61 "L++;" ist zu viel und daher erhältst du den Overflow.

    Ach Gott, thx ^^

    Und noch viele andere Fehler:
    Warum verwendest du double als vector-Elemente (anstatt byte)?

    Hatte einiges aus einer kleinen Übung von mir einfach so übernommen ohne nach zu denken.
    Habs geändert.

    Warum erstellst du drei unterschiedliche Vektoren anstatt einen (mit jeweils der Farbe (int) als Element)?

    Brauch ich für setPixel nicht einzelne RGB-Werte?
    Ich hatte das von einem Vektor, der nach einander alle Pixel-Infos enthält (R(01), G(01), B(01), R(02)...), in 3 einzelne geändert, weil mir nicht ganz klar war wie ich das am Ende am besten wieder per Schleife einzelnen Pixeln zu weise.
    Habs dann erst mal beiseite geschoben und mir gedacht, dass ich solche Logikprobleme auch später noch bearbeiten kann.

    Die Höhe und Breite des Bildes solltest du aus den Bitmap-Daten lesen (und nicht fix als 200 annehmen).

    Jop, das hab ich nach dem Post hier schon geändert ^^

    P.S. Für Bitmapmanipulationen ist GetPixel und SetPixel viel zu langsam - dafür gibt es bessere Implementationen, z.B.
    GetPixel und SetPixel um Längen geschlagen. 800 mal schneller
    Bitmap-Manipulation (MemBitmap)
    (ist zwar C#, aber dies ist sowieso die bessere Sprache für .NET!)

    Ehrlich gesagt bin ich eh etwas unzufrieden damit ^^
    Mein Plan ist momentan das jetzt aber zu Ende zu bringen. Und dann das ganze nochmal zu schreiben ohne .NET aber dann von Hand für unkomprimierte Bilder.

    Aber Geschwindigkeit ist eh eher nebensächlich.


Anmelden zum Antworten