mirror of
https://github.com/adafruit/Adafruit-GFX-Library.git
synced 2024-09-20 01:26:24 -04:00
Merge pull request #237 from michaelkamprath/master
Added support in GFXcanvas* classes to access pixel values
This commit is contained in:
commit
e4fcdba2b2
177
Adafruit_GFX.cpp
Executable file → Normal file
177
Adafruit_GFX.cpp
Executable file → Normal file
@ -1734,6 +1734,14 @@ bool Adafruit_GFX_Button::justReleased() { return (!currstate && laststate); }
|
||||
// scanline pad).
|
||||
// NOT EXTENSIVELY TESTED YET. MAY CONTAIN WORST BUGS KNOWN TO HUMANKIND.
|
||||
|
||||
#ifdef __AVR__
|
||||
// Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
|
||||
const uint8_t PROGMEM GFXcanvas1::GFXsetBit[] = {0x80, 0x40, 0x20, 0x10,
|
||||
0x08, 0x04, 0x02, 0x01};
|
||||
const uint8_t PROGMEM GFXcanvas1::GFXclrBit[] = {0x7F, 0xBF, 0xDF, 0xEF,
|
||||
0xF7, 0xFB, 0xFD, 0xFE};
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instatiate a GFX 1-bit canvas context for graphics
|
||||
@ -1763,18 +1771,10 @@ GFXcanvas1::~GFXcanvas1(void) {
|
||||
@brief Draw a pixel to the canvas framebuffer
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@param color 16-bit 5-6-5 Color to fill with
|
||||
@param color Binary (on or off) color to fill with
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
#ifdef __AVR__
|
||||
// Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
|
||||
static const uint8_t PROGMEM GFXsetBit[] = {0x80, 0x40, 0x20, 0x10,
|
||||
0x08, 0x04, 0x02, 0x01},
|
||||
GFXclrBit[] = {0x7F, 0xBF, 0xDF, 0xEF,
|
||||
0xF7, 0xFB, 0xFD, 0xFE};
|
||||
#endif
|
||||
|
||||
if (buffer) {
|
||||
if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height))
|
||||
return;
|
||||
@ -1812,10 +1812,67 @@ void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get the pixel color value at a given coordinate
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@returns The desired pixel's binary color value, either 0x1 (on) or 0x0
|
||||
(off)
|
||||
*/
|
||||
/**********************************************************************/
|
||||
bool GFXcanvas1::getPixel(int16_t x, int16_t y) const {
|
||||
int16_t t;
|
||||
switch (rotation) {
|
||||
case 1:
|
||||
t = x;
|
||||
x = WIDTH - 1 - y;
|
||||
y = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - 1 - x;
|
||||
y = HEIGHT - 1 - y;
|
||||
break;
|
||||
case 3:
|
||||
t = x;
|
||||
x = y;
|
||||
y = HEIGHT - 1 - t;
|
||||
break;
|
||||
}
|
||||
return getRawPixel(x, y);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get the pixel color value at a given, unrotated coordinate.
|
||||
This method is intended for hardware drivers to get pixel value
|
||||
in physical coordinates.
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@returns The desired pixel's binary color value, either 0x1 (on) or 0x0
|
||||
(off)
|
||||
*/
|
||||
/**********************************************************************/
|
||||
bool GFXcanvas1::getRawPixel(int16_t x, int16_t y) const {
|
||||
if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT))
|
||||
return 0;
|
||||
if (this->getBuffer()) {
|
||||
uint8_t *buffer = this->getBuffer();
|
||||
uint8_t *ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)];
|
||||
|
||||
#ifdef __AVR__
|
||||
return ((*ptr) & pgm_read_byte(&GFXsetBit[x & 7])) != 0;
|
||||
#else
|
||||
return ((*ptr) & (0x80 >> (x & 7))) != 0;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Fill the framebuffer completely with one color
|
||||
@param color 16-bit 5-6-5 Color to fill with
|
||||
@param color Binary (on or off) color to fill with
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void GFXcanvas1::fillScreen(uint16_t color) {
|
||||
@ -1854,7 +1911,7 @@ GFXcanvas8::~GFXcanvas8(void) {
|
||||
@brief Draw a pixel to the canvas framebuffer
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@param color 16-bit 5-6-5 Color to fill with
|
||||
@param color 8-bit Color to fill with. Only lower byte of uint16_t is used.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
@ -1884,10 +1941,58 @@ void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get the pixel color value at a given coordinate
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@returns The desired pixel's 8-bit color value
|
||||
*/
|
||||
/**********************************************************************/
|
||||
uint8_t GFXcanvas8::getPixel(int16_t x, int16_t y) const {
|
||||
int16_t t;
|
||||
switch (rotation) {
|
||||
case 1:
|
||||
t = x;
|
||||
x = WIDTH - 1 - y;
|
||||
y = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - 1 - x;
|
||||
y = HEIGHT - 1 - y;
|
||||
break;
|
||||
case 3:
|
||||
t = x;
|
||||
x = y;
|
||||
y = HEIGHT - 1 - t;
|
||||
break;
|
||||
}
|
||||
return getRawPixel(x, y);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get the pixel color value at a given, unrotated coordinate.
|
||||
This method is intended for hardware drivers to get pixel value
|
||||
in physical coordinates.
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@returns The desired pixel's 8-bit color value
|
||||
*/
|
||||
/**********************************************************************/
|
||||
uint8_t GFXcanvas8::getRawPixel(int16_t x, int16_t y) const {
|
||||
if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT))
|
||||
return 0;
|
||||
if (buffer) {
|
||||
return buffer[x + y * WIDTH];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Fill the framebuffer completely with one color
|
||||
@param color 16-bit 5-6-5 Color to fill with
|
||||
@param color 8-bit Color to fill with. Only lower byte of uint16_t is used.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void GFXcanvas8::fillScreen(uint16_t color) {
|
||||
@ -1993,6 +2098,54 @@ void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get the pixel color value at a given coordinate
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@returns The desired pixel's 16-bit 5-6-5 color value
|
||||
*/
|
||||
/**********************************************************************/
|
||||
uint16_t GFXcanvas16::getPixel(int16_t x, int16_t y) const {
|
||||
int16_t t;
|
||||
switch (rotation) {
|
||||
case 1:
|
||||
t = x;
|
||||
x = WIDTH - 1 - y;
|
||||
y = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - 1 - x;
|
||||
y = HEIGHT - 1 - y;
|
||||
break;
|
||||
case 3:
|
||||
t = x;
|
||||
x = y;
|
||||
y = HEIGHT - 1 - t;
|
||||
break;
|
||||
}
|
||||
return getRawPixel(x, y);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get the pixel color value at a given, unrotated coordinate.
|
||||
This method is intended for hardware drivers to get pixel value
|
||||
in physical coordinates.
|
||||
@param x x coordinate
|
||||
@param y y coordinate
|
||||
@returns The desired pixel's 16-bit 5-6-5 color value
|
||||
*/
|
||||
/**********************************************************************/
|
||||
uint16_t GFXcanvas16::getRawPixel(int16_t x, int16_t y) const {
|
||||
if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT))
|
||||
return 0;
|
||||
if (buffer) {
|
||||
return buffer[x + y * WIDTH];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Fill the framebuffer completely with one color
|
||||
|
@ -310,6 +310,7 @@ public:
|
||||
~GFXcanvas1(void);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
bool getPixel(int16_t x, int16_t y) const;
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get a pointer to the internal buffer memory
|
||||
@ -318,8 +319,16 @@ public:
|
||||
/**********************************************************************/
|
||||
uint8_t *getBuffer(void) const { return buffer; }
|
||||
|
||||
protected:
|
||||
bool getRawPixel(int16_t x, int16_t y) const;
|
||||
|
||||
private:
|
||||
uint8_t *buffer;
|
||||
|
||||
#ifdef __AVR__
|
||||
// Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR
|
||||
static const uint8_t PROGMEM GFXsetBit[], GFXclrBit[];
|
||||
#endif
|
||||
};
|
||||
|
||||
/// A GFX 8-bit canvas context for graphics
|
||||
@ -330,6 +339,7 @@ public:
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
uint8_t getPixel(int16_t x, int16_t y) const;
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get a pointer to the internal buffer memory
|
||||
@ -338,6 +348,9 @@ public:
|
||||
/**********************************************************************/
|
||||
uint8_t *getBuffer(void) const { return buffer; }
|
||||
|
||||
protected:
|
||||
uint8_t getRawPixel(int16_t x, int16_t y) const;
|
||||
|
||||
private:
|
||||
uint8_t *buffer;
|
||||
};
|
||||
@ -350,6 +363,7 @@ public:
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
void byteSwap(void);
|
||||
uint16_t getPixel(int16_t x, int16_t y) const;
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Get a pointer to the internal buffer memory
|
||||
@ -358,6 +372,9 @@ public:
|
||||
/**********************************************************************/
|
||||
uint16_t *getBuffer(void) const { return buffer; }
|
||||
|
||||
protected:
|
||||
uint16_t getRawPixel(int16_t x, int16_t y) const;
|
||||
|
||||
private:
|
||||
uint16_t *buffer;
|
||||
};
|
||||
|
72
examples/GFXcanvas/GFXcanvas.ino
Normal file
72
examples/GFXcanvas/GFXcanvas.ino
Normal file
@ -0,0 +1,72 @@
|
||||
/***
|
||||
This example is intended to demonstrate the use of getPixel() versus
|
||||
getRawPixel() in the GFXcanvas family of classes.
|
||||
|
||||
When using the GFXcanvas* classes as the image buffer for a hardware driver,
|
||||
there is a need to get individual pixel color values at given physical
|
||||
coordinates. Rather than subclasses or client classes call getBuffer() and
|
||||
reinterpret the byte layout of the buffer, two methods are added to each of the
|
||||
GFXcanvas* classes that allow fetching of specific pixel values.
|
||||
|
||||
* getPixel(x, y) : Gets the pixel color value at the rotated coordinates in
|
||||
the image.
|
||||
* getRawPixel(x,y) : Gets the pixel color value at the unrotated coordinates
|
||||
in the image. This is useful for getting the pixel value to map to a hardware
|
||||
pixel location. This method was made protected as only the hardware driver
|
||||
should be accessing it.
|
||||
|
||||
The GFXcanvasSerialDemo class in this example will print to Serial the contents
|
||||
of the underlying GFXcanvas buffer in both the current rotated layout and the
|
||||
underlying physical layout.
|
||||
***/
|
||||
|
||||
#include "GFXcanvasSerialDemo.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// first create a rectangular GFXcanvasSerialDemo object and draw to it
|
||||
GFXcanvasSerialDemo demo(21, 11);
|
||||
|
||||
demo.fillScreen(0x00);
|
||||
demo.setRotation(1); // now canvas is 11x21
|
||||
demo.fillCircle(5, 10, 5, 0xAA);
|
||||
demo.writeLine(0, 0, 10, 0, 0x11);
|
||||
demo.writeLine(0, 10, 10, 10, 0x22);
|
||||
demo.writeLine(0, 20, 10, 20, 0x33);
|
||||
demo.writeLine(0, 0, 0, 20, 0x44);
|
||||
demo.writeLine(10, 0, 10, 20, 0x55);
|
||||
|
||||
Serial.println("Demonstrating GFXcanvas rotated and raw pixels.\n");
|
||||
|
||||
// print it out rotated
|
||||
|
||||
Serial.println("The canvas's content in the rotation of '0':\n");
|
||||
demo.setRotation(0);
|
||||
demo.print(true);
|
||||
Serial.println("\n");
|
||||
|
||||
Serial.println("The canvas's content in the rotation of '1' (which is what "
|
||||
"it was drawn in):\n");
|
||||
demo.setRotation(1);
|
||||
demo.print(true);
|
||||
Serial.println("\n");
|
||||
|
||||
Serial.println("The canvas's content in the rotation of '2':\n");
|
||||
demo.setRotation(2);
|
||||
demo.print(true);
|
||||
Serial.println("\n");
|
||||
|
||||
Serial.println("The canvas's content in the rotation of '3':\n");
|
||||
demo.setRotation(3);
|
||||
demo.print(true);
|
||||
Serial.println("\n");
|
||||
|
||||
// print it out unrotated
|
||||
Serial.println("The canvas's content in it's raw, physical layout:\n");
|
||||
demo.print(false);
|
||||
Serial.println("\n");
|
||||
}
|
||||
|
||||
void loop() {}
|
32
examples/GFXcanvas/GFXcanvasSerialDemo.cpp
Normal file
32
examples/GFXcanvas/GFXcanvasSerialDemo.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "GFXcanvasSerialDemo.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
GFXcanvasSerialDemo::GFXcanvasSerialDemo(uint16_t w, uint16_t h)
|
||||
: GFXcanvas8(w, h) {}
|
||||
|
||||
void GFXcanvasSerialDemo::print(bool rotated) {
|
||||
char pixel_buffer[8];
|
||||
uint16_t width, height;
|
||||
|
||||
if (rotated) {
|
||||
width = this->width();
|
||||
height = this->height();
|
||||
} else {
|
||||
width = this->WIDTH;
|
||||
height = this->HEIGHT;
|
||||
}
|
||||
|
||||
for (uint16_t y = 0; y < height; y++) {
|
||||
for (uint16_t x = 0; x < width; x++) {
|
||||
uint8_t pixel;
|
||||
if (rotated) {
|
||||
pixel = this->getPixel(x, y);
|
||||
} else {
|
||||
pixel = this->getRawPixel(x, y);
|
||||
}
|
||||
sprintf(pixel_buffer, " %02x", pixel);
|
||||
Serial.print(pixel_buffer);
|
||||
}
|
||||
Serial.print("\n");
|
||||
}
|
||||
}
|
25
examples/GFXcanvas/GFXcanvasSerialDemo.h
Normal file
25
examples/GFXcanvas/GFXcanvasSerialDemo.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __GFXcanvasSerialDemo__
|
||||
#define __GFXcanvasSerialDemo__
|
||||
#include <Adafruit_GFX.h>
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Demonstrates using the GFXconvas classes as the backing store
|
||||
for a device driver.
|
||||
*/
|
||||
/**********************************************************************/
|
||||
class GFXcanvasSerialDemo : public GFXcanvas8 {
|
||||
public:
|
||||
GFXcanvasSerialDemo(uint16_t w, uint16_t h);
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Prints the current contents of the canvas to Serial
|
||||
@param rotated true to print according to the current GFX rotation,
|
||||
false to print to the native rotation of the canvas (or unrotated).
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void print(bool rotated);
|
||||
};
|
||||
|
||||
#endif // __GFXcanvasSerialDemo__
|
Loading…
Reference in New Issue
Block a user