Using CIMG and JAGPDF to print a grid - c++

I need to print a grid like the one in the photo on a PDF document
I am using CIMG to create the image in bmp, then save it as jpg and paste it in the PDF using JagPDF
The code for the graph is as follows:
int lineseparation=3;
int lineseparationbold=lineseparation*5;
CImg<unsigned char> graph1;
graph1.assign(50*lineseparationbold+1, 28*lineseparationbold+1, 1, 3, 255);
static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 };
static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 }, gray[] = { 220, 220, 220 };
static const unsigned char red[] = { 255, 200, 200 }, bred[] = { 255, 100, 100 };
graph1.draw_grid(lineseparation, lineseparation, 0, 0, false, true, red, 10.0f, 0xFFFFFFFF, 0xFFFFFFFF);
graph1.draw_grid(lineseparationbold, lineseparationbold, 0, 0, false, true, bred, 10.0f, 0xFFFFFFFF, 0xFFFFFFFF);
graph.save("plot.bmp");
Then after saving it as JPG I put it in the PDF using jagPDF this way:
pdf::Document doc(pdf::create_file("report.pdf"));
doc.page_start(pagewidth, pageheight);
pdf::Image imag2 = doc.image_load_file("plot1.jpg");
doc.page().canvas().image(imag2, 10, 50);
doc.page_end();
doc.finalize();
I need the grid to be 1mm separation between the lines (5mm the bold ones), when I put 3 pixels as separation when I print it is a little more than 1mm and if I put 2 pixels then is less than 1mm.
Putting non integers (e.g int lineseparation=2.9;) as input allow me to get bold lines closer to 5mm but the small lines are uneven. Saving the figure as BMP and resizing it is messing with the grid.
How can I make it print in the correct size?
Note: BMP and JPG have same size in pixels. I do the convertion without any resizing (although I tried that too).

Related

Custom background color per item?

I have a Fl_Choice with few options, for example:
Fl_Choice* o = new Fl_Choice(70, 100, 240, 25, "Some Options:");
o->add("Blue");
o->add("Black");
o->add("Orange");
o->add("Purple");
I did like to set a custom color for the background of each item while leaving the foreground color to white.
How do I set a custom background per item?
NOTE: I am using v90, not sure what tag I should use for that one or if vs2008 is sufficient, kindly remove this note if its sufficient as is or drop me a comment with what other tag I should add.
Not so easy to set the background colour but you can set the foreground colour
Fl_Menu_Item choices[] =
{
// ,-- The colour
{"red",0,(Fl_Callback*)0, (void*) 0, 0, 0, 0, 0, 0xFF000000},
{"blue",0,(Fl_Callback*)0, (void*) 0, 0, 0, 0, 0, 0x0000FF00},
{"green",0,(Fl_Callback*)0, (void*) 0, 0, 0, 0, 0, 0x00FF0000},
{"yellow",0,(Fl_Callback*)0, (void*) 0, 0, 0, 0, 0, 0xFFFF0000},
{0}
};
...
Fl_Choice *c = new Fl_Choice(50,250,200,25);
c->menu(choices);
Alternatively, you can derive from Fl_Choice if you don't want so many zeros
class ColourChoice: public Fl_Choice
{
public:
ColourChoice(int x, int y, int w, int h, const char* l = 0)
: Fl_Choice(x, y, w, h, l)
{
}
void add(const char* text, Fl_Color color)
{
Fl_Choice::add(text);
Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(find_item(text));
item->labelcolor(color);
}
};
...
ColourChoice* c = new ColourChoice(...);
c->add("purple", (Fl_Color)0xFF00FF00);

CImg get_crop() returns wrong pixels / getting a subimage of CImg

I am trying to get a subimage of a CImg. As I understand the method get_crop() does what I need, but the subimages that I get do not contain the pixel values I expected them to have.
unsigned char* StringTextureGenerator::GetTexture(int &width, int &height)
{
cil::CImg<unsigned char>* tmp = new cil::CImg<unsigned char>(512, 512, 1, 4);
*tmp = _alphabet.get_crop(0, 0, 0, 0, 511, 511, 0, 3);
width = tmp->width();
height = tmp->height();
return tmp->data();
}
The _alphabet CImg is 512x512x1x4 and contains an rgba image. For a test I am trying to get the whole the image x = 0 - 511, y = 0 - 511.
The result is this:
This is the expected outcome. I got the whole image as I loaded it from the file.
But when I try to get a sub-image, strange things do happen.
unsigned char* StringTextureGenerator::GetTexture(int &width, int &height)
{
cil::CImg<unsigned char>* tmp = new cil::CImg<unsigned char>(256, 256, 1, 4);
*tmp = _alphabet.get_crop(0, 0, 0, 0, 255, 255, 0, 3);
width = tmp->width();
height = tmp->height();
return tmp->data();
}
Here I am getting the pixels x = 0 - 255, y = 0 - 255, which I expect to be the top left quarter of the picture.
The result is this:
As you can see I get the top left quarter of every 128x128 block. Which is not what I wanted.
Not sure what is going on with your code, but this works fine on my machine. I am using CImg v169. I use this as a test image:
And run this code:
#include <iostream>
#include "CImg.h"
using namespace cimg_library;
int main()
{
CImg<unsigned char> alphabet = CImg<unsigned char>("alphabet.png");
CImg<unsigned char> tmp = CImg<unsigned char>(512, 512, 1, 4);
//tmp = alphabet.get_crop(0, 0, 0, 0, 511, 511, 0, 3);
tmp = alphabet.get_crop(0, 0, 0, 0, 255, 255, 0, 3);
tmp.save_png("result.png");
}
And get this, which looks correct to me:
I am compiling with options:
-Dcimg_use_png -lpng -lz

RaphaelJS image clip-rect not working

In this jsfiddle I have a Raphael canvas with two images. The first one is the complete image (not clipped) and the second one is the same image but clipped. For some reason the second image is not showing up. What's wrong with this code?
javascript:
var paper = Raphael(document.getElementById('canvas'));
var img = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png', 0, 0, 480, 259 );
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png', 0, 300, 40, 40 );
img2.attr({'clip-rect': "0,0,40,40" });
You made two mistakes.
First: You scaled your image down. Change
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png',
0, 300, 40, 40 );
to
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png',
0, 300, 480, 259 );
Second: You used the wrong clipping coordinates. Change
img2.attr({'clip-rect': "0,0,40,40" });
to
img2.attr({'clip-rect': "0,300,40,40" });
see your edited fiddle here.

Drawing in-memory 8-bit greyscale image buffer to screen using wxWidgets

I would like to draw 8-bit grayscale image data to a wxPaintDC, but I have been having trouble. The data is made available to me in a uint8_t array. See the non-working code below (this is one of several attempts). I am able to draw using other wxPaintDC::Draw* functions, so I believe that everything else is set up fine.
uint8_t testBuffer[] =
{
250, 220, 222, 223, 210,
186, 22, 29, 89, 110,
250, 220, 222, 203, 210,
240, 120, 220, 123, 210,
230, 210, 252, 223, 210
};
wxBitmap cameraImage(5, 5, 8);
wxNativePixelData cameraImageData(cameraImage);
wxNativePixelData::Iterator p(cameraImageData);
for(unsigned y = 0; y < 5; ++y)
{
wxNativePixelData::Iterator rowStart = p;
for(unsigned x = 0; x < 5; ++x, ++p)
{
uint8_t value = testBuffer[5 * y + x];
p.Red() = value;
p.Green() = value;
p.Blue() = value;
}
p = rowStart;
p.OffsetY(cameraImageData, 1);
}
// _dialogDrawingCanvas is a wxPaintDC*
_dialogDrawingCanvas->DrawBitmap(cameraImage, 50, 50);
EDIT
I looked at wxImage based on the suggestion made by Thomas Matthews. Using wxImage works when I use testBuffer, but not when I use the actual buffer.
This works:
uint8_t testBuffer[] =
{
250, 220, 222, 223, 210,
186, 22, 29, 89, 110,
250, 220, 222, 203, 210,
240, 120, 220, 123, 210,
230, 210, 252, 223, 210
};
wxImage image(5, 5, testBuffer, true);
wxBitmap bmp(image);
_dialogDrawingCanvas->DrawBitmap(bmp, 50, 50);
However, the code below does not. I get a crash in the wxBitmap ctor.
// Returns instance of a class that provides access to camera image.
CameraImage camImage = grabCameraImage();
uint8_t* buf = camImage.getBuffer();
wxImage image(camImage.getWidth(), camImage.getHeight(), buf, true);
wxBitmap bmp(image); // Crashes here.
_dialogDrawingCanvas->DrawBitmap(bmp, 50, 50);
The crash I get is:
First-chance exception at 0x000007fdcf824b5b in [redacted].exe: 0xC0000005: Access violation reading location 0x000000000304d27a.
Unhandled exception at 0x000007fdcf824b5b in [redacted].exe: 0xC000041D: An unhandled exception was encountered during a user callback.
EDIT 2
I linked the wxWidgets DLL to its source code and traced into the call to the wxBitmap ctor. It looks like it's expecting at least 24BPP and starts reading at the end of the wxImage buffer and goes backwards so it's crashing as soon as it tries to access what it thinks is the last 3 bytes of the buffer. It looks like the depth argument to the wxBitmap constructor is ignored. I think maybe this wasn't an issue with testBuffer because it was a fixed size array.
This is basically answered in my edits, but the problem was caused by using 8 BPP data in the buffer. I was able to accomplish what I wanted to do as follows:
CameraImage camImage = grabCameraImage();
wxImage image(camImage.getWidth(), camImage.getHeight());
const uint8_t* cameraBuffer = camImage.getBuffer();
for(uint16_t y = 0; y < camImage.getHeight(); ++y)
{
for(uint16_t x = 0; x < camImage.getWidth(); ++x)
{
uint8_t intensity = cameraBuffer[y * camImage.getWidth() + x];
image.SetRGB(x, y, intensity, intensity, intensity);
}
}
wxBitmap bmp(image, 8);
_dialogDrawingCanvas->DrawBitmap(bmp, 50, 50);

Filling a Partially Rounded Rectangle with GDI+

I have a rounded rectangle that I make like so
dc.RoundRect(textBorder, CPoint(20, 20));
Later on I draw a line through it about 1/3 of the way down.
dc.LineTo(textBorder.right, textBorder.top + 15);
Now I would like to fill just the part above the line with a solid color. In other words I need to fill a partially rounded rectangle, because the top of the rectangle is rounded, but the bottom of it is truncated by the line. Is there an easy way to do this?
Have you tried using a combination of CreateRoundRectRegion and then FillRgn to fill the non-rectangular area?
This the example given in the docs for CreateRoundRectRegion:
CRgn rgnA, rgnB, rgnC;
VERIFY(rgnA.CreateRoundRectRgn( 50, 50, 150, 150, 30, 30 ));
VERIFY(rgnB.CreateRoundRectRgn( 200, 75, 250, 125, 50, 50 ));
VERIFY(rgnC.CreateRectRgn( 0, 0, 50, 50 ));
int nCombineResult = rgnC.CombineRgn( &rgnA, &rgnB, RGN_OR );
ASSERT( nCombineResult != ERROR && nCombineResult != NULLREGION );
CBrush brA, brB, brC;
VERIFY(brA.CreateSolidBrush( RGB(255, 0, 0) ));
VERIFY(pDC->FillRgn( &rgnA, &brA)); // rgnA Red Filled
VERIFY(brB.CreateSolidBrush( RGB(0, 255, 0) ));
VERIFY(pDC->FillRgn( &rgnB, &brB)); // rgnB Green Filled
VERIFY(brC.CreateSolidBrush( RGB(0, 0, 255) )); // rgnC Blue
VERIFY(pDC->FrameRgn( &rgnC, &brC, 2, 2 ));
In general, when you want to do something with non-rectangular areas you have to start looking into regions.