Delphi TImage: Как отобразить изображения, которые больше, чем компонент TImage, в который они загружаются или назначаются?
Некоторые файлы JPEG со следующими форматами не отображаются в Delphi's TImage
контроль.
- проблема решена. [TImage.Autosize] Флажок в элементе управления изображением не установлен по умолчанию, и в результате размер изображения не изменился. Я работал с этим проектом. https://community.embarcadero.com/blogs/entry/converting-to-grayscale-with-tbitmapscanline-property-39051
и сравнивая скорость с моим существующим кодом в градациях серого. Процесс сканирования, который они используют, кажется, немного быстрее, чем процесс сканирования, который у меня сейчас есть. Это отличная отправная точка для тех, кто работает с изображениями. Я добавил стандартный код преобразования jpeg и поля прокрутки, когда столкнулся с проблемой и заметил размер файла. Я считаю, что вопрос был верным, но я перефразировал его. Если я найду другой связанный ответ, где вопрос легче найти, я потяну этот пост. Если нет, я оставлю это.
Например, с цифровой камеры Nikon.
Размеры: ширина 5184 х высота 3888
Разрешение по вертикали: 300 точек на дюйм
Представление цвета: sRGB
Сжатые биты / пиксель: 2
Битовая глубина: 24
EXIF версия: 0230
Атрибуты: N
С камеры мобильного телефона Samsung:
Размеры: ширина 4128 х высота 2322
Горизонтальное и вертикальное разрешение: 72 dpi
Представление цвета: sRGB
Блок разрешения: 2
Сжатые биты / пиксель: [пусто]
Битовая глубина: 24
EXIF версия: 0220
Атрибуты: A
Файл в градациях серого из Adobe Photoshop:
Размеры: ширина 1800 х высота 3600
Горизонтальное и вертикальное разрешение: 300 точек на дюйм
Представление цвета: некалиброванный
Сжатые биты / пиксель: [пусто]
Битовая глубина: 8
Версия EXIF: [пусто]
Атрибуты: A
Работает файл с точным форматом, как у последнего, но с гораздо меньшими размерами.
Размеры одного рабочего файла: ширина 570 х высота 248
Файлы с 24-битной глубиной, меньшими размерами и без настроек разрешения или сжатия также работают правильно.
Когда я пытаюсь отобразить изображения с помощью приведенного ниже кода, изображение в файлах с ошибками всегда остается пустым, и ошибки не возвращаются. Это прекрасно работает со многими другими jpg
а также bmp
файлы.
Требуется ли преобразование для файлов в формате sRGB? Есть ли ограничение по размеру того, что элемент управления может отображать на экране? Если да, есть ли способ отобразить файлы большего размера?
procedure TForm1.btnBrowseClick(Sender: TObject);
var
bmp: TBitmap;
c2g: TColor2Grayscale;
ba: TBitmapAccess;
sw: TStopwatch;
jpg : TJPEGImage; // jpeg does not show 32-bit support in Delphi, only 24 and 8.
path, name, ext : string;
alreadyGray : boolean;
begin
bmp := TBitmap.Create;
jpg := TJPEGImage.Create;
OpenPicturedialog1.InitialDir := FindImageFolder(true);
if OpenPictureDialog1.Execute() then
try
name := OpenPictureDialog1.FileName;
path := ExtractFilePath(name);
ext := Lowercase ( ExtractFileExt(name) );
alreadyGray := false;
try
if ( ext = '.jpg' ) or ( ext = '.jpeg' ) then
begin
jpg.LoadFromFile(name);
bmp.Assign(jpg);
alreadyGray := jpg.Grayscale;
end
else
bmp.LoadFromFile( name );
except
on err: Exception do
begin
ShowMessage(err.Message);
Exit;
end;
end;
if bmp.PixelFormat = pfDevice then
bmp.PixelFormat := pf32bit;
Image1.Picture.Assign(bmp);
if alreadyGray then
begin
Image2.Picture.Assign(bmp);
Exit;
end;
finally
jpg.Free;
bmp.Free;
end;
end;
1 ответ
Так как вы не получаете сообщение об ошибке при загрузке изображения JPEG, я подозреваю, что проблема может быть в преобразовании из TJPEGImage
в TBitmap
, Если вы не собираетесь манипулировать пикселями изображения, вам вообще не нужно конвертировать, вы можете назначить оригинал TJPEGImage
прямо к TImage
, VCL's TPicture
класс использует производные TGraphic
классы, чтобы он мог отображать изображения в их собственных форматах, вы должны использовать эту функцию, например:
procedure TForm1.btnBrowseClick(Sender: TObject);
var
jpg: TJPEGImage;
bmp: TBitmap;
begin
OpenPicturedialog1.InitialDir := FindImageFolder(true);
if OpenPictureDialog1.Execute then
begin
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
if Image1.Picture.Graphic is TJPEGImage then
begin
if TJPEGImage(Image1.Picture.Graphic).Grayscale then
begin
Image2.Picture.Assign(Image1.Picture.Graphic);
end else
begin
jpg := TJPEGImage.Create;
try
jpg.Assign(Image1.Picture.Graphic);
jpg.Grayscale := True;
Image2.Picture.Assign(jpg);
finally
jpg.Free;
end;
end;
end else
begin
bmp := TBitmap.Create;
try
bmp.PixelFormat := pf32bit;
bmp.Assign(Image1.Picture.Graphic);
...
Image2.Picture.Assign(bmp);
finally
bmp.Free;
end;
end;
end;
end;
Обновление: я провел несколько тестов в XE2 в Windows 7 и увидел ту же проблему, что и вы.
Если я загружаю JPG как есть TImage.Picture.LoadFromFile()
, они отображаются нормально только если TImage.Stretch
или же TImage.Proportional
Свойство Истина. Если они оба установлены в False (по умолчанию), изображения отображаются пустыми.
Если я загружу JPG в TJPEGImage
сначала, а затем назначьте это TBitmap
само преобразование работает нормально (доказано сохранением TBitmap
к .bmp
файл), и растровые изображения отображаются нормально, только если Stretch
или же Proportional
True, в противном случае они отображаются пустыми.
Итак, в качестве другого теста я попытался использовать TPaintBox
, рисуя изображения вручную в своем OnPaint
событие. Если я использую TCanvas.Draw()
чтобы нарисовать изображения в полном размере, они отображаются пустыми. Если я использую TCanvas.StretchDraw()
чтобы соответствовать изображениям в клиентской области PaintBox, они отображаются нормально.
Я так думаю TCanvas
Вероятно, возникают проблемы с памятью при попытке отображения изображений в таких больших размерах. Это не имеет никакого отношения к конкретному типу используемых JPG (которые загружаются нормально).
Обновление: неважно, что я сказал выше. Я вижу, что предоставленные JPG-файлы имеют действительно большие DPI и все они имеют белый цвет в верхнем левом углу. Если TImage
/ TPaintBox
имеет большой размер, чтобы компенсировать, теперь я могу видеть изображения в их полном размере (легче увидеть, если TImage
находится на TScrollBox
с TImage.AutoSize
установить в True). Это объясняет, почему растягивание / пропорциональное рисование работает, растягивая изображения, чтобы соответствовать TImage
Размеры при необходимости.