Drawing App, How to Erase - drawing

(I'm a newbie in AS3) I found a usefull code here http://www.flashandmath.com/advanced/smoothdraw/ and I'm trying to create an Erase button, I'm trying to use .cacheAsBitmap = true; but this work only if there is a mask(I saw this on some AS2 app where you can erase a bitmap then you can redraw).
P.S. I changed the code slightly to change the background now the drawBackgroundfunction look like this:
function drawBackground():void {
//We draw a background with a very subtle gradient effect so that the canvas darkens towards the edges.
var mesh:Shape = new Shape();
var gradMat:Matrix = new Matrix();
gradMat.createGradientBox(700,500,0,0,0);
var bg:Sprite = new Sprite();
mesh.graphics.beginBitmapFill(new lignes(), null, true, false);
//bg.graphics.beginGradientFill("radial",[0xDDD0AA,0xC6B689],[1,1],[1,255],gradMat);
//bg.graphics.drawRect(0,0,700,500);
//bg.graphics.endFill();
mesh.graphics.drawRect(0, 0, 700, 500);
mesh.graphics.endFill();
boardBitmapData.draw(mesh);
mesh.cacheAsBitmap = true;
//We clear out the undo buffer with a copy of just a blank background:
undoStack = new Vector.<BitmapData>;
var undoBuffer:BitmapData = new BitmapData(boardWidth, boardHeight, false);
undoBuffer.copyPixels(boardBitmapData,undoBuffer.rect,new Point(0,0));
undoStack.push(undoBuffer);
}
I just want to create an Erase methode, thanks for your help
Edit: I meant to erase only the clicked area

To clean the Shape Try:
mesh.graphics.clear();
To clean the Shape object. I don't know what else you are doing with the boardBitmapData variable, maybe will be necessary to do something about as well.
clear() - Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings.

You need convert your canvas in bitmap, then use a mask to delete or blend mode ERASE, and to draw again create a new bitmap from the masked bitmap and finally use this as background.

Related

Qt - Adding a drawing to a Layout

I'm trying to make an application where the user can input some drawings (gestures) that will then be saved and displayed in a gallery on the top of the screen:
When the user presses "Validate", the drawing is supposed to be displayed on the scroll area on the top. However, for some reason, my code is not working the way I intended it to. It saves the drawing with no problem, but when I tell it to add it to the top, nothing happens.
Code here:
void MainWindow::galleryUpdate()
{
for (int i = 0; i < gestureTemplates.size(); i++)
{
QPolygonF scaledGesture = gestureTemplates[i].scaleToSquare(gestureTemplates[i]);
StrokeDrawer * strD = new StrokeDrawer();
QPalette Pal(palette());
Pal.setColor(QPalette::Background, Qt::white);
strD->setMinimumSize(50, 50);
strD->setAutoFillBackground(true);
strD->setPalette(Pal);
galleryList.append(strD);
topZone->addWidget(strD);
strD->setStroke(scaledGesture);
}
}
gestureTemplates is a vector of GestureTemplate (a custom class inheriting from QPolygonF) containing all the drawings. The first line inside the for simply scales the drawing to fit in a square, and returns a QPolygonF.
StrokeDrawer is the class used to display the drawing (code below). I then try to fill it with a white background, save it to galleryList which is a list of StrokeDrawer for each drawing, and then add it to the top, by using topZone->addWidget(strD), where topZone is a HBoxLayout.
I also use the setStroke method to set the drawing to the StrokeDrawer (this method also calls the update() function in the class, which calls its paintEvent, which should take care of actually drawing the QPolygonF).
Initially, I tried to do addWidget by directly using the QPolygonF but that didn't work. That's why I'm using this StrokeDrawer class (which just displays the drawing, it doesn't even allow making changes to it).
By debugging the code on QtCreator, everything works fine until the addWidget line, where nothing happens. I mean, even if the drawing is not being correctly displayed, it should at least show a small, white, 50x50 square, or am I missing something here?
Some code for StrokeDrawer:
void StrokeDrawer::setStroke(QPolygonF g)
{
gesture = g;
update();
}
void StrokeDrawer::paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QPainter pait(this);
if (!gesture.empty())
pait.drawPolyline(gesture);
}

SDL Resetting Surfaces

I draw some text to a surface (using SDL_ttf) and then I want to change the text on the surface. If I just redraw the surface the text does not go away. I have looked at several forum posts on how to fix the problem but I just cannot seem to figure it out. In particular I cannot understand why this solution does not work: (code is long so this just gives the essentials)
In Class file declared:
SDL_Surface* box; // These two are initialised to the
SDL_Surface* boxCopy; // same image
At the start of my render function:
*box = *boxCopy; \\Reset box surface
My understanding of pointers and C++ (which is admittedly limited) suggests that this should make the surface pointed at by box equal to the surface pointed at by boxCopy. Instead the boxCopy surface becomes a copy of box. I have no idea how boxCopy can be changed by this line of code but it seems like that is what is happening.
I'm not sure i completely understand your problem but hopefully this can help.. It's easier to update the text whenever the surface it's drawn on is to be updated rather than updating it whenever the actual text is updated. It might not be as optimized performance wise but i would say it's easier in most cases.
A typical program loop would include a re-rendering of a surface representing the screen followed by an SDL_Flip of this surface. You can of course optimize your re-rendering so you only render what has actually been updated since last frame. Is that what you're working on perhaps? If so, and if you use the method below you should be aware that the new text only covers the size of the new text and not the entire old text. I usually solve this by first drawing a filled rectangle and then the new text.
Here is a TTF example showing how text can be drawn on a surface (here called m_Screen, which is the surface flipped to screen every frame) in the simple case where i have one background color only:
void drawText(const char* string, int x, int y,
int fR, int fG, int fB, int bR, int bG, int bB)
{
SDL_Color foregroundColor = { fR, fG, fB };
SDL_Color backgroundColor = { bR, bG, bB };
SDL_Surface* textSurface = TTF_RenderText_Shaded(m_Font, string,
foregroundColor,
backgroundColor);
SDL_Rect textLocation = { x, y, 0, 0 };
SDL_BlitSurface(textSurface, NULL, m_Screen, &textLocation);
SDL_FreeSurface(textSurface);
}
Notice that this has been done before calling drawText (with some suitable font size):
m_Font = TTF_OpenFont("arial.ttf", size);
And this is done at cleanup:
TTF_CloseFont(m_Font);

Draw a circle on top of Renderer2D

I created a renderer2D so the user can click and pick the centre of a lesion. I want to show the user where he clicked. Currently my idea is to freeze the renderer (so the slice will be the same and the zoom too) and then use the canvas to draw a circle.
Here is my code:
centerpick2D = new X.renderer2D();
centerpick2D.container = 'pick_center_segment';
centerpick2D.orientation = 'Z';
centerpick2D.init();
centerpick2D.add(volumeT1DCM);
centerpick2D.render();
centerpick2D.interactor.onMouseDown = function(){
tumorCenter=centerpick2D.xy2ijk(centerpick2D.interactor.mousePosition[0],centerpick2D.interactor.mousePosition[1]);
centerpick2D.interactor.config.MOUSEWHEEL_ENABLED = false;
centerpick2D.interactor.config.MOUSECLICKS_ENABLED = false;
$('canvas').attr('id', 'xtkCanvas');
var myCanvas = document.getElementById("xtkCanvas");
var ctx=myCanvas.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.beginPath();
ctx.arc(centerpick2D.interactor.mousePosition[0],centerpick2D.interactor.mousePosition[1],20,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
};
I have two problems:
The MOUSEWHEEL_ENABLED=false and MOUSECLICKS_ENABLED = false do not work. I tried adding a centerpick2D.init() which works but add a second canvas on top of the previous one.
My circle does not appear anywhere.
Any help would be greatly appreciated. :-D
Sorry took me a while to get this uploaded. Here's a quick overview of how I am copying the XTK canvas' contents into my own canvas and then do my own custom drawing on top of it. The actual code for my project is all over the place, so am just pasting formatted snippets here. Again there's a definite drawback in terms of performance here (due to the copying of pixels), so I think it would be better to introduce all this into the XTK Code in the first place and do all the drawing in one Canvas element.
// initialise animation loop with requestAnimationFrame
startDraw:function(){
var _this = this;
var time = new Date().getTime();
function draw() {
//update time
var now = new Date().getTime();
//only draw the frame if 25 milliseconds have passed!
if(now > (time + 25)){
// call drawing function here
drawFrame();
time = now;
}
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
};
//...
// actual drawing function, for each frame copy the pixel contents from a XTK canvas
// into custom canvas and do custom drawing on top of it, so drawing is actually at each
// frame
drawFrame:function(){
//...
// this.ctx is the context of my own custom canvas element
// I use drawImage() function to copy the pixels from this.srcCanvasA
// this.srcCanvasA is a predefined XTKCanvas
this.ctx.drawImage(this.srcCanvas, 1, 1)
// custom func to draw on top of this same canvas (ie. this.ctx) with standard
// HTML Canvas functionality, so this is where you could draw your own circle based
// on the user mouse coords
this.drawAnnotation();
//...
}
Let me know if you have any more questions. The full code is available here:
https://github.com/davidbasalla/IndividualProject

QGraphicsRectItem and QGraphicsScene problems at Scene change

what I want to do is the following:
I have a little GUI with a QGraphicsView. In this graphics View I load a picture:
// m_picture is QPixmap
// image is QImage
// m_graphic is QGraphicsScene
// graphicsView is QGraphicsView
m_picture.convertFromImage(image);
m_graphic->addPixmap(m_picture);
ui->graphicsView->setScene(m_graphic);
This doesn't cause any problems and I can always load a new image without problems.
Now in addition to just display the pictures I want to give the user the ability to draw a rectangle on them ( to "focus" on a specific area ). Actually the user just types in the coordinates in four text boxes on the GUI ( x,y, width,heigth). After providing the coordinates the User presses a button and the rectangle at the following coordinates shall be displayed.
I accomplished this with this code:
void tesseract_gui::show_preview_rect()
{
int x,y,h,w;
x = ui->numBox_x->value();
y = ui->numBox_y->value();
h = ui->numBox_h->value();
w = ui->numBox_w->value();
if( rect_initialized )
{
m_graphic->removeItem(m_rect);
}
else
{
rect_initialized = true;
}
m_rect->setPen(QPen(Qt::red));
m_rect->setRect(x,y,h,w);
m_graphic->addItem(m_rect);
return;
}
The remove call is because I always want to display just one rectangle.
Now as I mentioned this works fine. But if the user now loads another picture ( with the calls at the top of my post ) the program crashes when I try to draw a new rectangle. I
get a Segmentation fault at the call of
m_rect->setPen(QPen(Qt::red));
If I call
m_graphic->removeItem(m_rect);
after loading a new picture I get
QGraphicsScene::removeItem: item 0x8c04080's scene (0x0) is different from this scene (0x8c0a8b0)
and then it crashes with the same Error at setPen.
What I don't get is, I don't change the scene. I just add another picture to it ( or overwrite it) .
Well any suggestions how I could do this right?
Best Regards
// edit:
I tried to do it just with everytime a new rectangle like this:
void tesseract_gui::show_preview_rect()
{
int x,y,h,w;
x = ui->numBox_x->value();
y = ui->numBox_y->value();
h = ui->numBox_h->value();
w = ui->numBox_w->value();
m_graphic->clear();
m_graphic->addRect(x,y,h,w);
return;
}
Problem at this is that with the clear() call it also clears the picture itself from my GraphicsView... so no solution there
// edit:
As suggested I got rid of the Warning like this:
if( m_rect->scene() != 0 )
{
m_graphic->removeItem(m_rect);
}
m_rect->setPen(QPen(Qt::red));
m_rect->setRect(x,y,h,w);
m_graphic->addItem(m_rect);
I know it's not the best way but I tried it also this way ( did not work for me ):
I added the item in the constructor:
m_graphic->addItem(m_rect);
and then
m_rect->setPen(QPen(Qt::red));
m_rect->setRect(x,y,h,w);
m_graphic->update();
and I get the "same" error as always ( Program crashes at m_rect->setPen() )
So it seems the problem always occurs when I already added the rectangle to the graphic, THEN changed the image of m_graphic and then did any operation with m_rect. ( Actually I guess m_graphic takes ownership of m_rect and so this causes the segmentation fault ... ? )
The message QGraphicsScene::removeItem: item 0x8c04080's scene (0x0) is different from this scene (0x8c0a8b0) tells you m_rect is not in any scene at the time you call it. It's probably removed somewhere else in your code or you have 2 variables with the same name in the class hierarchy.
Also, you don't need to remove it from scene to change it. Just change it while it's in the scene. It will get repainted with the new color and geometry in the next paint event.
Even if you REALLY want to remove it before changing it, just check if it's in a scene by calling QGraphicsItem::scene(). There's no need for the init check variable.

Usage of CScrollView in MFC application

I am using CSCrollView window for our Application in which i have table drawn in View.
I have derived the CMYclass from CSCrollView, But whenevr i am scrolling the window up and down whatever i have drwan is getting erased. How i can acheive it this... i need to perform same actvity like a Word Pad is doing with images and Text. I want to keep scroll the View Vertically. Till the page ends.
Here is the code snippet:-
void CMyView::OnInitialUpdate()
{
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = 450;
sizeTotal.cy = 700;
SetScrollSizes(MM_TEXT, sizeTotal);
}
void CMyView::OnDraw(CDC* pDC)
{
for(int i = 1;i<50;++i)
{
AddRow(pDC);
TopPos = Height+TopPos;// ![Outpu Window Image][1]
nCountRow++;
}
}
it is only drawing 18 rows, but when iam scrolling down above drawn content is no more and also there is nothing coming up in scrolled area.
Is there anything more need to add?
Thanking for help
Regards,
Mukesh
Long time I have used CScrollView. Here is my hint: Try mapping modes other than MM_TEXT. Also look up other functions in CScrollView. I suggest to draw simple stuff first than some complicated rows.