# Friday, March 19, 2010

UPDATE : This code doesn't work properly, go here for a properly working one.

I needed to resize an image in Silverlight and then save it out as a JPEG. I could have just used a transform on it then rendered it to a WriteableBitmap but the transforms were optimized for realtime performance and doesn't work too well when you need to maintain quality.

I stumbled upon a Bicubic Resize code in a library called AForge.Net and it was in C#, so it was simple enough for me to convert it to VB for me to use it in Silverlight. And since I DIDN'T find a lot of Bicubic Interpolation .Net resize code on the net, I'm gonna just put this copy up here.

As a bonus I kept on my comments in so you guys can see what was going through my head as I was working my way through the code.

Bicubic Interpolation
''' <summary>
  ''' Bicubically resize the src bitmap to the dest bitmap
  ''' </summary>
  ''' <param name="src"></param>
  ''' <param name="dest">Destination Bitmap, should be initialized to the requested size.</param>
  ''' <remarks>Original Source For This Function - http://www.codeproject.com/KB/recipes/aforge.aspx</remarks>    
  Sub Resize(ByVal src As Imaging.WriteableBitmap, ByVal dest As Imaging.WriteableBitmap)

      Dim startTime As DateTime = Now


      Dim srcwidth As Integer = src.PixelWidth
      Dim srcHeight As Integer = src.PixelHeight

      Dim destWidth As Integer = dest.PixelWidth
      Dim destHeight As Integer = dest.PixelHeight

      Dim xFactor As Double = srcwidth / destWidth
      Dim yFactor As Double = srcHeight / destHeight

      'Coordinates of src points and  coefficients.. WTF?
      Dim ox, oy, dx, dy, k1, k2 As Double
      Dim ox1, oy1, ox2, oy2 As Integer

      'new color values
      Dim r, g, b As Double

      Dim xmax As Integer = srcwidth - 1
      Dim ymax As Integer = srcHeight - 1

      For y As Integer = 0 To destHeight - 1
          'this is getting the original Y pixel if I'm not mistaken
          oy = y * yFactor - 0.5F
          'WHY is this necessary?
          oy1 = oy
          'WTF? It's getting the FRACTIONAL difference between
          'oy and oy1?
          dy = oy - oy1


          For x As Integer = 0 To destWidth - 1
              'same WTF as with the Y values,
              'maybe will make more sense later?
              ox = x * xFactor - 0.5F
              ox1 = ox
              dx = ox - ox1

              r = 0
              g = 0
              b = 0


              'this loop is to gather the interpolated
              'values of 2 pixels surrounding the current one
              For n As Integer = -1 To 2
                  'this gets the Y coefficient

                  k1 = BicubicKernel(dy - n)

                  'this seems to be getting the new
                  'Y pixel where the interpolated
                  'value comes from
                  oy2 = oy1 + n

                  'this is to ensure we're in the right spot
                  If oy2 < 0 Then
                      oy2 = 0
                  ElseIf oy2 > ymax Then
                      oy2 = ymax
                  End If

                  For m As Integer = -1 To 2
                      'for X coefficient
                      k2 = k1 * BicubicKernel(m - dx)

                      ox2 = ox1 + m

                      If ox2 < 0 Then
                          ox2 = 0
                      ElseIf ox2 > xmax Then
                          ox2 = xmax
                      End If

                      'get original pixel color
                      ' Dim origColor As Color = source.GetPixel(ox2, oy2)

                      'writablebitmap pixel is AARRGGBB
                      Dim srcColor As Integer = src.Pixels(ox2 + (srcwidth * oy2))


                      'set interpolated values
                      r += k2 * ((srcColor >> 16) And &HFF)
                      g += k2 * ((srcColor >> 8) And &HFF)
                      b += k2 * (srcColor And &HFF)
                  Next
              Next

              'after calculating coefficients we have our new color               
              dest.Pixels(x + (destWidth * y)) = &HFF000000 Or (r << 16) Or (g << 8) Or b


          Next
      Next
      dest.Invalidate()
      Dim endTime As DateTime = Now
      Diagnostics.Debug.WriteLine(String.Format("Time taken to squish {0}x{1} to {2}x{3} : {4} seconds", srcwidth, srcHeight, destWidth, destHeight, endTime.Subtract(startTime).TotalSeconds))

  End Sub

  Shared Function BicubicKernel(ByVal x As Double) As Double

      If x > 2.0 Then
          Return 0.0
      End If

      Dim a, b, c, d As Double
      Dim xm1 As Double = x - 1.0
      Dim xp1 As Double = x + 1.0
      Dim xp2 As Double = x + 2.0



      If xp2 <= 0 Then
          a = 0
      Else
          a = xp2 * xp2 * xp2
      End If

      If xp1 <= 0 Then
          b = 0
      Else
          b = xp1 * xp1 * xp1
      End If

      If x <= 0 Then
          c = 0
      Else
          c = x * x * x
      End If

      If xm1 <= 0 Then
          d = 0
      Else
          d = xm1 * xm1 * xm1
      End If
     
      Return (0.16666666666666666 * (a - (4.0 * b) + (6.0 * c) - (4.0 * d)))

  End Function

There's one caveat though, I didn't do any Alpha premultiplication with this code, which basically means if your images have a non FULLY opaque region, the results won't be pretty. Here's your homework assignment if you want to have that functionality.

I learnt 2 things while porting this code.

  1. Don't use Math.Pow() if your code is time sensitive, ie. it needs to work REALLY REALLY fast. Like in a game render loop. Takes a bit longer to run math.pow(x,3) instead of x*x*x. Not saying you shouldn't use it, just don't use it when MILISECONDS matter.
  2. Visual Basic's IIF statement isn't good for performance as well since BOTH true and false statements seem to be evaluated and does execution time is wasted when execution time matters. Better to use the usual IF..ELSE..ENDIF construct.

After my little exercise in dabbling with this, THEN I find a WriteBitmapEx library which pretty much seems to be a very useful class for raw manipulation of images in Silverlight, check it out!


Friday, March 19, 2010 12:24:20 AM (Malay Peninsula Standard Time, UTC+08:00)  #    Comments [0]  | 
# Sunday, March 14, 2010

Now that I've made my mobile hotspot belt, and then having everyone say... it's a terrorist's suicide belt. My aim was now to make the thing NOT look like I want to blow myself up with it. So again I head down to Daiso to see what kind of weird shit I can find and use.

Why do I love going to Daiso? Because for a crazy person like me, it's a supermarket filled with things I can use for my ideas and all going for a single price of RM5 so I don't have to think too much about how expensive the item I'm cutting up. And also, when I buy something I can think of it's FUNCTION and not of it's PRICE. So.. from today's shopping.

First of is a open ended measuring tape on belt carrying case.

DSC06287

Which I turn into my mobile router carrying case

DSC06292

COMPLETE with easy access holes for the power and USB ports.

DSC06293

A closed version of the measuring tape carrying case.

DSC06288

Is used to house the smaller 6V battery.

DSC06294

An old MiniDisc belt case.

DSC06286

Due to it's stretchable nature, can be used to carry the bigger 6V SLAB.

DSC06289

This is what the belt now looks like when multiple components are attached to it.

DSC06300

More like some dumb ass wearing way too much on his belt, less like some house made explosives. Some wiring is still exposed but most people wouldn't notice it unless they stare at it for too long.

The back of the belt where the power wires run along is covered by some felt and held in place with some velcro strips.

DSC06299

So, less exposed wiring means less people freaking out. :P While the belt works and looks proper now, I found a problem with the construction. The power jack that connects to the mobile router is too loose, it's easily jostled and causes the router to loose power long enough to cause a reset. I'll need to way  of securing the power plug to the mobile router if I want to use it this way.

Then I took a quick look back at my little insect cage layout.

DSC06301

And I realized that it's actually a pretty good configuration. First of all, as the components are more or less secured in the cage, they don't jostle around that much and thus the power jack stays put. The reason the router stays put is because of this.

DSC06303

The USB modem almost touches the edge of the cage, so it acts as a support and stops the router from slipping around in the cage.

DSC06304

While the larger 6V battery does slip around if there's too much movement, it's cushioned from the router by the strap securing the router. Unfortunately during my latest testing I noticed that when the router get's uncomfortably hot, heat is transferred to the top of the battery. Not very cool since there's a "Do not overheat above 60 degrees Celsius"  warning on the battery. Must see if I can do anything about that.

The cage design also allows for me to reach the power switch to turn the whole system on or off.

DSC06307

I guess I should stop trying so hard to make a wearable mobile router solution, and work more on how to make a proper transportation case for the whole setup so I can just throw it into a bag. :P


Sunday, March 14, 2010 7:52:38 PM (Malay Peninsula Standard Time, UTC+08:00)  #    Comments [2]  | 
# Saturday, March 13, 2010

Today I went to pick up some parts to complete my Mobile Hotspot Project, first of all I decided to get a smaller sized battery since the one I had original, is big and bulky. So I wanted to get something that's smaller and easier to carry around.

DSC06275

So I got this, 6V 1.2AH battery. My first surprise was that while the battery capacity was about 1/4 of the big battery, it costs TWICE as much! While I was soldering the connection wire I learnt something new. I should solder the connector first, before soldering the wires to the battery. Because I soldered the wires to the battery first while I was soldering the connector... I shorted the connection with my soldering iron, sparks flew! Good lesson...

So after the smaller battery was completed and tested to be working I created the other component which I wanted to make.

DSC06276

A 4AA battery holder, with normal alkaline batteries these would theoretically give out 6V of power which should be more than enough to power the router. I measured the current with a multimeter and got a nice reading of 6.6V, So I went ahead and plugged it to the router. And I was happily surfing the net with AA batteries.... for about 10 minutes. Then the router started flickering on and off, a good indication of low power scenario. I unplugged the batteries and measured the power output and I got... 5.5V!?!?!?

I figured it's because that when an alkaline battery is used out the voltage gradually decreases on a slope. Unlike a rechargeable battery which is at the same voltage for most of it's usable lifespan and then drops. I guess the way is to introduce more power into the loop.

Luckily I was prepared for this scenario. While I was thinking of using AA batteries to power the setup, I was planning to use rechargeable batteries. But.. a rechargeable AA battery only has a voltage capacity of 1.25V, 4x1.25V = 5V. Cutting it a bit close so I thought of an idea, which is to make a power booster to bump up the voltage.

DSC06277

This battery case will be linked in series to the power source it's connected to, boosting the voltage of whatever it's connected to by 3V. Once I plugged this in I can again power the router... for a while, once again I could see a very drastic drop of power in the alkalines once hooked up to the router. It's obvious that alkalines aren't the best source of power to be used in this scenario.

I then decided to work on a power switch so I can turn power on and off when I wanted to without having to disconnect the power source to the component.

DSC06278

You might have noticed that each piece is more or less interchangable. This allows me to have some form of extendable system, for example I can have the router powered by 4AA batteries, as well as controlled by the power switch.

DSC06280

Then if needed to, I can plug in the booster pack.

DSC06282

Depending on the situation, I can plug in an extension wire, and then the lightweight 6V battery.

DSC06283

The reason I needed this extensibility was because I had a crazy idea, and it involves this thing.

DSC06284

A belt strap... cause I want to try and do this.

DSC06285

Hook everything up to it and really carry it around in a portable manner, the problem of course is that if people saw a SLAB strapped to someone, they probably would think that I'm a suicide bomber or something!

Anyone have a good idea to make a belt like this look less like a suicide belt?


Saturday, March 13, 2010 9:51:42 PM (Malay Peninsula Standard Time, UTC+08:00)  #    Comments [0]  | 
# Friday, March 12, 2010

There are times when I wish I had more training and understanding about how to build electronic hacks. Especially at times when it involves AC current.

DSC06270

Here I've taken an AC/DC adapter, replaced it's head with a composite jack.

DSC06271

Just so I can charge the SLAB I gotten for my portable hotspot project.

DSC06273

And I don't think I chose a safe spot to do it too!

DSC06272

Well, power should flow from the higher 7.5V of the adapter to recharge the lower 6V of the battery.. I THINK! The charging method matches what Adrian used in his battery extender project. But heck, I'm not sure if I done everything right!

Also, the power adapter is FICKLE!! Sometimes when I turn it on it pumps out 3.5V, sometimes.. it pumps out 7.5V.. it's weird! And... how do I know if the battery is being charged? Well... the adapter was hot for a while. And I think at charge the battery has a 6.5V rating.

Maybe I should abandon project Mobile Belt?

image


Friday, March 12, 2010 10:26:41 PM (Malay Peninsula Standard Time, UTC+08:00)  #    Comments [0]  | 

DSC06269

Just one more!


Friday, March 12, 2010 9:50:27 AM (Malay Peninsula Standard Time, UTC+08:00)  #    Comments [0]  |