www.mikrocontroller.net

Forum: Projekte & Code Bitmap Konverter


Autor: Hagen Re (hagen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anbei eine Beta meines Konverters.

Vorerst müsste das Exportieren in das RAW Format ausreichend sein. Dazu 
einfach die Checkbox "RAM Data" anhacken und es wird eine C Header Datei 
gespeichert in der die Pixel mit 16Bit Farbwerten codiert sind.

Für die anderen 3 Datenformate die ich verwende kann ich noch 
Erklärungen und Beispielcode in C nachliefern, wenn gewünscht. Vorerst 
nur mal par Stichpunkte was drinnen ist:

- 1 Farb Bitmaps, das sind nichts anderes als mit einer Farbe 
ausgefüllte Rechtecke, quasi leere Bitmaps mit einer Hintergrundfarbe

- 16 Bit Bitmaps, das sind unkomprimierte Bitmaps in voller Farbe, 
meistens weil eine Komprimierung nichts bringt

- Monochrome Bitmaps (2 Farben) mit Komprimierung. Die Daten sind per 
RLE komprimiert und man erreicht ca. 2000-3000% Packungsrate im 
Vergleich zu RAW

- 2 Bit bis 15 Bit Farbbitmaps, also von 3 Farben bis 32765 Farben. Die 
Daten sind komprimiert und benutzen eine Farbtabelle. Die 
Komprimierungsrate ist fast immer besser als bei PNG Bildern. Wichtig 
ist das man nur durchschnittlich 16 AVR Takte pro Datenbyte in den 
Zeichenroutinen benötigt für diese Dekomprimierung. Man erreicht also 
defakto den maximalen Datendurchsatz bei 8Mhz SPI auf einem 16Mhz AVR, 
direkt aus dem FLASH ohne zusätzlichen SRAM zu verbrauchen.


Die Software selber kann
- PNG, BMP, WMF, EMF, ICO, JPEG laden
- in beliebigem Farbformat
- in beliebiger Größe
- das Bild wird runter skaliert auf maximal 176x132 Pixeln wenn nötig, 
Seitenverhältnis wird beibehalten
- die Farbpalette/-anzahl kann reduziert werden
- das Bild kann in 90 Gradschritte rotiert, und gespiegelt werden


Gruß Hagen

Ausschnitt meines bisherigen Codes für meine S65-GLCD des LPH88xxx 
Display (Philips HD66773R Controller).
#include "glcd.h"

uint16_t colormasks[14] PROGMEM = {0x0006, 0x000E, 0x001E, 0x003E, 0x007E, 0x00FE, 0x01FE, 0x03FE, 0x07FE, 0x0FFE, 0x1FFE, 0x3FFE, 0x7FFE, 0xFFFE};

void glcdDrawBitmap(glcdCoord_t x, glcdCoord_t y, const prog_char* bitmap, uint8_t flags) {


#define GLCD_LOAD_BITS(data0, data2, databits, addr, bitsmul) \
   asm volatile(                            \
    "cpi   %2, lo8(16)"         "\n\t"  \
        "brsh  .%=2"                "\n\t"  \
        "movw  r30, %A3"            "\n\t"  \
        "lpm   r0, Z+"              "\n\t"  \
        "mul   r0, %4"              "\n\t"  \
        "cpi   %2, lo8(8)"          "\n\t"  \
        "brsh  .%=1"                "\n\t"  \
        "or    %A0, r0"             "\n\t"  \
        "or    %B0, r1"             "\n\t"  \
        "subi  %2, lo8(-(8))"       "\n\t"  \
        "lpm   r0, Z+"              "\n\t"  \
        "mul   r0, %4"              "\n\t"  \
".%=1:"                             "\n\t"  \
        "or    %B0, r0"             "\n\t"  \
        "or    %1, r1"              "\n\t"  \
        "subi  %2, lo8(-(8))"       "\n\t"  \
        "movw  %A3, r30"            "\n\t"  \
".%=2:"                             "\n\t"  \
        "clr   r1"                  "\n\t"  \
      : "=r" (data0),                     \
        "=r" (data2),                     \
        "=a" (databits),                  \
        "=r" (addr),                      \
        "=r" (bitsmul)                    \
      : "r" (data0),                      \
        "r" (data2),                      \
        "a" (databits),                   \
        "r" (addr),                       \
        "r" (bitsmul)                     \
        : "r0", "r1", "r30", "r31"          \
     );

#define GLCD_LOAD_COLOR(data0, data2, databits, colortable, colormask, bpp, bitsmul, bkcolor) \
   asm volatile(                            \
        "movw  r30, %A0"            "\n\t"  \
        "lsr   %1"                  "\n\t"  \
        "ror   %B0"                 "\n\t"  \
        "ror   %A0"                 "\n\t"  \
        "brcs  .%=0"                "\n\t"  \
        "dec   %2"                  "\n\t"  \
        "lsr   %6"                  "\n\t"  \
        "brne  .%=3"                "\n\t"  \
        "ori   %6, lo8(0x80)"       "\n\t"  \
        "rjmp  .%=3"                "\n\t"  \
".%=0:"                             "\n\t"  \
        "and   r30, %A4"            "\n\t"  \
        "and   r31, %B4"            "\n\t"  \
        "add   r30, %A3"            "\n\t"  \
        "adc   r31, %B3"            "\n\t"  \
        "lpm   %A7, Z+"             "\n\t"  \
        "lpm   %B7, Z"              "\n\t"  \
        "mov   r30, %5"             "\n\t"  \
        "cpi   r30, lo8(8)"         "\n\t"  \
        "brlo  .%=1"                "\n\t"  \
        "mov   %A0, %B0"            "\n\t"  \
        "mov   %B0, %1"             "\n\t"  \
        "clr   %1"                  "\n\t"  \
        "andi  r30, lo8(0x07)"      "\n\t"  \
        "breq  .%=2"                "\n\t"  \
".%=1:"                             "\n\t"  \
        "lsr   %1"                  "\n\t"  \
        "ror   %B0"                 "\n\t"  \
        "ror   %A0"                 "\n\t"  \
        "dec   r30"                 "\n\t"  \
        "brne  .%=1"                "\n\t"  \
".%=2:"                             "\n\t"  \
        "sub   %2, %5"              "\n\t"  \
        "dec   %2"                  "\n\t"  \
        "mov   r30, %2"             "\n\t"  \
        "andi  r30, lo8(0x07)"      "\n\t"  \
        "clr   r31"                 "\n\t"  \
        "subi  r30, lo8(-(powerof2))"   "\n\t"  \
        "sbci  r31, hi8(-(powerof2))"   "\n\t"  \
        "lpm   %6, Z"               "\n\t"  \
".%=3:"                             "\n\t"  \
      : "=r" (data0),                     \
        "=r" (data2),                     \
        "=a" (databits),                  \
        "=r" (colortable),                \
        "=r" (colormask),                 \
        "=r" (bpp),                       \
        "=r" (bitsmul),                   \
        "=r" (bkcolor)                    \
      : "r" (data0),                      \
        "r" (data2),                      \
        "a" (databits),                   \
        "r" (colortable),                 \
        "r" (colormask),                  \
        "r" (bpp),                        \
        "r" (bitsmul),                    \
        "r" (bkcolor)                     \
        : "r30", "r31"                      \
     );


    if (!(bitmap)) return;
    uint8_t w = pgm_read_byte_inc(bitmap);
    if (!(w)) return;
    uint8_t h = pgm_read_byte_inc(bitmap);
    if (!(h)) return;
    uint8_t bpp = pgm_read_byte_inc(bitmap);
    uint16_t bkcolor = pgm_read_word_inc(bitmap);
    if (flags & GLCD_BMP_USECOLORS) bkcolor = glcd.Colors[0];
    if (bpp == 0) {
      glcdFillRect(x, y, x + w -1, y + h -1, bkcolor);
      return;
    }
    GLCD_CS_ON();
    GLCD_SETADDR(x, y);
    GLCD_WINDOW(x, y, x + w -1, y + h -1);
    if (flags & GLCD_BMP_TRANSPARENT) {
      GLCD_SETMODE(0x38 | GLCD_ROP_WNE);
      GLCD_SETCOMPARE(bkcolor);
    } else {
      GLCD_SETMODE(0x38);
    }
    GLCD_STARTDATA();
    if (bpp == 1) {// monochrome
      uint16_t pixelcount = w * h;
      uint16_t fgcolor = pgm_read_word_inc(bitmap);
      if (flags & GLCD_BMP_USECOLORS) fgcolor = glcd.Colors[1];
      uint16_t color = bkcolor;
      if (flags & GLCD_BMP_SWAPCOLORS) {
        bkcolor = fgcolor;
        fgcolor = color;
        color   = bkcolor;
      }
      uint8_t data = pgm_read_byte_inc(bitmap);
      uint8_t pixelbits = ((data >> 4) +1) << 2;
      data &= 0x0F;
      uint8_t temp = data << 4;
      data |= temp;
      do {
        GLCD_WAIT();
        GLCD_OUT(H8(color));
        if (!(--pixelbits)) {
          data = pgm_read_byte_inc(bitmap);
          pixelbits = ((data >> 4) +1) << 2;
          data &= 0x0F;
          uint8_t temp = data << 4;
          data |= temp;
        }
        GLCD_WAIT();
        GLCD_OUT(L8(color));
        ROL(data);                                // rotate data, data = (data << 1) | (data >> 7);
        color = bkcolor;
        if (data & 0x01) color = fgcolor;
      } while (--pixelcount);
    } else if (bpp == 16) { // full color
      uint16_t pixelcount = w * h;
      while (pixelcount) {
        GLCD_WAIT();
        GLCD_OUT(H8(bkcolor));
        pixelcount--;
        GLCD_WAIT();
        GLCD_OUT(L8(bkcolor));
        bkcolor = pgm_read_word_inc(bitmap);
      }
    } else {// color, 2 upto 15 BPP
      uint16_t colortablesize = pgm_read_word_inc(bitmap);
      uint8_t* colortable = (uint8_t*)bitmap;
      bitmap += colortablesize;
      uint16_t colormask = pgm_read_word(&colormasks[bpp -2]);
      uint8_t databits = 0, data2 = 0, bitsmul = 1;
      uint16_t data0 = 0;
//      uint32_t data = 0;
      uint16_t pixelcount = w * h;
      do {
        GLCD_WAIT();
        GLCD_OUT(H8(bkcolor));
        pixelcount--;
        GLCD_LOAD_BITS(data0, data2, databits, bitmap, bitsmul);

//        while (databits < 16) {
//          uint16_t t = pgm_read_byte_inc(bitmap) * bitsmul;
//          if (databits >= 8) data |= (uint32_t)t << 8;
//            else data |= t;
//          databits += 8;
//        }

        GLCD_WAIT();
        GLCD_OUT(L8(bkcolor));

        GLCD_LOAD_COLOR(data0, data2, databits, colortable, colormask, bpp, bitsmul, bkcolor);

//        if (LL8(data) & 0x01) {
//          bkcolor = pgm_read_word(colortable + (L16(data) & colormask));
//          data >>= bpp;
//          databits -= bpp;
//          bitsmul = pgm_read_byte(&powerof2[databits & 0x07]);
//        }
//        bitsmul >>= 1;
//        if (!(bitsmul)) bitsmul |= 0x80;
//        data >>= 1;
//        databits--;
      } while (pixelcount);
    }
    GLCD_WAIT();
    GLCD_CS_PULSE();
    GLCD_SETMODE(0x30);
    GLCD_CS_OFF();
}


  

Autor: Michele B.. (luxx) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
super sache! vielen dank!

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, dieser Beitrag sollte hier eigentlich garnicht landen. Könnte 
aber auch seine Vorteile haben einen extra Thread abzuspalten.

Es geht um eine PC Software die Bilder auf dem PC so bearbeitet und 
konvertiert das man sie auf den S65 Displays benutzen kann.

Gruß Hagen

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

super Programm - kann ich das auch für andere Bildgrößen kriegen?

Autor: Richard (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

versuche gerade ein kleines Bitmap (10x10 Pixel) auf meinem S65 LCD 
darzustellen. Habe den Converter von Hagen Re benutzt um die Bilddaten 
als raw data in einem array zu speichern. Das Bild im Anhang möchte ich 
gerne darstellen lassen. Zu sehen ist aber nur ein bunter Pixelhaufen. 
So sehen die raw daten des Bildes aus:
uint8_t img_bmp[] PROGMEM = 
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 
  0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 
  0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 
  0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
  0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

Und das sind die Routinen für die Bildwiedergabe von Christian Kranz:
void LCD_WrData(unsigned char data)
{
 CLR(LCD_CS);          
 CLR(LCD_RS);          
 SPDR = data;
 while(!(SPSR & (1<<SPIF)));
 SET(LCD_CS);
}

void S65_wrcmd16(uint16_t dat)
{
 LCD_WrCmd((dat>>8));
 LCD_WrCmd(dat);
}

void S65_allocatearea(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
 uint8_t x, y;
 if(x1 < x2)
 { 
  x = x2; 
  x2 = x1; 
  x1 = x;
 }
 if(y2 < y1)
 { 
  y = y1; 
  y1 = y2; 
  y2 = y;
 }
 S65_wrcmd16(0xEF80);    
 S65_wrcmd16(0x1805);
 S65_wrcmd16(0x1200 + x1);  
 S65_wrcmd16(0x1500 + x2);
 S65_wrcmd16(0x1300 + y1);  
 S65_wrcmd16(0x1600 + y2);
}

void S65_PutRawBmp16(uint8_t x, uint8_t y, uint8_t *pic, uint8_t w, uint8_t h)
{
 uint8_t dimx = w-1; 
 uint8_t dimy = h-1;
 S65_allocatearea(x, y, x+dimx, y+dimy);
  
 for(uint16_t counter = 0; counter < ((dimx+1)*(dimy+1))*2; counter++)
 {
  LCD_WrData(pgm_read_byte_near(&pic[counter]));
 }
}

Wird dann in der main() so aufgerufen:
S65_PutRawBmp16(60, 60, img_bmp, 10, 10);

Ich betreibe das Display an einem ATmega644 bei 16MHz. Die Wiedergabe 
von Text funktioniert bereits. Nur mit dem Bild habe ich Probleme.

Wer hat einen Tipp für mich?
Gruß
Richard

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.