Announcement

Collapse
No announcement yet.

TBitmap um 90° drehen bei PixelFormat = pf8Bit

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TBitmap um 90° drehen bei PixelFormat = pf8Bit

    Hallo Leute,

    irgendwie bin ich zu doof dazu...

    Ich muß hier einen kleinen JPEGViewer in ein Programm integrieren. Eigentlich kein Problem, aber das Bitmap muß um 90° drehbar sein.
    Die JPEGs liegen alle in Graustufen vor. Jedoch gelingt es mir nicht, eine von dem JPEG abgeleitete Bitmap bei Pixelformat = pf8Bit auch nur in ein anderes Bitmap zu schreiben.

    Mit pf24Bit ist mir das durchaus gelungen. Allerdings ist die Routine VIEL zu langsam (4 Sek. auf einem P266, die JPEGs sind alle DINA4).

    Also habe ich mir gedacht, ich schreibe die Daten in Array, und baue aus diesem Array ein neues Bitmap auf... Funktioniert allerdings nicht. Man kann das Bitmap soeben noch erraten, allerdings mit sehr vielen Fehlfarben.

    Hier die Testroutine, mit der ich versuche die Daten von einem in ein anderes Bitmap zu schreiben. Beim Erzeuben des gedrehten Bitmaps wird die Farbpalette und das Pixelformat aus dem Originalbitmap übernommen, ebenso wie die Größe.
    <PRE>
    int ymax = BitmapOriginal->Height;
    int xmax = BitmapOriginal->Width;

    Byte* slRotated;
    Byte* slOriginal;

    Byte* Imagedata = new Byte[xmax * ymax];
    Byte* pImagedata;

    pImagedata = Imagedata;
    for (int y = ymax - 1; y >= 0; y--)
    {
    slOriginal = (Byte*) BitmapOriginal->ScanLine[y];
    for (int x = xmax - 1; x >= 0; x--)
    {
    *pImagedata = *slOriginal;
    slOriginal++;
    pImagedata++;
    }
    }

    pImagedata = Imagedata;
    for (int y = ymax - 1; y >= 0; y--)
    {
    slRotated = (Byte*) BitmapRotated->ScanLine[y];
    for (int x = xmax - 1; x >= 0; x--)
    {
    *slRotated = *pImagedata;
    slRotated++;
    pImagedata++;
    }
    }
    delete Imagedata;
    </PRE>
    Falls ich, nach Durchlauf der Routine, die Palette erneut auf die Originalpalette setze, wird das gesamte Bitmap schwarz ausgegeben.

    Was übersehe ich dabei? Jemand eine Idee?

    Wen es interessiert, hier ist die Methode, die bei pf24Bit funktioniert, aber eben zu langsam ist:
    <PRE>
    RGBTRIPLE* slRotated;
    RGBTRIPLE* slOriginal;

    for (int y = 0; y < BitmapRotated->Height; y++)
    {
    slRotated = (RGBTRIPLE*) BitmapRotated->ScanLine[y];
    for (int x = 0; x < BitmapRotated->Width; x++)
    {
    slOriginal = (RGBTRIPLE*) BitmapOriginal->ScanLine[x];
    slRotated[x] = slOriginal[BitmapOriginal->Width - y - 1];
    }
    }
    </PRE>

    Vielen Dank schon mal,

    Jochen

  • #2
    Schau mal hier:

    http://www.bytesandmore.de/rad/ib/index.php?act=ST&f=3&t=330&s=5a746b804db29f50a6435 869923dfe9e

    vielleicht hilft es
    Christian

    Comment


    • #3
      Hallo Christian,

      leider bekomme ich die Routine nicht in mein Projekt eingebunden. Alle rotierten Bilder sind komplett blau (also leer). Ich bin mir allerdings nicht sicher, ob das mein Fehler ist, oder ein Fehler in der Routine. Außerdem kann die Routine auch nur pf24bit oder pf32bit und ist genauso langsam (oder schnell) wie meine Routine für pf24bit. Noch schlimmer ist das CodeGuard Ressource-Leaks feststellt...

      Aber wenn keiner eine bessere Idee, oder eine funktionierende Routine hat, werde ich mal näher damit befassen.

      Danke und Gruß,

      Joche

      Comment


      • #4
        Hallo Leute,

        seltsam genug, aber wenn ich pf24bit verwende, funktioniert das auch mit dem Array. Dauert dann auf den P266 ca. 500 - 800 ms. Das ist schon deutlich besser als 4 Sekunden.

        So sieht die Routine im Moment aus (ich bin noch nicht sicher, ob irgendwo eine Zeile verloren geht, muß ich noch mal prüfen):
        <PRE>
        if (!BitmapRotated)
        {
        BitmapRotated = new Graphics::TBitmap();
        BitmapRotated->PixelFormat = BitmapOriginal->PixelFormat;
        }

        if (bmp_rotate == 2)
        {
        BitmapRotated->Width = BitmapOriginal->Width;
        BitmapRotated->Height = BitmapOriginal->Height;
        }
        else
        {
        BitmapRotated->Width = BitmapOriginal->Height;
        BitmapRotated->Height = BitmapOriginal->Width;
        }

        int ymaxorg = BitmapOriginal->Height;
        int xmaxorg = BitmapOriginal->Width;

        int ymaxrot = BitmapRotated->Height;
        int xmaxrot = BitmapRotated->Width;

        RGBTRIPLE* slRotated;
        RGBTRIPLE* slOriginal;

        RGBTRIPLE* Imagedata = new RGBTRIPLE[xmaxorg * ymaxorg];
        RGBTRIPLE* pImagedata;

        // Daten in Array schreiben
        pImagedata = Imagedata;
        for (int y = ymaxorg - 1; y >= 0; y--)
        {
        slOriginal = (RGBTRIPLE*) BitmapOriginal->ScanLine[y];
        for (int x = xmaxorg - 1; x >= 0; x--)
        {
        *pImagedata = *slOriginal;
        slOriginal++;
        pImagedata++;
        }
        }

        pImagedata = Imagedata;

        if (bmp_rotate == 2) // 180° gedreht
        {

        for (int y = 0; y < ymaxrot; y++)
        {
        slRotated = (RGBTRIPLE*) BitmapRotated->ScanLine[y];
        slRotated += xmaxrot - 1;
        for (int x = 0; x < xmaxrot; x++)
        {
        *slRotated = *pImagedata;
        slRotated--;
        pImagedata++;
        }
        }
        }

        if (bmp_rotate == 3) // 270° gedreht
        {
        for (int y = ymaxrot - 1; y >= 0; y--)
        {
        slRotated = (RGBTRIPLE*) BitmapRotated->ScanLine[y];
        slRotated += xmaxrot - 1;
        for (int x = 0; x < xmaxrot; x++)
        {
        *slRotated = Imagedata[ymaxrot - 1 - y + (x * xmaxorg - 1)];
        slRotated--;
        }
        }
        }

        if (bmp_rotate == 1) // 90° gedreht
        {
        for (int y = 0; y < ymaxrot; y++)
        {
        slRotated = (RGBTRIPLE*) BitmapRotated->ScanLine[y];
        for (int x = 0; x < xmaxrot; x++)
        {
        *slRotated = Imagedata[ymaxrot - 1 + y + (x * xmaxorg - 1)];
        slRotated++;
        }
        }
        }

        delete Imagedata;

        bmp_rotate_old = bmp_rotate;
        </PRE>
        Aber wenn jemand eine Idee hat, wie das auch mit pf8bit funktioniert - das wäre nochmal um
        den Faktor 2-3 schneller und würde deutlich weniger Speicher verbrauchen...

        Grüße

        Joche

        Comment


        • #5
          Habe zu Hause noch ein Buch über Windows -> API. Stammt noch aus der WIN 3.1 Zeit. Darin wird das mit den Bitmaps und Scanlines genau erklärt. Und wenn ich mich rechtg erinnere war da mal was, dass die Bitmapdaten bei weniger als 24-Bit je Zeile auf durch einen 4 teilbaren Betrag aufgefüllt werden müssen. Habe mal vor X-Jahren eine LIB mit Grafikprogrammierung germacht, diese aber "entsorgt". Wenn du willst kann ich dir die Seiten einscannen?
          Christian

          Comment


          • #6
            Hallo Chrístian,

            das wäre echt nett. E-Mail: [email protected]

            Danke vielmals,

            Joche

            Comment


            • #7
              bin auf Arbeit heute aben
              Christian

              Comment


              • #8
                <PRE>
                Die gekürzte Version der Routine
                innerhalb meiner Komponente.

                // 90 Grad
                int b = bitmap->Width;
                int h = bitmap->Height;
                bitmap1->Height = bitmap->Width;
                bitmap1->Width = bitmap->Height;

                for( int y = 0; y < h; y++ )
                for( int x = 0; x < b; x++ )
                {
                // c brauchst du eigentlich nicht benutzen
                TColor c = bitmap->Canvas->Pixels[x][y];
                bitmap1->Canvas->Pixels[h-y-1][x] = c;

                }//for

                Gruß Fred

                </PRE&gt

                Comment


                • #9
                  Hi Fred,

                  eider ist der Zugriff über Canvas extrem langsam. Im Momment mach ich es mit der Routine aus Posting 3. Sobald ich ein bißchen mehr Zeit hab', werde ich mich mit den Informationen von Christian beschäftigen.

                  Ich werde das Ergebnis hier posten.

                  Danke trotzdem für Deine Mühe.

                  Joche

                  Comment


                  • #10
                    äh - ich trau mich gar nicht das zu sagen...

                    Aber wenn ich bei dem Bitmap nicht HandleType = pbDIB, sondern HandleType = pmDDB verwende funktioniert die Routine in Posting 3 auch mit pf8bit (natürlich müssen alle RGBTRIPLE durch Byte ersetzt werden...).

                    Laut Doku sollte ich aber nur Zugriff auf die ScanLine haben, wenn HandleType = pmDIB ist...

                    @Christian: Nochmal bedankt, ohne Deine Infos wäre ich da nie drauf gekommen.

                    Grüße

                    Joche

                    Comment


                    • #11
                      :-)
                      Christian

                      Comment

                      Working...
                      X