I used this link and added lots of enhancements related to GDI.
https://github.com/microsoft/Windows-driver-samples/tree/master/print/OEM%20Printer%20Customization%20Plug-in%20Samples/C%2B%2B/bitmap
The above samples generates a bitmap driver with output as a bitmap image. Now using the bitmap I am able to generate working PCL for monochrome. I need some help for enhancing it further to generate PCL for 16bpp, 24 color and gray scale
Can anyone suggest some samples where I could see the PCL commands written in C++?
The monochrome part works correctly but the remaining color or gray scale just produce a blank image. I am using GhostPCL to convert to jpeg for testing purposes.
Can anyone provide a sample for where given an appropriate bitmap there is some PCLstream as output?
If you can't provide an entire working sample, how about things in commands which need to be addressed.
The one obvious thing is the buffer, rowsize.
This is the PCL for monochrome.
https://mega.nz/file/rNlFFRYL#CDK_l6s9KojLzywI3drsO1yt_OaK7-n5TNWdj1x8Aa4
This is the PCL for TrueColor same document. Nothing is printed except text
https://mega.nz/file/jI0lXRxZ#DmjLiDlNR8CfisN9UsRgz0F-FwXgOC0DCkaRPxqYCh4
I am using ghostPCL to convert to jpeg.
Code for monochrome:
//Header
// Universal Exit
char bufUnivExit[10];
StringCchPrintfA(bufUnivExit, 10, "%c%s", 27, "%-12345X"); // 9 chars
MoveMemory(pOemPDEV->pBufStart, bufUnivExit, 10);
dwOffset += 9;
// PJL
char bufPJL[38];
StringCchPrintfA(bufPJL, 38, "%s%c%c", "#PJL COMMENT ROMFOBMAYCE TEST-PRINT", 13, 10); // 37 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufPJL, 38);
dwOffset += 37;
// PCL Esc
char bufEsc[3];
StringCchPrintfA(bufEsc, 3, "%c%s", 27, "E"); // 2 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufEsc, 3);
dwOffset += 2;
// Raster Res
char bufRes[8];
StringCchPrintfA(bufRes, 8, "%c%s%d%s", 27, "*t", pPubDM->dmYResolution, "R"); // 7 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufRes, 8);
dwOffset += 7;
// Units of Measure
char bufUOM[8];
StringCchPrintfA(bufUOM, 8, "%c%s%d%s", 27, "&u", pPubDM->dmYResolution, "D"); // 7 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufUOM, 8);
dwOffset += 7;
// Raster Presentation
char bufPres[6];
StringCchPrintfA(bufPres, 6, "%c%s", 27, "*r3F"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufPres, 6);
dwOffset += 5;
// Orientation
char bufOrient[6];
if (pPubDM->dmOrientation == 1)
orient = 0;
else
orient = 1;
StringCchPrintfA(bufOrient, 6, "%c%s%d%s", 27, "&l", orient, "O"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufOrient, 6);
dwOffset += 5;
// Paper Size
char bufPaperSize[6];
if (pPubDM->dmPaperSize == 1)
pageSize = 2;
else
pageSize = 3;
StringCchPrintfA(bufPaperSize, 6, "%c%s%d%s", 27, "&l", pageSize, "A"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufPaperSize, 6);
dwOffset += 5;
// Set horizontal and vertical registration (page margins)
char bufRegistration[14];
StringCchPrintfA(bufRegistration, 14, "%c%s", 27, "&l-180u-360Z"); // 13 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufRegistration, 14);
dwOffset += 13;
//Code for Page
BYTE bitmapRow[1050];
BYTE compRow[2100];
DWORD dwRowSize = 0;
DWORD dwCompPCLBitmapSize = 0;
for (i = 0; i < pso->sizlBitmap.cy; i++) {
// Zero Memory hack for bottom of form black line
if (*(((PBYTE &)pso->pvScan0) + (i * pso->lDelta) + 319) == 0xFF)
ZeroMemory(((PBYTE &)pso->pvScan0) + (i * pso->lDelta), 320);
// Copy the bitmap scan line into bitmapRow and send them off to be compressed
ZeroMemory(bitmapRow, 1050);
ZeroMemory(compRow, 2100);
MoveMemory(bitmapRow, ((PBYTE &)pso->pvScan0) + (i * pso->lDelta), pso->lDelta);
dwRowSize = CompressBitmapRow(compRow, bitmapRow, pso->lDelta);
// Create PCL Row Heading
char bufPCLLineHead[9];
StringCchPrintfA(bufPCLLineHead, 9, "%c%s%d%s", 27, "*b", dwRowSize, "W");
if ((dwCompPCLBitmapSize + dwRowSize + strlen(bufPCLLineHead))
> pOemPDEV->dwCompBitmapBufSize) {
if (!GrowCompBitmapBuf(pOemPDEV)) {
//ZeroMemory(traceBuff, 256);
//StringCchPrintf(traceBuff, 256,
// L"Compressed bitmap buffer could not allocate more memory.");
//WriteTraceLine(traceBuff);
}
}
if (pOemPDEV->pCompBitmapBufStart) {
// write the PCL line heading to the buffer
MoveMemory(pOemPDEV->pCompBitmapBufStart + dwCompPCLBitmapSize,
bufPCLLineHead, strlen(bufPCLLineHead));
dwCompPCLBitmapSize += strlen(bufPCLLineHead);
// write the compressed row to the buffer
MoveMemory(pOemPDEV->pCompBitmapBufStart + dwCompPCLBitmapSize,
compRow, dwRowSize);
dwCompPCLBitmapSize += dwRowSize;
}
}
// Calculate size and create buffer
dwPageBufferSize = 21;
if (!firstPage)
dwPageBufferSize++;
bGrowBuffer(pOemPDEV, dwPageBufferSize);
// Add all Raster Header Lines
if (!firstPage)
{
// Add a Form Feed
char bufFormFeed[2];
StringCchPrintfA(bufFormFeed, 2, "%c", 12); // 1 char
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufFormFeed, 2);
dwOffset += 1;
}
// Position cursor at X0, Y0
char bufXY[8];
StringCchPrintfA(bufXY, 8, "%c%s", 27, "*p0x0Y"); // 7 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufXY, 8);
dwOffset += 7;
// Start Raster Graphics
char bufStartRas[6];
StringCchPrintfA(bufStartRas, 6, "%c%s", 27, "*r1A"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufStartRas, 6);
dwOffset += 5;
// Raster Encoding - Run-Length Encoding
char bufRasEncoding[6];
StringCchPrintfA(bufRasEncoding, 6, "%c%s", 27, "*b1M"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufRasEncoding, 6);
dwOffset += 5;
// Write out bitmap header PCL
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, pOemPDEV->pBufStart, dwPageBufferSize);
// Write out PCL plus compressed bitmap bytes
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, pOemPDEV->pCompBitmapBufStart, dwCompPCLBitmapSize);
// End Raster Graphics
char bufEndRas[5];
StringCchPrintfA(bufEndRas, 5, "%c%s", 27, "*rB"); // 4 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufEndRas, 5);
// Write out PCL end bitmap
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, bufEndRas, 4);
Can anyone suggest? I don't have working knowledge of PCL or C++ except learning it like this.
Related
We have an old Print driver which takes a document and sends PCL to the spooler. The client then processes this PCL and displays everything as TIFF. Our users have been complaining that the TIFF is fuzzy and the image is not sharp. I am given this stupid task of solving the mystery
Is the PCL itself bad. I don't have enough knowledge about a PCL and if it has resolution. How do I trap the output of a driver that's being sent to the spooler?
Or is it the client that is somehow not rendering the PCL with a good resolution. Do I need to go through the pain of learning how to debug this driver. I will but is it going to help me fix a resolution issue. I have never done driver development so its going to be a curve for me. But if I need to do then thats ok. Where should I start? Is the PCL thats bad or the client that converts PCL to bitmap bad?
This is the C++ code
BOOL APIENTRY
CreatePCLRasterGraphicPage(
SURFOBJ *pso,
BOOL firstPage,
char *pageText
)
/*++
Routine Description:
Creates standard PCL end-of-document lines.
Arguments:
SURFOBJ - Surface Object
BOOL - First Page ?
char * Page Text
Return Value:
BOOL - True if successful
--*/
{
PDEVOBJ pDevObj = (PDEVOBJ)pso->dhpdev;
POEMPDEV pOemPDEV = (POEMPDEV)pDevObj->pdevOEM;
DWORD dwOffset = 0;
DWORD dwWritten = 0;
DWORD dwPageBufferSize = 0;
int i = 0;
ULONG n = 0;
BYTE bitmapRow[1050];
BYTE compRow[2100];
DWORD dwRowSize = 0;
DWORD dwCompPCLBitmapSize = 0;
//wchar_t traceBuff[256];
pOemPDEV->dwCompBitmapBufSize = 0;
// TRACE OUT ----------------------------------------------------
//ZeroMemory(traceBuff, 256);
//StringCchPrintf(traceBuff, 256, L"Top of CreatePCLRasterGraphicPage");
//WriteTraceLine(traceBuff);
// -----------------------------------------------------------------
// Invert color
for (n = 0; n < pso->cjBits; n++)
*(((PBYTE &)pso->pvBits) + n) ^= 0xFF;
// compress each row and store in a buffer with PCL line headings
for (i = 0; i < pso->sizlBitmap.cy; i++) {
// Zero Memory hack for bottom of form black line
if (*(((PBYTE &)pso->pvScan0) + (i * pso->lDelta) + 319) == 0xFF)
ZeroMemory(((PBYTE &)pso->pvScan0) + (i * pso->lDelta), 320);
// Copy the bitmap scan line into bitmapRow and send them off to be compressed
ZeroMemory(bitmapRow, 1050);
ZeroMemory(compRow, 2100);
MoveMemory(bitmapRow, ((PBYTE &)pso->pvScan0) + (i * pso->lDelta), pso->lDelta);
dwRowSize = CompressBitmapRow(compRow, bitmapRow, pso->lDelta);
// Create PCL Row Heading
char bufPCLLineHead[9];
StringCchPrintfA(bufPCLLineHead, 9, "%c%s%d%s", 27, "*b", dwRowSize, "W");
if ((dwCompPCLBitmapSize + dwRowSize + strlen(bufPCLLineHead))
> pOemPDEV->dwCompBitmapBufSize) {
if (!GrowCompBitmapBuf(pOemPDEV)) {
//ZeroMemory(traceBuff, 256);
//StringCchPrintf(traceBuff, 256,
// L"Compressed bitmap buffer could not allocate more memory.");
//WriteTraceLine(traceBuff);
}
}
if (pOemPDEV->pCompBitmapBufStart) {
// write the PCL line heading to the buffer
MoveMemory(pOemPDEV->pCompBitmapBufStart + dwCompPCLBitmapSize,
bufPCLLineHead, strlen(bufPCLLineHead));
dwCompPCLBitmapSize += strlen(bufPCLLineHead);
// write the compressed row to the buffer
MoveMemory(pOemPDEV->pCompBitmapBufStart + dwCompPCLBitmapSize,
compRow, dwRowSize);
dwCompPCLBitmapSize += dwRowSize;
}
}
// Calculate size and create buffer
dwPageBufferSize = 21;
if (!firstPage)
dwPageBufferSize++;
bGrowBuffer(pOemPDEV, dwPageBufferSize);
// Add all Raster Header Lines
if (!firstPage)
{
// Add a Form Feed
char bufFormFeed[2];
StringCchPrintfA(bufFormFeed, 2, "%c", 12); // 1 char
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufFormFeed, 2);
dwOffset += 1;
}
// Position cursor at X0, Y0
char bufXY[8];
StringCchPrintfA(bufXY, 8, "%c%s", 27, "*p0x0Y"); // 7 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufXY, 8);
dwOffset += 7;
// Start Raster Graphics
char bufStartRas[6];
StringCchPrintfA(bufStartRas, 6, "%c%s", 27, "*r1A"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufStartRas, 6);
dwOffset += 5;
// Raster Encoding - Run-Length Encoding
char bufRasEncoding[6];
StringCchPrintfA(bufRasEncoding, 6, "%c%s", 27, "*b1M"); // 5 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufRasEncoding, 6);
dwOffset += 5;
// Write out bitmap header PCL
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, pOemPDEV->pBufStart, dwPageBufferSize);
// Write out PCL plus compressed bitmap bytes
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, pOemPDEV->pCompBitmapBufStart, dwCompPCLBitmapSize);
// End Raster Graphics
char bufEndRas[5];
StringCchPrintfA(bufEndRas, 5, "%c%s", 27, "*rB"); // 4 chars
MoveMemory(pOemPDEV->pBufStart + dwOffset, bufEndRas, 5);
// Write out PCL end bitmap
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, bufEndRas, 4);
// Free Compressed Bitmap Memory
if (pOemPDEV->pCompBitmapBufStart) {
MemFree(pOemPDEV->pCompBitmapBufStart);
pOemPDEV->pCompBitmapBufStart = NULL;
pOemPDEV->dwCompBitmapBufSize = 0;
dwPageBufferSize = 0;
}
// Free Memory
vFreeBuffer(pOemPDEV);
// Write Page Text to the spooler
size_t charCount = 0;
StringCchLengthA(pageText, 32767, &charCount);
char bufWriteText[15];
ZeroMemory(bufWriteText, 15);
StringCchPrintfA(bufWriteText, 15, "%c%s%d%s", 27, "(r", charCount, "W");
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, bufWriteText, strlen(bufWriteText));
dwWritten = pDevObj->pDrvProcs->DrvWriteSpoolBuf(pDevObj, pageText, charCount);
return TRUE;
}
BOOL
GrowCompBitmapBuf(
POEMPDEV pOemPDEV
)
/*++
Routine Description:
Grows memory by 1000 bytes (per call) to hold compressed
bitmap and PCL data.
Arguments:
POEMPDEV - Pointer to the private PDEV structure
Return Value:
BOOL - True is successful
--*/
{
DWORD dwOldBufferSize = 0;
PBYTE pNewBuffer = NULL;
dwOldBufferSize = pOemPDEV->pCompBitmapBufStart ? pOemPDEV->dwCompBitmapBufSize : 0;
pOemPDEV->dwCompBitmapBufSize = dwOldBufferSize + 4096;
pNewBuffer = (PBYTE)MemAlloc(pOemPDEV->dwCompBitmapBufSize);
if (pNewBuffer == NULL) {
MemFree(pOemPDEV->pCompBitmapBufStart);
pOemPDEV->pCompBitmapBufStart = NULL;
pOemPDEV->dwCompBitmapBufSize = 0;
return FALSE;
}
if (pOemPDEV->pCompBitmapBufStart) {
CopyMemory(pNewBuffer, pOemPDEV->pCompBitmapBufStart, dwOldBufferSize);
MemFree(pOemPDEV->pCompBitmapBufStart);
pOemPDEV->pCompBitmapBufStart = pNewBuffer;
}
else {
pOemPDEV->pCompBitmapBufStart = pNewBuffer;
}
return TRUE;
}
RLE encoding (I have not had a chance to add this yet). I was looking at different forums as how the code should like and this is what I came up with. I will add, test the document and update the post
public virtual sbyte[] decompressRL(sbyte[] data, int startOffset, int width, int count)
{
/*type 1 compression*/
int dataCount = count;
List<sbyte> decompressed = new List<sbyte>();
int numberOfDecompressedBytes = 0;
int dataStartOffset = startOffset;
while (dataCount-- > 0)
{
int cntrlByte = (int) data[dataStartOffset++];
// Repeated pattern
int val = data[dataStartOffset++];
dataCount--;
while (cntrlByte >= 0)
{
decompressed.Insert(numberOfDecompressedBytes++, new sbyte?((sbyte) val));
cntrlByte--;
}
}
mMaxUncompressedByteCount = numberOfDecompressedBytes;
return getBytes(decompressed);
}
This is how fuzzy the users claim that the image looks. This is when printed from a word document to the driver. The original is very clear.
I am trying to extract frames from a stream which I create with Gstreamer and trying to save them with FreeImage or QImage ( this one is for testing ).
GstMapInfo bufferInfo;
GstBuffer *sampleBuffer;
GstStructure *capsStruct;
GstSample *sample;
GstCaps *caps;
int width, height;
const int BitsPP = 32;
/* Retrieve the buffer */
g_signal_emit_by_name (sink, "pull-sample", &sample);
if (sample) {
sampleBuffer = gst_sample_get_buffer(sample);
gst_buffer_map(sampleBuffer,&bufferInfo,GST_MAP_READ);
if (!bufferInfo.data) {
g_printerr("Warning: could not map GStreamer buffer!\n");
throw;
}
caps = gst_sample_get_caps(sample);
capsStruct= gst_caps_get_structure(caps,0);
gst_structure_get_int(capsStruct,"width",&width);
gst_structure_get_int(capsStruct,"height",&height);
auto bitmap = FreeImage_Allocate(width, height, BitsPP,0,0,0);
memcpy( FreeImage_GetBits( bitmap ), bufferInfo.data, width * height * (BitsPP/8));
// int pitch = ((((BitsPP * width) + 31) / 32) * 4);
// auto bitmap = FreeImage_ConvertFromRawBits(bufferInfo.data,width,height,pitch,BitsPP,0, 0, 0);
FreeImage_FlipHorizontal(bitmap);
bitmap = FreeImage_RotateClassic(bitmap,180);
static int id = 0;
std::string name = "/home/stadmin/pic/sample" + std::to_string(id++) + ".png";
#ifdef FREE_SAVE
FreeImage_Save(FIF_PNG,bitmap,name.c_str());
#endif
#ifdef QT_SAVE
//Format_ARGB32
QImage image(bufferInfo.data,width,height,QImage::Format_ARGB32);
image.save(QString::fromStdString(name));
#endif
fibPipeline.push(bitmap);
gst_sample_unref(sample);
gst_buffer_unmap(sampleBuffer, &bufferInfo);
return GST_FLOW_OK;
The color output in FreeImage are totally wrong like when Qt - Format_ARGB32 [ greens like blue or blues like oranges etc.. ] but when I test with Qt - Format_RGBA8888 I can get correct output. I need to use FreeImage and I wish to learn how to correct this.
Since you say Qt succeeds using Format_RGBA8888, I can only guess: the gstreamer frame has bytes in RGBA order while FreeImage expects ARGB.
Quick fix:
//have a buffer the same length of the incoming bytes
size_t length = width * height * (BitsPP/8);
BYTE * bytes = (BYTE *) malloc(length);
//copy the incoming bytes to it, in the right order:
int index = 0;
while(index < length)
{
bytes[index] = bufferInfo.data[index + 2]; //B
bytes[index + 1] = bufferInfo.data[index + 1]; //G
bytes[index + 2] = bufferInfo.data[index]; //R
bytes[index + 3] = bufferInfo.data[index + 3]; //A
index += 4;
}
//fill the bitmap using the buffer
auto bitmap = FreeImage_Allocate(width, height, BitsPP,0,0,0);
memcpy( FreeImage_GetBits( bitmap ), bytes, length);
//don't forget to
free(bytes);
I have a problem, I am sending some data from a PC C++ app with this structure from a visual studio app:
puerto1.WriteLine(rpm + ";" + gea + ":" + speed + ";;" + fuel + "::" + boost + ";;;" + rtemp + ":::" + atemp + ";;;;" + gas + "::::" + brk + ";;;;;");
And then on the Arduino, I parse it in 9 different strings and when I want to display it on a screen it reports the problem of the pic attached.
It works correctly sometimes, but it stopped working correctly a few days ago and it haven't returned to work properly, it should print the strings indepently like:
XXX
XXX
XXX
XXX
XXX
Not like the image.
Arduino code:
#include <UTFTGLUE.h>
UTFTGLUE myGLCD(0, A2, A1, A3, A4, A0);
extern uint8_t BigFont[];
String command;
String part1;
String part2;
String part3;
String part4;
String part5;
String part6;
String part7;
String part8;
String part9;
void setup() {
Serial.begin(9600);
myGLCD.InitLCD();
myGLCD.setFont(BigFont);
myGLCD.clrScr();
myGLCD.setColor(255, 255, 255);
myGLCD.setBackColor(0, 0, 0);
myGLCD.print("RPMs", 1, 10);
myGLCD.print("Gear", 1, 40);
myGLCD.print("Speed", 1, 70);
myGLCD.print("Fuel", 1, 100);
myGLCD.print("Boost", 1, 130);
myGLCD.print("Asphalt Temp", 1, 160);
myGLCD.print("Air Temp", 1, 190);
myGLCD.print("Gas", 1, 220);
myGLCD.print("Brake", 1, 250);
myGLCD.print("Engine Brake", 1, 280);
}
void loop() {
if (Serial.available()) {
char c = Serial.read();
if (c == '\n') {
parseCommand(command);
command = "";
} else {
command += c;
}
}
myGLCD.setColor(255, 255, 255);
myGLCD.setBackColor(0, 0, 0);
myGLCD.printNumI(val1, 5, 20);
myGLCD.print(part2, 5, 50);
myGLCD.printNumI(val3, 5, 80);
myGLCD.print(part4, 5, 110);
myGLCD.print(part5, 5, 140);
myGLCD.print(part6, 5, 170);
myGLCD.print(part7, 5, 200);
myGLCD.print(part8, 5, 230);
myGLCD.print(part9, 5, 260);
myGLCD.print(part10, 5, 290);
}
void parseCommand(String com) {
part1 = com.substring(0, com.indexOf(";"));
part2 = com.substring(com.indexOf(";") + 1, com.indexOf(":"));
part3 = com.substring(com.indexOf(":") + 1, com.indexOf(";;"));
part4 = com.substring(com.indexOf(";;") + 2, com.indexOf("::"));
part5 = com.substring(com.indexOf("::") + 2, com.indexOf(";;;"));
part6 = com.substring(com.indexOf(";;;") + 3, com.indexOf(":::"));
part7 = com.substring(com.indexOf(":::") + 3, com.indexOf(";;;;"));
part8 = com.substring(com.indexOf(";;;;") + 4, com.indexOf("::::"));
part9 = com.substring(com.indexOf("::::") + 4, com.indexOf(";;;;;"));
int val1 = part1.toInt();
int val3 = part3.toInt();
}
problem image
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!
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!
QString str = QString::number((double)i, 'd', 1);
painter->drawText(100 + i * 800/9 - 6, 910, 40, 40, 0, str );
I would like to increase fontSize to 2x what is showing?
You could try something like this (haven't compiled code to see if it works!):
QFont font = painter->font() ;
/* twice the size than the current font size */
font.setPointSize(font.pointSize() * 2);
/* set the modified font to the painter */
painter->setFont(font);
/* draw text etc. */
painter.drawText(....);
Figured it out:
QFont font;
font.setPixelSize(12);
for(int i = 0; i < 10; i++){
painter->drawLine(100, 100 + i * 800/9, 900, 100 + i * 800/9);
str = QString::number((double)9 - i, 'd', 1);
painter->setFont(font);
painter->drawText(75, 100 + i * 800/9 - 6, 40, 40, 1, str);
}
this is the easiest way
painter.setFont(QFont("times",22)); //22 is a number which you have to change