Allocating a list of objects?

I have this object that grabs rectangle from a bitmap and blits it to the screen. It works fine, never gives any issues but its bloody slow. So, now that I'm on a machine with some RAM, how about allocating a line buffer and letting it do things line by line? Instead of pixel by pixel. The logic is already setup for this kind of thing, I just need to pass in a correctly sized buffer.

And it just blows up!

I think I'm not allocating the buffer correctly. I want a buffer that is an array of colorObj(s). Then I can poke colors into them one at a time. Once I set them all, I can switch over and blit them to the screen one at time.

I get the buffer, I see things run 'till I want to poke in some data and.. It locks up.

drawBitmap() is what is called originally. It sets the stage and gets things ready for blitting line by line.

drawLine() is called for each line. The original grabs one pixel at time, reads it then writes it to the screen.

The new drawLine() is passed in an array of colorObj(s) this should allow it to grab the entire line before switching hardware for drawing. But it just blows up.

Thanks millions.

-jim lee

// Your standard do it one at a time.
void bmpPipe::drawLine(File bmpFile,int x,int y) {

    colorObj  thePixal;
    uint8_t   buf[COLOR_BUF_SIZE];   
    int       trace;
    int       endTrace;

    endTrace = x+sourceRect.width;
    for (trace=x;trace<endTrace; trace++) {       // Ok, trace does x..x+width.
      bmpFile.read(buf,pixBytes);                 // Grab a pixel.
      thePixal.setColor(buf[2],buf[1],buf[0]);    // Load colorObj.
      screen->drawPixel(trace,y,&thePixal);       // Spat it out to the screen.
	}
}

// If we were able to allocate a line buffer for the colors, try it line at a time.
void bmpPipe::drawLine(File bmpFile,int x,int y,colorObj* colorBuff) {

	uint8_t	buf[COLOR_BUF_SIZE];   
	int		trace;
	int		endTrace;
	int		i;
	 
	i = 0;
	endTrace = x+sourceRect.width;
	Serial.println("Filling buffer");Serial.flush();
	for (trace=x;trace<endTrace; trace++) {				// Ok, trace does x..x+width.
		bmpFile.read(buf,pixBytes);							// Grab a pixel.
		colorBuff[i].setColor(buf[2],buf[1],buf[0]);		// Load colorObj.
		i++;
	}
	Serial.println("Drawing buffer to screen");Serial.flush();
	i = 0;
   for (trace=x;trace<endTrace; trace++) {				// Ok, trace does x..x+width.
   	screen->drawPixel(trace,y,&(colorBuff[i]));		// Spat it out to the screen.
   	i++;
	}
}

  
void bmpPipe::drawBitmap(int x,int y) {
  
	File			bmpFile;
	int			trace;
	int			endY;
	int			srcY;
	colorObj*	colorBuff;
	colorObj		aColor;
	
	colorBuff = (colorObj*)malloc(sizeof(colorObj)*sourceRect.width);	// Have a shot at grabbing aline buffer.
	if (colorBuff) {																	// We get one?
		for (int i=0;i<sourceRect.width;i++) {									// Initialize it with default color objects.
			colorBuff[i] = aColor;													// Stuffing in the i-th object.
		}
	}
	Serial.println("buffer allocated");Serial.flush();
	if (haveInfo) {																	// We have valid bmp info.
		bmpFile = SD.open(filePath);												// Open up the file.
		if (bmpFile) {																	// If we opened it.
			endY = y+sourceRect.height;											// Start calculating endpoints and things.
			srcY = sourceRect.y;
			for (trace=y; trace<endY;trace++) {									// Ready to pull data through to the screen.
				bmpFile.seek(filePtr(x,srcY++));									// Position the file pointer to the line of pixels we want.
				if (colorBuff) {														// Now, if we were able to allocate a buffer, we'll use it.
					drawLine(bmpFile,x,trace,colorBuff);						// Fancy buffered line draw.
				} else {																	// Ir if not..
					drawLine(bmpFile,x,trace);										// Standard old pixel by pixel draw. (Least it works.)
				}
			}
			bmpFile.close();															// Drawing is done for now. Close the file.
		}      
	}
	if (colorBuff) { free(colorBuff); }											// So if we did get that buffer free it.
}

What do your Serial debug prints report? Can you tell when and where things go off the rails?

Which screen? Which driver? Which library? Which Arduino?

Some screen drivers such as the RA8875 will take a continuous stream of bytes and put them into a rectangular window.

It gets to the point where the first line loop writes into it. That's the last message I get. Like I'm writing into random memory.

The screen (this time) is adafruit 1947 Their cap. touch screen I use a bunch of them. The other screen I use a lot is the Adafruit 1431. The 1947 uses an ILI9341, whereas the 1431 uses a SSD1351 drive chip. The processor is a Teensy 3.2 running at 72 Mhz.

I'm using the Adafruit libraries to talk to the hardware.

-jim lee

I have the Adafruit ILI9340 library. I've used it with several of their screens. I don't have the other one.

ILI9340 has a setAddrwindow() function and a pushColor(). Use those two together to send BMP data to the screen with the minimum possible overhead. The example spitftbitmap which comes with the library seems to do exactly what you are asking for.

Or is this a significant difference between ILI9340 and ILI9341?

Phew.. Not to that point yet. I've not done much at the hardware level, so the learning curve would be pretty steep. I'm working on tons of high level stuff right now. What happened was that I added a cool home screen feature, but it would draw so slowly, I thought the poor thing was broken. There are other ways to skin this cat. For now I pulled out the line buffer code and dropped the home screen image feature.

Back on course. But I'm really tired and heading off to sleep.

Thanks for looking at it.

-jim lee

Well, after all that hair pulling and nonsense. Finally got it working with an array of structs for using as a line buffer.

Then I timed it. It actually made the drawing SLOWER. Not by much, but certainly not worth the headache.

Sigh.. I had such high hopes!

It takes me 3.248 seconds to blit my 240x320 .bmp image to the screen (Of the same size).

-jim lee

But you are still using drawPixel(x, y, color). Of course it is slow.

You need pushColor() if it exists in the library you are using.

It doesn't, as far as I can tell. Also, it seems the chipset also supports inverse drawing rectangles and lines. That's the foundation of small CPU dragging and things. (that I can't have) So it's a little frustrating.

Oh well, for now I'll just make the best of it and move forwards.

-jim lee

Try to use something like:

display.beginWrite();

//Write pixels to the display

display.endWrite();

It may improve drawing performance. Also remember that there is a "display.writePixels()" method which takes an array of pixels rather than a single pixel, which may be a lot faster :slight_smile:

EDIT: I suppose you are using this library.

THANK YOU VERY MUCH FOR THAT TIP!!

Yes, that is the library I'm using.

I'd heard about the transaction thing, or at least rumors. Had no idea that it was actually something I could hook into. So, I rewrote my .bmp code to use it when it drew the array.

2.543 for my larger rectangle, original way with buffer.
2.308 using buffer and startWrite(), endWrite() and hooking my pixel from drawPixel() to writePixel(). I wonder if there's something like that for the SD library?

-jim lee

Dunno about the SD stuff, never used it. But mind that you can write an array of pixels using "display.writePixels(array, length)" which again should be faster than writing single pixels. Good luck :slight_smile: