Bug 970691 - Part2: Restore digit stamping function to YuvStamper. r=jesup

Refactor digit writing method to use the new internals. Allows digit string
to wrap through multiple lines in a small frame.
This commit is contained in:
Paul Kerr [:pkerr] 2014-04-23 10:03:18 -07:00
Родитель 7db94a6847
Коммит c45ebab36f
2 изменённых файлов: 323 добавлений и 26 удалений

Просмотреть файл

@ -8,6 +8,7 @@
#include <winsock2.h>
#endif
#include "nspr.h"
#include "YuvStamper.h"
typedef uint32_t UINT4; //Needed for r_crc32() call
@ -17,21 +18,235 @@ extern "C" {
namespace mozilla {
#define ON_5 0x20
#define ON_4 0x10
#define ON_3 0x08
#define ON_2 0x04
#define ON_1 0x02
#define ON_0 0x01
/*
0, 0, 1, 1, 0, 0,
0, 1, 0, 0, 1, 0,
1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1,
0, 1, 0, 0, 1, 0,
0, 0, 1, 1, 0, 0
*/
static unsigned char DIGIT_0 [] =
{ ON_3 | ON_2,
ON_4 | ON_1,
ON_5 | ON_0,
ON_5 | ON_0,
ON_5 | ON_0,
ON_4 | ON_1,
ON_3 | ON_2
};
/*
0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0,
0, 0, 0, 1, 0, 0,
*/
static unsigned char DIGIT_1 [] =
{ ON_2,
ON_2,
ON_2,
ON_2,
ON_2,
ON_2,
ON_2
};
/*
1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 0,
1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1,
*/
static unsigned char DIGIT_2 [] =
{ ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
ON_0,
ON_0,
ON_4 | ON_3 | ON_2 | ON_1,
ON_5,
ON_5,
ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
};
/*
1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 0,
*/
static unsigned char DIGIT_3 [] =
{ ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
ON_0,
ON_0,
ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_0,
ON_0,
ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
};
/*
0, 1, 0, 0, 0, 1,
0, 1, 0, 0, 0, 1,
0, 1, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1
*/
static unsigned char DIGIT_4 [] =
{ ON_4 | ON_0,
ON_4 | ON_0,
ON_4 | ON_0,
ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_0,
ON_0,
ON_0,
};
/*
0, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 0,
*/
static unsigned char DIGIT_5 [] =
{ ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_5,
ON_5,
ON_4 | ON_3 | ON_2 | ON_1,
ON_0,
ON_0,
ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
};
/*
0, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 0,
1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 0,
*/
static unsigned char DIGIT_6 [] =
{ ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_5,
ON_5,
ON_4 | ON_3 | ON_2 | ON_1,
ON_5 | ON_0,
ON_5 | ON_0,
ON_4 | ON_3 | ON_2 | ON_1,
};
/*
1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0
*/
static unsigned char DIGIT_7 [] =
{ ON_5 | ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_0,
ON_1,
ON_2,
ON_3,
ON_4,
ON_5
};
/*
0, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 0,
1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 0
*/
static unsigned char DIGIT_8 [] =
{ ON_4 | ON_3 | ON_2 | ON_1,
ON_5 | ON_0,
ON_5 | ON_0,
ON_4 | ON_3 | ON_2 | ON_1,
ON_5 | ON_0,
ON_5 | ON_0,
ON_4 | ON_3 | ON_2 | ON_1,
};
/*
0, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 0
*/
static unsigned char DIGIT_9 [] =
{ ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_5 | ON_0,
ON_5 | ON_0,
ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
ON_0,
ON_0,
ON_4 | ON_3 | ON_2 | ON_1,
};
static unsigned char *DIGITS[] = {
DIGIT_0,
DIGIT_1,
DIGIT_2,
DIGIT_3,
DIGIT_4,
DIGIT_5,
DIGIT_6,
DIGIT_7,
DIGIT_8,
DIGIT_9
};
YuvStamper::YuvStamper(uint8_t* pYData,
uint32_t width,
uint32_t height,
uint32_t stride,
uint32_t x,
uint32_t y):
uint32_t y,
uint8_t symbol_width,
uint8_t symbol_height):
pYData(pYData), mStride(stride),
mWidth(width), mHeight(height),
mSymbolWidth(symbol_width), mSymbolHeight(symbol_height),
mCursor(x, y) {}
bool YuvStamper::Encode(uint32_t width, uint32_t height, uint32_t stride,
uint8_t* pYData, uint8_t* pMsg, size_t msg_len,
uint32_t x, uint32_t y)
{
YuvStamper stamper(pYData, width, height, stride, x, y);
YuvStamper stamper(pYData, width, height, stride,
x, y, sBitSize, sBitSize);
// Reserve space for a checksum.
if (stamper.Capacity() < 8 * (msg_len + sizeof(uint32_t)))
@ -64,7 +279,9 @@ namespace mozilla {
uint8_t* pYData, uint8_t* pMsg, size_t msg_len,
uint32_t x, uint32_t y)
{
YuvStamper stamper(pYData, width, height, stride, x, y);
YuvStamper stamper(pYData, width, height, stride,
x, y, sBitSize, sBitSize);
uint8_t* ptr = pMsg;
size_t len = msg_len;
uint32_t crc, msg_crc;
@ -95,19 +312,19 @@ namespace mozilla {
inline uint32_t YuvStamper::Capacity()
{
// Enforce at least a symbol width and height offset from outer edges.
if (mCursor.y + sBitSize > mHeight) {
if (mCursor.y + mSymbolHeight > mHeight) {
return 0;
}
if (mCursor.x + sBitSize > mWidth && !AdvanceCursor()) {
if (mCursor.x + mSymbolWidth > mWidth && !AdvanceCursor()) {
return 0;
}
// Normalize frame integral to sBitSize x sBitSize
uint32_t width = mWidth / sBitSize;
uint32_t height = mHeight / sBitSize;
uint32_t x = mCursor.x / sBitSize;
uint32_t y = mCursor.y / sBitSize;
uint32_t width = mWidth / mSymbolWidth;
uint32_t height = mHeight / mSymbolHeight;
uint32_t x = mCursor.x / mSymbolWidth;
uint32_t y = mCursor.y / mSymbolHeight;
return (width * height - width * y)- x;
}
@ -129,8 +346,8 @@ namespace mozilla {
{
// A bit is mapped to a sBitSize x sBitSize square of luma data points.
uint8_t value = one ? sYOn : sYOff;
for (uint32_t y = 0; y < sBitSize; y++) {
for (uint32_t x = 0; x < sBitSize; x++) {
for (uint32_t y = 0; y < mSymbolHeight; y++) {
for (uint32_t x = 0; x < mSymbolWidth; x++) {
*(pYData + (mCursor.x + x) + ((mCursor.y + y) * mStride)) = value;
}
}
@ -140,14 +357,14 @@ namespace mozilla {
bool YuvStamper::AdvanceCursor()
{
mCursor.x += sBitSize;
if (mCursor.x + sBitSize > mWidth) {
mCursor.x += mSymbolWidth;
if (mCursor.x + mSymbolWidth > mWidth) {
// move to the start of the next row if possible.
mCursor.y += sBitSize;
if (mCursor.y + sBitSize > mHeight) {
mCursor.y += mSymbolHeight;
if (mCursor.y + mSymbolHeight > mHeight) {
// end of frame, do not advance
mCursor.y -= sBitSize;
mCursor.x -= sBitSize;
mCursor.y -= mSymbolHeight;
mCursor.x -= mSymbolWidth;
return false;
} else {
mCursor.x = 0;
@ -157,7 +374,8 @@ namespace mozilla {
return true;
}
bool YuvStamper::Read8(uint8_t &value) {
bool YuvStamper::Read8(uint8_t &value)
{
uint8_t octet = 0;
uint8_t bit = 0;
@ -176,15 +394,65 @@ namespace mozilla {
bool YuvStamper::ReadBit(uint8_t &bit)
{
uint32_t sum = 0;
for (uint32_t y = 0; y < sBitSize; y++) {
for (uint32_t x = 0; x < sBitSize; x++) {
for (uint32_t y = 0; y < mSymbolHeight; y++) {
for (uint32_t x = 0; x < mSymbolWidth; x++) {
sum += *(pYData + mStride * (mCursor.y + y) + mCursor.x + x);
}
}
// apply threshold to collected bit square
bit = (sum > (sBitThreshold * sBitSize * sBitSize)) ? 1 : 0;
bit = (sum > (sBitThreshold * mSymbolWidth * mSymbolHeight)) ? 1 : 0;
return AdvanceCursor();
}
bool YuvStamper::WriteDigits(uint32_t value)
{
char buf[20];
PR_snprintf(buf, sizeof(buf), "%.5u", value);
size_t size = strlen(buf);
if (Capacity() < size) {
return false;
}
for (size_t i=0; i < size; ++i) {
if (!WriteDigit(buf[i] - '0'))
return false;
if (!AdvanceCursor()) {
return false;
}
}
return true;
}
bool YuvStamper::WriteDigit(uint8_t digit) {
if (digit > sizeof(DIGITS)/sizeof(DIGITS[0]))
return false;
unsigned char *dig = DIGITS[digit];
for (uint32_t row = 0; row < sDigitHeight; ++row) {
unsigned char mask = 0x01 << (sDigitWidth - 1);
for (uint32_t col = 0; col < sDigitWidth; ++col, mask >>= 1) {
if (dig[row] & mask) {
for (uint32_t xx=0; xx < sPixelSize; ++xx) {
for (uint32_t yy=0; yy < sPixelSize; ++yy) {
WritePixel(pYData,
mCursor.x + (col * sPixelSize) + xx,
mCursor.y + (row * sPixelSize) + yy);
}
}
}
}
}
return true;
}
void YuvStamper::WritePixel(uint8_t *data, uint32_t x, uint32_t y) {
uint8_t *ptr = &data[y * mStride + x];
*ptr = (*ptr > sLumaThreshold) ? sLumaMin : sLumaMax;
return;
}
} // Namespace mozilla.

Просмотреть файл

@ -7,18 +7,37 @@ namespace mozilla {
class
YuvStamper {
public:
YuvStamper(uint8_t* pYData,
uint32_t width, uint32_t height, uint32_t stride,
uint32_t x = 0, uint32_t y = 0);
bool WriteDigits(uint32_t value);
template<typename T>
static bool Write(uint32_t width, uint32_t height, uint32_t stride,
uint8_t *pYData, const T& value,
uint32_t x=0, uint32_t y=0)
{
YuvStamper stamper(pYData, width, height, stride,
x, y,
(sDigitWidth + sInterDigit) * sPixelSize,
(sDigitHeight + sInterLine) * sPixelSize);
return stamper.WriteDigits(value);
}
static bool Encode(uint32_t width, uint32_t height, uint32_t stride,
uint8_t* pYData, uint8_t* pMsg, size_t msg_len,
uint32_t x, uint32_t y);
uint32_t x = 0, uint32_t y = 0);
static bool Decode(uint32_t width, uint32_t height, uint32_t stride,
uint8_t* pYData, uint8_t* pMsg, size_t msg_len,
uint32_t x, uint32_t y);
uint32_t x = 0, uint32_t y = 0);
private:
YuvStamper(uint8_t* pYData,
uint32_t width, uint32_t height, uint32_t stride,
uint32_t x, uint32_t y,
uint8_t symbol_width, uint8_t symbol_height);
bool WriteDigit(uint8_t digit);
void WritePixel(uint8_t* data, uint32_t x, uint32_t y);
uint32_t Capacity();
bool AdvanceCursor();
bool WriteBit(bool one);
@ -26,15 +45,25 @@ public:
bool ReadBit(uint8_t &value);
bool Read8(uint8_t &bit);
const static uint8_t sPixelSize = 3;
const static uint8_t sDigitWidth = 6;
const static uint8_t sDigitHeight = 7;
const static uint8_t sInterDigit = 1;
const static uint8_t sInterLine = 1;
const static uint32_t sBitSize = 4;
const static uint32_t sBitThreshold = 60;
const static uint8_t sYOn = 0x80;
const static uint8_t sYOff = 0;
const static uint8_t sLumaThreshold = 96;
const static uint8_t sLumaMin = 16;
const static uint8_t sLumaMax = 235;
uint8_t* pYData;
uint32_t mStride;
uint32_t mWidth;
uint32_t mHeight;
uint8_t mSymbolWidth;
uint8_t mSymbolHeight;
struct Cursor {
Cursor(uint32_t x, uint32_t y):