Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 4 076

/ вопрос открыт /

Здравствуйте уважаемые знатоки Delphi!

Мне приходится отображать JPEG-изображение через компонент типа TImage (в качестве подложки для нехитрого ручного векторизатора). В принципе, всё уже работает, н оя неожиданно столкнулся с тем, что не могу получить абсолютный размер JPEG-изображения в сантиметрах (извлечь из недр TImage разрешение в "пикселях на что-нибудь" или абсолютный размер пикселя пока тоже не получается).

Подскажите пожалуйста как решить эту проблему.

С признательностью всем кто ответит,
Виталий

VNik Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: VNik (статус: Посетитель)
Вопрос отправлен: 22 апреля 2010, 01:19
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 14; последнее сообщение — 22 апреля 2010, 22:53; участников в обсуждении: 3.
min@y™

min@y™ (статус: Доктор наук), 22 апреля 2010, 08:31 [#1]:

Для этого нужно узнать разрешение экрана (пикс/дюйм) по вертикали и горизонтали для текущего монитора. Это делается с помощью функции GetDeviceCaps().
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
VNik

VNik (статус: Посетитель), 22 апреля 2010, 12:50 [#2]:

Попробовал сделать так, как советовал min@y™, однако следующий фрагмент кода выдаёт для монитора нулевые разрешения и по вертикали, и по горизонтали.
procedure TImageForm.DetectResolution;
var
  I: Integer;
begin
  with Screen do
    for I := 0 to pred (MonitorCount) do
      if Monitors [I].Primary then
        begin
          vResol := GetDeviceCaps (Monitors [I].Handle, HORZRES);
          hResol := GetDeviceCaps (Monitors [I].Handle, VERTRES);
          exit;
        end;
  raise Exception.Create(InternalProgrammError);
end;
Тоже самое получается, если запрашивать разрешение рабочего стола.
procedure TImageForm.DetectResolution;
begin
  vResol := GetDeviceCaps (GetDesktopWindow, HORZRES);
  hResol := GetDeviceCaps (GetDesktopWindow, VERTRES);
end;
Я что-то не так делаю?
Вадим К

Вадим К (статус: Академик), 22 апреля 2010, 12:58 [#3]:

а вот эти функции также не работают? http://www.delphisources.ru/pages/faq/base/api_printer_params.html (только не нужно пугаться, что там о принтере речь. Нужно подставить правильный хендл, и любое устройтво вывода может выдать характеристики, если они к нему применимы)
Галочка "подтверждения прочтения" - вселенское зло.
VNik

VNik (статус: Посетитель), 22 апреля 2010, 13:36 [#4]:

По совету Вадим К изменил код так
procedure TImageForm.DetectResolution;
var
  I: Integer;
begin
  with Screen do
    for I := 0 to pred (MonitorCount) do
      if Monitors [I].Primary then
        begin
          vResol := GetDeviceCaps (Monitors [I].Handle, LogPixelsX);
          hResol := GetDeviceCaps (Monitors [I].Handle, LogPixelsY);
          exit;
        end;
  raise Exception.Create(InternalProgrammError);
end;
и, соответственно, так
procedure TImageForm.DetectResolution;
begin
  vResol := GetDeviceCaps (GetDesktopWindow, LogPixelsX);
  hResol := GetDeviceCaps (GetDesktopWindow, LogPixelsY);
end;
По прежнему возвращаются нули. В цикле я убедился, что оба оператора присваивания действительно выполняются. Может быть я именно "хендл" устройства неправильно подставляю?
Вадим К

Вадим К (статус: Академик), 22 апреля 2010, 13:47 [#5]:

Вспомнил, что можно попробовать Monitors[i].PixelsPerlnch
как видно с названия - єто кол-во точек на дюйм. Помня,что дюйм это 25.4 мм, можно легко перейти к метрической системе.
Галочка "подтверждения прочтения" - вселенское зло.
VNik

VNik (статус: Посетитель), 22 апреля 2010, 14:21 [#6]:

По совету Вадим К изменил код так
procedure TImageForm.DetectResolution;
begin
  vResol := Screen.PixelsPerInch;
  hResol := vResol;
end;
(свойство PixelsPerlnch определено в классе TScreen и отсутствует в классе TMonitor). С учётом этой поправки, - действительно работает, однако абсолютный размер изображения определяется неверно.

Точнее, таким способом я получаю разрешение экрана (96), а в свойствах JPEG-файла указано разрешение 300 пикселей на дюйм (то же показывает и PhotoShop).
Вадим К

Вадим К (статус: Академик), 22 апреля 2010, 14:48 [#7]:

ну почему люди придумывают "упрощения" своего вопроса ???
Ну не нужно этого делать. И не будете получать "неверных ответов".

Скажем так, при отображении картинки, она может отображаться как пиксель к пикселю, так и с учетом разрешения, указанного внутри файла. у класса TJPEGImage есть свойство dpi, которое и должно показать Вам долгожданные 300.
var jpg:TJPEGImage;
begin
  jpg := TJPEGImage.create;
  jpg.LoadFromFile(имяфайла);
  dpi := jpg.dpi;
  jpg.free;
end;


У bmp файла такое понятие как dpi отсутствует, а при загрузке с jpg файла оно теряется. (точнее оно может быть использовано для масштабирования картинки при загрузке).
Галочка "подтверждения прочтения" - вселенское зло.
VNik

VNik (статус: Посетитель), 22 апреля 2010, 15:09 [#8]:

Вадим К написал: ну почему люди придумывают "упрощения" своего вопроса ???

Я в исходном варианте вопроса спрашивал как получить абсолютный размер изображения в каких нибудь единицах или в пикселях на какую-нибудь абсолютную единицу. Вероятно, я что-то неправильно сформулировал, но, увы, до сих пол не понимаю что.

Изменил код так
procedure TImageForm.DetectResolution;
begin
  hResol :=  (Image.Picture.Graphic as TJPEGImage).dpi;
  vResol := hResol;
end;
Выяснилось, что присвоенный Image.Picture.Graphic объект класса TJPEGImage не имеет свойства dpi, что, возможно, связано с особенностями Delphi-7, которой я пользуюсь.

Может быть можно получить какие-то другие параметры и на их основе вычислить этот?
Вадим К

Вадим К (статус: Академик), 22 апреля 2010, 15:16 [#9]:

У картинки, отрисованной на экране нет размера внутри. Его можно попытаться сосчитать, если знать размер в пикселях и параметры монитора.

У картинки, сохраненной в файле такой параметр может быть. Но в некоторых случаях он бессмысленный. Почему? Ну к примеру картинка отсканированая, тут можно понять, тут dpi имеет смысл. А вот у фотографии вида из окна он уже не имеем смысла, так как нельзя провести соответствие (чуточку подумав, поймете почему). Но вот в случае фотографии Земли с космоса уже может иметь смысл.

Цитата (VNik):

hResol :=(Image.Picture.Graphic as TJPEGImage).dpi;


Внимательно читаем мой предыдущий пост, где рассказывается, почему это не будет работать.
Галочка "подтверждения прочтения" - вселенское зло.
VNik

VNik (статус: Посетитель), 22 апреля 2010, 15:57 [#10]:

Если я правильно понял мысль Вадим К, после присвоения JPEG-картинки Image.Picture.Graphic один раз происходит её преобразование, исходные параметры которого затем теряются (не хранятся в недрах экземпляра компонента типа TImage).

Однако до этой "продвинутой" проблемы я просто не дошёл. Вот изменённый код, который с этой точки зрения корректен.
// ...
var
  JPEG: TJPEGImage;
// ...
      JPEG := TJPEGImage.Create;
      JPEG.LoadFromFile (FileName);
      ImageResol := JPEG.dpi;
      Image.Picture.Graphic := JPEG;
Он спотыкается ровно там же, где и прежний код
procedure TImageForm.DetectResolution;
begin
  hResol :=  (Image.Picture.Graphic as TJPEGImage).dpi;
  vResol := hResol;
end;
В обоих случаях на стадии компиляции мне просто сообщается, что свойство dpi не определено.
Undeclared identifier: 'dpi'
Вадим К

Вадим К (статус: Академик), 22 апреля 2010, 16:27 [#11]:

По поводу свойства dpi - у меня нет сейчас под рукой делфи. может я и ошибся - все помнить не могу. Но разве сложно нажать точку после jpeg и посмотреть список свойств?

По поводу

Цитата (VNik):

Image.Picture.Graphic := JPEG;

Не пишите так. Это утечка памяти. используйте assign
Галочка "подтверждения прочтения" - вселенское зло.
VNik

VNik (статус: Посетитель), 22 апреля 2010, 16:30 [#12]:

Вадим К: разве сложно нажать точку после jpeg и посмотреть список свойств?

Да делал уже и Help через поиск сканировал. Пока чего-то не находится.
VNik

VNik (статус: Посетитель), 22 апреля 2010, 22:52 [#13]:

Задал тот же вопрос на Ответы@Mail.Ru.

http://otvet.mail.ru/question/39284107/

"Знаток" Трегубенков Евгений

http://otvet.mail.ru/mail/evgtreg89/

предложил мне решить проблему следующим образом (я только немного "причесал" присланный им текст).

procedure GetResJPEG(JPGFile: string; var HorzRes, VertRes: Word; var DP: Byte);
var
  FileStream: TFileStream;
  BufferSize, Index: integer;
  Buffer: string [50];
begin
  FileStream := TFileStream.Create(JPGFile, fmOpenRead);
  try
    BufferSize := High (Buffer);
    SetLength (Buffer, BufferSize);
    FileStream.Read (buffer[1], BufferSize);
    Index := Pos ('JFIF' + #0, Buffer);
    if Index > 0 then
      begin
        FileStream.Seek (Index + 6, soFromBeginning);
        FileStream.Read (DP, 1); // DP=1: Dots Per Inch; DP=2: Dots Per Cm.
        FileStream.Read (HorzRes, 2); // X axis
        FileStream.Read (VertRes, 2); // Y axis
        HorzRes := Swap (HorzRes);
        VertRes := Swap (VertRes);
      end;
  finally
    FileStream.Free;
  end;
end;

Полагаю что для страждущих, вроде меня, небезинтересна будет и следующая присланная им информация.

Это взято из проекта DelphiWorld, где есть "очень много интересных вещей". Еще есть сайт DelphiKingdom - королевство Delphi.

Справедливости ради надо сказать, что в "Королевство" я заглядывал и ответа на свой вопрос там не нашёл (может быть, - плохо искал)...
VNik

VNik (статус: Посетитель), 22 апреля 2010, 22:53 [#14]:

Вдогонку (забыл сказать), работает это правильно.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 16:20
Выполнено за 0.05 сек.