Rotieren eines Bildes um 90°



  • Hallo zusammen,

    ich schreibe zur Zeit ein Archivieungstool, mit dem man Bilder mit Text usw archivieren kann. Alles funkt. bis auf das Drehen eines Bildes um 90°.
    Arbeite mit dem ScanLine Algo, da alles andere zu lange dauert. Nach dem Drehen um 90° verfärbt sich das Bild in Blau. Sie Routine:

    if (jp)
      {
        int *ptr;
        Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
        Graphics::TBitmap *bmp = new Graphics::TBitmap();
    
        bmp->Assign(jp);
    
        pBitmap->Height = bmp->Width;
        pBitmap->Width = bmp->Height;
        pBitmap->PixelFormat = pf32bit;
    
        bmp->PixelFormat = pf32bit;
    
        for( int i = 0; i < bmp->Height; i++)
        {
          ptr = (int*)bmp->ScanLine[i];
          for(int y = 0; y < bmp->Width; y ++)
          {
            pBitmap->Canvas->Pixels[pBitmap->Width-i][y] = TColor(ptr[y]);
          }
        }
       Image1->Picture->Assign(pBitmap);
       Image1->Center = true;
       jp->Assign(pBitmap);
       delete bmp;
       delete pBitmap;
      }
      else
      {
       ShowMessage("Vorher ein Bild auswählen");
      }
    }
    

    Danke schon mal für die Antworten.



  • Bilder, Bitmaps, Standard C++ 😕 😕

    WINAPI bzw. Borland(TBitmap?) würden wohl besser passen.



  • Dieser Thread wurde von Moderator/in Marc++us aus dem Forum C++ in das Forum VCL/CLX (Borland C++ Builder) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hi,

    Vieleicht hilft dir das weiter
    http://www.tutorials.de/tutorials206514.html



  • Ja dankeschön, aber mit der Matrixopperation, wie auf dem anderen Forum beschrieben dauert die Geschichte relativ lange. Das hatte ich schon vorher ausprobiert.





  • Nach dem Drehen um 90° verfärbt sich das Bild in Blau. Sie Routine:
    

    Vielleicht liegt es an der Farbtiefe von 32Bit. Kann man denn an den Konturen erkennen, ob wenigstens das Drehen funktioniert?



  • Fiel mir noch dazu ein: Muss man nicht ein Video-LookUp-Table machen, wenn man die Farbtiefe verändert?





  • Ja danke für die Antworten, also erstmal die Frage von Helfer: Also das Bild wird einwandfrei gedreht, einziges Problem, die Farbe Orange oder Hautfarbe usw. verfärben sich in Blau, alles andere ist ok. Da ich bei dem Horizontalspiegeln auch mit 32 Bit Farbtife arbeite und alles einwandfrei funkt, glaube ich dass das in Ordnung ist. Was du mit deiner Tabelle meinst, weiss ich nicht so ganz, vielleicht kannst du das ja mal näher erläutern, alle anderen Links bringen mich nicht weiter, da eins mit 24 Bit arbeitet, welche auf meine Bilder nicht anwendbar sind, und das andere von Christian mit 8 Bit.



  • Das auf Christians Homepage müßte sich durch ändern des Datentyps anpassen lassen. Das ist zur Zeit Byte* (pf8Bit). Durch änderung auf DWORD* sollte das dann mit pf32Bit funktionieren. Du solltest dir dennoch das ganze Projekt herunterladen, damit Du siehst was pImagedata ist.

    Solche Farbverschiebungen hatte ich anfangs auch in dieser Routine. Lag damals daran, dass die Rotationsschleife fehlerhaft war und teilweise unter, respektvive über die Arraygrenzen geschrieben wurde.

    Grüße Joe_M.



  • Wenn du ein Bild hast, dessen Farbwerte von 0-255 (8 Bit) verteilt sind und du seinen Farbwertebereich auf 16 Bit (Farbwerte 0-65535) ausweitest muss man solch ein Video-Look-Up-Table machen. Du skalierst dann die Werte linear auf den neuen Bereich. 0 bleibt dann 0, aus 255 wird 65535, aus 127 wird 32767, ... und immer so weiter. Genauso geht man umgekehrt vor, wenn man den Wertebereich verkleinert (runterskalieren).
    Am Anfang musst du vom Originalbild vorher die Farbtiefe auslesen. Wenn dessen Farbtiefe mit dem neuen Bid übereinstimmt, brauchst du gar nichts tun. Lege am besten die Farbtiefe des neuen Bildes gleich der des alten und nicht generell auf 32Bit.



  • Hallo zufaulzumeinloggen,
    das könnte auch der Fehler sein. Aber auch hier sollte man vorher die Farbtiefe des Bildes auslesen und nicht generell auf 32Bit setzen. Man bläht sonst Bilder unnütz auf. Oder irre ich mich da?



  • Nein, dass ist schon richtig, aber ich brauchte es damals nur für 8Bit. Also war ich zu faul weiter zu testen und eine Template-Klasse draus zu machen.

    Grüße Joe_M.



  • Ich habe alle Bittiefen ausprobiert, von 1 bis 32 Bit, es funktionert aber nicht, alles andere ausser 32 Bit verzerrt das bild. Also ich habe mit 32Bit den besten erfolg, ausser dass sich das bild verfärbt. Ich habe es einfach mal mit der Matrix-Opperation durchgeführt, also jedes Pixel von einem Bild angepackt und auf das andere übertragen, klappt aber dauert sehr lange, die Bilder sind 4 MB groß. Das spigeln der Bilder horizontal führe ich auch mit ScanLine durch, das sind die selben Bilder. Bei dieser Methode benutzte ich 32 Bit, also ich meine, das müsste passen. Wie kann man den rauslesen, welche Farbtiefe das Bild überhaupt besitzt, gibt es da eine C++ funktion?

    Gruß

    Tolga



  • Memo1->Lines->Add(Image1->Picture->Bitmap->PixelFormat);

    Du bekommst dann eine Zahl zurück, die einer Farbtiefe entspricht. Die stehen dann in der Hilfe zu PixelFormat.



  • Bei mir ist es schnell genug.

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Graphics::TBitmap *Bitmap1 = new Graphics::TBitmap();
     Bitmap1->PixelFormat=Image1->Picture->Bitmap->PixelFormat;  // Pixelformat übernehmen
     Bitmap1->Height=Image1->Width; //Höhe des neuen = Breite des alten
     Bitmap1->Width=Image1->Height; //Breite ...     = Höhe...
    
     for (int h=0; h<Image1->Height; h++)
     {
      for (int w=0; w<Image1->Width; w++)
      {
       Bitmap1->Canvas->Pixels[h][w]=Image1->Canvas->Pixels[w][h];
      }
     }
     Image1->Picture->Bitmap->Assign(Bitmap1);
     Image1->AutoSize=true;
    }
    


  • Ja das liegt warscheinlich am folgenden: Du nimmst die Bildinformation aus Image1, das sind aber nicht die eigentlichen Bilddaten, denn die eigentlichen Bilddaten, die auf der Festplatte gespeichert sind, sind größer, als du sie im kleinen Inage1 anzeigst, mit deiner Methode hast du meiner Meinung nach Qualitätsverlust. Deswegen klappt das auch relativ schnell, weil die Daten gering sind.



  • Solche Farbverschiebungen hatte ich anfangs auch in dieser Routine. Lag damals daran, dass die Rotationsschleife fehlerhaft war und teilweise unter, respektvive über die Arraygrenzen geschrieben wurde.

    Würde hier keine Fehlemldung vom Compiler auftreten?



  • helfer 22 schrieb:

    Bei mir ist es schnell genug.

    Schnell genug ist relativ. Mit was für Dateien hast du das getestet?
    Fakt ist, Zugriffe per TBitmap::ScanLine sind rund 30 mal schneller als TCanvas::Pixels.

    Den vermuteten Qualitätsverlust gibt es bei letzterem allerdings nicht, die Informationen im Image sind identisch mit denen in der (BMP-)Datei.



  • Grau ist alle Theorie.

    TJPEGImage *jp = new TJPEGImage();
      try
      {
        jp->LoadFromFile("c:\\bild1.jpg");
    
        Graphics::TBitmap *tgtbmp = new Graphics::TBitmap();
        Graphics::TBitmap *srcbmp = new Graphics::TBitmap();
    
        srcbmp->Assign(jp);
    
        tgtbmp->Height = srcbmp->Width;
        tgtbmp->Width = srcbmp->Height;
        tgtbmp->PixelFormat = pf32bit;
        srcbmp->PixelFormat = tgtbmp->PixelFormat;
    
        int *tgtptr, *srcptr;
        for( int y = 0; y < tgtbmp->Height; y++)
        {
          tgtptr = (int*)tgtbmp->ScanLine[y];
          for(int x = 0; x < tgtbmp->Width; x++)
          {
            srcptr = (int*)srcbmp->ScanLine[x];
            tgtptr[x] = srcptr[y];
          }
        }
        Image1->Picture->Bitmap = tgtbmp;
        delete tgtbmp;
        delete srcbmp;
      }
      catch(Exception &E)
      {
        MessageBox(0, (E.Message).c_str(), String(E.ClassName()).c_str(), MB_ICONSTOP);
      }
      delete jp;
    

    Warum hier nicht nur gedreht sondern auch noch gespiegelt wird solltest du mit etwas logischem Denken selbst herausbekommen. Schliesslich wollen wir es ja nicht zu einfach machen. 😉


Anmelden zum Antworten