使用gdi+绘制缩放位图的问题

使用gdi+绘制缩放位图的问题,会有一个像素的偏差,网上看到一篇解决方案,收藏之:

http://www.tecgraf.puc-rio.br/~scuri/gdiplus/drawimage_scale_problem.html

GDI+ DrawImage Scale Problem

Here is the source code and screen shot of the problem described in:

http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.gdi/2007-01/msg00122.html

Source code: drawimage_scale_problem.cpp

The green lines marks the end of the image, or the last pixel of the image.

The red rectangle is drawn using the same rectangle coordinates used in the DrawImage.

For each test, 3 rectangles are drawn, one with no zoom, one with InterpolationModeBilinear, and one withInterpolationModeNearestNeighbor.

1. The Problem

使用gdi+绘制缩放位图的问题_第1张图片

Notice that the first image with no zoom is correctly drawn.

The next two images do not fill the entire rectangle, and the resample is not equally balanced in the edges.

2. First Solution

Draw using a larger rectangle and clip the result.

使用gdi+绘制缩放位图的问题_第2张图片

It works... But I have to change the current clipping, and it becomes more complicated if I have another clipping region selected. Notice that the clipping rectangle must be reduced by 1 pixel to be 100% correct.

3. An Experiment

What happens if the source rectangle is larger than the image?

使用gdi+绘制缩放位图的问题_第3张图片

The image is resized down!!! So I found that this is a valid operation and it affects the final result.

4. Using the Experiment results for a Solution

使用gdi+绘制缩放位图的问题_第4张图片

Just using a smaller source rectangle by 1 pixel, the image is correctly resized*. So the DrawImage parameterssrcwidth andsrcheight are in fact srcright andsrcbottom, that in Windows convention are outsize the image.

*But only when the image is zoomed. Notice that in the image with no zoom, using the same strategy is incorrectly drawn.

5. Another Solution

Michael Phillips Jr suggested another solution very similar of my first solution, also using clipping to get rid of the background.

使用gdi+绘制缩放位图的问题_第5张图片

Here is the result, but the resampling is not equally balanced. Notice that the clipping rectangle must be reduced by 1 pixel to be 100% correct.

6. Conclusions

None of these effects are described in the GDI+ documentation.

In my point of view it was a bug of the resampling algorithm (*see the After Words Bellow).

7. After Words (The real thing)

When using PixelOffsetModeHalf to center the pixel at (+0.5, +0.5) in the code, I found also some interesting results. See the screenshots of the problem just adding the PixelOffsetMode.

使用gdi+绘制缩放位图的问题_第6张图片

The size and position are correct (ignore the red rectangle), resampling is also equally balanced, but GDI+ insist in include the background in the resampling when usingInterpolationModeBilinear.

Now I think I understond what's going on. It is a GDI+ design decision and not a bug. But the lack of good documentation makes me lose several hours just to understand what's going on. Also the decision to include the background in the resampling is something weird for me, and not acceptable for our applications. I guess I will have to live with my solution using -1 in thesrcwidth andsrcheight.

Update - 20/Oct/2008

Vlad Grachov sent me a solution for the inclusion of the background. If you set theWrapMode toWrapModeTileFlipXY the background is filled with the own image instead of the background. I checked and it worked. Thanks.

Here are the results:

使用gdi+绘制缩放位图的问题_第7张图片

Notice the top red line how it is filled with black instead of the white background. The solution code is:

ImageAttributes imAtt; 
imAtt.SetWrapMode(WrapModeTileFlipXY); 
graphics->SetInterpolationMode(InterpolationModeNearestNeighbor);
graphics->SetPixelOffsetMode(PixelOffsetModeHalf);
graphics->DrawImage(&image, zoomRect, 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel, &imAtt);

But keep in mind that PixelOffsetModeHalf will affect the position of other primitives. It is a good idea to set PixelOffsetModeNone after drawing the image.


If you have any comments or other approaches to this problem please feel free to contact me.

Best Regards,
Antonio Scuri
[email protected]


你可能感兴趣的:(使用gdi+绘制缩放位图的问题)