I am drawing lines on Canvas of SurfaceView which is in FrameLayout. I receive image from camera preview, process it, get coordinates of rectangles and raw the lines of it on canvas. I get a displacement of those lines in y axis when drawn, the lower the line is, the bigger displacement occurs (see photos below):
With red line I marked (with Paint program, not the actual app) the approximate position of where the coordinates coordinates of lower line are on bitmap, and the lower green line of rectangle (placed by the actual app, drawn on canvas) along with red line shows, how much coordinates are displaced. The coordinates on top cannot cross the screen, but on the bottom they can- if the rectangle is low enough, lines come below the screen, but on top they do not (they should not do that on either of all 4 sides, because the given coordinates are never out of bitmap).
The drawing function looks like this:
public void DrawAllContours(List<Point[]> rectPoints, int ratio)
{
paint.setColor(Color.GREEN);
paint.setStrokeWidth(2.5f);
canvas = sh.lockCanvas();
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
for (int i = 0; i < rectPoints.size(); i++)
{
for (int j = 0; j < 4; j++)
canvas.drawLine((float)rectPoints.get(i)[j].x*ratio, (float)rectPoints.get(i)[j].y*ratio,
(float)rectPoints.get(i)[(j+1)%4].x*ratio, (float)rectPoints.get(i)[(j+1)%4].y*ratio, paint);
}
sh.unlockCanvasAndPost(canvas);
}
The ratio variable is the difference between the actual preview image size and resized bitmap for processing size (usualy the value is 3). The actual coordinates are as they should be on preview bitmap, but not on Canvas.
How can I overcome this issue and place lines on their exact places?
Thank you in advance.
So I found out, that camera preview size does differ from the canvas size. My preview size was 1920X1080, and canvas 1845X1080 or so, so thats why Y coordinate was displaced. I just found out the difference ratio and drew lines respectively by that ratio. Canvas resolution can be found with Canvas.getWidth(), Canvas.getHeight().
Related
can anyone help me and tell me how to create a gray scale image where one pixel of the image is shown as a square with the size 2 x 2?
I already searched for help and found this how to create a gray scale image from pixel values using java but i don't know how to create a gray scale with the information that one pixel is shown as a square with the size 2 x 2.
thanks!
to create a picture where each pixel has the size 2x2 you must either scale the image (factor 2) for display only... or if you want to create a image you have to do it manually and create an image and draw with scale factor 2 on it
int[] pixels = ... //we already have our gray scale pixels here
int widthOriginal = ... //size of original image
int heightOriginal = ...
//let's create an buffered Image twice the size
BufferedImage img =
new BufferedImage(2*widthOriginal, 2*heightOriginal, BufferedImage.TYPE_4BYTE_ABGR);
//we paint on the buffered image's graphic...
Graphics gr = img.getGraphics();
//we draw all pixels on the graphic
for(int y = 0; y < heightOriginal; y ++){
for(int x = 0; x < widthOriginal; x ++){
int index = y*widthOriginal + x;
int gray = pixels[index];
//to draw we first set the color
gr.setColor(new Color(gray));
//then draw the pixel
gr.drawRect(2*x, 2*y,2,2); //draw a 2x2 pixel instead of a 1x1 pixel
}
}
uhm - honestly i've written that code entirely out of my head, so there may be some minor compilation problems... but the technique is explained properly...
I have a Jpeg image with a "seeming" uniform background and an actual object in it. I want to crop the image to extract only the object.
I started with following code where I am trying to find the (x,y) on left side to start cropping.
I found out that bottom left corner of the image has (0,0) coordinates. I am looping through and trying to find out the exact point where the color changes.
The problem is during first iteration itself : when x=0 and y is incrementing, though there is no change in color it is giving different RGB values for few pixels.(like pixel 240 , 241, 242)
BufferedImage bf =ImageIO.read.file(imagePath);
for(int x= 0;x<bf.getWidth();x++)
{
for(int y=0; j<bf.getHeight();y++)
{
int color = bf.RGB(x,y);
int adjacentColor = bf.(x,y+1);
if(color !=adjacentColor)
{
LeftBoundaryPixels[count]=y;
count++;
break;
}
}
}
You can use a color distance formula (like the distance formula sqrt(x^2 + y^2)) with a threshold distance to dismiss pixels that are close but not completely the same. For example: sqrt(r^2 + g^2 + b^2);.
I'm working on a drawing application and am pretty close to release but I'm having issues with the eraser part of the app. I have 2 main screens (fragments) one is just a blank white canvas that the user can draw on with some options and so on. The other is a note taking fragment. This note taking fragment looks like notebook paper. So for erasing on the drawing fragment, I can simply use the background of the canvas and the user wont know the difference. On the note fragment though I cannot do this beacuse I need to keep the background in tact. I have looked into PorterDuffer modes and have tried the clear version and tried to draw onto a separate bitmap but nothing has worked. If there was a way to control what gets draw ontop of what then that would be useful. I'm open to any suggestions, I can't seem to get anything to work.
Ive also played with enabling a drawing cache before erasing and that doesn't work. In addition I tried hardware enabling and that made my custom view behave oddly. Below is the relavent code. My on draw methods goes through a lot of paths because I am querying them in order to allow for some other functionallity.
#Override
protected void onDraw(Canvas canvas) {
//draw the backgroumd type
if(mDrawBackground) {
//draw the background
//if the bitmap is not null draw it as the background, otherwise we are in a note view
if(mBackgroundBitmap != null) {
canvas.drawBitmap(mBackgroundBitmap, 0, 0, backPaint);
} else {
drawBackgroundType(mBackgroundType, canvas);
}
}
for (int i = 0; i < paths.size(); i++ ) {
//Log.i("DRAW", "On draw: " + i);
//draw each previous path.
mDrawPaint.setStrokeWidth(strokeSizes.get(i));
mDrawPaint.setColor(colors.get(i));
canvas.drawPath(paths.get(i), mDrawPaint);
}
//set paint attributes to the current value
mDrawPaint.setStrokeWidth(strokeSize);
mDrawPaint.setColor(mDrawColor);
canvas.drawPath(mPath, mDrawPaint);
}
and my draw background method
/**
* Method that actually draws the notebook paper background
* #param canvas the {#code Canvas} to draw on.
*/
private void drawNoteBookPaperBackground(Canvas canvas) {
//create bitmap for the background and a temporary canvas.
mBackgroundBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBackgroundBitmap);
//set the color to white.
mBackgroundBitmap.eraseColor(Color.WHITE);
//get the height and width of the view minus padding.
int height = getHeight() - getPaddingTop() - getPaddingBottom();
int width = getWidth() - getPaddingLeft() - getPaddingRight();
//figure out how many lines we can draw given a certain line width.
int lineWidth = 50;
int numOfLines = Math.round(height / lineWidth);
Log.i("DRAWVIEW", "" + numOfLines);
//iterate through the number of lines and draw them.
for(int i = 0; i < numOfLines * lineWidth; i+=lineWidth) {
mCanvas.drawLine(0+getPaddingLeft(), i+getPaddingTop(), width, i+getPaddingTop(), mNoteBookPaperLinePaint);
}
//now we need to draw the vertical lines on the left side of the view.
float startPoint = 30;
//set the color to be red.
mNoteBookPaperLinePaint.setColor(getResources().getColor(R.color.notebook_paper_vertical_line_color));
//draw first line
mCanvas.drawLine(startPoint, 0, startPoint, getHeight(), mNoteBookPaperLinePaint);
//space the second line next to the first one.
startPoint+=20;
//draw the second line
mCanvas.drawLine(startPoint, 0, startPoint, getHeight(), mNoteBookPaperLinePaint);
//reset the paint color.
mNoteBookPaperLinePaint.setColor(getResources().getColor(R.color.notebook_paper_horizontal_line_color));
canvas.drawBitmap(mBackgroundBitmap, 0, 0, backPaint);
}
To all who see this question I thought I would add how I solved the problem. What I'm doing is creating a background bitmap in my custom view and then passing that to my hosting fragment. The fragment then sets that bitmap as its background for the containing view group so that when I use the PorterDuff.CLEAR Xfermode, the drawn paths are cleared but the background in the fragment parent remains untouched.
I'm drawing some points in OpenGL (JOGL) as follows:
BufferedImage image = loadMyTextureImage();
Texture tex = TextureIO.newTexture(image, false);
tex.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
tex.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
tex.bind();
gl.glColor4f(r,g,b,a);
gl.glBegin(GL_POINTS);
for ( int i = 0; i < numPoints; i++ ) {
// compute x,y,z
gl.glVertex3f(x,y,z);
}
gl.glEnd();
My image is a white image, so I can reuse that same texture and just color it using gl.glColor4f, but I would like to draw an outline around it in a different color. Is there a way to do that?
If you're using the texture to determine the shape of the point, then the obvious way to do the outline would be to add a second texture to draw the outline of the point on top.
The outline texture would also be white, so you could colour it to any colour you like in the same way.
Depending on the alpha-blending mode you use, this can also be used to give a "glowing" edge effect.
i want my Bitmap that has the height of the screen and has a bigger width than the screen to be moved a little bit to the right or left if the user changes the desktop so he can see the entire image.
Here is my code that just works partially:
int x = -1*(int)((xOffset*bmp.getWidth()));
canvas.drawBitmap(bmp, x, 0, null);
thank you!
You get exact pixel values via the variables xPixels and yPixels in onOffsetsChanged(). See my answer here: android live wallpaper rescaling
For example, in onOffsetsChanged(), you can set a private class variable
mPixels = xPixels;
Then, in your draw routine
holder = getSurfaceHolder();
c = holder.lockCanvas();
c.translate(mPixels, 0f);
// c.drawBitmap ... goes here :-)
Typically, you will want a bitmap twice the width of your screen, with your artwork centered in the middle. For example: 320 pixel width screen -> 640 pixel width bitmap with "center" from 160 to 480. mPixels will be 0 at the left most launcher screen (of 5), -160 at the center, and -320 at the rightmost screen.