Posts tagged “math”
 
Kip Side projects

Here’s an update on a few side projects I have going. First, you may remember QuickReplace. As I used it myself, I realized that there were some limitations, which I set out to address. So now we have QuickReplace 2.0. One thing I found myself doing with QuickReplace was opening it in several tabs, pasting text in the first tab, copying the output and pasting it in the next tab, because each tab could only run one filter at a time. But now, instead of having a fixed number of filters, which are executed in a fixed order, you can add as many filters as you want. The filters can be dragged and dropped in whatever order you want. And, if you want to save a filter and run it later, there is now a permalink option to do so. As before, the tool was written for me by me, with the assumption that the user (me) knows what they want to do. If you’re a programmer and you understand regular expressions, you should be able to figure it out. I’ve been using the new version for about a month and I think I’ve ironed out all the bugs, but if you find one let me know and I’ll take a look. Unless your “bug” is that it doesn’t work in a browser other than Firefox or Chrome. In which case the bug is that you’re using the wrong browser. (That being said, it seems to work just fine in IE, Safari, and Opera, but I haven’t tested extensively.) Also, the HTML file is self-contained, so you can save it locally if you’d like. (But you can’t run it offline because of a dependency on Google-hosted jQuery.)

The other side project I’ve made some updates to is my gradient generator. The previous version would generate horizontal or vertical gradients. But then I started thinking, wouldn’t it be better if it generated diagonal gradients too? So I worked out the math and made it happen. Now, instead of an “orientation” parameter that takes either “h” or “v”, we have an “angle” parameter, which takes a number in degrees (from 0 to 360, inclusive). It still takes “h” or “v”, for backwards compatibility—”h” is converted to 0, and “v” is converted to 90.

I added an extra parameter, “extend”. If it is false, the image is only as large as it needs to be to hold the gradient. This is OK if the image is being used as the background of a fixed-size element, but otherwise you won’t see the whole gradient. This is where the extend parameter comes in. If it’s set to true, you will see the whole gradient.

So here’s what it looks like without the extend parameter:

You might also notice that the y axis is inverted. That’s just how images are oriented, and I didn’t correct for it since I figure the most common case is a gradient oriented in the top-left corner. Now, if the gradient is extended, it will look like this:

You can view the gradient generator source code here.

Of course in a few years, when CSS 3 gradients are fully supported, my gradient generator will be obsolete. Oh well.

No Comments | Add Comment
Kip Mexican food

I have devised a very simple scale for evaluating Mexican restaurants. There are only two points of evaluation:

1. Are the fajitas sizzling when they are brought to your table? If so, the restaurant gets 25 points.

2. Are the tortillas there as soon as the fajitas are brought to the table? If so, the restaurant gets 75 points. (Score no points if you have to sit there and watch your fajitas sizzle out (assuming they were sizzling in the first place) waiting on the waiter to bring out the tortillas.)

For those of you who aren’t mathematically inclined, the only scores possible are 0, 25, 75, and 100.  0 and 25 are equivalent to an F-.  75 is a C. 100 is an A+.

No Comments
Kip ImageSizer

I wrote a program last week for resizing images so that they can fit onto a two-monitor desktop, and I figured I’d share with the world before heading to the beach.  This program does more than just resize an image, though.  It accounts for the gap between the two monitors, so that it looks much more like you are looking through the monitors.  Most of this post will consist of an explanation of what exactly that means and why you’d want to do it.

Okay, for starters let’s say you have two monitors sitting side-by-side.  In our example, these monitors each have a resolution of 304×228 pixels, giving a resolution of 608×228 for the entire desktop.  Here is what that looks like:1

Blank two-monitor example

Now, let’s say you want to use this photo of the Gizah pyramids by Ricardo Liberato, the #21 finalist for Wikimedia Commons Picture of the Year 2007, as your wallpaper.  Here is what the photo looks like initially:

A great photo of the Gizah pyramids

There is a problem here, because that’s not the right proportion, so you’d want to crop out a portion of the image that is the right proportion.  Here is a cropped portion that is the proper ratio and size (608×228):

The Gizah pyramids photo, resized to 608×228

Now, let’s use that image as our desktop wallpaper on our dual-monitor setup:

The Gizah pyramids stretched across a two-monitor setup

I don’t know about you, but I find this very aesthetically displeasing.  Suddenly the pyramid is not shaped like a pyramid anymore!  Your mind expects the image to continue through the space between the monitors, but it actually just picks up where it left off on the edge of the other screen.  In fact, it kinda makes it look like there is a fourth, smaller pyramid, between the first and second one.

So here’s where my app comes in.  We need to figure out how wide that gap is, in pixels.  If you knew the dpi of your monitor, you could measure the gap in inches and calculate the number of pixels.  But if you don’t know that, here’s how I measure it.  Open up any kind of image editing app (Paint will do just fine).  Place the window so that it straddles the gap between monitors.  Draw a 45-degree line that spans the monitors.  It is very important that the line be exactly 45 degrees (you can hold control or shift or something to fix the line to 45 degrees in most image editing apps).  Now, hold something with a straight edge (say, a piece of paper) so that it lines up with the line on one monitor.  Holding the straight edge there, click somewhere on the other monitor, where the line would be if it was accounting for the gap, and draw another 45-degree line starting from there.  Now measure the vertical distance, in pixels, between the two lines.  This will be equivalent to the horizontal distance, in pixels, between the two monitors.  For our example, here is what that might look like:

Example of measuring gap between monitors

You can see the solid black line is “straight” if the gap is not accounted for.  However, the dashed line shows how the line would behave if the gap was considered to have a width.  The distance between the dashed line and the solid line on the right-hand monitor is 50 pixels, so that is the width of our gap.  So now, let’s use my app:

1
java -jar ImageSizer.jar pyramids.jpg -monitorWidth 304 -height 228 -gap 50

This will generate pyramids.resized.png, which looks like this:

Gizah pyramids resized by tool, accounting for gap

When we use this image as our desktop wallpaper, we get an image that looks correct:

The Gizah pyramids stretched across a two-monitor setup, accounting for the gap between the monitors

If you’d like the program, you can download it right here.  But before you use it, here are a few things you should know:

  • You may get OutOfMemory exceptions on very large images.  If this happens (thanks Peter), you can increase the Java heap size from the command line like this:
        java -Xmx256m -jar ImageSizer.jar ....
    If that still doesn’t work, increase the 256 to a bigger number.  It is important that the -Xmx parameter comes before the -jar parameter, so that Java knows it is a parameter to the JVM and not to the ImageSizer.

  • When the image is not the proper proportion (which will be nearly all the time), it will crop from the middle of the image.  In many cases, this will be a less-than-ideal cropping.  If that happens, you should crop the image the way you want it cropped first.  (The tool will still help you out because removing the middle of an image is much more tedious.)

  • Your monitors must be of equal resolution.

  • Supported file types are .jpg, .png, and (I think) .bmp and .gif.  (I’ve only tested jpg and png myself though.)

  • Output file will always be .png format, even if a different extension is used on output file.  This is important because a lossy compression can cause some pixels to “bleed” between the monitors.

  • There is only support for two-monitor setups.

  • If you want to modify the code, feel free to do so.  You can even redistribute if you want, just be sure to leave my name and URL in the comments and help info.  The source is included in the jar file (open it as a zip file).  There are only two Java files.

  • There is a good chance there are some bugs, as this was written in two evenings, with a fourteen-month-old competing with the computer for my attention.  The vast majority of that time was spent trying to figure out how to use the Java image libraries.  I probably could have written this in PHP in an hour, but I didn’t want to use PHP from the command line, and I didn’t want to have to upload large images.

1 yes, these monitor images are stolen from Windows XP display settings
Kip Free code giveaway

I added some code to the site to improve the way source code is displayed, both in snippets in my blog and when viewing an entire file directly.  I’m adding line numbers on the server-side, but they are in a separate div so you won’t end up copying the line numbers if you copy and paste the code.  The syntax highlighting is all done in Javascript by prettify, an open-source library provided by Google.  After getting around two annoying jQuery bugs (one which is only present on IE6, and another which was fixed by upgrading to the latest jQuery level) I got it up and running, and it looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
  /**
   * Returns 1/this.
   * 
   * @throws ArithemeticException if this == 0.
   */
  public BigFraction reciprocal()
  {
    if(numerator.equals(BigInteger.ZERO))
      throw new ArithmeticException("Divide by zero: reciprocal of zero.");
    
    return new BigFraction(denominator, numerator, true);
  }

Anyway, I figured I’d show off the full-file view with some source code you’re free to use if you want to.  You can find the BigFraction class I wrote in Java when working on some Project Euler problems.  The class represents a fraction as a ratio of two BigIntegers, so it will never overflow, and there will never be roundoff error.  It was fun to write, because it involved lots of math and manipulation of base-2 numbers (especially for the constructors which took one or two double variables), and I’m one of those weirdos who really likes those things.  This works in all the Project Euler problems I’ve used it in, and I’ve done some pretty exhaustive ad-hoc testing, but there’s still a good chance I’ve missed a bug or two.  Especially since I didn’t bother writing any unit tests or anything (hey, this is spare-time coding!).  If you use this and happen to find any bugs, let me know.  And of course, I need to close with:

Disclaimer: the BigFraction class is provided as-is with no warranty expressed or implied.  If you use it to calculate missile trajectories and end up nuking the wrong city, you shouldn’t come whining to me.

No Comments | Add Comment
Kip Little things

This post is to let you know about several small tweaks to this site that I’ve been working on lately, even though you probably don’t care at all. :)

One of the cooler things is that I’ve written some PHP code to programmatically generate gradient images.  If you’ve looked around the web you know that gradients are essential to modern web design, and I figure there’s no need to fire up Photoshop everytime I need one.  (Now if I can just write a glossy floor generator I’ll be totally web 2.0 compliant.)  You can view the gradient generator source code, if you’d like.  Of course, this kind of thing is so easy to do with PHP and a bit of 7th grade math that it’s almost not worth posting.  But I figured I’d share anyway.

Thus far I have put these gradients into action in two places on this site: as sexy new comment headers (as seen here, for example); and in the background of any picture in our photo album.

I can’t remember if I ever posted about this, but I wrote some Javascript a while back which is currently in use on the photos page, which scales the photo to fill your browser.  jQuery is awesome.  (And every modern browser1 can scale images without making them look grainy.)

I’ve also fixed the bug with the stored name/e-mail from adding a comment.  I have to apologize for the accidental breach of privacy, which would have exposed your e-mail address to other visitors to the site for up to an hour after your visit.  Now the name/e-mail fields are filled in by Javascript, so they are not cached server-side.

Another small change is that timestamps on posts and comments are now converted to your local timezone.  You can still hover over the timestamp to see an ISO-8601 timestamp, part of the datetime microformat I adopted when I added hAtom support.  Speaking of which, I finally found a way to validate hAtom: there is a site, transformr.co.uk, which will take a URL to a page supporting hAtom, and it will generate a true atom feed for it.  Here is mine.  I’m still not sure who would benefit from that though.  If you know enough to use the hAtom feed, then you probably know enough to click the little feed icon in the address bar too.  Oh well, it’s there if you want it.

1 I don’t consider IE6 to be a modern browser.
Kip Java overload

Something I learned today: overloaded method resolution in Java is done at compile-time, not runtime.  Warning: if you have no idea what half the words in that sentence meant, then you probably don’t care about the rest of this post.

Let’s say Alice (who is in tons of hacking books for some reason) wrote this code:

1
2
3
4
5
6
7
public class Alice
{
  public static long roundToNearestFive(long n)
  {
    return Math.round(n / 5.0) * 5L;
  }
}

And let’s say Bob (who totally has a thing for Alice even though she says they are just friends) wrote this code:

1
2
3
4
5
6
7
public class Bob
{
  public static void main(String[] args)
  {
    System.out.println(Alice.roundToNearestFive(12.7);
  }
}

When Bob runs his code it will print 10, since 12.7 will be silently converted to an integer (12) to be passed into roundToNearestFive(), and 12 is closer to 10 than to 15.  Bob could call roundToNearestFive( Math.round(12.7)) to fix this, but that is annoying because now he has to first round his floating-point numbers before passing them into a rounding function.  So Bob asks Alice to provide a fix, and she adds a version of the function which takes a floating-point number:

1
2
3
4
5
6
7
8
9
10
11
public class Alice
{
  public static long roundToNearestFive(long n)
  {
    return Math.round(n / 5.0) * 5L;
  }
  public static long roundToNearestFive(double d)
  {
    return Math.round(d / 5.0) * 5L;
  }
}

She sends a new .jar file to Bob with the change, and he runs his code again, expecting it to now output 15.  But it still prints 10.

The problem is that when Bob compiled his code, there was no roundToNearestFive(double) function available.  So the compiler generated bytecode that looked something like Parent.roundToNearestFive( (long)12.7).  So even when he runs with Alice’s new code in place, the bytecode is still forced to call the integer version of the function.  The only solution for Bob is to recompile his code against the new .jar file sent from Alice.

For further reference, here is the spec for binary compatibility in Java.  And here is more information about Alice and Bob.

No Comments
 
 
 
RSS feeds: Kip's - Stephanie's - Both