Table of Contents |
Hack 24 Solve the Bitmap-Shift Bug
In Flash Player 6 and below, bitmap images are displaced and distorted. Place the bitmap at the right location and correct for the distortion in those versions of the Flash Player. As with most extensive tools, you must learn a few tricks to overcome Flash Player's drawbacks. Bitmap shifting is one such drawback; it's a bug dating back to the earliest Flash Players and was corrected only recently-in Flash Player 7. Even if you're creating movies with Flash MX 2004, you still have to deal with this problem if you're exporting your movies for Flash Player 6 or below. And considering Flash Player 7 is not yet ubiquitous, this problem will face Flash developers for some time. Flash has a primarily vector-based renderer, and the bitmap-rendering routines in the Flash Player have a few calculation problems that end up distorting the bitmap display. As a result, a compiled Flash movie running in a browser won't always look the same as it did when being tested in authoring: bitmap images may have their content shifted or appear to jump or shake even though there's no movement on the image at all. Macromedia technote 14256 "Bitmaps shift in Macromedia Flash" (http://www.macromedia.com/support/flash/ts/documents/bitmaps_shift.htm) discusses the so-called image-shift bug. In practical terms, when you use an image in Flash, some content of the image is shifted 1 pixel down and to the right. The entire image is not shifted, just some pixels within it. Not only is most of the image shifted, it's also distorted; you may notice some pixel rows/columns disappearing or getting duplicated. If you use the image inside a movie clip, depending on your registration point (the movie clip origin), you'll notice different portions of the image getting distorted. It's easier to understand with a visual example. Consider the sample image on the left of Figure 3-45, When you import this image into the Flash authoring tool (including Flash MX 2004), position it properly (on whole pixels, with no decimal places in the X and Y values), and export it as a Flash Player 6 movie, the result is the distorted image on the right of Figure 3-45. Figure 3-45. A sample image (left) showing the image-shift bug (right)The content was shifted down and to the right. While the left column and the top row of pixels were unaltered, because of the shift on the rest of the content, the top and left outlines became stronger while the bottom and right outlines almost disappeared. Depending on the bitmap's registration point, you'll notice different areas of the image shifting. How Not to Fix ItThis bug is widely known in the Flash community, although getting around it is still black magic for most people. Unfortunately, several solutions are floating around, most of which are ineffective or have more drawbacks than they're worth. For clarification's sake, avoid or otherwise be careful if you're trying to fix this bug by any of these techniques:
While these so-called "solutions" are effective to some extent, they fail to really fix the problem, so it's hard to recommend any of them, save for image resizing (which is useful in one special case-read further). How to Fix It (the Good Way)On careful examination, you'll notice this bug occurs only when your image's X and Y positions within the clip or on the Stage are positive. An easy solution then, is to move your image to the area of a movie clip in which the Flash Player has to deal with negative numbers to calculate each pixel position. Doing this is easy: after placing your image on the Stage in the desired position, convert it to a movie clip symbol by pressing F8. In the Convert to Symbol dialog box, shown in Figure 3-46, give it a name, and, more importantly, select the bottom-right box as being the position for the registration point. This positions the movie clip contents-your image-on the top-left side of the middle axis (i.e., in the quadrant for which X and Y positions are negative). Figure 3-46. Setting the registration point in the Convert to Symbol dialog boxMoving the registration point is enough to fix the image bug when using images in the Flash authoring environment; you won't have any more image shifting or flickering bugs. One slight problem though-Macromedia "fixed" the bug in Flash Player 7 by reversing the problem! In Flash Player 7, the bug occurs when your image's X and Y positions are negative rather than positive. The rationale there was that almost everyone will place their images in the positive portion of the clip coordinates.
How to Fix It in Dynamically Loaded Files (the Effective Way)While the previous solution is enough to get around the image-shift bug when working with bitmaps inside the Flash authoring tool, it does not apply when loading images into Flash with loadMovie( ). Unfortunately, you can't move a loaded image's registration point so that the graphic location is in the upper-left quadrant (negative X and Y coordinates); since the loaded image is a movie clip container itself, the image content will still be on the positive side of the axes. For example, the following code produces the same results as Figure 3-45; content is shifted down and to the right: // Creates and loads the image into the Stage this.createEmptyMovieClip("myImage", 1); this.myImage.loadMovie("testImage.jpg"); However, there's a simple solution to this problem. By scaling the image by a very small fraction-so small it's unnoticeable-you can force the Flash Player to use precise values that'll make the end image seem correct when calculating pixel position. This has to be done after the image is loaded. The image can be scaled slightly in several ways. The following code fires the resize commands as soon as the image is loaded, thus counteracting the bug: // Creates and loads the image into the myImage clip // and places it on stage this.createEmptyMovieClip("myImage", 1); this.myImage.loadMovie("testImage.jpg"); // Creates a "watcher" movie to fix the size as soon as it's loaded this.createEmptyMovieClip("myImageLoader", 2); this.myImageLoader.onEnterFrame = function( ) { if (this._parent.myImage._width > 1) { // Image has been loaded this._parent.myImage._xscale = 99.98; this._parent.myImage._yscale = 99.98; this.removeMovieClip( ); } }; While resizing the image is usually not desirable, in this special case it's acceptable because it's the best way to avoid the image-shift bug. Usually, distortion, if any, caused by resizing isn't noticeable. In the preceding code, for example, resizing the test image solves the bitmap-shift problem, but it still maintains the same width and height; if you do a trace( ) on the image _width after loading, you'll notice it displays the original image width. -Zeh Fernando |
Table of Contents |