I am trying to learn how to do OpenGL using OpenTK and I can successfully draw polygons, circles, and triangles so far but my next question is how to draw text? I have looked at the example on their homepage which was in C# and I translated it to VB .NET.
It currently just draws a white rectangle so I was hoping that someone could spot an error in my code or suggest another way to draw text. I will just list my paint event.
Paint event:
GL.Clear(ClearBufferMask.ColorBufferBit)
GL.Clear(ClearBufferMask.DepthBufferBit)
Dim text_bmp As Bitmap
Dim text_texture As Integer
text_bmp = New Bitmap(ClientSize.Width, ClientSize.Height)
text_texture = GL.GenTexture()
GL.BindTexture(TextureTarget.Texture2D, text_texture)
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, All.Linear)
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, All.Linear)
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, text_bmp.Width, text_bmp.Height, 0 _
, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero)
Dim gfx As Graphics
gfx = Graphics.FromImage(text_bmp)
gfx.DrawString("TEST", Me.Font, Brushes.Red, 0, 0)
Dim data As Imaging.BitmapData
data = text_bmp.LockBits(New Rectangle(0, 0, text_bmp.Width, text_bmp.Height), Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)
text_bmp.UnlockBits(data)
GL.MatrixMode(MatrixMode.Projection)
GL.LoadIdentity()
GL.Ortho(0, width, Height, 0, -1, 1)
GL.Enable(EnableCap.Texture2D)
GL.Enable(EnableCap.Blend)
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha)
GL.Begin(BeginMode.Quads)
GL.TexCoord2(0.0F, 1.0F)
GL.Vertex2(0.0F, 0.0F)
GL.TexCoord2(1.0F, 1.0F)
GL.Vertex2(1.0F, 0.0F)
GL.TexCoord2(1.0F, 0.0F)
GL.Vertex2(1.0F, 1.0F)
GL.TexCoord2(0.0F, 0.0F)
GL.Vertex2(0.0F, 1.0F)
GL.End()
GlControl1.SwapBuffers()
You'll get a white rectangle if your card doesn't support NPOT (non-power-of-two) texture sizes. Try testing by setting the bitmap size to e.g. 256x256.
That is an ok method. If you plan to draw lots of text or even a medium amount, that will absolutely destroy performance. What you want to do is look into a program called BMFont:
www.angelcode.com/products/bmfont/
What this does is create a texture atlas of text, along with an xml file with the positions, width and height and offsets of every letter. You start off by reading that xml file, and loading each character into a class, with the various values. Then you simply make a function that you pass a string which binds the atlas, than depending on the letters in the string, draws a quad with texture coordinates that vary on the xml data. So you might make a:
for each _char in string
create quad according to xml size
assign texture coordinates relative to xml position
increase position so letters don't draw on top of each other
There are tutorials in other languages on the BMFont website which can be helpful.
Related
I have detected blob keypoints in opencv c++. The centroid displays fine. How do I then draw a bounding box around the detected blob if I only have the blob center coordinates? I can't work backwards from center because of too many unknowns(or so I believe).
threshold(imageUndistorted, binary_image, 30, 255, THRESH_BINARY);
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
// Detect blob
detector->detect(binary_image, binary_keypoints);
drawKeypoints(binary_image, binary_keypoints, bin_image_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//draw BBox ?
What am I overlooking to draw the bounding box around the single blob?
I said:
I can't work backwards from center because of too many unknowns(or so I believe).
There is not limited information if blob size is used: keypoints.size which returns the diameter of the blob in question. Though there might be some inaccurate results with highly asymmetric or lopsided targets, this worked well for me b/c I used spheroid objects. Moments/ is probably the better approached for the asymmetrical targets.
keypoints.size should not be confused with keypoints.size(). The latter does a count in the vector of objects in my case the former is the diameter. Using both.
Using the diameter I can then calculate the rest with no problem:
float TLx = (ctr_x - r);
float TLy = (ctr_y - r);
float BRx = (ctr_x + r);
float Bry = (ctr_y + r);
Point TLp(TLx-10, TLy-10); //works fine without but more visible with enhancement
Point BRp(BRx+10, Bry+10); //same here
std::cout << "Top Left: " << TLp << std::endl << "Right Lower:" << BRp << std::endl;
cv::rectangle(bin_with_keypoints, TLp, BRp, cv::Scalar(0, 255, 0));
imshow("With Green Bounding Box:", bin_with_keypoints);
TLp = top left point with 10px adjustments to make box bigger.
BRp = bottom right point
TLx, TLy are calculated from blob center coordinates as well as BRps. If you are going to use multiple targets would suggest contours approach (with the moments). I have 1 - 2 blobs to keep track of which is a lot easier but keeps resource usage down.
Rectangle drawing function can also work with Rect (diameter = keypoint.size)
Rect r(TLp, BRp, center_x + diameter/2, center_y+diamter/2) // r(TLc, BRc, width, heigth)
cv::rectangle(bin_with_keypoints, rect, cv::Scalar(0, 255, 0));
I have a grayscale image that serves as a soft mask and I want to use it on a group of PDF objects (images or paths).
The mask and the objects do not necessarily use the same transformation matrix, and there might be more than one object to mask, so that excludes the possibility of using the SMask attribute of the ImageXObject dictionary.
So after reading some of the PDF specification, it looks like I should do the following: create a transparency group with the objects to mask, then draw it with the soft mask set on the graphics state.
Will that work? How can I achieve this, preferably with PDFBox?
Here's an example. I have these two images: the mask and another image.
The mask image is 200x200. It is drawn with the matrix [[4 0 100] [0 4 100]].
The image is 400x300. It is drawn with the matrix [[2 0 100] [0 2 150]].
Additionally, a 400x400 black square is drawn below the image with no transform matrix.
So a transparency group is created with the image and the square, then it's drawn with the mask image. Here's the expected result:
Rather ugly as far as the effect goes, but that's just an example.
As far as I can see establishing an extended graphics state soft mask is a very manual task in PDFBox. You can do so as follows:
try ( PDDocument document = new PDDocument() ) {
final PDImageXObject image = RETRIEVE PHOTO IMAGE;
final PDImageXObject mask = RETRIEVE MASK IMAGE;
PDTransparencyGroupAttributes transparencyGroupAttributes = new PDTransparencyGroupAttributes();
transparencyGroupAttributes.getCOSObject().setItem(COSName.CS, COSName.DEVICEGRAY);
PDTransparencyGroup transparencyGroup = new PDTransparencyGroup(document);
transparencyGroup.setBBox(PDRectangle.A4);
transparencyGroup.setResources(new PDResources());
transparencyGroup.getCOSObject().setItem(COSName.GROUP, transparencyGroupAttributes);
try ( PDFormContentStream canvas = new PDFormContentStream(transparencyGroup) ) {
canvas.drawImage(mask, new Matrix(400, 0, 0, 400, 100, 100));
}
COSDictionary softMaskDictionary = new COSDictionary();
softMaskDictionary.setItem(COSName.S, COSName.LUMINOSITY);
softMaskDictionary.setItem(COSName.G, transparencyGroup);
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
extendedGraphicsState.getCOSObject().setItem(COSName.SMASK, softMaskDictionary);
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
try ( PDPageContentStream canvas = new PDPageContentStream(document, page) ) {
canvas.saveGraphicsState();
canvas.setGraphicsStateParameters(extendedGraphicsState);
canvas.setNonStrokingColor(Color.BLACK);
canvas.addRect(100, 100, 400, 400);
canvas.fill();
canvas.drawImage(image, new Matrix(400, 0, 0, 300, 100, 150));
canvas.restoreGraphicsState();
}
document.save(new File(RESULT_FOLDER, "SoftMaskedImageAndRectangle.pdf"));
}
The result:
If I were you, though, I would not use a bitmap image for the soft mask but instead a PDF gradient. The result most likely will be much less pixelated.
I am trying to create jigsaw puzzle shapes using P5.js. After creating puzzle shapes, I want to cut areas from main image into pieces. For that I have options of using GET() or COPY():
But both of them take fix height and width as parameter. How can I copy a custom area like given in following shapes:
https://editor.p5js.org/techty/sketches/h7qwatZRb
let cutout = createGraphics(w, h);
cutout.background(255, 255);
cutout.blendMode(REMOVE);
//draw shape on cutout
let newshapeimagegraphic = createGraphics(w, h);
newshapeimagegraphic.image(myImg, 0, 0);
newshapeimagegraphic.blendMode(REMOVE);
newshapeimagegraphic.image(cutout, 0, 0);
image(newshapeimagegraphic, 0, 0);
I want to resize an image into a 4x4 pixel image in vb.net.
Using the Internet I got this code:
Public Function ResizeImage(ByVal image As Image) As Image
Try
Dim newWidth = 4
Dim newHeight = 4
Dim newImage As New Bitmap(newWidth, newHeight)
newImage.SetResolution(100, 100)
Using graphicsHandle As Graphics = Graphics.FromImage(newImage)
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic
graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight)
End Using
Return newImage
Catch ex As Exception
Return image
End Try
End Function
Original:
Resized with photoshop(the real way of resizing it):
using InterpolationMode.Bilinear
using InterpolationMode.HighQualityBicubic
What is the problem ?
The settings you'll want are bilinear or bicubic interpolation (avoid the "high-quality" options) and PixelOffsetMode.Half.
graphicsHandle.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear
graphicsHandle.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half
When interpolating, GDI+ normally offsets the center of the pixel by a half pixel. This can have an undesirable effect when scaling, with the appearance of shifting the scaled image up and left. Using PixelOffsetMode.Half shifts the pixels back where they "belong".
The high-quality bilinear and bicubic interpolation modes appear to blend the edge pixels with hypothetical transparent pixels beyond the image bounds, creating a fringe of semi-transparency at the edges.
How do you fade out/in a button in VB.NET properly? I can fadeout/in labels using:
Controls(i).ForeColor = Color.FromArgb(255, alpha, alpha, alpha)
(where Controls(i) is a label from a For Next loop through all controls in Me.Controls; alpha is the value of the RGB, also from a For Next loop).
This did not work for me with buttons because changing the ForeColor leaves the rest of the buttons' UIs visible!
So, the way I'm trying uses a saved Resource image of the button (from a screenshot) and creates a faded in/out version to be displayed as the image in a PictureBox:
Public Function SetImageOpacity(ByVal imgPic As Image, ByVal imgOpac As Double) As Image
Dim bmpPic As New Bitmap(imgPic.Width, imgPic.Height)
Dim grPic As Graphics = Graphics.FromImage(bmpPic)
Dim imgAtt As New ImageAttributes()
Dim cmxPic As New ColorMatrix()
cmxPic.Matrix33 = imgOpac
imgAtt.SetColorMatrix(cmxPic, ColorMatrixFlag.[Default], ColorAdjustType.Bitmap)
grPic.DrawImage(imgPic, New Rectangle(178, 144, bmpPic.Width, bmpPic.Height), imgPic.Width, imgPic.Height, imgPic.Width, imgPic.Height, GraphicsUnit.Pixel, imgAtt)
grPic.Dispose()
imgAtt.Dispose()
Return bmpPic
End Function
(where imgPic is the Resource image of the button, and imgOpac is the opacity on a scale of 1 to 0, where 0 is transparent).
I then use this image to set my PictureBox's image:
picbox.Image = SetImageOpacity(My.Resources.Nextbutton, 1)
However, I get a glitch where, even though the PictureBox is located at coordinates 178, 144, the image it is showing is displayed at the left edge of the form (i.e. wrong X coordinate), with the Y coordinate correct!
I have a feeling it may lie with my call of .DrawImage(...) (at line 8 of the function) - but the MSDN docs on this subject are very unclear to me.
Please link if this has been asked before!
The coordinates in the Graphics grPic are client coords relative to the image itself, not the Form. So (0, 0) is the top left of the image regardless of where that image ends up being displayed in some kind of control.
Try changing it to (0, 0):
grPic.DrawImage(imgPic, New Rectangle(0, 0, bmpPic.Width, bmpPic.Height), imgPic.Width, imgPic.Height, imgPic.Width, imgPic.Height, GraphicsUnit.Pixel, imgAtt)
why not just use a for loop to change the opacity of the button control from 1 to 0 in increments of say .01 ?