С++ .NET - как распоряжаться растровым изображением?

Я хочу загрузить растровое изображение из файла, выполнить над ним некоторые операции и сохранить его под тем же именем файла. Шаблон таков:

Bitmap in = gcnew Bitmap(fileName);
Bitmap out = gcnew Bitmap(in.Width, in.Height, in.PixelFormat);

fill [out] with data from [in]

out.Save(fileName);

но это не работает. Это очевидно. Я не могу сохранить в файл, который все еще открыт (из-за растрового изображения). Вопрос в том, как, черт возьми, закрыть растровое изображение?! Я пробовал много способов, но ничего не работает. Вызов Dispose работал в C#, но этот метод защищен в C++. Вызов удаления также не работает. Какое решение?

РЕДАКТИРОВАТЬ: работа с одним растровым изображением тоже не работает. Но я нашел проблему. Вызов удаления сработал. Я забыл объявить свои растровые изображения указателями

Bitmap^ in = gcnew Bitmap(fileName);
Bitmap^ out = gcnew Bitmap(in.Width, in.Height, in.PixelFormat);

fill [out] with data from [in]

delete in;
out.Save(fileName);

person maxest    schedule 20.05.2012    source источник
comment
Вы взглянули на msdn.microsoft.com/en-us/library/ ms177197.aspx еще?   -  person user287107    schedule 20.05.2012


Ответы (2)


Это обычная ловушка в кодировании C++/CLI, вы используете stack semantics. Другими словами, вы не объявили переменную ссылочного типа со шляпой ^. Это заставляет компилятор автоматически выдавать вызов Dispose() в конце блока области видимости. Очень удобно и является симуляцией шаблона RAII в C++, но здесь он мешает. Вы хотите удалить растровое изображение in перед сохранением нового растрового изображения.

Два способа сделать это. Вы можете играть в игру с блоками области видимости, добавляя фигурные скобки:

Bitmap^ out;
try {
    {
        Bitmap in(fileName);
        out = gcnew Bitmap(in.Width, in.Height, in.PixelFormat);
        // etc..
    }   // <== "in" gets disposed here
    out->Save(fileName);
}
finally {
    delete out;
}

Но это как-то некрасиво, тем более, что в этом очень конкретном случае его нужно смешивать с out. Альтернативой является просто сделать все явно:

Bitmap^ out;
Bitmap^ in;
try {
    in = gcnew Bitmap(fileName);
    out = gcnew Bitmap(in->Width, in->Height, in->PixelFormat);
    // etc..
    delete in;
    in = nullptr;
    out->Save(fileName);
}
finally {
    delete in;
    delete out;
}
person Hans Passant    schedule 20.05.2012
comment
Итак, во втором примере delete in; избавляется от in? - person shoelzer; 08.05.2017

Вам не нужен out Bitmap. Просто отредактируйте in и сохраните его. Также я бы посоветовал вместо этого использовать класс CImage

CImage image;
image.Load(filename);
fill [image] with whatever data you want
image.Save(filename);
person Ash Burlaczenko    schedule 20.05.2012
comment
Почему вы советуете использовать CImage? - person svick; 20.05.2012
comment
Мне просто проще использовать IMO, и он позволяет использовать многие другие форматы изображений. - person Ash Burlaczenko; 20.05.2012