Jun 23 2012

Image comparison with CSS

Category: Software,WebdevelopmentSpiller @ 16:07

As I’m browsing the web I sometimes tend to look at the source of the webpages and if it is questionable I consider how this could be improved. However at times it is just to painful to watch…

This website was reviewing Blue-Ray releases of TV broadcasts and showed the differences by overlaying screenshots from the TV and BD versions. When you hovered over them with the mouse, the image switched. This was implemented like this:

<style>
  .himage
  {
    -webkit-transition: opacity .4s ease-in-out 0s;
    -moz-transition: opacity .4s ease-in-out 0s;
    -o-transition: opacity .4s ease-in-out 0s;
    transition: opacity .4s ease-in-out 0s;
  }
</style>
<div style="position:relative;">
  <img src="http://i.minus.com/j5BVlrAz0767W.jpg" width="640" height="360" />
  <img class="himage" src="http://i.minus.com/j0KF3taUebpkC.jpg"
      width="640" height="360" onmouseover="this.style.opacity=0;"
      onmouseout="this.style.opacity=1;" style="position:absolute; top:0; left:0;"
    />
</div>

Instead of having the CSS in the style sheet as it should, it is unneeded repeated like this for every image. It also uses the style attribute on the elements which is also considered bad practice. (XHTML 1.1 actually deprecated it, but nobody uses that anyway…) I don’t see why you would use JavaScript here either when it is just a simple hover effect.

The HTML can be much simpler:

<div class="himage">
  <img src="http://i.minus.com/j0KF3taUebpkC.jpg">
  <img src="http://i.minus.com/j5BVlrAz0767W.jpg">
</div>

As you can see, the only requirements to do this in CSS is a container and a way to identify this container, here done with a class. The CSS is much the same, just not done as attributes:

.himage{ position: relative; }
.himage img{
  -webkit-transition: opacity .4s ease-in-out 0s;
  -moz-transition: opacity .4s ease-in-out 0s;
  -o-transition: opacity .4s ease-in-out 0s;
  transition: opacity .4s ease-in-out 0s;

  opacity: 0;
  position:absolute; top:0; left:0;
  max-width:640px;
}
.himage img:first-child{
  opacity:1;
  position: relative;
}
.himage:hover img{ opacity:1; }

There are some differences however:

  • The JavaScript have been replaced with the :hover selector (which is the last line).
  • Instead of specifying a fixed width and height, max-width have been used. The browser automatically resizes it to keep aspect ratio. (which was slightly wrong btw…)
  • To keep the HTML as clean as possible, the :first-child selector was used to differentiate the first and second img element. :last-child would have made the CSS simpler, however it is not supported in older versions of IE.

Live versions

You can watch the two versions here:

Note: The CSS is included in the HTML for ease of distribution, it should of course be in the style sheet.

Edit: My version behaves a bit differently, the hover area is the whole div and not just the img, if you want the same effect change .himage:hover img to .himage img:hover.

Compatibility

I cannot currently test it in IE7 and IE8 (and I don’t care about IE6), however I think it should work if you take the following in account:

  • The :first-child selector is supported from IE7, but not on content which have been inserted with JavaScript.
  • opacity is not supported in IE5-8, you will have to use MS filters in addition to opacity to get it working there. It is two extra lines of CSS for each time opacity is used, see this article on how to do it: quirksmode.org: opacity – IE compatibility note
  • The CSS3 transitions effects degrade gracefully. IE support will be in IE10, prefix not necessary (source).


Jun 19 2012

RICcreator – pugixml

Category: Lego,Mindstorms,Programs,RICcreator,SoftwareSpiller @ 01:22

Since I’m not working actively on RICcreator in the moment, not much have happened the last few months, however I just rewrote some terrible code which was not safe. RICcreator would crash if the settings.xml file is formed differently than expected, so when a new version changed the format, it would crash if the old .xml file was kept.

XML handling

The XML parser previously used was rapidXML which promises great performance, and since I want to do some game related programming with XML I wanted to learn the API. However as I tried to use it with RICcreator I quickly realized it was rather tedious to work with. So I slacked on the implementation. Most importantly, I didn’t do any validation and simply chained the node lookups. So for example to get to the “settings” node in the “RICcreator” node I did this:

doc.first_node( "RICCreator" )->first_node( "settings" )

However if first_node() can’t find the node it returns NULL and in case of this the second call will try to dereference a NULL pointer and crash the application. To avoid this it should have been done like this:

xml_node<>* root = doc.first_node( "RICcreator" );
if( root ){
  xml_node<>* settings = root->first_node( "settings" );
  if( settings ){
    //Process it here
  }
}

This is quite some code for a simple lookup, so as said I slacked. Adding nodes to a new document (when saving the settings) was even more tedious as you had to allocate nodes and then add them. (On the other hand, I couldn’t slack here.)

So I have been looking for a simpler C++ XML parser and recently I heard about pugixml. I like the API much better, it is also a lightweight parser and apparently even faster than rapidXML so I tried it out. The previous lookup would look like this in pugixml:

doc.child( "RICCreator" ).child( "settings" )

This doesn’t share the problem rapidXML has, because child() returns a “NULL” object on failure. The NULL objects functions all return another NULL object, so you can chaining like this is completely safe as long as you check the final result.

So I have rewritten all XML handling to use pugixml now and I’m quite happy with the result. The code is a lot prettier and most importantly, it shouldn’t be able to crash like before.

Other changes

The dithering have been changed to use Filter Lite instead of  Floyd-Steinberg, which produces nearly as good result but which is quite simpler (and therefore faster).

A fun addition is grayscale importing support. If you want to toy around with grayscale images on your NXT, RICcreator makes this easy by letting you import the same image several times with different thresholds in one step.

The Number opcode is now no longer aligned to multiples of 8, as this limitation has been removed in the enhanced firmware.

A few bugs have been fixed and it should be possible to compile in Visual Studio again. (I haven’t checked after rewriting the XML stuff though.)

Download

Revision 165 win32: RICcreator rev. 165 – win32.zip

Revision 165 source:  RICcreator rev. 165 – src.zip

Tags: , ,