Форум программистов, компьютерный форум, киберфорум
Программирование графики
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/25: Рейтинг темы: голосов - 25, средняя оценка - 4.56
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
1

Как из файла JPEG вытащить размер изображения в пикселях?

07.11.2014, 12:43. Показов 5113. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пишу на С курсовую "Работа с бинарными файлами" ( Пишу в тему по С++) потому в "Сс для начинающих ответа не будет точно" уж извините Админы, требуется алгоритм поэтому просто не знаю уже куда и написать.

Прочел EXIF спецификацию, понял что да есть много битов с разными значениями разных типов и тд. Начал с простого нашел биты по которым хранится строковые данные, от файла к файлу тото читается что то нет (Модель камеры и прочее)
понял что все очень специфично для каждого производителя ну да ладно, напишу в виде учебного задания про Apple и Canon. НО никак немого вычитать разрешение W H.
Изучил efix.c и jhead.h - мощные функции описаны, структуры для всего EXIF, я понимаю что истина в этих файлов но пока не хватает знаний разобраться куча #define и передача параметров в функции , не могу проследить интересующий меня момент.
Прочел про золовок JPEG и нашел откуда вычитать соотношение сторон, в чем разрешение в дюймах или сантиметрах, разрешение на дюйм (72, 96 и тд) НО никак не пойму откуда берется или как высчитывается банальные размеры W x H
(1920 * 1080 к примеру).
Забил на EXIF создал тупо в PAINTE белый квадратный холст 200 на 200 сохранил как JPEG, открываю Hex редактором все заголовок есть 96 pix/inc есть, но где (200 на 200) ГДЕ искать или Как оно вычисляется? Сижу неделю.. Прошу помощи..

Администрация еще раз извиняюсь есть не в ту тему написал, перенесите куда следует лишь бы был толк.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.11.2014, 12:43
Ответы с готовыми решениями:

Как зафиксировать размер изображения в пикселях
Установил изображение на рабочий лист excell, на изображении присутствую части этого изображения...

Размер изображения в см. если дан размер в пикселях
Смотрю свойства изображения, а мне пишет 2652х4999 пикселей. Что это? Как их перевести в...

Как вытащить размер изображения при загрузки через OpenFileDialog?
На помощь, не знаю как вытащить, а то просто нужно пихнуть его в string

Как узнать размер строки в пикселях?
У меня есть строка. Хочу узнать размер в пикселях. Это надо для того, чтобы потом узнав размер...

18
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
07.11.2014, 14:33 2
Размеры в хранятся в секциях SOF (Y и X).
Миниатюры
Как из файла JPEG вытащить размер изображения в пикселях?  
1
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
07.11.2014, 17:07  [ТС] 3
1) Правильно ли я понимаю что у блоков нет фиксированного адреса в файле и искать его нужно по всему файлу в данном случае сочетание (FF C0), ок допустим написали поиск дошли до маркера.
2) Отступаем длину последовательно идущих данных от начала маркера до интересующих нас значений? (поправьте меня пожалуйста если я никак отсчитываю)
FF C0 - Marker
00 11 - Frame Header
08 - Sample Precision
0A 20 - Y , 07 90 - X?
переводим целиком из hex в dec = 2592 * 1936
И все черт возьми получаеться!)

Тогда остается самый главный вопрос маркеры строго адресованные в файле или надо устраивать программный поиск?

Как из файла JPEG вытащить размер изображения в пикселях?
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
07.11.2014, 21:08 4
Лучший ответ Сообщение было отмечено tezaurismosis как решение

Решение

Фиксированной структуры нет, файл состоит из секций, длина которых может быть различной. Маркеры секций надо не искать по всему файлу, а перемещаться последовательно от начальной секции, пока не дойдёшь до интересующей. Большинство секций после маркера содержат длину. Вот я на скорую руку сделал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <cstdlib>
#include <iostream>
#include <fstream>
 
using std::cout;
using std::cin;
using std::endl;
int main()
{
    unsigned short int d, pic_height, pic_width;
    std::ifstream ifs("d:\\jpegfile.jpg", std::ifstream::binary);
    if (!ifs) return 1;
    ifs.read((char *)&d, 2);
    if (d != 0xD8FF) return 1;
    while (d != 0xC0FF && d != 0xC1FF && d != 0xC2FF && !ifs.eof())
    {
        ifs.read((char *)&d, 2);
 
        if (d == 0xD9FF) break;
 
        if (d >= 0xD0FF && d <= 0xD7FF) continue;
 
        if (d >= 0xE0FF && d <= 0xEFFF)
        {
            ifs.read((char *)&d + 1, 1);
            ifs.read((char *)&d, 1);
            ifs.ignore(d - 2);
            continue;
        }
 
        switch (d)
        {
        case 0xDDFF:
            ifs.ignore(4);
            break;
        case 0xC4FF:
        case 0xDBFF:
        case 0xDAFF:
        case 0xFEFF:
            ifs.read((char *)&d + 1, 1);
            ifs.read((char *)&d, 1);
            ifs.ignore(d - 2);
        }
    }
 
    switch (d)
    {
    case 0xC0FF:
    case 0xC1FF:
    case 0xC2FF:
        ifs.ignore(2 + 1);
        ifs.read((char *)&pic_height + 1, 1);
        ifs.read((char *)&pic_height, 1);
        ifs.read((char *)&pic_width + 1, 1);
        ifs.read((char *)&pic_width, 1);
        cout << "height: " << pic_height << ", width: " << pic_width << endl;
        break;
    }
 
    ifs.close();
 
    system("pause");
    return 0;
}
Добавлено через 4 минуты
Здесь только три типа SOF учтено. Вообще их больше.
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
07.11.2014, 21:15  [ТС] 5
nmcf, Супер спасибо, если не трудно буду расспрашивать по твоему листингу ( потому как официально прогу свою должен написать на Си)

Почему ты ищешь маркеры 0xC1FF а не FFC1? я наверно не знаю каких то совсем основ(
остальное пока вроде бы понятно ..
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
07.11.2014, 21:19 6
Потому что в памяти байты хранятся от младших к старшим в порядке возрастания адреса, а в файле почему-то наоборот. Я реализовал чтение каждого из двух байтов раздельно. Ты можешь по-другому придумать.
1
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
07.11.2014, 21:31  [ТС] 7
nmcf, вот в моем тупом случае считываю в 2 переменных char 0A и 20
как мне из этого потом сложить число 0A 20 (hex) = 2592 (dec)
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
07.11.2014, 21:48 8
Сдвигом, например, (0A << 8) + 20
Только char - тип со знаком, поэтому если арифметически соединять, могут быть сложности при больших величинах. Лучше сделай как у меня через unsigned short int и указатели.
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
07.11.2014, 22:02  [ТС] 9
ifs.ignore(2 + 1); не могу найти аналог на си
ifs.read((char *)&pic_height + 1, 1); и тут понимаю что чтение из файла в переменную pic_height (типа unsinget char а вот что такое +1 и ,1) непонимаю
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
07.11.2014, 22:11 10
Зачем тебе этот древний Си? Где ты его вообще откопал? ftell() и fseek() попробуй.
Вот это достаточно древняя конструкция: (char *)&pic_height - интерпретировать unsigned short как массив из двух байтов. У нулевого будет адрес (char *)&pic_height, у первого (char *)&pic_height + 1. Арифметика указателей.
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
08.11.2014, 02:31  [ТС] 11
nmcf, Си в учебных целях для понимания основ... учусь на курсах, пройду си потом будет с++ там будут потоки и тд будет попроще.

Написал вот так, громоздко глупо но пока хоть так, у тебя возьму алгоритм поиска маркеров, еще раз тебе спасибо!
C
1
2
3
4
5
6
7
8
9
10
11
unsigned char xd=0;
       double adr = 0x0145c;
       double *ff;
       ff=&adr;
       fseek(fp, adr, 0); 
       fread(&xd,1,1,fp);
       int c1 = xd << 8;
       fread(&xd,1,1,fp);
       int s=c1+xd;
       printf(" Density X = %d \n ",s);
      fseek(fp, 0x00000000, 0);
Добавлено через 3 часа 19 минут
nmcf,
Все получилось вынул разрешение, проверил на нескольких файлах, хотел спросить то что ты в первый самый пост отправил это что за мануал? я из твоей картинки там я понял больше чем за часа в google...
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
08.11.2014, 10:40 12
это что за мануал?
Не знаю. Я его с помощью Google и нашёл: http://lad.dsc.ufcg.edu.br/mul... marker.pdf
По твоему коду замечания. Нельзя в целочисленной арифметике использовать double, он не гарантирует точность представления, используй long. Далее, двухбайтные длины секций беззнаковые, судя по всему, поэтому хранить в беззнаковой переменной надо, а у тебя int. Сдвиг, как я сказал, из-за этих знаков может некорректный результат дать для секций большой длины. Не понимаешь указатели, используй, например union, он есть в Си:
C++
1
2
3
4
5
union d
{
    unsigned short int d16;
    char d8[2];
}
Cоответственно, считываешь в d.d8[1] и в d.d8[0], а используешь d.d16. Если у тебя unsigned short int не 2 байта, поставь свой двухбайтный беззнаковый тип.

Добавлено через 20 минут
Можно сразу читать по 2 байта, и менять местами:
C++
1
2
            ifs.read((char *)&d, 2);
            __asm { ror d, 8 }
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
08.11.2014, 12:36  [ТС] 13
Тут так не проходит наверно из за собственностей древнего fread

C
1
2
3
4
5
6
7
8
9
10
 union xx
              {
                   unsigned int d16;
                   char d8[2];
               };
              
               fseek(fp, 3, 1); 
              fread(xx.d8[1],1,1,fp);
              fread(xx.d8[2],1,1,fp);
              printf(" X = %d \n",xx.d16)
Как из файла JPEG вытащить размер изображения в пикселях?

Как из файла JPEG вытащить размер изображения в пикселях?
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
08.11.2014, 13:03 14
fread() принимает указатель. У тебя же в прошлом фрагменте это учтено. И нумерация 1, 0.
C++
1
2
fread(&xx.d8[1],1,1,fp);
fread(&xx.d8[0],1,1,fp);
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
08.11.2014, 13:08  [ТС] 15
второй скрин сообщает нам что и & не прокатывает, я пробовал еще в первый раз
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
08.11.2014, 13:12 16
Как тогда это у тебя работало?
C++
1
fread(&xd,1,1,fp);
Может так:
C++
1
2
fread(&(xx.d8[1]),1,1,fp);
fread(&(xx.d8[0]),1,1,fp);
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
08.11.2014, 14:16  [ТС] 17
нет скобки ожидаемо не помогли, тут дело скорее в том кто под чем пишет и компилирует, вот у меня Дельфийское Чудовище для обучающийся " DevC++ 5.8.1 с компилятором (TDM-GCC 4.8.1 64-bit Debug) " Win 7 HP 64.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <stdlib.h>
#define FNAME "C:\\Users\\RUNA\\Dropbox\\13.jpg"
 
int main(int argc, char *argv[])
{    
 
     char fname[40] = FNAME;
     FILE *fp;
     if ((fp=fopen(fname, "rb")) == NULL)
     {
          printf("Error read file");
          system("pause");
          return 1;
    }
//------------------------------------------------------
    printf("\n Start file %s\n", fname);
     puts ("--------------------------------");
//------------------------------------------------------
      unsigned char  mark=0x0;
       fseek(fp, 0x0, 0); 
 
       while (fread(&mark,1,1,fp) == 1)
       {       
          if (mark == 0xff)
          {
               fread(&mark,1,1,fp);
                 if (mark == 0xc0)
               {              
               // ----------- XXX ----------------
               unsigned char xd=0;
              fseek(fp, 3, 1); 
              fread(&xd,1,1,fp);
              unsigned int xxx = xd << 8;
              fread(&xd,1,1,fp);
              unsigned int sx=xxx+xd;
              printf(" X = %d \n",sx);
              //------------ YYY -----------------
             fread(&xd,1,1,fp);
             unsigned int yyy = xd << 8;
              fread(&xd,1,1,fp);
              unsigned int sy=yyy+xd;
              printf(" Y = %d \n",sy);
 
            }
          }
 
       }   
     fclose(fp);
     puts ("--------------------------------");    
     printf("          End file\n");
     system("pause");         
 
     return 0;
}
Это работает !

А ты под чем пишешь?
0
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
08.11.2014, 18:07 18
Это же стандартные вещи, а не какие-то специфические библиотеки. Должно работать. И что, в этом DevC++ тип int двухбайтный?
У меня Visual C++.
0
12 / 11 / 6
Регистрация: 05.10.2013
Сообщений: 219
08.11.2014, 20:19  [ТС] 19
nmcf,
unsigned int 2 (16) от 0 до 65535
0
08.11.2014, 20:19
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.11.2014, 20:19
Помогаю со студенческими работами здесь

Как узнать размеры изображения в пикселях (N x N) не загружая его в память
Здравствуйте. Есть изображения в формате jpeg. Вопрос : как узнать размер изображения(ширину и...

Как узнать размеры изображения в пикселях (высоту и ширину) до его загрузки в TImage
Здравствуйте. Через OpenPictureDialog есть возможность выбирать графические изображения для...

как восстановить поврежденные jpeg изображения?
Всем привет, недавно мне пришлось форматировать диск, а на нем много важных фоток. Некоторые...

Как сделать размер jpeg равный размеру timage
в программе открывается фото и нужно на ней нарисовать,мой jpeg файл в форме занимает лишь верхний...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru