Firstly, the stretching isn't done in the vertical direction: Game Boy (and Color) games only used 144 rows of the 160 available on Advance screen, so there'd be black "letterbox" bars at the top and bottom, whether you stretched the image widescreen (with the shoulder buttons) or not.
Horizontally, the image is definitely stretched. If the Advance had twice the horizontal resolution of the Game Boy, it would be easy to stretch: each column of pixels could be repeated twice. It would effectively mean that each of the Game Boy's pixels were twice as wide as before. It's not always feasible to double the resolution of your screen; it's likely that such a resolution wasn't available (or affordable) in a handheld size at the time of the Advance.
Instead, Nintendo selected a screen for the Advance that had a resolution that is one and a half times (or 3/2) that of the original Game Boy (160 x 3/2 = 240). Every two columns of pixels from an old Game Boy game will now need to be "stretched" over three columns of the Advance's screen.
But what values should be assigned to the pixels in these extra third columns? You could double up some of the original columns' pixels, doubling the "width" of all the odd columns, or perhaps the even ones. It's a simple method, but doesn't look that good, because some columns won't be doubled at all, but others will.
An alternative approach is to use a technique called interpolation.[*1] In this instance, rather than choosing to duplicate one column to fill the empty pixels, you take an average of the values in the columns to the left and the right of each empty pixel, and use this calculated value instead.
If you look closely at the Advance's display with an un-stretched Game Boy game, then a stretched one, it's possible to identify which columns have had their values calculated by this "averaging" interpolation.
Here are some detailed photos of the "AY" from the "1Player" text:
<-unstretched
<-stretched
On the left side of the "A", a column of pixels has been interpolated between the dark pixels of the "A" and the light pixels of the background. These pixels have been averaged out as a medium gray.
On the right side of the "A", another column of interpolated pixels has ended up in between the two columns of dark pixels. The average of two dark pixels is also dark, so it is the same colour as the rest of the "A". Similar interpolations are visible on the left and right sides of the "Y", and elsewhere on the screen.
Here is pair of pictures from another game, taken on the AGS-101 model of the Advance SP (which has a brighter, backlit screen).[*2] You can play guess-the-game if you like!
<- unstretched
<- stretched
Why did Nintendo choose to stretch the Game Boy display in one direction, and not the other? One reason is that interpolating in one dimension is a lot simpler than doing it in two. But stretching the screen vertically would also have created unsightly visual artefacts in the game.
If Nintendo had decided to stretch the 144 rows of pixels over the 160 rows available on the Advance's screen, they would have had to insert 16 interpolated rows of pixels. 16 is a factor of 160, so the interpolated rows could be spaced evenly: one every 10 rows. But of the nine original rows, only two would be next to a new row pf pixels, the other seven wouldn't. As a result, some rows would be "stretched" out by the interpolation, others wouldn't. This would result in Mario's hat stretching and compressing slightly as he jumped, for example, and would be distracting for the player.
This technique (specifically the two-dimensional bilinear interpolation) is used when you resize a picture in image manipulation software such as Photoshop or GIMP. It's also used on computer LCD displays, if you select a resolution (e.g. 640x480) that doesn't match the display's native resolution (e.g 1024x768). But because the GBA only stretches the display in one dimension (horizontally), it only needs to do a simpler linear interpolation of the image.
Courtesy of snips-n-snails