【问题标题】:C++ GDI+ loading an image from a file then deleting the file *before* unloading the imageC++ GDI+ 从文件加载图像然后在卸载图像之前*删除文件
【发布时间】:2011-06-26 02:12:25
【问题描述】:

简单地说就是罐头上的内容 我正在使用 Bitmap::FromFile 从文件中加载位图,但之后我想将其从磁盘中删除。
问题是,Bitmap::FromFile 绝对锁定文件以防止任何更改/删除,直到加载的图像被卸载

这是因为我将位图存储在二进制文件中,所以我想按以下顺序进行操作:
1. 从二进制文件中提取图像
2.加载图片
3.删除#1中提取的文件
(只是对我的图像资源的一些基本保护,我只是不希望它们位于我的程序目录中)

Bitmap::FromFile 仍然锁定文件不被删除,即使在我尝试从文件中克隆加载的图像时:

    Bitmap* tempbmp = Bitmap::FromFile(fileanddir.c_str(),false);
    Rect temprect( 0, 0, tempbmp->GetWidth(), tempbmp->GetHeight() );

    // make the image to be used as a clone to the temporary
    // bitmap to avoid file locking
    image_to_be_used = tempbmp->Clone(temprect, PixelFormatDontCare);

    // delete temporary loaded bitmap since it shouldn't be needed
    delete tempbmp;

    // delete the file itself, too bad the file is locked
    int theresult = remove(tocharptr(fileanddir)); 
    // returns -1, also: manually deleting at this point gives the error
    // that the file is being used by another person/program

知道如何加载位图或以某种方式将其复制到内存中以使文件本身不会被锁定吗?
(所以我可以在加载后删除它)

【问题讨论】:

    标签: c++ file bitmap gdi+ locked


    【解决方案1】:

    你可以这样做

    Gdiplus::Bitmap* LoadImageFromFileWithoutLocking(const WCHAR* fileName) {
        using namespace Gdiplus;
        Bitmap src( fileName );
        if ( src.GetLastStatus() != Ok ) {
            return 0;
        }
        Bitmap *dst = new Bitmap(src.GetWidth(), src.GetHeight(), PixelFormat32bppARGB);
    
        BitmapData srcData;
        BitmapData dstData;
        Rect rc(0, 0, src.GetWidth(), src.GetHeight());
    
        if (src.LockBits(& rc, ImageLockModeRead, PixelFormat32bppARGB, & srcData) == Ok)
        {
            if ( dst->LockBits(& rc, ImageLockModeWrite, PixelFormat32bppARGB, & dstData) == Ok ) {
                uint8_t * srcBits = (uint8_t *) srcData.Scan0;
                uint8_t * dstBits = (uint8_t *) dstData.Scan0;
                unsigned int stride;
                if (srcData.Stride > 0) { 
                    stride = srcData.Stride;
                } else {
                    stride = - srcData.Stride;
                }
                memcpy(dstBits, srcBits, src.GetHeight() * stride);
    
                dst->UnlockBits(&dstData);
            }
            src.UnlockBits(&srcData);
        }
        return dst;
    }
    

    【讨论】:

    • 此代码将只使用第一帧动画图像
    【解决方案2】:

    如果您对 MFC-OLE 示例感兴趣:

    CFile file;
    CFileException fe;
    CString strFileName = "C:\\yours.bmp";
    
    if (!file.Open(strFileName, CFile::modeRead | CFile::shareDenyNone , &fe))
    {
        return;
    }
    COleStreamFile stream;
    if(!stream.CreateMemoryStream(NULL))
    {
        return;
    }
    BYTE buf[1024];
    int readed = 0;
    do
    {
        readed = file.Read(buf,1024);
        stream.Write(buf,readed);
    }
    while(readed > 0);
    
    file.Close();
    stream.SeekToBegin();
    USES_CONVERSION;
    m_pImage = new Gdiplus::Bitmap(stream.GetStream( ));
    

    【讨论】:

      【解决方案3】:

      看看Bitmap::FromStream。您应该能够使用SHCreateStreamOnFileEx 在文件上打开IStream。加载位图后,您可以安全地删除流,然后删除临时文件。

      如果二进制文件仅使用支持的算法进行压缩,则将相应的标志传递给SHCreateStreamOnFileEx 并让它读取存档,绕过将图像提取到临时文件中。否则可以实现IStream接口读取二进制文件,直接提取你的图片数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-11
        • 2019-03-31
        • 2012-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多