0
votes

I'm currently using Python 2.7 to pull pixel information from a series of bitmaps, and writing 24 bits of information to a file (with an arbitrary extension, ".bfs", to make it easy to find down the pipeline), 8 bits for position x, 8 bits for position y, 16 bits for color.

from PIL import Image
import struct

filename = raw_input('Please choose destination filename:  ')

file_in = [0]*27
im = [0]*27

for i in range(1,27):
    file_in[i] = str(i)+".bmp"
    im[i] = Image.open(file_in[i])

file_out = open(filename+".bfs", 'w')
readable_out = open(filename+".txt", 'w')

for q in range(1,27):    
    pix = im[q].load()
    width, height = im[q].size 
    for y in range (height):
        for x in range (width):
            rgb = pix[x,y]

            red = rgb[0]
            green = rgb[1]
            blue = rgb[2]

            Uint16_val = (((31*(red+4))/255)<<11) | (((63*(green+2))/255)<<5) | ((31*(blue+4))/255)
            hex_16 = int('%.4x'%Uint16_val, 16)
            print(str(x)+", "+str(y)+", "+str(hex_16)+"\n")

            readable_out.write(str(x)+", "+str(y)+", "+str(hex_16)+"\n")

            file_out.write(struct.pack('<1B', x))
            file_out.write(struct.pack('<1B', y))
            file_out.write(struct.pack('<1H', hex_16))

On the PC side everything is coming out clean how I expect (this is copied from a .txt file that I output and format to make it easier to read):

0, 0, 40208
1, 0, 33544
2, 0, 33544
3, 0, 39952
4, 0, 39944
5, 0, 33544
6, 0, 39688
7, 0, 39952
8, 0, 39944
9, 0, 33544
10, 0, 33800
11, 0, 39952
12, 0, 39952
13, 0, 33544
14, 0, 33800
15, 0, 48400

From here I'm taking the .bfs file and loading it onto an SD card for an Arduino Uno to read from. The Arduino code is supposed to read from the SD card, and output the x, y, and color values to a TFT LCD. Here is the Arduino Code:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <SD.h>

#define TFT_CS  10  // Chip select line for TFT display
#define TFT_RST  9  // Reset line for TFT (or see below...)
#define TFT_DC   8  // Data/command line for TFT

#define SD_CS    4  // Chip select line for SD card

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

void setup(void) {
  Serial.begin(9600);

  tft.initR(INITR_144GREENTAB);


  Serial.print("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("failed!");
    return;
  }
  Serial.println("OK!");

 tft.fillScreen(0x0000);
}

uint32_t pos = 0;
uint8_t  x,y;
uint8_t  buffpix[3];
uint16_t c;

void loop() {
bfsDraw("image.bfs");
}

#define BUFFPIXEL 20

void bfsDraw(char *filename) {

  File     bfsFile;
  int      w, h, row, col;
  uint8_t  x,y;
  uint16_t c;
  uint32_t pos = 0, startTime = millis();

  if((0 >= tft.width()) || (0 >= tft.height())) return;

  if ((bfsFile = SD.open(filename)) == NULL) {
    Serial.print("File not found");
    return;
  }
      w = 128;
      h = 128;
      tft.setAddrWindow(0, 0, 0+w-1, 0+h-1);

        for (row=0; row<h; row++) {
          for (col=0; col<w; col++) {
            x = bfsFile.read();
            Serial.print(x);
            Serial.print(", ");
            y = bfsFile.read();
            Serial.print(y);
            Serial.print(", ");
            c = read16(bfsFile);
            Serial.print(c);
            Serial.print(" ");
            Serial.println(" ");
            tft.drawPixel(x,y,c);
          } 
         } 
    }

uint8_t read8(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read();
  return result;
}

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

I have some print statements around the code that reads from the card before sending out to the TFT, and instead of matching the file that (I think) I wrote it outputs like this:

0, 0, 40208  
1, 0, 33544  
2, 0, 33544  
3, 0, 39952  
4, 0, 39944  
5, 0, 33544  
6, 0, 39688  
7, 0, 39952  
8, 0, 39944  
9, 0, 33544  
13, 10, 2048  
132, 11, 4096  
156, 12, 4096 

As you can see the reading from the Arduino starts out matching the writing of the Python script, but after 9 the "X" byte has shifted into the middle instead of the leading position. My question, is what is causing this shift, after x = 9? is this a little endian versus big endian issue?

Thanks for your help!

1

1 Answers

0
votes

You opened your file in text mode, not binary mode. On Windows, that means that every newline character (byte value 10) that you write gets converted into carriage return + linefeed (byte values 13, 10). Use 'wb' for the mode when opening the .bfs file.

Note that writing the coordinates of each pixel into the file is insane - you're doubling the size of the file for absolutely no benefit. You can easily recreate the coordinates as you're reading the file - in fact you're ALREADY DOING SO, in the form of the row and col variables!