|
Вопрос # 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]:
Вдогонку (забыл сказать), работает это правильно.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|