| 
| 
 | Вопрос # 4 076/ вопрос открыт / | 
 |  Здравствуйте уважаемые знатоки Delphi!
 Мне приходится отображать JPEG-изображение через компонент типа TImage (в качестве подложки для нехитрого ручного векторизатора). В принципе, всё уже работает, н оя неожиданно столкнулся с тем, что не могу получить абсолютный размер JPEG-изображения в сантиметрах (извлечь из недр TImage разрешение в "пикселях на что-нибудь" или абсолютный размер пикселя пока тоже не получается).
 
 Подскажите пожалуйста как решить эту проблему.
 
 С признательностью всем кто ответит,
 Виталий
 
|  |   Вопрос задал: VNik (статус: Посетитель)Вопрос отправлен: 22 апреля 2010, 01:19
 Состояние вопроса: открыт, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 14; последнее сообщение — 22 апреля 2010, 22:53; участников в обсуждении: 3. 
|   | min@y™ (статус: Доктор наук), 22 апреля 2010, 08:31 [#1]:Для этого нужно узнать разрешение экрана (пикс/дюйм) по вертикали и горизонтали для текущего монитора. Это делается с помощью функции GetDeviceCaps(). Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | 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 (статус: Посетитель), 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 (статус: Посетитель), 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 (статус: Посетитель), 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 (статус: Посетитель), 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 (статус: Посетитель), 22 апреля 2010, 16:30 [#12]:Вадим К: разве сложно нажать точку после jpeg и посмотреть список свойств? 
 Да делал уже и Help через поиск сканировал. Пока чего-то не находится.
 |  
|   | 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 (статус: Посетитель), 22 апреля 2010, 22:53 [#14]:Вдогонку (забыл сказать), работает это правильно. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |