Jpeg dither added.
This commit is contained in:
parent
6fd0a07186
commit
2ba755e9b2
|
@ -0,0 +1,24 @@
|
|||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012 Adafruit Industries. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -95,7 +95,7 @@
|
|||
|
||||
#define DATA 0x0E8C0030
|
||||
|
||||
Inkplate::Inkplate(uint8_t _mode) : GFX(E_INK_WIDTH, E_INK_HEIGHT)
|
||||
Inkplate::Inkplate(uint8_t _mode) : Graphics(E_INK_WIDTH, E_INK_HEIGHT)
|
||||
{
|
||||
setDisplayMode(_mode);
|
||||
for (uint32_t i = 0; i < 256; ++i)
|
||||
|
|
|
@ -23,7 +23,7 @@ Graphics::Graphics(int16_t w, int16_t h)
|
|||
setTextColor(0xFFFF, 0xFFFF);
|
||||
setTextWrap(true);
|
||||
cp437(false);
|
||||
GraphicsFont = NULL;
|
||||
gfxFont = NULL;
|
||||
}
|
||||
|
||||
void Graphics::setRotation(uint8_t x)
|
||||
|
|
|
@ -57,15 +57,20 @@ class Image : virtual public Network
|
|||
static bool drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool dither, bool invert);
|
||||
|
||||
uint8_t pixelBuffer[800 * 4 + 5];
|
||||
uint8_t ditherBuffer[2][800 + 5];
|
||||
uint8_t ditherBuffer[2][800 + 20];
|
||||
uint8_t jpegDitherBuffer[18][18];
|
||||
int16_t blockW = 0, blockH = 0;
|
||||
int16_t lastY = -1;
|
||||
|
||||
uint8_t ditherPalette[256]; // 8 bit colors
|
||||
uint8_t palette[128]; // 2 3 bit colors per byte, _###_###
|
||||
|
||||
bool legalBmp(bitmapHeader *bmpHeader);
|
||||
|
||||
uint8_t ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted);
|
||||
uint8_t ditherGetPixelJpeg(uint8_t px, int x, int y, int w);
|
||||
uint8_t ditherGetPixelJpeg(uint8_t px, int i, int j, int x, int y, int w, int h);
|
||||
void ditherSwap(int w);
|
||||
void ditherSwapBlockJpeg(int x);
|
||||
|
||||
void readBmpHeader(uint8_t *buf, bitmapHeader *_h);
|
||||
void readBmpHeaderSd(SdFile *_f, bitmapHeader *_h);
|
||||
|
|
|
@ -5,6 +5,9 @@ uint8_t Image::ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted)
|
|||
if (paletted)
|
||||
px = ditherPalette[px];
|
||||
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
px = (uint16_t)px >> 1;
|
||||
|
||||
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][i] + px));
|
||||
|
||||
uint8_t newPixel = oldPixel & (getDisplayMode() == INKPLATE_1BIT ? B10000000 : B11100000);
|
||||
|
@ -22,21 +25,29 @@ uint8_t Image::ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted)
|
|||
return newPixel >> 5;
|
||||
}
|
||||
|
||||
uint8_t Image::ditherGetPixelJpeg(uint8_t px, int x, int y, int w)
|
||||
uint8_t Image::ditherGetPixelJpeg(uint8_t px, int i, int j, int x, int y, int w, int h)
|
||||
{
|
||||
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][x] + px));
|
||||
if (blockW == -1)
|
||||
{
|
||||
blockW = w;
|
||||
blockH = h;
|
||||
}
|
||||
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
px = (uint16_t)px >> 1;
|
||||
|
||||
uint16_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)px + (uint16_t)jpegDitherBuffer[j + 1][i + 1] +
|
||||
(j ? (uint16_t)0 : (uint16_t)ditherBuffer[0][x + i])));
|
||||
|
||||
uint8_t newPixel = oldPixel & (getDisplayMode() == INKPLATE_1BIT ? B10000000 : B11100000);
|
||||
uint8_t quantError = oldPixel - newPixel;
|
||||
|
||||
ditherBuffer[1][x + 0] += (quantError * 5) >> 4;
|
||||
if (x != w - 1)
|
||||
{
|
||||
ditherBuffer[0][x + 1] += (quantError * 7) >> 4;
|
||||
ditherBuffer[1][x + 1] += (quantError * 1) >> 4;
|
||||
}
|
||||
if (x != 0)
|
||||
ditherBuffer[1][x - 1] += (quantError * 3) >> 4;
|
||||
jpegDitherBuffer[j + 1 + 1][i + 0 + 1] += (quantError * 5) >> 4;
|
||||
|
||||
jpegDitherBuffer[j + 0 + 1][i + 1 + 1] += (quantError * 7) >> 4;
|
||||
jpegDitherBuffer[j + 1 + 1][i + 1 + 1] += (quantError * 1) >> 4;
|
||||
|
||||
jpegDitherBuffer[j + 1 + 1][i - 1 + 1] += (quantError * 3) >> 4;
|
||||
|
||||
return newPixel >> 5;
|
||||
}
|
||||
|
@ -48,4 +59,20 @@ void Image::ditherSwap(int w)
|
|||
ditherBuffer[0][i] = ditherBuffer[1][i];
|
||||
ditherBuffer[1][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Image::ditherSwapBlockJpeg(int x)
|
||||
{
|
||||
for (int i = 0; i < 18; ++i)
|
||||
{
|
||||
if (x + i)
|
||||
ditherBuffer[1][x + i - 1] += jpegDitherBuffer[blockH - 1 + 2][i];
|
||||
jpegDitherBuffer[i][0 + 1] = jpegDitherBuffer[i][blockW - 1 + 2];
|
||||
}
|
||||
for (int j = 0; j < 18; ++j)
|
||||
for (int i = 0; i < 18; ++i)
|
||||
if (i != 1)
|
||||
jpegDitherBuffer[j][i] = 0;
|
||||
|
||||
jpegDitherBuffer[17][1] = 0;
|
||||
}
|
|
@ -20,6 +20,11 @@ bool Image::drawJpegFromSd(SdFile *p, int x, int y, bool dither, bool invert)
|
|||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
blockW = -1;
|
||||
blockH = -1;
|
||||
lastY = -1;
|
||||
memset(ditherBuffer, 0, sizeof ditherBuffer);
|
||||
|
||||
TJpgDec.setJpgScale(1);
|
||||
TJpgDec.setCallback(drawJpegChunk);
|
||||
|
||||
|
@ -76,6 +81,13 @@ bool Image::drawJpegFromBuffer(uint8_t *buff, int32_t len, int x, int y, bool di
|
|||
{
|
||||
bool ret = 0;
|
||||
|
||||
blockW = -1;
|
||||
blockH = -1;
|
||||
lastY = -1;
|
||||
|
||||
TJpgDec.setJpgScale(1);
|
||||
TJpgDec.setCallback(drawJpegChunk);
|
||||
|
||||
if (TJpgDec.drawJpg(x, y, buff, len, dither, invert) == 0)
|
||||
ret = 1;
|
||||
|
||||
|
@ -87,20 +99,32 @@ bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t
|
|||
if (!_imagePtrJpeg)
|
||||
return 0;
|
||||
|
||||
if (dither && y != _imagePtrJpeg->lastY)
|
||||
{
|
||||
_imagePtrJpeg->ditherSwap(800);
|
||||
_imagePtrJpeg->lastY = y;
|
||||
}
|
||||
|
||||
_imagePtrJpeg->startWrite();
|
||||
for (int j = 0; j < h; ++j)
|
||||
{
|
||||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
uint16_t rgb = bitmap[j * w + i];
|
||||
uint8_t val = RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb));
|
||||
|
||||
uint8_t val;
|
||||
if (dither)
|
||||
val = _imagePtrJpeg->ditherGetPixelJpeg(RGB8BIT(RED(rgb), GREEN(rgb), BLUE(rgb)), i, j, x, y, w, h);
|
||||
else
|
||||
val = RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb));
|
||||
if (invert)
|
||||
val = 7 - val;
|
||||
|
||||
if (_imagePtrJpeg->getDisplayMode() == INKPLATE_1BIT)
|
||||
val = (~val >> 2) & 1;
|
||||
_imagePtrJpeg->writePixel(x + i, y + j, val);
|
||||
}
|
||||
}
|
||||
if (dither)
|
||||
_imagePtrJpeg->ditherSwapBlockJpeg(x);
|
||||
_imagePtrJpeg->endWrite();
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
#define RGB3BIT(r, g, b) ((54UL * (r) + 183UL * (g) + 19UL * (b)) >> 13)
|
||||
#define RGB8BIT(r, g, b) ((54UL * (r) + 183UL * (g) + 19UL * (b)) >> 8)
|
||||
|
||||
#define READ32(c) (uint32_t)(*(c) | (*((c) + 1) << 8) | (*((c) + 2) << 16) | (*((c) + 3) << 24));
|
||||
#define READ16(c) (uint16_t)(*(c) | (*((c) + 1) << 8));
|
||||
#define READ32(c) (uint32_t)(*(c) | (*((c) + 1) << 8) | (*((c) + 2) << 16) | (*((c) + 3) << 24))
|
||||
#define READ16(c) (uint16_t)(*(c) | (*((c) + 1) << 8))
|
||||
#define ROWSIZE(w, c) (((int16_t)c * w + 31) >> 5) << 2
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
#include "Inkplate.h"
|
||||
#include "SdFat.h"
|
||||
Inkplate display(INKPLATE_1BIT);
|
||||
Inkplate display(INKPLATE_3BIT);
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
@ -19,18 +19,9 @@ void loop()
|
|||
display.clearDisplay();
|
||||
display.display();
|
||||
|
||||
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
Serial.println(display.drawBitmapFromSd("Lenna.bmp", 0, 0, 0, 0));
|
||||
}
|
||||
display.display();
|
||||
|
||||
delay(5000);
|
||||
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
Serial.println(display.drawBitmapFromSd("Lenna.bmp", 0, 0, 1, 0));
|
||||
Serial.println(display.drawJpegFromSd("Lenna.jpg", 0, 0, 1, 0));
|
||||
}
|
||||
display.display();
|
||||
|
||||
|
|
Loading…
Reference in New Issue