C ++ GDI + загрузка изображения из файла, затем удаление файла * перед * выгрузкой изображения - PullRequest
2 голосов
/ 12 февраля 2011

Просто то, что написано на банке Я загружаю растровое изображение из файла, используя 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

Есть идеи, как я могу загрузить растровое изображение или как-то скопировать его в память, чтобы сам файл не был заблокирован?
(Так что я могу удалить его через мгновение после загрузки)

Ответы [ 3 ]

4 голосов
/ 24 марта 2015

Вы можете сделать это так

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;
}
3 голосов
/ 12 февраля 2011

Взгляните на Bitmap::FromStream.Вы должны иметь возможность использовать SHCreateStreamOnFileEx, чтобы открыть IStream для файла.После загрузки вашего растрового изображения вы можете безопасно удалить поток, а затем временный файл.

Если двоичный файл сжат только с помощью поддерживаемого алгоритма, тогда передайте соответствующий флаг в SHCreateStreamOnFileEx и попросите его прочитать архив,минуя извлечение изображения во временный файл.В противном случае можно реализовать интерфейс IStream для чтения двоичного файла и непосредственного извлечения данных изображения.

1 голос
/ 13 марта 2013

, если вы заинтересованы в образце 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( ));
...