急!wince5.0下,怎么样实现对大尺寸jpg图片的显示?

时间:2022-02-20 17:33:13
想在wince5.0下做一个类似照片浏览器的东东,能够实现对jpg图片的浏览,放大,缩小,以及缩略图等简单图片浏览功能。因为5.0下没有imgdecmp.dll,所以用的是ce自带的IImage接口。但发现最多只能显示1.5M左右大小的jpg图片,不能满足需要。查了一下以前的帖子,可能是因为wince每个进程内存的限制。有人提出将大图切割分块实现,不知道这样可不可行(或者有没有更简单的方法或接口)?不知道哪位牛人以前实现过类似的东东,可否指点一下?

25 个解决方案

#1


为什么没有鸟我?这个问题问错了么?还是没人知道?

#2


顶上去

#3


内存是有限制,但是可以通过createfilemap映射内存,需要用多大内存都没有问题的
具体的再网上查查吧,如果没有找到给我发消息...

#4


可能我对问题阐述得还是不清楚,先贴一段代码再说:
/*----------------------------------------------------
功能描述:根据图片的文件路径,将JPG/GIF/PNG等图片转换成位图
入口参数:&strFileName 图片路径   
出口参数:无
返回值:  HBITMAP 位图句柄;
备注:  调用com,利用IImage接口,显示BMP/JPG/GIF/PNG图片,
 不支持WBMP,GIF也只能显示一帧
-------------------------------------------------------*/
HBITMAP CPic2Bmp::LoadImageFromFile(const CString &strFileName)
{
    IImagingFactory *pImgFactory = NULL;
    IImage *pImage = NULL;
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
HBITMAP hResult = 0;
    if (SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory,
                                    NULL,
                                    CLSCTX_INPROC_SERVER,
                                    IID_IImagingFactory,
                                    (void **)&pImgFactory)))
    {
ImageInfo imageInfo;
        if (SUCCEEDED(pImgFactory->CreateImageFromFile(strFileName, &pImage))
&& SUCCEEDED(pImage->GetImageInfo(&imageInfo)))
        {
CWindowDC dc(0);
CDC dcBitmap;
dcBitmap.CreateCompatibleDC(&dc);
hResult = CreateCompatibleBitmap(dc.GetSafeHdc(), imageInfo.Width, imageInfo.Height);
if (hResult) {
HGDIOBJ hOldBitmap = dcBitmap.SelectObject(hResult);
        pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, imageInfo.Width, imageInfo.Height), NULL);
dcBitmap.SelectObject(hOldBitmap);
}
pImage->Release();
        }
        pImgFactory->Release();
    }
    CoUninitialize();

return hResult;

}
按照我的理解,显示jpg等其他格式图片,最终还是要转换成位图显示,那么如果将一幅3054×2336×24位的jpg一次转换成bmp,就有20M的样子,挂掉也是可能的。调用IImage接口,对于大尺寸的图片就搞不定了。难道唯一的方法是自己写代码decode吗?

#5


IImage::Draw是可以设置目标区域和源图区域的啊,你最多就只用显示屏幕大小不就完了

#6


pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN)), CRect(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN)));

超出屏幕部分你显示它也看不见,没用

#7


随便写了下,大致如下,不知道能不能跑,反正大致意思就是只取能显示的部分,多余部分不用管了

int nWidth  = ::GetSystemMetrics(SM_CXSCREEN);
int nHeight  = ::GetSystemMetrics(SM_CXSCREEN);
CWindowDC dc(0);
CDC dcBitmap;
dcBitmap.CreateCompatibleDC(&dc);
hResult = CreateCompatibleBitmap(dc.GetSafeHdc(), nWidth , nHeight);
if (hResult) {
     HGDIOBJ hOldBitmap = dcBitmap.SelectObject(hResult);
     pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, nWidth , nHeight), CRect(0, 0, nWidth , nHeight));
     dcBitmap.SelectObject(hOldBitmap);
}

#8


to yzx0023(无聊客) :
不行,试过了。上面代码要修改两个地方:
1.int nHeight  = ::GetSystemMetrics(SM_CYSCREEN);
2.pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, nWidth , nHeight), CRect(0, 0, nWidth , nHeight));

srcRect 
[in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect. 
To display the entire image, set this value to NULL. 


#9


呵呵! 楼主, 你只能自己写代码decode了, 你只经想调用系统的东东, 系统就会给你一次性解析完, 这样你就至少得要付出这么多内存.
不过就是自己写也不会太大动手笔的, 现在关于JPEG的Decode都是标准的东东, 你可以去Download一个lib, 一样支持的格式很多的.

#10


你要是觉得JPG太大可以在PC上用工具人为切成几个大小一致的矩形小图片,比如切成8*8,就有64块,对每一块建立索引,画的时候做一个投影映射就行了,对于数据画一块读一块,画完了一块就释放它的空间,防止刷新就画在内存DC上面,画完了Bitblt一下,你还可以小图片和索引信息放在一个文件里管理。
自己Decode Jpeg的意义也不是很大,基本上也是要解成对应大小的DIB

#11


to navi_dx() :
我是要做一个类似照片浏览的功能,人为切割肯定行不通。

#12


要是大的BMP倒是可以分行读取,分别画,消耗不了太多内存,大JPG就比较麻烦了

#13


我实验过IImage,也是几千X几千的图,内存消耗很小

#14


to yzx0023(无聊客):
是用上面的代码测试的吗?我是在64M模拟器上测试的,跑不了。Draw()的时候就出错了??

#15


升级后就有imgdecmp.dll了

#16


怎么升级?

#17


关注一下,我也在做这个

#18


http://www.microsoft.com/downloads/details.aspx?familyid=6c69461e-89fa-40b0-8953-b4cc1adbc8d8&displaylang=en

#19


建议试一下 GetThumbnail 感觉这个用了局部解码,显示缩略图的时候应该有用,不过要完整显示大图片的时候就没用了

#20


我装了这个升级包,好像还是没有imgdecmp.dll

#21


位图太大了系统业不能创建呀
在WINDOWS下面也是形不通的呀

#22


我也遇到这个问题,请问你解决了吗

#23


我试了两种办法,getthumbnail的方法是行不通的,
用下面这种办法可以显示出缩小后的图片来:
IBitmapImage* pBitmap;
pImgFactory->CreateImageFromFile(strFileName, &pImage);
pImgFactory->CreateBitmapFromImage(pImage, width, height, PixelFormat24bppRGB, InterpolationHintDefault, &pBitmap); // width和height就是缩小后的尺寸
pBitmap->QueryInterface(IID_IImage, (void **)&pImage);
pImage->Draw...

我用5M的图片试过,

#24


奇怪了,再试的时候getthumbnail也是可以的

#25


问题解决了,感谢各位的热心回复,特别感谢无聊客、iLookee()。

#1


为什么没有鸟我?这个问题问错了么?还是没人知道?

#2


顶上去

#3


内存是有限制,但是可以通过createfilemap映射内存,需要用多大内存都没有问题的
具体的再网上查查吧,如果没有找到给我发消息...

#4


可能我对问题阐述得还是不清楚,先贴一段代码再说:
/*----------------------------------------------------
功能描述:根据图片的文件路径,将JPG/GIF/PNG等图片转换成位图
入口参数:&strFileName 图片路径   
出口参数:无
返回值:  HBITMAP 位图句柄;
备注:  调用com,利用IImage接口,显示BMP/JPG/GIF/PNG图片,
 不支持WBMP,GIF也只能显示一帧
-------------------------------------------------------*/
HBITMAP CPic2Bmp::LoadImageFromFile(const CString &strFileName)
{
    IImagingFactory *pImgFactory = NULL;
    IImage *pImage = NULL;
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
HBITMAP hResult = 0;
    if (SUCCEEDED(CoCreateInstance (CLSID_ImagingFactory,
                                    NULL,
                                    CLSCTX_INPROC_SERVER,
                                    IID_IImagingFactory,
                                    (void **)&pImgFactory)))
    {
ImageInfo imageInfo;
        if (SUCCEEDED(pImgFactory->CreateImageFromFile(strFileName, &pImage))
&& SUCCEEDED(pImage->GetImageInfo(&imageInfo)))
        {
CWindowDC dc(0);
CDC dcBitmap;
dcBitmap.CreateCompatibleDC(&dc);
hResult = CreateCompatibleBitmap(dc.GetSafeHdc(), imageInfo.Width, imageInfo.Height);
if (hResult) {
HGDIOBJ hOldBitmap = dcBitmap.SelectObject(hResult);
        pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, imageInfo.Width, imageInfo.Height), NULL);
dcBitmap.SelectObject(hOldBitmap);
}
pImage->Release();
        }
        pImgFactory->Release();
    }
    CoUninitialize();

return hResult;

}
按照我的理解,显示jpg等其他格式图片,最终还是要转换成位图显示,那么如果将一幅3054×2336×24位的jpg一次转换成bmp,就有20M的样子,挂掉也是可能的。调用IImage接口,对于大尺寸的图片就搞不定了。难道唯一的方法是自己写代码decode吗?

#5


IImage::Draw是可以设置目标区域和源图区域的啊,你最多就只用显示屏幕大小不就完了

#6


pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN)), CRect(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN)));

超出屏幕部分你显示它也看不见,没用

#7


随便写了下,大致如下,不知道能不能跑,反正大致意思就是只取能显示的部分,多余部分不用管了

int nWidth  = ::GetSystemMetrics(SM_CXSCREEN);
int nHeight  = ::GetSystemMetrics(SM_CXSCREEN);
CWindowDC dc(0);
CDC dcBitmap;
dcBitmap.CreateCompatibleDC(&dc);
hResult = CreateCompatibleBitmap(dc.GetSafeHdc(), nWidth , nHeight);
if (hResult) {
     HGDIOBJ hOldBitmap = dcBitmap.SelectObject(hResult);
     pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, nWidth , nHeight), CRect(0, 0, nWidth , nHeight));
     dcBitmap.SelectObject(hOldBitmap);
}

#8


to yzx0023(无聊客) :
不行,试过了。上面代码要修改两个地方:
1.int nHeight  = ::GetSystemMetrics(SM_CYSCREEN);
2.pImage->Draw(dcBitmap.GetSafeHdc(), CRect(0, 0, nWidth , nHeight), CRect(0, 0, nWidth , nHeight));

srcRect 
[in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect. 
To display the entire image, set this value to NULL. 


#9


呵呵! 楼主, 你只能自己写代码decode了, 你只经想调用系统的东东, 系统就会给你一次性解析完, 这样你就至少得要付出这么多内存.
不过就是自己写也不会太大动手笔的, 现在关于JPEG的Decode都是标准的东东, 你可以去Download一个lib, 一样支持的格式很多的.

#10


你要是觉得JPG太大可以在PC上用工具人为切成几个大小一致的矩形小图片,比如切成8*8,就有64块,对每一块建立索引,画的时候做一个投影映射就行了,对于数据画一块读一块,画完了一块就释放它的空间,防止刷新就画在内存DC上面,画完了Bitblt一下,你还可以小图片和索引信息放在一个文件里管理。
自己Decode Jpeg的意义也不是很大,基本上也是要解成对应大小的DIB

#11


to navi_dx() :
我是要做一个类似照片浏览的功能,人为切割肯定行不通。

#12


要是大的BMP倒是可以分行读取,分别画,消耗不了太多内存,大JPG就比较麻烦了

#13


我实验过IImage,也是几千X几千的图,内存消耗很小

#14


to yzx0023(无聊客):
是用上面的代码测试的吗?我是在64M模拟器上测试的,跑不了。Draw()的时候就出错了??

#15


升级后就有imgdecmp.dll了

#16


怎么升级?

#17


关注一下,我也在做这个

#18


http://www.microsoft.com/downloads/details.aspx?familyid=6c69461e-89fa-40b0-8953-b4cc1adbc8d8&displaylang=en

#19


建议试一下 GetThumbnail 感觉这个用了局部解码,显示缩略图的时候应该有用,不过要完整显示大图片的时候就没用了

#20


我装了这个升级包,好像还是没有imgdecmp.dll

#21


位图太大了系统业不能创建呀
在WINDOWS下面也是形不通的呀

#22


我也遇到这个问题,请问你解决了吗

#23


我试了两种办法,getthumbnail的方法是行不通的,
用下面这种办法可以显示出缩小后的图片来:
IBitmapImage* pBitmap;
pImgFactory->CreateImageFromFile(strFileName, &pImage);
pImgFactory->CreateBitmapFromImage(pImage, width, height, PixelFormat24bppRGB, InterpolationHintDefault, &pBitmap); // width和height就是缩小后的尺寸
pBitmap->QueryInterface(IID_IImage, (void **)&pImage);
pImage->Draw...

我用5M的图片试过,

#24


奇怪了,再试的时候getthumbnail也是可以的

#25


问题解决了,感谢各位的热心回复,特别感谢无聊客、iLookee()。