Alex B дата публикации 04-10-2010 07:25 КАТЕГОРИЯ | | СИСТЕМА .CreateCompatibleBitmap и EOutOfResources | ПРОДУКТ | | Delphi | ПЛАТФОРМА | | Windows |
Для создания DDB (Device Dependent Bitmap, предназначен, в основном, для быстрого рисования на экране) Windows использует общесистемный (разделяемый ВСЕМИ приложениями с системе) статический буфер предопределенного при загрузке размера. Размер буфера зависит от драйвера видеокарты, версии Windows (например, Win95 имел размер этого буфера не более 16Мб) и проч., но даже на современных компьютерах с большими объемами памяти и видеопамяти объем буфера весьма ограничен (всего лишь десятки мегабайт). Если одно из приложений, запущенных в системе, создаст слишком большой DDB и займет таким образом бОльшую часть буфера, то в дальнейшем для этого или ДРУГОГО приложения создание очередного DDB ресурса окончится неудачей. Получается, что даже одно-единственное "жадное" приложение ставит под угрозу стабильность работы всей системы.
Альтернативой DDB являются DIB (Device Independent Bitmap). Такие объекты создаются в виртуальном адресном пространстве программы и, естественно, не влияют на другие приложения.
Класс VCL TBitmap может создавать как DDB, так и DIB. По умолчанию немедленно после создания объект TBitmap работает с DDB. Как следствие, с виду невиннейший код создает большие проблемы:
bmp:=TBitmap.Create;
bmp.SetSize(4096, 4096); // EOutOfResources (out of memory)
или (jpg: TJPEGImage, bmp - объект достаточно большой, но еще
работающий):
jpg.Assign(bmp); // EOutOfResources (out of memory)
Во избежание проблем, в большинстве случаев (а при работе с большими изображениями альтернативы нет вообще) желательно сразу после создания переводить объекты TBitmap в режим DIB. Для этого необходимо и достаточно присвоить свойству PixelFormat любое значение, отличное от pfDevice; присвоение pfDevice возвращает объект к работе с DDB.
bmp:=TBitmap.Create;
bmp.PixelFormat := pf24bit;
bmp.SetSize(4096, 4096); // нет проблем
TBitmap.CopyImage: EOutOfResources in CreateCompatibleBitmap
Not enough storage is available to process this command?
Why does CreateCompatibleBitmap fails if there is 'enough' memory?
Эффект имеет место быть. Размер создаваемого DDB битмапа, на котором возникает ошибка, зависит от многих факторов, и, возможно, для демонстрации эффекта приведенные в коде размеры придется увеличить, или создавать несколько экземпляров TBitmap. Кроме того, в Delphi 7 и более ранних версиях у TBitmap отсутствует метод SetSize, и нужно отдельно задавать ширину и высоту.
В качестве альтернативы TBitmap можно использовать TBitmap32 из библиотеки Graphics32, которая не имеет данной проблемы.
[TBitmap] [Растры, BMP]
Обсуждение материала [ 23-10-2010 06:52 ] 6 сообщений |