I'm building a Bitmap by layering images one above another, and when I'm done I want to write text around the edges. The top and bottom are simple because they're written horizontally, but I'd prefer to write the text on the left and right sides vertically so they don't take up as much space.
The Graphics.DrawString method doesn't allow you to specify an angle of rotation; what other methods exist?
I think you may get some pointers from this answer about rotating text for printing that I wrote a while ago.
Here is a tutorial that may help
http://www.c-sharpcorner.com/Blogs/BlogDetail.aspx?BlogId=580
I believe StringFormatFlags.DirectionVertical is what you are looking for
Maybe you can rotate the bitmap 90 degrees and write the text to the top of the bitmap - then rotate again and write the next side's text - this would give you text running CW/CCW around the edges.
If you want it horizontally across the top and bottom and vertically on the left and right, I suggest measuring (or assumning) the size of the largest character you need to write and then use this to position the drawn text - one character at a time - first on the left side then the right then moving down one char and repeating. You could of course just right the left side in totality and then the right side. just use the width of the char to inset from the right side and the height of the char to offset vertically between chars.
e.g.
1 2 OR 1 4 GIVING C D
3 4 2 5 A O
5 6 3 6 T G
Probably not the most elegant solution, but may help you.
You can use a logical font for this. But it's a pain - you're better off using Fredrik's answer (unless you're doing this in the Compact Framework, where RotateTransform isn't available).
Related
I have strings formatted using the code below
String.Format("{0,-10} {1,10}", "Kills:", kills);
String.Format("{0,-10} {1,10}", "Points:", points);
String.Format("{0,-10} {1,10}", "$:", currency);
From what I understood, the first part of the strings should be left justified with a 10 space buffer and then the integer variables should be printed right justified with a 10 space buffer.
However when attempt to draw the strings using SpriteBatch.DrawString, nothing aligns properly.
The left aligned side prints properly, but the right aligned side centres on a certain point, for example if kills = 50 and points = 5002, the 50 will be centered over the 00 in the 5002...
What is going on?
Quite simply, I suspect you're not using a monospaced font. When different characters have different widths, you can't use spaces to line things up. (Your sample works when using Console.WriteLine for example, as the console has a fixed width font by default.)
You'll either have to use a monospaced font, or you'll have to draw the strings separately - draw each string to fit the relevant area. I don't know anything about XNA, but I'd expect you to either have to measure the width of the string before you draw it (so you can subtract it from the right-hand edge, for example) or specify some sort of layout value which indicates "right-align this string with a particular point".
Most likely you draw the text with a proportional font. Bear in mind that characters don't have the same width, so you cannot align texts with spaces.
As I do not have reply privileges, (or some such thing, as there is no reply button for answers), but I would like to contribute, I will post this answer.
Jon's answer mentioned measuring the string, this is possible by spriteFont.MeasureString(string s);. This returns a Vector2, the X portion of which is the width of the rendered text. (Y is height, which could be helpful for other things) This allows you to use a font other than a monospace font.
Here is an example of using MeasureString:
I'm not really sure what the question is asking, but if you wanted a single line of text similar to "Kills:50 Points:5002" but width two different spritebatch calls you could do the following (note I typed this directly into stackoverflow, so there may be minor syntax errors):
float killStringWidth = spriteFont.MeasureString(killString).X;
spriteBatch.DrawString(spriteFont, killString, new Vector2(0,0), Color.White );
spriteBatch.DrawString(spriteFont, pointString, new Vector2(killStringWidth + 10, 0), Color.White );
Im trying to isolate and segment the yellow car body to change the color of it. in order to do that i need to separately identify the body from the image. And continue oration with the remaining white pixels. And im using C#, here the plan
Color d;
Color newColor = Color.YellowGreen;
for(inti =0;i<carimage.Width;i++){
for(intj =0;j<carimage.Height;j++){
d = carimage.GetPixel(i, j);
if(d.R == 255 && d.G==255 && d.B == 255)
image.SetPixel(i, j, newColor );
}
}
simple thresholding will trow the second image where car body is not separated correctly. i tried Aforge.net Fill holes image filter but no significant change has been done to the threshold image. I tried to use color filter but it i did not return a correct output due to color vary of the body. can anyone suggest and solution for this?
Original Image
Threshold Image
Instead of thresholding, you might want to look into clustering.
As a quick&dirty test, I've increased the image brightness in HSB space (using Mathematica):
brightnessAdjusted = Image[
Map[#^{1, 1, 0.2} &, ImageData[ColorConvert[img, "HSB"]], {2}],
ColorSpace -> "HSB"]
Then I've used simple K-Nearest clustering:
(clusters = ClusteringComponents[ColorConvert[brightnessAdjusted, "RGB"], 3,
Method -> "KMeans"]) // Colorize
to find clusters of similar colors in the image (there are many more, probably more suitable clustering algorithms, so you should experiment a little). Then I can just adjust the color in one of the clusters:
Image[MapThread[If[#1 == 2, #2[[{1, 3, 2}]], #2] &, {clusters, ImageData[brightnessAdjusted]}, 2]]
If you want to use thresholding, you should probably use a CIE color space, since euclidian distances in that color space are closer to human perception.
I had a similar project few years ago. I can't remember the exact details, but the idea was to shift a (not too small) sliding window over the image, and calculate the average intensity (maybe for R, G and B separately) inside the window at each position. I filled a "threshold image" with these averages, and subtracted it from the original image. There was a scaling factor somewhere, and other tuning stuff, but the point is, such an approach was way better than using a constant threshold.
If you are going to use a set of thresholds, you might be better of selecting yellow hues in the Hue Saturation Value colorspace. See the related SO question.
I=imread('test.jpg');
I=im2double(rgb2gray(I));
BW=im2bw(I,0.64);imshow(BW)
Gives me :
I got the 0.64 threshold by looking at the image's histogram. I suggest you use MATLAB to do image processing as it is much easier. Hope that helps you in colouring the image.
As part of my self-education of programming I decided to make a snake in C#. The problem I have is about the client size of the game form.
I want player to be able to scale the window of the game, which is divided into 25 x 25 grid (every coordinate is like "one pixel") - it means, that at any moment, the window is divided into 25 x 25 identical squares.
The problem I get is near this code:
int SquareSide = (ClientSize.Width / 25);
When I set the ClientSize strictly to for example 600 x 600, which is a multiple of 25, everything goes OK. But when I don't (for example by manual resizing, which can change the size to, for example, 711 x 711), it creates at the right side a 'strip', which seems to be the rest of pixels, which can't be used because we are dividing to integer number.
My question is - is there any not-extremely-hard way to achieve dividing ANY client size of form into 25 x 25 grid without this problem? I tried using double, but FillRectangle method doesn't accept it.
I hope my question is understandable and thank you for replies.
To tell you the truth, there is
g.FillRectangle(Brush b, RectangleF rect)
RectangleF is a rectangle whose coordinates are float.
So you can use:
float SquareSide = (ClientSize.Width * 1f / 25);
I would try to simply handle OnResize event of the window, and at the moment user finishes rezise it, force the size that program need for perfect fit of the grid.
So for example at the moment user releases mouse and you figure out that one dimensions of the window 711x711, bring it to nearest correct fit 700x700.
In this way you guarantee good user experience on different monitor resolutions and for you guarantee a correct fit of the grid you draw.
Hope this helps.
Switch to float coordinates for everything. Make sure your game looks OK when lines do not have whole pixel coordinates. Make sure you "find next cell" code also works with floats, including mouse position detection if needed.
The other approach is to be happy with integer coordinates (and cells of the same size) and make page layout flexible to accomodate some unused space for odd 711x711 layouts (i.e. just center the field and keep some variable width border).
So I'm building a custom control in C# (not WPF), and I basically want to implement text highlighting with the mouse.
How do I efficiently find the character at a given Point (say where the mouse is clicked) in a string? I have the layout rectangle of the string as it was drawn and I could calculate the length of the string up to every character until I find the one closest to where the mouse is clicked... but there has to be a better way. Any suggestions?
If I had to do this, I would look at it backward.
I'd keep the text entered as a string member in the control, so at all times I know what is actually entered in the control (like the Text property in a TextBox).
Then I would use the TextRenderer.MeasureText() method (http://msdn.microsoft.com/en-us/library/7sy6awsb.aspx) and I would keep measuring the length of the string repeatedly until I pass the X coordinate of the mouse within the control, right then I know how many characters are chosen.
For example, assume the user has the text Hello written in the control.
And the X coordinate hit right between the l and the o, which could be of value 20.
Then I would repeatedly calling MeasureText() on the following strings:
H: width of 5 pixels.
He: width of 10 pixels.
Hel: width of 14 pixels.
Hell: width of 17 pixels.
Hello: width of 22 pixels.
Then I know the mouse was hit between the l and the o, so I would then highlight the text Hell.
Sorry for the distasteful example =)
UPDATE:
You can optimize this a bit by calculating the lengths in a binary-search-tree-like fashion.
Just like you would look up a name in the phonebook, you don't look page by page, but rather split in half as you go along, getting closer and closer until it's definitely between these two pages.
Similarly, especially for long string values of the control, calculate the width of the entire string, then half its length, and split there. I think that would be O(n log n) at that point.
Of course it would be O(1) if the text is of fixed width =)
Another thing you can do to build upon BeemerGuy's great suggestion is to precalculate an array of offsets. As the string is changed (the user types or the property is set in code) you can recalculate the offset array. That will save you the call to MeasureFont on the mouse clicks and will make finding the character trivial. You basically iterate the array until you find the nearest character. Since the offsets are implicitly sorted by value you can even use a binary search to make it more effective.
I want to create some heat-map style tiles to overlay over our base maps using Open Layers. Basically, I want to divide some some bounding box into a grid, and display each square of the grid using a different color based on how many points of a sample fall within that grid square.
The technologies involved are C#, OpenLayers, SQL Server 2008 and GeoServer.
My question is basically one of general approach, I'm not really sure where to put the tip of the chisel on this one.
My ultimate goal is to be able to take any arbitrary bounding box, calculate an x-mile by x-mile grid that fits within that bounding box, the iterate over a collection of individual points and assign them to one grid square or another so I can calculate point density per grid square, then color the grid according to the densities, then overlay that on a CloudMade base map using Open Layers.
Any help at all would be greatly appreciated, on the whole thing or any piece of it.
If your bounding box is axis aligned, this is fairly simple. Just make your image, and create a world file for it by hand. The world file is just 6 lines of text, and you already know everything needed (x & y pixel size, coordinate of your upper left corner).
Just make sure that you use the CENTER of the upper left corner pixel, not the corner of the box.
------ Here's how you'd make the world file -------
Say your bounding box's upper left corner is at 203732x598374, and you want an image that has rectangles that are 200m wide east<->west and 300m tall north<->south.
You'd make an image that was the appropriate number of pixels, then a world file that had the following 6 lines:
200
0
0
-300
203632
598524
This corresponds to:
200 == size of one pixel in X
0 == shear1
0 == shear2
-300 == size of one pixel in Y (from top down)
203632 == left edge - 1/2 pixel size (to center on pixel instead of edge of box)
598524 == top edge - 1/2 pixel size (to center on pixel instead of edge of box)
If you use a .png image, you'll want to save this with the same name, but as .pgw. If you use a .jpg, it'd be .jgw, etc.
For complete details, see:
Wiki on World Files
"Dividing some some bounding box into a grid, and displaying each square of the grid using a different color based on how many points of a sample fall within that grid square." This is a raster and there are features in GeoServer for displaying these with colour shading, legends and so on. I think it will be more flexible to use these features than to create image tiles in C#.
From the GeoServer documentation:
Raster data is not merely a picture,
rather it can be thought of as a grid
of georeferenced information, much
like a graphic is a grid of visual
information (with combination of reds,
greens, and blues). Unlike graphics,
which only contain visual data, each
point/pixel in a raster grid can have
lots of different attributes, with
possibly none of them having an
inherently visual component.
This is also called thematic mapping or contour plots or heatmaps or 2.5D plots in other GIS packages.
You could use a free GIS like Grass to create the raster grids, but from your description you don't need to interpolate (because every cell contains at least one point) so it might be just as easy to roll your own code.
EDIT: there is an open source library GDAL which you can use to write raster files in various formats. There are C# bindings.
I think the formulas for computing the center of the upper left pixel are wrong. In the example, the center of the upper left pixel would be down and to the right of (203732,598374). So shouldn't it be the following?
203832 == left edge + 1/2 pixel size (to center on pixel instead of edge of box)
598224 == top edge - 1/2 pixel size (to center on pixel instead of edge of box)