Go Down

Topic: Librería para TFT con RA8875 para manejo de imágenes [Solucionado] (Read 1 time) previous topic - next topic

18turbo

Hola compañeros,

He estado buscando durante varios días hasta aburrirme, y no he encontrado una librería que maneje cualquier tipo de imagen (me da igual que sea JPG, BMP o PNG) y que la muestre en una pantalla TFT de 7" de Buydisplay. La pantalla funciona de lujo, y con Arduino DUE va realmente rápido.

He probado las librerías de RA8875 y la misma de Adafruit. Con la primera funciona todo, pero la imagen de 24 bits que pone como ejemplo de representación de una imagen en pantalla, funciona porque está en hexadecimal. Yo quiero que lea un fichero de imagen (me da igual qué tipo) de la SD Card, y la muestre en la pantalla. SIMPLEMENTE (o no).

Pensé que sería más fácil, pero no hay manera.

¿Me podéis orientar un poco?

Y si no se puede, ¿me podéis decir cómo pasar una imagen a HEX en Linux? He probado Image2LCD con wine, pero no sé si es que no lo codifica como debe, o que estoy haciendo algo mal (seguramente esto último).

Un saludo a todos, y gracias por leerme. Espero que puedan ayudarme

Eduardosanchez

Hola de echo yo cree un método para mostrar imágenes en una TFT , te lo advierto no es para nada eficiente en términos de escritura pero quizás te pueda servir.
Solo utilice un programa llamado Octave (opensource) si te interesa puedo decirte como.

18turbo

Hola Eduardosanchez,

Lo primero gracias por contestar.

Sí, claro que me interesa :) . Aunque no sea eficiente, me puede interesar (seguro que sí).

Estaría interesado también en saber de qué manera podría hacerse el incluir 20 pequeñas imágenes de 60x60 pixels de 6 colores máximo en un sketch para Arduino DUE.

Si alguien sabe cómo, por favor, que me diga dónde puedo encontrar información al respecto.

Gracias.

Eduardosanchez

#3
Apr 05, 2018, 04:10 pm Last Edit: Apr 05, 2018, 04:12 pm by Eduardosanchez
Sí, claro que me interesa :) . Aunque no sea eficiente, me puede interesar (seguro que sí).

Gracias.
ok yo maneje un TFT con comunicación SPI, no se que tipo de comunicación utilice la tuya de cualquier modo eso es lo de menos. Lo unico que si te servira es saber cual es la profundidad de color de tu pantalla (8,12,16 bits) esto definirá la codificacion de la imagen, yo como tal codifique una imagen PGN en un tipo formato RGB565 (la pantalla era de 16 bits) en un archivo de texto. lo único que hice en realidad es abrir el archivo txt e ir obteniendo la información para "colorear" los píxeles a partir de caracteres.
tarda como medio segundo en dibujar una imagen completa(240*204 pixeles).
En cuanto a la imagen de 60x60 es por eso que debes saber cual es la profundidad del color. y te puede servir como referencia esta página.(incluso esa la puedes dejar en la memoria EEPROM como indica la siguiente pagina)
https://www.prometec.net/shield-mega-tft-imagen/

surbyte

Primero leo esto
Quote
Con la primera funciona todo, pero la imagen de 24 bits que pone como ejemplo de representación de una imagen en pantalla, funciona porque está en hexadecimal. Yo quiero que lea un fichero de imagen (me da igual qué tipo) de la SD Card, y la muestre en la pantalla. SIMPLEMENTE (o no).
Los archivos deben convertirse. No hay ningun arduino que lea un formato .jpg o .bmp o lo que sea y lo presente, asi que olvidate de resolver eso porque no le da la potencia de cálculo.

Existen programas que convierten los archivos del formato que sea en hexa. Y esa es tu solución.
Lo guardas como Hexa en la SD y luego lo presentas.

Acá tendras tu respuesta Algunos consejos para usar TFT´s

El tema esta en Documentacion => Indice de temas tutoriales =>TFT => Algunos consejos para usar TFT´s

18turbo

@eduardoSanchez

La TFT la compré preparada para SPI (aunque puede ir por paralelo) porque me interesaba así. Es de 24 bits, y la resolución de 800x480pixels. La SD Card no la he hecho funcionar todavía (me refiero a la que va en la TFT, no sé bien qué pasa, pero eso quizás sea para otro post).

Gracias por la info, muy interesante, aunque de poco me sirve porque en el ejemplo de la librería RA8875 que me funciona, la imagen está de la forma:

Code: [Select]
static const uint32_t image_data_batman_ume[16384] = {
    0x976a40, 0xaa8a3f, 0xb49f42, 0xb3a044, 0xb19b45, 0xac983f,...}


Y en el código veo que transforma ésta a RGB565:

Code: [Select]
void drawArray(const uint32_t * image,uint16_t isize,uint16_t iwidth,uint16_t x,uint16_t y){
  uint16_t pixels[iwidth];//container
  uint32_t i,idx;
  for (idx=0;idx<isize/iwidth;idx++){
    for (i = (iwidth*idx); i < iwidth*(idx+1);i++){
      pixels[i - (iwidth*idx)] = tft.Color24To565(image[i]);
    }
    tft.drawPixels(pixels,iwidth,x,idx+y);
  }
}


Por lo que me interesaba saber cómo consigo esta codificación (la que pongo en el primer código), porque a RGB565 no hay problemas.


@surbyte

Muchas gracias por la información tan clara. Necesitaba algo así. Sabiendo que nada lee los formatos de imagen y los presente por pantalla "tal cual" (al menos para la pantalla que yo tengo o de forma fácil o "limpia"), ya me busco la vida en hexadecimal, pero debo resolver el problema del código anterior (primer código que puse), porque no llego a entender como pasar una imagen a esa codificación. Si me podéis echar una manilla más...

Luego, con las pautas que me has dado (guardar en hexadecimal los ficheros en la SD para leerlos y presentarlos), pues ya lo tengo.

Gracias por el enlace del uso de las TFTs (estuve "procesándolo" toda la tarde ;) )



Gracias a los 2.


Moderador: Texto editado

18turbo

Buscando en el baúl de los recuerdos, he encontrado una función que me funcionaba en otra pantalla, y que creo que funcionaría en ésta.

Pongo el código por si le sirve a alguien, AUNQUE YO NO LA HE PROBADO TODAVÍA:

Code: [Select]
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

void writePixb(int16_t x,uint16_t color){
  tft.setX(x);
  tft.writeCommand(RA8875_MRWC);
  tft.writeData16(color);
}


void bmpDraw(const char *filename, int16_t x, int16_t y)
  {

  File     bmpFile;
  int16_t  bmpWidth = 0, bmpHeight = 0;   // W+H in pixels
  uint8_t  bmpDepth = 0;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset = 0;        // Start of image data in file
  uint32_t rowSize = 0;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int16_t  w=0, h=0, row=0, col=0;
  uint32_t pos = 0;
  uint16_t lcdidx = 0;

  if((x >= tft.width()) || (y >= tft.height())) return;
  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == 0) return;
  // Parse BMP header
  if (read16(bmpFile) == 0x4D42) { // check BMP signature
    read32(bmpFile);
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    read32(bmpFile);
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if (read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // determine color depth
      if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;
        // If bmpHeight is negative, image is in top-down order.This is not canon but has been observed in the wild.
        if (bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }
        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        for (row=0; row<h; row++) { // For each scanline...
          tft.setY(row+y);
          if (flip) { // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          }
          else {     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          }
          if (bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }
          for (col=0; col<w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if (lcdidx > 0) {
                writePixb(col+x,lcdbuffer[lcdidx]);
                lcdidx = 0;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }
            lcdbuffer[lcdidx] = tft.Color565(sdbuffer[buffidx++],sdbuffer[buffidx++],sdbuffer[buffidx++]);
            writePixb(col+x,lcdbuffer[lcdidx]);
          } // end pixel

        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) writePixb(col+x,lcdbuffer[lcdidx]);
      } // end goodBmp
    }//correct plane
  }//end BMP signature
  bmpFile.close();
}



uint16_t read16(File f) {
  uint16_t result = 0;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result = 0;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}


El tema está ahora en conseguir hacer funcionar la SD Card de la TFT para que lea un BMP y pueda probar el código.

No sé si llegado este punto, debiera abrir otro hilo o seguir con el problema de la SD Card aquí.

Eduardosanchez

#7
Apr 06, 2018, 12:08 am Last Edit: Apr 06, 2018, 12:25 am by Eduardosanchez
bueno si consigues la forma de hacer que una librería SD pueda leer archivos decodificados en 16 o 24 bits me avisas que he estuve cerca de dos meses y no encontre nada.
para saber cómo pasa una imagen a una pantalla es bastante interesante para hacer que la mía funcionara lo hice como te dije pero tuve que hacer una libreria para el manejo de mi pantalla lo que necesitas saber es 1 el tipo de interfaz como te mencionaba en mi caso una spi de 4 hilos estos son

mosi
sclk
slave select
data/cmand

si tu pantalla funciona de forma similar estamos en el mismo canal. pues al final lo que hace un microcontrolador es mandar el comando(a través del dato/comando) un valor por SPI a la pantalla que le indica que registros de la memoria RAM de la pantalla se van a escribir "habilitar una ventana" después de eso (en mi código 9 transferencias de SPI 3 comandos los demás datos) y despues solo envía datos que contienen la información osea el valor para cada píxel, en mi caso al ser RGB565 con dos transferencias SPI de 8bits rellenaba un pixel, obvio primero se envian los mas significativos después los menos.
@eduardoSanchez

La TFT la compré preparada para SPI (aunque puede ir por paralelo) porque me interesaba así. Es de 24 bits, y la resolución de 800x480pixels. La SD Card no la he hecho funcionar todavía (me refiero a la que va en la TFT, no sé bien qué pasa, pero eso quizás sea para otro post).

Gracias por la info, muy interesante, aunque de poco me sirve porque en el ejemplo de la librería RA8875 que me funciona, la imagen está de la forma:

Code: [Select]
void drawArray(const uint32_t * image,uint16_t isize,uint16_t iwidth,uint16_t x,uint16_t y){
  uint16_t pixels[iwidth];//container
  uint32_t i,idx;
  for (idx=0;idx<isize/iwidth;idx++){
    for (i = (iwidth*idx); i < iwidth*(idx+1);i++){
      pixels[i - (iwidth*idx)] = tft.Color24To565(image[i]);
    }
    tft.drawPixels(pixels,iwidth,x,idx+y);
  }
}


Por lo que me interesaba saber cómo consigo esta codificación (la que pongo en el primer código), porque a RGB565 no hay problemas.
bien lo que necesitas es codificación RGB888 eso queire decir al parecer(falta verificar con la datasheet del controlador de tu pantalla) que la configuración de color es 8 bit rojo, 8 bit verde, 8 bit azul.
con Octave puedes hacer esto descargar octave instalar modulo Image. y empezar es básicamente mathlab open source. lo único que haces es tratar una imagen como una matriz , si tu imagen BMP ya está codificada en 24 bit lo único que haces es guardar ese valor en un archivo de texto separado con comas y después abrirlo declarar un array de 60x60 y guardarlo en la EEPROM. Exacto solo funcionaria para la de 60x60 y digo quizas por que no se si quepa en la EEPROM de arduino. (hace poco me ayudaron a guardar matrices de 32 bits en la EEPROM de arduino si te interesa te lo paso).
ACLARO LO ANTERIOR SOLO PARA LA DE 60X60 UNA IMAGEN DE PANTALLA COMPLETA NO CABRIA
con el SPI de transferencias  de 8 bits que segun yo solo se puede asi en arduino necesitas enviar una componente de color es decir 3 transferencias SPI por pixel.
Todo mi proceso de "destripado" de librerias similares esta en una memoria( la uso para la titulación) si gustas te puedo compartirla como referencia.
Saludos

18turbo

@Eduardosanchez

Sí, mi TFT usa 4 hilos SPI (podía haberla comprado para 3 hilos), pero compré para 4, que son:
*MISO
*MOSI
*SCK
*CS

Ahora bien, no sé qué pasa que en la DUE no funciona la SD Card. Y pensándolo, ANTES DE NADA, ya que tengo la Arduino MEGA por aquí donde sí me funciona la SD Card, voy a ver si hago funcionar la TFT en la Mega (aunque vaya más lenta, que creo que la configuración es la misma para la DUE que para la MEGA para mi TFT), y vamos despejando problemas...

Por mí, todo lo que quieras compartir, adelante. Yo, si consigo hacer funcionar lo que quiero no tendré inconveniente en pasártelo.

Un saludo, y gracias por ayudarme.

Moderador: No repitas lo que se lee arriba

18turbo

Mi MEGA funciona con la TFT y la SD Card a la vez.

Además lee la tarjeta con el archivo BMP. Ahora falta que funcione  :(  Estoy en ello.

Por cierto, con GIMP puedes coger el fichero gráfico que quieras, exportarlo a BMP (y en configuraciones Avanzadas de la exportación, seleccionar RGB565 para exportarlo a este formato.

Seguiré probando un poco más, y sino, lo dejo para mañana.

Saludos

18turbo

He probado lo básico y no me funciona. Mañana seguiré, pero yo creo que esa función debe funcionar. Es posible que mi BMP no esté correctamente exportado, o algo así.


18turbo

Pues funciona el código (la función) para mostrar cualquier BMP en una TFT. El código es parte copiado de algo antiguo que tenía por ahí pero funciona. Tendré que mejorarlo un poquito.

No doy por solucionado este hilo, porque me falta probarlo en la DUE, pero en el Arduino MEGA con la TFT y la SD Card, funciona.

Gracias a todos los que me habéis ayudado.

Un saludo


surbyte

Y como haras para pasar de una Mega que trabaja a 5V a un DUE que lo hace a 3.3V con tu TFT ?


Go Up