I am trying to display a bitmap image to an OpenGL control called GL (I am using SharpGL as the wrapper). In practice, a text string is written to a GDI+ Picture box from which the Bitmap is obtained.
The GLBitmap function requires a Byte() array as input; I convert the Bitmap to a Byte() array. Does not seem to work as I get a bunch of dots on screen. I have also saved the PictureBox image to a Bmp file on disk and cross-checked that it had the desired content. So, the Bmp image does not appear to be the issue here.
Actual OpenGL display
Bmp file created from the code below
Wondering what I am doing wrong. Anybody would have a suggestion ? Thanks in advance.
The VB.Net code appears below.
' Create Bitmap & Graphics context for string
'
' iWidth and iHeight are the dimensions of the bitmap;
' they are a power of 2.
Dim SharpBMap As Bitmap = New Bitmap(iWidth, iHeight)
Dim SharpGraf As Graphics = Graphics.FromImage(SharpBMap)
' Draw text string to SharpGraf PictureBox
'
SharpGraf.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
SharpGraf.Clear(Color.White)
SharpGraf.DrawString(TxtStr, CurrFont, CurrBrush, 0, 0, CurrFormat)
' OutSharpGL is the Picture box to which the text string is sent
OutSharpGL.Image = SharpBMap
' Save the bitmap to disk: when the file is viewed, the image is Ok.
SharpBMap.Save(FilNameStr)
' Set the color
Gl.Color(1.0f, 1.0f, 1.0f)
' Set the Raster position
Gl.RasterPos(0, 0)
' Transfer the Bitmap
Gl.Bitmap(iWidth, iHeight, 0.0f, 0.0f, 0.0f, 0.0f, BitmapToByte(SharpBMap))
' Function to convert a Bitmap to a Byte() array
Friend Function BitmapToByte(ByRef Bmp As Bitmap) As Byte()
Dim converter As New ImageConverter()
Return DirectCast(converter.ConvertTo(Bmp, GetType(Byte())), Byte())
End Function
OpenGL requires raw pixel data ... BMP has encoding ...
In order to make this work you need to extract the raw pixel data from your BMP. That might be a bit too much to do correctly as there are a lot of format configurations out there ...
So make sure you change your bitmap to format that is easily handled like:
uncompressed
24 or 32 bpp
Now bitmap has a BMP header at its start describing the file is BMP and stuff like resolution, encoding, organization etc ... The header also usually holds the start address of the pixels... So extract that and pass the RAW pixels to your GL texture...
Beware BMP pixels are aligned on ScanLine basis so each line of image has some gap BYTE to align to certain multiple of size (usually 1..4 Bytes) you need to skip it and then process another line. Here related QA (but solved easily by VCL which is not your case)
How to get a pixel array from TBitmap?
However you need to do this on your own so you need:
dive into BMP fileformat
obtain resolution and pixel data start address from the header
construct your raw pixel data by copying the lines into yours memory array
skipping header and the align bytes
pass that as OpenGL texture
its faster to pass whole image than do it on per line basis. Beware you need to set the pixel format so it matches your raw data copied from bmp. So bpp must match and also the R,G,B order.
render textured quad
btw. much easier would be to print the texts directly in OpenGl. There are libs for that like FreeType but you can use textures instead like this:
GLSL debug prints
Of coarse CPU side GL text rendering using such texture is much easier than in GLSL. You just handle the texture as Texture Atlas where the Texture coordinates are computed from ASCII code and Texture font organisation.
Related
My application acts as a document template with textboxes for users to fill in. Once they've completed, they can "print" the document to a PDF using PDFsharp. This is done by converting the panel on which the textboxes are on to a bitmap image using the code below;
ConditionReportConfig.PG1.Panel2.DrawToBitmap(Bitmap, New Rectangle(0, 0, Bitmap.Width, Bitmap.Height))
frm_MsgPrint.lbl_Page.Text = "Page: 1" : frm_MsgPrint.lbl_Page.Refresh()
frm_MsgPrint.PictureBox1.Image = Bitmap
frm_MsgPrint.PictureBox1.Refresh()
BXImage = Bitmap
GFX.ScaleTransform(0.82)
GFX.DrawImage(BXImage, 25, 0)
GFX.Dispose()
CDR1 = Nothing
Unfortunately, when the PDF pops up with the image the entire image, more so the text in the textboxes, are fuzzy. They aren't fuzzy to the point you can't read, but they do make reading the text incredibly stressful on your eyes.
I've tried adding various settings in such as;
Dim Bitmap2 = New Bitmap(894, 1367)
Using G As Graphics = Graphics.FromImage(Bitmap2)
G.InterpolationMode = Drawing2D.InterpolationMode.Bicubic
G.DrawImage(Bitmap, 0, 0, 120, 150)
End Using
I've even tried changing the font, size, even saving the bitmap as a TIFF, PNG and it still appears fuzzy. I would change printing methods, but the whole point of the panel is to be printed. Not only that but the panel contains images so I can't just print the text on the PDF.
Edit:
I've tried changing some of the interpolation settings, and it is slightly clearer but still a strain on your eyes.
Below is a snippet of the Bitmap image as a TIFF. Notice how the text in the textboxes is "Fuzzy" but the vertical text alongside is perfect. Is there really no way of getting textbox contents to be as sharp as the vertical text?
Blurry image with crystal clear vertical text:
Create an XImage from your bitmap and set
image.Interpolate = false;
for that image. This is a hint for Adobe Reader not to smooth the image.
Also check that ClearType does not make your image blurry before adding it to the PDF.
I am using GDI+ to draw the initial image on PictureBox - which renders a clean image. I am trying to then capture that drawing and draw it on a PDF using PDFSharp which works, but comes out blurry. I am sure it has something to do with the fact I have changed the destination Rectangle's size. What do i need to do to clean it up?
Code:
Dim bmp As New Bitmap(pb.Width, pb.Height)
Dim pdf As New PdfDocument
Dim page As PdfPage = pdf.AddPage
Dim g As XGraphics = XGraphics.FromPdfPage(page)
pb.DrawToBitmap(bmp, New Rectangle(pb.ClientRectangle.X, pb.ClientRectangle.Y, pb.Width, pb.Height + 20))
g.SmoothingMode = XSmoothingMode.AntiAlias
g.DrawImage(bmp, New XRect(New RectangleF(20, 0, 600, 800)))
pdf.Save(_path)
It's the anti-aliasing that makes images blurry.
AFAIK Adobe Reader draws images with anti-aliasing when used with PDFsharp.
With PDFsharp create an XImage from your BMP and then set
image.Interpolate = false;
for that XImage. This will give a hint to Adobe Reader that anti-aliasing is not wanted for that image.
With respect to screen shots, anti-aliasing is useful when scaling down (e.g. when taking a 400x300 bitmap from an 800x600 screen), but not when scaling up (like Adobe Reader will do with images embedded in PDF files).
See also:
http://forum.pdfsharp.net/viewtopic.php?p=5370#p5370
If you scale an image up, it will come out blurred. There is no other way since there are no additional information in the image and it will just be interpolated in some way. There is no "Zoom in and ENHANCE"-button. :-)
What I did in one of my programs where I wanted to save a controls current look to a file, was to first scale the control to the desired size, then draw it to the bitmap, then resize it down again.
If this works depends on the content of the control of course, wether it's scalable or not and so on.
e.g.
In the example below I have a Chart control that I work with in my export dialog called workingChart.
The steps that are used are:
Save old size
Resize chart to the desired size
Draw control to bitmap
Resize chart back to the old size
This works well and the image comes out crisp, since you do not resize the image itself.
Private Function GetChartScaledImage(wantsize As Size) As Bitmap
Dim oldsize As Size = workingChart.Size
Dim bmp As New Bitmap(wantsize.Width, wantsize.Height)
workingChart.Size = wantsize
workingChart.DrawToBitmap(bmp, New Rectangle(0, 0, wantsize.Width, wantsize.Height))
workingChart.Size = oldsize
Return bmp
End Function
I am creating program with multileyered picturebox, the image of picturebox is update dynamically from bitmap in memory, and i want to clear the selected part on bitmap to transparent color so i can see image of picturebox behind it.
Here is my code
Dim gBmp As Graphics = Graphics.FromImage(GraphLayer(LayerArray))
Dim TileSrcCrop As New Rectangle(nVal(xTile), nVal(yTile), TileSize, TileSize)
Dim TileDrawSize As New Rectangle(nVal(H), nVal(V), TileSize, TileSize)
gBmp.DrawImage(GraphImage(LayerArray), TileDrawSize, TileSrcCrop, GraphicsUnit.Pixel)
PicMap(LayerArray).Image = GraphLayer(LayerArray)
Thanks
What I'm about to say may only be for Windows icons, but IIRC, the top left pixel must be assigned the color that you want to designate as the color for transparency. You'll usually see MS use Magenta (255, 0, 255). This is called a transparency mask. Then, anywhere you want the color to be transparent, you use the color you placed in the top left pixel.
HTH -- and let me know if it's only for icons, but I think it's for Windows bitmap files, too.
I am resetting the text for an MdiTab in an UltraWinTabbedMdi. I reset it to be bold and longer, but the tab does not resize so the text is truncated. Right now, I'm just resetting the size of the tab to some magic number that I've found looks decent on my computer, but I don't know if it will work elsewhere. I would like to be able to get the dimensions of the new text and add the same size to that every time or call some auto-resize method.
Is there a way to do this?
You could use the MeasureString of the Graphics class.
// Set up string.
string measureString = "YourText";
// The font name and size used to draw the string (from your MdiTab)
Font stringFont = new Font("Arial", 16);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = this.Graphics.MeasureString(measureString, stringFont);
// now you have a stringSize.Width and stringSize.Height to use
I toying with a project where I can position objects runtime on the screen. I also have an small "preview"-window, where I want to see the outline of the objects.
I have an object array who have size and location on the "scene". Now I want to loop through my scene-objects and create one picturebox in the preview-window for each object in the "scene".
So, I have the size of the "Scene" and an array of the objects that are visible on the scene. Every object have an size and location mapped to the scene.
I also have a preview window that have an dynamic size. How do I create a preview that scales down to the preview window? To make it easy, I loop through the scene objects in the scene and create a picturebox on the preview-form for each object, that uses the preview-forms size to do the scaling.
SceneSize=new size(800,600)
PreviewSize=new size(80,60)
For each obj as SceneObject in Scene
dim p as new picturebox
p.size=?? scaling here (we have obj.size and obj.location)
p.location=?? scaling here (we have obj.size and obj.location)
previewWindow.controls.add (p)
next
Any example in .Net would be nice.
Thanks.
Bob Powell's site on GDI+ might have some useful information on how to proceed. Check out his page on Matrix Transformations. This article might provide you with some good ideas on how to proceed
Bob Powell GDI+ Transformations
This did the trick, it wasn't harder than that.
Function GetPreviewRectangleForObject(ByVal ScreenSize As Size, ByVal PreviewSize As Size, ByVal OriginalRect As Rectangle) As Rectangle
Dim xFactor As Integer = ScreenSize.Width / PreviewSize.Width
Dim yFactor As Integer = ScreenSize.Height / PreviewSize.Height
With OriginalRect
Return New Rectangle(.X / xFactor, .Y / yFactor, .Width / xFactor, .Height / yFactor)
End With
End Function