在按钮背景上拉伸/缩小时,位图会丢失质量 [英] Bitmap loses quality when stretched/shrinked on buttons background

查看:100
本文介绍了在按钮背景上拉伸/缩小时,位图会丢失质量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

介绍和相关信息:



我有一个拥有者静态控制。



它应该在渐变背景上有位图。



静态控件尺寸不固定,在创建父窗口期间计算



我加载一个背景色为的位图来自资源文件的RGB(255,163,94)



使用 TransparentBlt(...,RGB( 255,163,94)) API我拉伸/缩小位图以适应静态控件客户区(位图是设备相关位图,而不是DIB,如果这很重要)。



位图图片的水平和垂直分辨率均为150 DPI,24位色深,宽度为4395像素,高度为5613像素。



位图通过 LoadBitmap(...) API在 WM_CREATE 上加载。



原始图片如下,但我有r因此我可以上传它:



http://pbrd.co/ 1a4P87E [ ^ ]



问题:



问题在于图片质量。



贝娄是业主绘制静态控制后得到的结果:



http://pbrd.co/1a4PkDU [ ^ ]



像素化很明显。



看点比率也会丢失,因为我使用 TransparentBlt()



我的努力解决这个问题:



浏览StackOverflow和CodeProject存档,我发现了类似的问题,但它们与Android有关。他们都没有帮助我。也许我的经验不足使我无法看到有用的信息。



根据这些问题的一个链接,我已经了解了图像缩放算法的存在。这是我想到的页面:

http://en.wikipedia.org / wiki / Resampling_%28bitmap%29 [ ^ ]



我试图使用较小的位图,但是图像模糊,即使我将像素化解析到某个点。



似乎我的问题在于位图中的数据不足或者很多,所以当我尝试将大位图推到小按钮时,它就可以'因为我得到像素化锯齿状效果,但如果我尝试将小位图放入大按钮,则数据丢失会导致图像模糊。



浏览互联网后,我看到了建议和建议,可以用矢量图形和<$ c $解决c>元文件。



因为我对此很沮丧,我会问几个问题stions。



如果主题很广泛,我会请求社区通过评论通知我,我会将其删除并尝试将其改写为适合发布问题的CP规则更好。



问题:



这个问题真的让我意外发生,所以我不知道如何开始解决它,因为我对WIN32还不太新。



我必须承认我很震惊,因为我预计 TransparentBlt()会为我做所有工作。



我怎样才能解决这个问题,所以我可以保持图片的宽高比和质量?



我会考虑以下解决方案:



1.将某些 GDI API调用组合到我现有的拉伸/收缩处理程序中,这样我就可以实现高质量并保持图片的宽高比,没有太多修改代码?



2.使用 GDI + 解决我的问题。到目前为止我还没有使用过 GDI + ,但是有一天必须开始,为什么不现在,如果这样可以解决我的问题呢?



3.如果矢量图形可以解决我的问题我必须 URGE 社区给我以下好处: ANY 推荐在PURE WIN32上的矢量图形 上的书/教程/文档/文章/代码示例非常感谢,因为我自己还没找到。



4.如果我必须实现其中一个缩放算法,请推荐一些书籍/教程/链接/代码示例,因为我自己还没有找到任何。



我不能使用库,这是对但是,如果解决方案可以接受并且可以快速实施,我可以尝试说服我的雇主放宽他们的标准,因此可以使用库。



如果我的标准是保留两者宽高比和图片的质量re太多了,我会选择图片的质量然后。我总是可以发布一个关于宽高比的新问题,也许我会同时找到一个解决方案。



我在Windows XP上工作,使用C ++和 PURE WIN32 API。



如果需要额外的源代码请求它,我很乐意发布它(我在此省略它以保留空间) 。



这就是全部。感谢您的耐心和时间。



问候。

INTRODUCTION AND RELEVANT INFORMATION:

I have an owner drawn static control.

It should have bitmap on top of a gradient background.

Static controls dimensions are not fixed, they are calculated during the creation of parent window.

I load a bitmap with background color of RGB( 255, 163, 94 ) from resource file.

Using TransparentBlt( ... , RGB( 255, 163, 94 ) ) API I stretch/shrink bitmap to fit the static controls client area ( bitmap is Device Dependant Bitmap, not a DIB, if that matters ).

Bitmap picture has both horizontal and vertical resolution 150 DPI, 24 color bit depth, width 4395 pixels, and height 5613 pixels.

Bitmap is loaded via LoadBitmap( ... ) API on WM_CREATE.

The original picture is bellow, but I have reduced its size, so I can upload it:

http://pbrd.co/1a4P87E[^]

THE PROBLEM:

The problem is in quality of the picture.

Bellow is the result I get after owner drawing the static control:

http://pbrd.co/1a4PkDU[^]

The pixelation is obvious.

Aspect ratio is lost as well, since I use TransparentBlt().

MY EFFORTS TO SOLVE THIS PROBLEM:

Browsing through StackOverflow and CodeProject archive, I have found similar questions, but they were related to Android. None of them helped me. Maybe my inexperience prevents me to see useful information.

Following one link from those questions I have learned about existence of image scaling algorithms. This is the page I have in mind:
http://en.wikipedia.org/wiki/Resampling_%28bitmap%29[^]

I have tried to use smaller bitmap, but picture is then blurry, even though I resolve pixelation to some point.

It seems that my problem lies in insufficient, or to much, data in bitmap so when I try to "push" large bitmap into small button, it just can't fit so I get pixelation and jagged effects, yet If I try to put small bitmap into big button, then data is missing which results in a blurry picture.

After browsing through Internet, I have seen advices and suggestions that this can be solved with vector graphics and meta files.

Since I am dumbstruck by this, I will ask several questions.

If the topic is broad then I ask the community to inform me of it through comments, and I will remove it and will try to rephrase it to fit the CP rules of posting questions better.

QUESTIONS:

This problem really happened unexpected to me, so I do not know how to start solving it, since I am fairly new to WIN32.

I must admit I am shocked, since I have expected that TransparentBlt() would do all the work for me.

How can I solve this problem, so I can keep aspect ratio and quality of the picture ?

I will consider the following solutions:

1. Combining certain GDI API calls into my existing handler for stretching/shrinking, so I can achieve high quality and preserve aspect ratio of the picture, without modifying the code too much ?

2. Using GDI+ to solve my problem. I haven't used GDI+ so far, but one has to start some day, why not now, if that is what will solve my problems ?

3. If vector graphics can solve my problem I must URGE the community to do me the following favor: ANY recommendation of book/tutorial/documentation/article/code example on Vector Graphics in PURE WIN32 would be greatly appreciated, since I myself haven't found any.

4. If I must implement one of the scaling algorithms please recommend some books/tutorials/links/code example, since I myself haven't found any.

I can't use libraries, it is the restriction imposed upon me, however, if the solution is acceptable and can be implemented fast, I could try to convince my employers to loosen their criteria, so libraries can be used.

If my criteria to preserve both aspect ratio and quality of the picture is too much, I will choose the quality of the picture then. I can always post a new question about aspect ratio, and maybe I will find a solution myself in the meanwhile.

I work on Windows XP, using C++ and PURE WIN32 API.

If additional source code is required ask for it, I will gladly post it ( I have omitted it here to preserve space ).

That would be all. Thank you for your patience and time.

Regards.

推荐答案

您可以尝试我的DLL [ ^ ],但我不知道它是否与你的清晰图像表现良好。
You may try my DLL[^], however I don't know if it performs well with your 'crisp' images.


提出问题的方式的最高分。这个问题是一个真正的享受!

不幸的是,我只能评价一次..



鉴于图像的尺寸非常大,我建议借用3d图形技术。 MIP映射。也就是说 - 您以不同的分辨率存储同一图像的多个副本。在显示时,您只需选择适当大小的图像并显示它。优点是您可以使用其中包含的任何调整大小方法在您喜欢的图像编辑程序中调整图像大小。缺点是可执行文件更大,加载和显示图像的代码的复杂性略有增加。当然,您可以在自己的代码中实现这样的缩放算法,然后使用它来动态创建适当大小的图像。

除非您计划显示尺寸为4395x5613的按钮(+非 - 客户区域)然后有一个这么大的图像完全没有任何目的。如果您希望以更大的尺寸显示相同的图像,则除按钮图像外还应包含单独且尺寸合适的图像。



每日例子' mip-mapping'可以在.ico文件中找到 - 单个文件在多个分辨率下包含相同图标的副本是很常见的。以一个窗口的小图标为例 - 它大约是12x12px。将其与窗口的大图标(在任务栏中显示或在旧版Windows中的alt-tab切换期间)进行对比 - 这是48x48。 Vista引入了128x128或256x256图标(我忘了)。在算法上调整这些小图像是不切实际的。图标是手绘的或至少是修饰的,以便它们仍能提供原始图形的良好表示。



Wikipedia:Mipmap

它可能值得指出 - 没有必要将不同大小的图像存储在单个位图中。我将不同的尺寸存储为单独的图像文件。除非您需要高性能图形应用程序中经常需要的那种速度,否则不需要通过将不同大小的图像填充到单个文件中来最小化缓存未命中并增加复杂性。它会被优化,但阅读不太清楚。



一个名叫Santosh的家伙做了一些有趣的文章,关于使用openGL来调整使用不同过滤器的图像。它们可能对您有用,也可能没用。



Santosh G_的文章 [ ^ ]





编辑:

什锦代码片段加载和显示具有透明度的32位图像:



Top marks for the manner in which the question has been posed. This question is a real treat!
Unfortunately, I can only rate it once..

Given the very large dimensions of your image, I would suggest a technique borrowed from 3d graphics. Mip-mapping. That is to say - you store several copies of the same image, at different resolutions. At display time, you simply pick the appropriately sized image and display it. The advantage is that you can resize images in your favourite image editing program using any of the resizing methods it includes. The downside is a larger executable and a minor increase in complexity in the code that loads and displays the image. Naturally, you could implement such a scaling algorithm in your own code and then use it to dynamically create the appropriately sized images.
Unless you're planning to display a button with the dimensions of 4395x5613 (+ non-client area) then having an image this large serves absolutely no purpose at all. A seperate and appropriately sized image should be included in addition to the button image, should you wish to display the same image at a larger size.

An everyday example of 'mip-mapping' may be found inside .ico files - it's very common for a single file to include copies of the same icon at multiple resolutions. Take for example a window's small icon - it's about 12x12px. Contrast this to a window's large-icon (displayed in task-bar or during alt-tab switching in older versions of windows) - this is 48x48. Vista introduced 128x128 or 256x256 icons (I forget). It's just not practical to resize these small images algorithmically. Icons are hand-drawn or at least, touched-up such that they still provide a good representation of the original graphic.

Wikipedia: Mipmap
It's probably worth pointing out - there's no real need to store the different sized images in a single bitmap. I'd store different sizes as seperate image files. Unless you need the kind of speed often required in high-performance graphics apps, there's no need to minimize cache-misses and increase complexity by stuffing different sizes images into a single file. It would be optimized, but less clear to read.

A fella by the name of Santosh has done some interesting articles regarding the use of openGL to resize images with different filters. They may or may not have utility to you.

Articles by Santosh G_[^]



Assorted code snippets to load and display 32bit images with transparency:

void CSomeClassName::displayImage()
{
    RECT myRect;
    BITMAP bm;
    HDC screenDC, memDC;
    HBITMAP oldBmp;
    BLENDFUNCTION bf;

    GetObject(mBmp, sizeof(bm), &bm);

    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 0xff;

    bf.AlphaFormat = AC_SRC_ALPHA;

    screenDC = GetDC(mHwnd);
    GetClientRect(mHwnd, &myRect);

    if (mBmp == NULL)
        FillRect(screenDC, &myRect, WHITE_BRUSH);

    else
    {
        memDC = CreateCompatibleDC(screenDC);
        oldBmp = (HBITMAP)SelectObject(memDC, mBmp);
        AlphaBlend (screenDC, 0, 0, myRect.right,myRect.bottom, memDC, 0, 0, bm.bmWidth,bm.bmHeight, bf);
        SelectObject(memDC, oldBmp);
        DeleteDC(memDC);
        ReleaseDC(mHwnd, screenDC);
    }
}







// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP mLoadImg(WCHAR *szFilename)
{
   HBITMAP result=NULL;

   Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(szFilename,false);
   bitmap->GetHBITMAP(0, &result);
   delete bitmap;
   return result;
}

// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP loadImgResource(LPCSTR pName, LPCSTR pType, HMODULE hInst)
{
    Gdiplus::Bitmap *m_pBitmap;
    HBITMAP result=NULL;

    HRSRC hResource = FindResource(hInst, pName, pType);
    if (!hResource)
        return NULL;

    DWORD imgSize = SizeofResource(hInst, hResource);
    if (!imgSize)
        return NULL;

    const void *pResourceData = LockResource(LoadResource(hInst, hResource));
    if (!pResourceData)
        return NULL;

    HANDLE m_hBuffer = GlobalAlloc(GMEM_MOVEABLE, imgSize);
	if (m_hBuffer)
	{
		void* pBuffer = GlobalLock(m_hBuffer);
		if (pBuffer)
		{
			CopyMemory(pBuffer, pResourceData, imgSize);
			IStream* pStream = NULL;
			if (CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK)
			{
				m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
				pStream->Release();
				if (m_pBitmap)
				{
					if (m_pBitmap->GetLastStatus() == Gdiplus::Ok)
					{
					    m_pBitmap->GetHBITMAP(0, &result);
                        delete m_pBitmap;
					}
				}
			}
			GlobalUnlock(m_hBuffer);
		}
		GlobalFree(m_hBuffer);
	}
	return result;
}

// example of use: tmpBmp = loadImgResource(IDR_PNG1, "PNG"); 
HBITMAP loadImgResource(WORD resNum, LPCSTR pType)
{
    return loadImgResource(MAKEINTRESOURCE(resNum), pType, NULL);
}







GDI +初始化示例




Example of GDI+ initialization

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
   static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
   static ULONG_PTR gdiplusToken;

    // so we can load all the image formats that windows supports natively - (I'm using a transparent PNG on the main dialog)
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    // run the app
    DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc);

    // clean-up stuff
    Gdiplus::GdiplusShutdown(gdiplusToken);
    WSACleanup();

    return 0;
}


我已经争斗了这个问题近三个月,经过所有研究,我必须承认Kryukov先生和Mr. Pallini是对的 - 不管算法有多好,因为清晰的图像更好地使用矢量图形。因此,我决定使用矢量图形。也许我会使用增强的Windows图元文件,或者尝试使用某些库来获取 SVG



我特此感谢所有想要提供帮助的人。



祝你好运。
I have "battled" this problem for nearly three months, and after all that research I must admit that Mr. Kryukov and Mr.Pallini were right-no matter how good the algorithm is, for the crisp images is better to use vector graphics. Therefore, I have decided to use vector graphics. Maybe I will use Enhanced Windows Metafiles or will try with some library for SVG.

I hereby thank to everyone trying to help.

Best regards.


这篇关于在按钮背景上拉伸/缩小时,位图会丢失质量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆