Drawing TTF text in Slick2D at large sizes causes distortion - lwjgl

Note: I am using Scala rather than Java but that should not make a difference.
I recently started using LWJGL and am currently trying to draw 2D strings using the TrueTypeFont Slick class, however when I draw a string using font.drawString(x, y, text, Color.white) at sizes larger than 48, the text gets distorted. Certain letters in the text become lines, and as I increase the size it becomes more extreme. Below is a comparison of font sizes 48 and 72 being drawn:
My code for creating the font is as follows:
val inputStream = ResourceLoader.getResourceAsStream("assets/font/" + file)
val font = new TrueTypeFont(Font.createFont(Font.TRUETYPE_FONT, inputStream).deriveFont(size.toFloat), true)
I have tried this with both built in fonts (Arial and Times New Roman) and custom fonts like the one above, Augustus and they all have the same problem. How can I render these fonts correctly at larger sizes?

Related

Is there a way to have smooth/subpixel motion without turning on smoothing on graphics?

I'm creating this 2D, pixel art game. When the camera follows the player (it uses easing), on the final approach, the position gets several subpixel adjustments.
If I have smoothing ON (on my graphic assets), the graphics look good (sharp. it's pixel art) but the subpixel motion is jerky/jumpy.
If I have smoothing OFF, the subpixel motion is smooth, but the pixel art graphics look blurry.
I'm using Flash player v21. I've tried this with Starling and with Flash's display list.
You have a pixelated object that is moving in increments of less than the pixel size, but you don't want to restrict your mathematical easing to integers, or even worse, factors of 8 or what have you. The solution I am using in my project for this exact issue is posted below (I just got it working last week!)
Concept
create a driver that is controlled by the easing using floating point numbers.
Allow this driver to then control where the actual display object is rendered. We can use a constraint to only allow the display object to render on your chosen resolution.
Code Example
// you'll put these lines or equivalent in the correct spots for your particular needs.
// SCALE_UP will be your resolution control. If your pixels are 4 pixels wide, use 4.
const SCALE_UP: int = 4;
var d:CharacterDriver = new CharacterDriver();
var c:Character = new Character();
c._driver = d; // I've found it useful to be able to reference the driver
d._drives = c; // or the thing the driver drives via the linked object.
// you don't have to do this.
then when you are ready to do your easing of the driver:
function yourEase(c:Character, d:CharacterDriver):void{
c.x = Math.ceil(d.x - Math.ceil(d.x)%SCALE_UP);//this converts a floating point number into a factor of SCALE_UP
c.y = Math.ceil(d.y - Math.ceil(d.y)%SCALE_UP);
Now this will make your character move around 4 pixels at a time, but still be able to experience easing!
The bit with the modulo (%) operator is the key. For instance, 102-102%4 = 100. 103-103%4 = 100. 104-104%4 = 104.
In case anyone is confused by that, look at what 102%4 does: 4 goes into 102 25 times with a remainder of 2. so 102%4 = 2. Then 102 - 2 = 100.
In your case, since the "camera" is following the player (i.e. the background is moving, right?) then you really need to apply drivers to everything in the background instead, but it is basically the same idea.
Hope this helps.
since you specifically mentioned the "final approach" i think your problem comes from the fact that the easing equations puts your graphics at fractional coordinates, especially while getting closer to the target, but you should also notice it during the rest of the animation.
depending on the easing "engine" that you're using you should be able to set a "round values" flag, so all the coordinates set will be integer values and not fractional
if that's not possible, find a way in your display objects to round the x and y values every time they change

Actionscript 3 number drawing recognition

I am working on a game to compare a kid drawing (with mouse or gesture) to numbers from 1 to 9, is converting the drawing to bitmap and compare it with number converted to bitmap a good idea?
and how to handle the difference in size (width-height) between the 2 images?
Thanks
You can do it with image comparison, but it's pretty tricky to get it right.What I would suggest is:
Pre-generate small (10x10 pixels or even smaller) grayscale images of the numbers and blur them a little
Convert drawing to grayscale
Blur drawing a bit
Crop borders from drawing
Resize drawing down to the size of your number images;
Compare the small drawing image with the generated number images, pixel by pixel and be lenient to what you accept as a match.
You can try Mouse Gesture Recognition
var gesture:MouseGesture = new MouseGesture(stage);
gesture.addGesture('B','260123401234');
gesture.addEventListener(GestureEvent.MATCH,matchHandler);
function matchHandler(event:GestureEvent):void
{
trace (event.datas + ' matched !')
}

Why would I want to use unit scale? (Libgdx)

I have looked into the SuperKaolio example on Libgdx github repo. It is basically a test for integrating Tiled maps with Libgdx. They are using the unit scale 1/16 and if I have understood it correctly it means that the world no longer is based on a grid of pixels but on a grid of units (each 16 pixels wide). This is the code and comment in the example:
// load the map, set the unit scale to 1/16 (1 unit == 16 pixels)
map = new TmxMapLoader().load("data/maps/tiled/super-koalio/level1.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 1 / 16f);
I am basically wondering why you would want to do that. I only got problems doing it and can't see any obvious advantages.
For example, one problem I had was adding a BitMap font. It didn't scale at all with the background and one pixel in the font occupied an entire unit. Image here.
I'm using this code for drawing the font. It's a standard 14 points arial font included in libgdx
BitmapFont font = new BitmapFont();
font.setColor(Color.YELLOW);
public void draw(){
spriteBatch.begin();
font.draw(batch, "Score: " + thescore, camera.position.x, 10f);
spriteBatch.end();
}
I assume there is a handy reason to have a 1/16th scale for tiled maps (perhaps for doing computations on which tile is being hit or changing tiles (they're at handy whole-number indices).
Anyway, regardless of what transformation (and thus what "camera" and thus what projection matrix) is used for rendering your tiles, you can use a different camera for your UI.
Look at the Superjumper demo, and see it uses a separate "guiCam" to render the "GUI" elements (pause button, game over text, etc). The WorldRenderer has its own camera that uses world-space coordinates to update and display the world.
This way you can use the appropriate coordinates for each aspect of your display.

In Reporting Services, increase the quality of the background image above 96 dpi

I'd like to use a background image, and when I put it in Reporting Services 2008 R2, the image dpi is reduced to 96 dpi. (instead of 300)
That's too low to be readable by the user, I fear.
When I go on the Internet, I find this result :
http://social.technet.microsoft.com/Forums/en-US/sqlreportingservices/thread/48de91f9-1844-40c1-9614-5ead0b4b69a5#P1Q14
Question 14: How to improve PDF quality of the report exported in Reporting Services 2005?
Answer: The PDF renderer in Reporting Services 2005 resizes all images that it is given at 96 DPI no matter what DPI the image is when
you pass it to the renderer. That means that a 300 DPI image or even a
600 DPI image will be sized in the PDF as if it is only 96 DPI. In
other words, your high DPI image may render larger than expected.
Despite sizing the images as if they were 96 DPI, the PDF renderer
appears to render higher DPI images at a higher quality than 96 DPI.
Even if the sizing being wrong, the image actually is rendering at a
higher quality. A necessary workaround is to size the image to the
proper number of inches based on 96 DPI calculations. Then use
Bitmap.SetResolution to set the images to at least 300 DPI. That may
provide a higher quality image that is the proper number of pixels to
fit properly in the report.
But I don't know how to use that Bitmap.SetResolution, I'm using the classic report viewer web control and I need really a fully functional pdf export.
PS : Maybe that issue is resolved in Reporting Services 2012. Does someone has some informations ?
Regards
I found a webpage which explain how to export PDF with a good dpi. http://codeproject.com/Articles/95750/High-fidelity-printing-through-the-SSRS-Report-Vie
The key is to initialize the deviceInfo string with a xml code
var sb = new System.Text.StringBuilder(1024);
var xr = System.Xml.XmlWriter.Create(sb);
xr.WriteStartElement("DeviceInfo");
xr.WriteElementString("DpiX", "296");
xr.WriteElementString("DpiY", "296");
xr.Close();
deviceInfo = sb.ToString();
rsExec.SetExecutionParameters(parameters, "fr-fr");
results = rsExec.Render(format, deviceInfo,
out extension, out encoding,
out mimeType, out warnings, out streamIDs);
In this case, this solution works. I can generate a pdf file with the good dpi BUT the print button with activex doesn't work (this shouldn't be a problem) and the export button either. I have to add a download button to print. that's a partial solution imho
If you use the WebAPI interface to Reporting Services, I found this way works:
In order to get better PDF rendering of Images, pass the Device Info like this: http://serverName/ReportServer?/pathtoReport/ReportName&InvoiceIdOrOtherParameter=24013&rs:Command=Render&rs:Format=PDF&rs:DeviceInfo=<DpiX>300<%2FDpiX><DpiY>300<%2FDpiY>
The answers above led me to this, but I wanted to clarify for those using different coding platforms. The goal is to build the following string to be sent as the DeviceInfo parameter:
DeviceInfo = '<DeviceInfo><DpiX>300</DpiX><DpiY>300</DpiY></DeviceInfo>'
By doing this, I was able to use a 300dpi image as a background image and render correctly to pdf, although you'll want to find a way to hide the image while you are designing in reportviewer as the preview still shows it much larger.

slightly blurred text and bitmaps AFTER 3d transformation

I have a series of movieclips containing both bitmaps and text.
After applying some 3d transformations and moving in 3d space, my text and bitmaps are slightly blurred. This is AFTER I reset all the 3d coordinates (ie z=0, rotationX=0, rotationY=0)
Has anyone else encountered this? Is there a solution to get my crisp text and bitmaps back?
this is a very interesting error.
the blur that appears is actually improper anti-aliasing, or smoothing that is usually solved by rendering the font with fine colors along the edges. in this case, it is in fact caused by 3D transformations and can be solved by nullifying the matrix3D after the animation:
myTextContainer.transform.matrix3D = null;
you could also write:
myTextContainer.transform.matrix = new Matrix();
but with this approach you'll have to import flash.geom.Matrix.
both options will also reset to zero the x and y coordinates, and possibly other important settings of the animated display object, so you'll also have to assign those values to variables and reapply them after nullifying the transform matrix.
it seems that once a font is transformed, it loses this fine color tinting. non transformed fonts have these color details while transformed fonts become completely desaturated.
attached is a zoomed in detail of 12 point font which exhibits this loss of color detail. the top string has no 3D transformation while the bottom string was animated onto the stage via rotationY.
here is the same image saturated to 90% to show the colors more clearly:
these color details are easier to see on grey text.
i believe this error has been present since Flash Player 9 / AVM2 was first introduced. additionally, the fine color detail around the properly rendered font was much more saturated in early versions of the Flash player, which, in my opinion, made the fonts look much better - although the difference could be considered negligible by non perfectionists unlike myself.
You need to make sure you set the matrix3D property to null on any objects that you've applied 3D transformation to.
Looking up another post on 3d issues and came across the solution.
You need to remove all 3d transformations by applying a new transfrom.matrix
var tempMatrix:Matrix = new Matrix();
this.transform.matrix = tempMatrix;
An Even better answer is to use this fix. It's one I used to use all the time.
/**
* Fixes the slight distortion that occurs when an object has a 3D transform associated with it.
* #param di:DisplayObject The DisplayOjbect to fix.
*/
public function fix3DBlur(di:DisplayObject):void {
di.scaleX = di.width / (di.width - 1);
di.scaleY = di.height / (di.height - 1);
}
This function sets a slightly offset scaleX and scaleY. It seems weird, but they when you make 3d adjustments to the object using any 3d property it keep it from looking blurry. You can always remove the 3DTransform, but sometimes you need it to stay in place.
I place this function on a Utilities3D class I have.