Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > баг с LoadFromFile 128x128 bmp ?


Автор: Sep. 18.8.2004, 18:08
натолкнулся на такую ошибку в своей delphi 6, имеется любой код типа:
Код
   Bmp := TBitmap.Create;
   Bmp.LoadFromFile(opendialog1.Filename);
   form1.Canvas.Draw(0,0,bmp);

так вот если ему подсовываешь bmp сохраненную photoshop cs8 или 6, любую 16bit или 24 или 32, но с размером 128х128 пикселей - то выдается ошибка stream read error.
Причем если эту картинку пересохранить 7ым фотошопом или IrfunView то все открывается нормально. Причем походу это только с 128х128 картинками.
Вот, если у вас нету фотошопа cs можете взять http://mdma.dax.ru/m55/128.bmpтакую bmp приколоться =)
Приходится перед этим открывать файл как file of byte и менять байтики. Может можно как нибудь более изящно этот баг обойти? Через bmp.loadfromstream тоже пробовал =(

Автор: Illusion Dolphin 18.8.2004, 19:02
Хм... интересный глюк... Присоединяюсь к вопросу... наверное, ошибка с записью заголовка в фотошопе... Но учитывая то, что стандартный mspaint его открывает, то, возможно, что borland что-то не учёл в своих исходниках... какие-нибудь новые тенденции...

Автор: p0s0l 19.8.2004, 01:38
Это из-за того, что PhotoShop сохраняет файл с немного большим размером, чем нужно (лишние нулевые байты в конце...), и это отражается в biSizeImage.
TBitmap.ReadDIB вызывает API-функцию CreateDIBSection, которая выделяет память в соответствии с параметрами битмапа (ширина, высота, битов на пиксел...). В случае 128x128x24, под ppvBits отводится системой $C000 байт, а в сохранённой в PS картинке biSizeImage = $C002 байта (из-за лишних двух нулей в конце), и когда потом TBitmap.ReadDIB делает чтение в ppvBits $C002 байт, происходит ошибка... При других размерах не возникает ошибки из-за того, что память всё равно выделяется страницами по 4кб, так что заезд за пределы был некритичен.
Я обходил этот баг так:
Код
procedure AntibugLoadBmp (bmp : TBitmap; const FileName : string);
var ms : TMemoryStream;
begin
 ms := TMemoryStream.Create;
 ms.LoadFromFile(FileName);
 PBitmapInfoHeader(DWORD(ms.Memory) + SizeOf(BITMAPFILEHEADER))^.biSizeImage := 0;
 bmp.LoadFromStream(ms);
 ms.Free;
end;

Смысл в том, что если присвоить biSizeImage нулевое значение, TBitmap.ReadDIB сама посчитает biSizeImage:
Код
// biSizeImage can be zero. If zero, compute the size.
if biSizeImage = 0 then            // top-down DIBs have negative height
 biSizeImage := BytesPerScanLine(biWidth, biBitCount, 32) * Abs(biHeight);

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)