mandag 21. mai 2012

Image zooming

A friend of mine posed the following problem to solve for his VB-in-Excel application:

In a view of 846 x 660, an image is rendered. By clicking anywhere on the image, zoom is multiplied by 1.2. However, and this is the important part, the part of the image clicked on shall remain the center of the zoom and remain in place of the part of the view clicked - i.e. directly below the mouse.

Since I'm not a VB-coder, my reply is in C-like quasi code.

Input data


To solve the problem, we need to be absolutely clear about what the input data is, which in turn is dependent on the source of the data. We start off with the follwing information:
// STATIC DATA
int imageWidth, imageHeight;              // Size of source image
int viewWidth=846, viewHeight=660; // Size of onscreen view 

// VARIABLE DATA
// Position of view/sliders on the projected (zoomed) image
int scrollX, scrollY;
// Size of projected (zoomed) view/sliders
int scrollWidth, scrollHeight;
// Bar/slider size represents the view compared to projected image
int barWidth=viewWidth, barHeight=viewHeight;
float zoom=1; // Current zoom
Then you have the mouse click. We need to know two things from the click: Visually where in the view you clicked (viewX,viewY where top left of view is 0,0), and what position this represents in the image (imgX,imgY). The image coordinates can be calculated from viewX,viewY this way:
int imgX=(viewX+scrollX)*zoom, imgY=(viewY+scrollY)*zoom;
However, in my friend's case, the input data had the entire zoomed image as its reference, so top left of entire zoomed image represents 0,0 and bottom right (with sliders also bottom right) represents scrollWidth,scrollHeight. Hence, the parameter representing the clicked position (clickX,clickY) is the position in the view (viewX,viewY) PLUS the position of the slider bar (scrollX,scrollY).

Since we need to know the actual visual position on screen, relative to the top left corner of the view, the two coordinates must be calculated as such:
// Position unzoomed to fit zoom=1
imgX=clickX/zoom; imgY=clickY/zoom;

// Pos. shifted to visual position
viewX=clickX-scrollX; viewY=clickY-scrollY;
User control

New zoom is calculated per policy defined by my friend - basically:
int zoomstep=1.2;
if(leftClick)zoom=zoom*zoomstep;
else if(rightClick)zoom=zoom/zoomstep; 
Calculating new scroll bars


We now know the new zoom and want to render the view with (imgX,imgY) located where the mouse is on screen (viewX,viewY). First step is to tell the scroll bar control what the new sizes are:
// Size of projected image changed with zoom
scrollWidth=imageWidth*zoom; scrollHeight=imageHeight*zoom;

// Size of bar/slider doesn't really change unless you change size of view
barWidth=viewWidth; barHeight=viewHeight;
If we set scrollX to imgX*zoom (image coordinate projected to new zoom level), our point ends up in top left corner of the view. However, we want this point at viewX,viewY, so we must offset the X-coordinate to the left, i.e. subtract the viewX,viewY coordinate:
scrollX=(imgX*zoom)-viewX; scrollY=(imgY*zoom)-viewY;
Edge adjustment

Unless we want to scroll off edge, we may need to adjust:
if(scrollX<0)scrollX=0;
  else if(scrollX+viewWidth>scrollWidth)scrollX=scrollWidth-viewWidth;
if(scrollY<0)scrollY=0;
  else if(scrollY+viewHeight>scrollHeight)scrollY=scrollHeight-viewHeight;
Rendering

If you need to render the image manually, the typical approach is to find the source rectangle within the image and project it to the full view.
int left=scrollX/zoom, top=scrollY/zoom;  // Reduce position to zoom=1
int right=(scrollX+viewWidth)/zoom, bottom=(scrollY+viewHeight)/zoom;
Then complete the operation using StretchBlt (if in a Windows development environment) to stretch-copy the rectangle from the source image to your new view context.

Other

Feel free to ask for further calculations or other parameters in the comments. If the above code fails, it may be that you have other input parameters or need to calculate some other numbers than what this article has attempted to convey.

lørdag 10. desember 2011

So what happened to trollsilm.com?

I was busy moving and spending time in hospital and preparing for the birth of my third child, all at the same time. So trollsilm.com renewal slipped, and soon after someone jumped on to it. I have tried to get in touch - after all, there should be a prize tag to get it back - but to no avail. Hence I have registered trollsilm.org and will be moving there soon.

If anyone has the time, determination and possibly money to bother the heck out of the squatters, feel free:

From http://www.ip-adress.com/whois/trollsilm.com
Registrant:
Above.com Domain Privacy
8 East concourse
Beaumaris
VIC
3193
AU

Tel. +61.395897946
Fax. 

mandag 25. juli 2011

The fertilizer man

I can not give this man a more fitting name. Some will call him "the devil" or "low life" or "insane" but after setting off a car full of fertilizer bomb, and knowing what that smells like, I will always think of him as "the fertilizer man" no matter how much damage he made and how many lives he took.

While most of the world seems to have arrived at logical conclusions around the entire incident, I have come across some - I'd almost say appologists - who seem to have failed miserably at their quest for logical reasoning as the perpetrator himself. From the point of view of the Fertilizer Man himself, the idea that multicultralism is destroying Norwegian culture, I beg to ask the following questions:
  • If the big enemy is multiculturalism, why kill Norwegians?
  • If the humongous problem is the destruction of Norwegian culture, why kill Norwegian youth?
  • If the big fear is massacres performed by foreigners, why make it so blatantly obvious that the self proclaimed protector of Norwegian culture also is the greatest mass murderer of those who could bring Norwegian culture forth?
  • And if protection of Norwegian culture was so important, why so much fear of the smallest group of cultural immigration, when it is so blatantly obvious that the greatest threat to Norwegian culture is Mickey Mouse and Ronald McDonald?
The idea that he blows up some government buildings - sure, I can see that happen. Happens all around the world from time to time. Many people have their secret wish to blow up the parliament every time some strange taxation law or other regulations interfere with their daily lives. The Fertilizer Man got that one down. Fine. You're angry with government, you blow up goverment, I get it.

But shooting youth who have barely reached legal age - and some of them not even that - is just an appalling act of evil. And a rediculous one at that. You first claim that non-Norwegians are a problem, and then you go shoot Norwegians.

The only logic to this is the idea is the "monoculturalist vs multiculturalist" scenario. So the monoculturalist went to war against the multiculturalist. And that's where some of foreign mass media have picked up.

Russia Today is repeatedly reporting about a "multikulti fail" in Norway:

Even the title is wrong, insisting that he turned "against his own." He did not. In his world, he was the monoculturalist against the multiculturalist. That's where the "us vs them" was.

Taken out of context is the Norwegian border closure. While they are still investigating the possibility of the Fertilizer Man not acting on his own, police want to make sure they know who leaves the country. This, however, is being portrayed as a sign that the European Union is falling apart in distrust.

To make sure everyone gets the problem with multiculturalism, Russia Today interviews the Spokesman for the Union of Russian Communities in Sweden, who apparently met the Fertilizer Man in his youth:


His opinion is clear. Multiculturalism is bad, he says. Spokesman of Russian Communities in Sweden. What are you doing in Sweden? You're not Scandinavian. You're a spokesman for the Union of Russian Communities. Preserving Russian Culture. In Sweden. Side-by-side by with Swedish communities. What do we call this, again, when several cultures live side by side? Multiculturalism?

It is obvious that Russia and Israel are vested in monoculturalism and therefore support this view. Since the Fertilizer Man was a monoculturalist, and the media of both countries blame multiculturalism, they are fairly appologetic: It wasn't the Fertilizer Man's fault, he was forced to do this by the multiculturalism that wouldn't let him sleep at night.

Again, if blowing up the government in protest was all he did, fine, it's a protest. Absurdely aggressive to be in Norway, but it's a legit target in war, and to him, this is war. Youth camp? Sure, it was a political youth camp, but still.

With all the talk of "multikulti fail" and the preservation of Norwegian culture, I can't help but think of what Norwegian culture has been for the last few thousands of years. As a friend in Atlanta once pointed out - our genes look so incredibly diverse to be such a small country.

Guess what, even our genes are multicultural, as we have been trading, importing culture, slaves and wives from large parts of the world since at least the viking age. And we traded and lived side by side with the Sámi people, even paying them local taxes whilst visiting anything north of Trondheim until Sápmi was annexed by the king of Sweden.

Multiculturalism is nothing new in Norway, it's monoculturalism that's new. The strange, suspect idea that we can preserve a culture that has been in constant change since before our written history. And people like the Fertilizer Man are trying to kill Norwegian culture by the sword - or rather by dung heap.

mandag 6. juni 2011

Who needs sticky yellow paper?

Post-its are all too often used to keep your username and password safe and secure to your monitor for everyone to see. As ICT Leader, I rip these away faster than I see them. Even if it should be at a publicly accessible airport terminal - which is probably why an airport has found a way round the "missing post-it" problem at their self service check-in terminal. (IMHO, This photo should be submitted to The Daily WTF)


Photo/observation tweeted by Per Thorsheim

fredag 3. juni 2011

Mission completed

I can not say it has been quiet here in the home of the trolls. While troll mom has been dealing with the troll kids, I have been away completing a decade old dream: To bicycle from Paris to Amsterdam. Indeed, it's the European version of my 1997 bicycle trip from Montreal to Toronto, with a few more personal touches and detours added, not to mention time. Over a 12 day period, I bicycled 900 km, which means an average 75 km/day.

Accomplishing personal goals, I believe, is vital for your psyche. It is easy to see how corporate support to achieve personal goals could increase morale - That is, if my dayjob paid all my hotels, spend work hours planning for the trip, etc. And certainly, had this been part of my job, I would probably spend work hours finding similar businesses to hook up with during my trip.

But be careful: It would be tempting to upgrade my bicycle to an electric one. It wouldn't be the same. I would spend more time stopping than riding, and I already spend about half my bicycling time doing other things than bicycling. It would feel more planned and with less freedom.

In short, as long as everything was in my own hands for the entirety of the trip, I was energized by self realization. This, in contrast to my trip to New Zealand about ten years ago, when I had this "wow, how did I end up on the other side of the planet, how cool is that?" form of self realization the first couple of days until work wore it off.

So the key leans more towards self realization than accomplishing the actual goal. In other words: support, but do not interfere. Or in the words of Dan Pink: You probably want to do something interesting, let me get out of your way.

Completing my mission motivated my wife to bake :)

mandag 25. april 2011

Pending name change

For a while, I have known that Agave has trademarked the name sqML for a product that is similar to (but not nearly as functional as) Trollsilm SQML. This has not been a problem, since development of Trollsilm SQML has been resting on a shelf for the last six years.

As I have pulled the product off the shelf, blown the dust off and started development again, I now see this as a pending problem. Not just in the form of possible law suits if I continue to use the name, but in the form of confusion between the products.

The new product will be open source, and it would therefore be fitting to open source the naming. SQML change 0.8.1 is therefore the actual name change, which will also affect the default extention used on the script/template files.

Suggestions will be accepted as comments to this blog post or to the facebook discussion until May 12th. As I ride from Paris to Amsterdam, I shall ponder the results.

søndag 24. april 2011

Unlean branch blocks road

After finally fixing up my bicycle for the season and going on my first proper morning trip (6.4 km), I encountered this branch half way:

[Photo of cut off branch locking the road]

My initial reaction, of course, was the knowledge that this branch would never have been "lying around" on the road for motorized vehicles. And so my brain started working on what process might be broken here, realizing that the lack of process might be the reason why the branch was still there.

I could go on about how counting the number of branches cut and then the number of branches cleaned away would make it blindingly obvious that one branch had not been cleaned away. Then again, just looking at the street should suffice.

But then, this was more likely the work of kids pulling a branch out, purposely blocking the road, long after the branch had been cleared. As such, the solution would be to bring the branch home, chop it up and dry for next winter.