Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 3 4 [Все]   Вниз
  Печать  
Автор Тема: Избавится от циклов при рисовании картинки в Qt  (Прочитано 87137 раз)
0 Пользователей и 1 Гость смотрят эту тему.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« : 14-05-2013 06:10 » 

Здравствуйте.

Я задавал много, где на форумах этот вопрос, но пока решения не получилось. Может быть здесь найдётся решение.

Задача:
У меня есть двоичный (бинарный) файл. То есть каждый байт файл это значение RGB.
R = 1-й байт
G = 1-й байт
B = 1-й байт
На следующей стадии цикла будет
R = 2-й байт
G = 2-й байт
B = 2-й байт
и так далее

Я пробовал заполнить объект QImage с помощью метода "setPixel" и выводить через метод "drawImage", так как этот метод позволяет выводить по частям.
Но увы для использования метода "setPixel" нужен двойной цикл, а значений очень много и из-за этого всё тормозит.

OpenGL использовать нельзя.

Может есть механизм без циклов заполнить объект QImage или какой-то другой механизм заполнения есть?

Мне нужно, что бы ни при заполнении, ни при выводе циклов не было,  при том вывод должен уметь выводить по частям.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 14-05-2013 06:14 » 

zuze, привет ) Я перенёс в общий, так как для Qt раздела у нас ещё нет, а тема не про Unix вовсе

Добавлено через 3 минуты и 12 секунд:
а по задаче - вроде всё уже выяснили неоднократно . Ты заполняешь QImage один раз (циклами или методом), потом пользуешься на здоровье.
« Последнее редактирование: 14-05-2013 06:17 от Алексей1153 » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #2 : 14-05-2013 06:21 » 

Цитата
Добавлено через 3 минуты и 12 секунд:
а по задаче - вроде всё уже выяснили неоднократно . Ты заполняешь QImage один раз (циклами или методом), потом пользуешься на здоровье.

Циклами заполнить QImage это легко, но тормозит всё, а что же за метод который может без циклов заполнить?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 14-05-2013 06:22 » 

zuze, покажи цикл, который у тебя тормозит. Без всего лишнего
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #4 : 14-05-2013 06:26 » 

Алексей++, вот этот цикл жутко тормозит.

Код:
// Глобальные
int buffer[492][720];
QImage im(720, 492, QImage::Format_ARGB32);

Код:
for (int j = 0; j < 720; j++)
{
     for (int i = 491; i >= 0; i--)
     {
          buffer[i][j] = getc(fp);
          im.setPixel(j, i, QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba());
      }
 }
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 14-05-2013 06:44 » 

zuze, есть метод

QImage::fromData ( const QByteArray & data, const char * format = 0 )

1) создаёшь экземпляр QByteArray
2) в цикле заполняешь его из источника
3) перетусовываешь байты под твой формат
4) вызываешь QImage::fromData

на мой взгляд это всё выполнится достаточно быстро
Записан

darkelf
Молодой специалист

ua
Offline Offline

« Ответ #6 : 14-05-2013 07:12 » 

Алексей++, вот этот цикл жутко тормозит.

Код:
// Глобальные
int buffer[492][720];
QImage im(720, 492, QImage::Format_ARGB32);

Код:
for (int j = 0; j < 720; j++)
{
     for (int i = 491; i >= 0; i--)
     {
          buffer[i][j] = getc(fp);
          im.setPixel(j, i, QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba());
     }
}
имхо, как вариант попробовать вычитать buffer, зараннее одним чтением fread(), правда тогда надо будет поменять int buffer[][] на unsigned char buffer[][] (или в файле хранить не байты, а int-ы), и поменять порядок обхода - тогда лучше будет работать кеши процессора:
Код:
fread(buffer, 1, sizeof(buffer), fp);
for (int i = 0; i < 492; i++)
{
     for (int j = 0; j < 720; j++)
     {
          im.setPixel(j, i, QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba());
     }
}
« Последнее редактирование: 14-05-2013 07:44 от darkelf » Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #7 : 14-05-2013 07:14 » 

zuze, есть метод

QImage::fromData ( const QByteArray & data, const char * format = 0 )

1) создаёшь экземпляр QByteArray
2) в цикле заполняешь его из источника
3) перетусовываешь байты под твой формат
4) вызываешь QImage::fromData

на мой взгляд это всё выполнится достаточно быстро

А почему это убыстрит скорость, ведь "2) в цикле заполняешь его из источника", тоже значит циклы есть?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 14-05-2013 07:21 » 

darkelf, это кроссплатформа, не думай про кеши ) А вычитать можно и кусками побольше, это я согласен.

zuze, потому что QImage::setPixel - медленная операция . Ну и побайтное чтение из потока - тоже не айс, как выше правильно отметили )
Записан

darkelf
Молодой специалист

ua
Offline Offline

« Ответ #9 : 14-05-2013 07:27 » 

Алексей++,  э.. ну если мы пишем на C/C++, а не на Java, то, по возможности, про кеши надо думать всегда, если интересно - есть статья Ульриха Дреппера "Что каждый программист должен знать о памяти" по этому поводу, если интересно - вот ссылка на её перевод на русский: http://rus-linux.net/MyLDP/hard/memory/memory.html, думаю, что она может оказаться полезной.

Кстати, по поводу конструктора - у QImage, если я правильно понял, есть ещё вариант:
Код:
QImage ( uchar * data, int width, int height, Format format );
т.е. можно,  сделать что-то типа такого:
Код:
fread(buffer, 1, sizeof(buffer), fp);
QImage (buffer, 720, 492, QImage::Format_ARGB32);
Хотя наверное надо будет буфер, как сказал Алексей++, ещё обработать..
« Последнее редактирование: 14-05-2013 07:45 от darkelf » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 14-05-2013 07:31 » 

darkelf, я гляну, но в данном случае это всё не имеет отношения к делу ИМХО )
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #11 : 15-05-2013 04:52 » 

zuze, потому что QImage::setPixel - медленная операция . Ну и побайтное чтение из потока - тоже не айс, как выше правильно отметили )

И что же в таких случаях используют? Скорее всего я не первый, кто с такой проблемой сталкивается. Может какие другие надо модули использовать.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 15-05-2013 11:26 » 

zuze, так уже снова всё расписали )) Прочитай!
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #13 : 17-05-2013 04:48 » 

zuze, так уже снова всё расписали )) Прочитай!

Прошу прощения, у нас сейчас переест вообще замаялся и не увидел Вашу строчку в конце "на мой взгляд это всё выполнится достаточно быстро".

Я понял, что надо сделать по Вашему алгоритму.

Цитата: Алексей++
QImage::fromData ( const QByteArray & data, const char * format = 0 )

1) создаёшь экземпляр QByteArray
2) в цикле заполняешь его из источника
3) перетусовываешь байты под твой формат
4) вызываешь QImage::fromData

Как будет готово всё покажу. Может кому тоже пригодится.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 17-05-2013 05:07 » 

ещё момент - если заранее знаешь, какой будет конечный объём QByteArray после чтения из файла , имеет смысл перед чтением вызвать

 QByteArray::reserve(конечный объём в байтах)

поскольку читать ты будешь  кусками, а не разом, это тоже чуток повысит скорость работы. Хотя, может и незначительно в данном случае. Попробуешь, в общем
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #15 : 17-05-2013 09:58 » 

Алексей++, вот у меня неожиданно появился вопрос по поводу заполнения QByteArray значениями из файла.

Пытался сделать так:

Код:
QByteArray b;

for (int k = 0; k < 492*720; k++)
     b[k] = getc(fp);

qDebug() << b.toInt();

fp определён так:

Код:
FILE *fp;

Выскакивает ошибка вообще, не из той области.
Ошибка такая: QColor::setRgb: RGB parameters out of range.

То есть данный код, повлиял на код который ниже расположен, а без этого кода ни какой ошибки нет.
Как же это поправить?

Я бы с удовольствием использовал в место FILE модуль QFile, но в нём возникает ошибка.

я делаю так:

Код:
chdir("file");

QFile fp("1.dat");

if (!fp.open(QIODevice::ReadOnly))
    qDebug() << "File not open";
   
QByteArray file;
file = fp.readAll();

qDebug() << file.toInt();

Выводиться 0 хотя в бинарном (двоичном) файле куча байт.
Если последнюю строчку заменяю на

Код:
qDebug() << file;

То выводятся, только первые десять байт.

Почему такие странные результаты вывода? Мне нужно, что бы выводились все значения из файла в десятичном виде.
« Последнее редактирование: 17-05-2013 12:09 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 17-05-2013 16:22 » 

ты же место в массиве не выделил, а заполняешь - естественно всё падать будет. Но в Qt всё проще можно, и не нужно никаких FILE :

Код:
QFile file("путь");
if(file.open(file.ReadOnly)
{
    QByteArray data=file.readAll ();
    file.close();

    //работаем ...
}


Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #17 : 20-05-2013 05:20 » 

Алексей++, сделал по Вашему примеру аналогичный код.

Вот он:

Код:
chdir("file");
QFile file("1.dat");

if (file.open(file.ReadOnly))
{
   QByteArray data = file.readAll();
   file.close();
   qDebug() << data;
 }

В результате всё равно выводятся только первый десять байт. А на самом деле байт намного больше. Я посмотрел в редакторе двоичных (бинарных) файлов и увидел, что обрыв происходит на байте со значением "00".
Но я не могу поверить, что "readAll()" не может обработать значение байта "00", а может это, так "qDebug()" реагирует на байт со значением "00".
Что же всё таки произошло, почему не всё выводится?
« Последнее редактирование: 20-05-2013 05:27 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 20-05-2013 05:44 » 

всё происходит правильно. Продолжай Улыбаюсь

размер

data.size()
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #19 : 20-05-2013 08:31 » 

всё происходит правильно. Продолжай Улыбаюсь

Код:
chdir("file");
QFile file("1.dat");

if (file.open(file.ReadOnly))
{
   file.seek(file.size() - (492*720));

   QByteArray mydata = file.readAll();
   file.close();

   im = QImage::fromData(mydata, QImage::Format_ARGB32);

   QPainter Tochka;
   Tochka.begin(this);

   Tochka.translate(50, 50);
   Tochka.drawImage(0, 0, im, 0, 0, 720, 492);

   Tochka.end();

Конечно перед строчкой "im = QImage::fromData(mydata, QImage::Format_ARGB32);" надо было сделать "перетусовывание байтов под формат", но я не совсем понял, как это сделать, это что надо было QByteArray надо использовать как двухмерный массив и возможно ли это.

Что касается строки:

Код:
file.seek(file.size() - (492*720));

Так это смещение, так как первые 8 байт это управляющие байты.

im объявлена глобально:

Код:
QImage im(720, 492, QImage::Format_ARGB32);

Но в результате выскакивает ошибка явно не с тем, что я не "перетусовал байты под формат".
Ошибка такая:
conversion from 'qbytearray' to 'const uchar*' is ambiguous
candidates are: QByteArray::operator QNotImplicitBoolCast() const <near match>
QByteArray::operator const void*() const <near match>
QByteArray::operator const char*() const <near match>

Ошибка указывает на строку:

Код:
im = QImage::fromData(mydata, QImage::Format_ARGB32);
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 20-05-2013 08:58 » 

Код: (C++)
        if (file.open(file.ReadOnly))
        {
                /*
                строка
                           file.seek(file.size() - (492*720));
                у тебя ничего не делает и вообще не нужна. Две цифры - вообще непонятно откуда )
               
                откуда инфа про 8 служебных байтов ? Где структура, которая их описывает ?
               
                пропустить размер в 8 байтов проще удалением их из загруженного массива
                */

               
                QByteArray mydata = file.readAll();
                file.close();
                mydata.remove(0,8/*sizeof(та самая структура с описанием)*/);
               
                /*сильно предполагаю, что в этой структуре и размеры сидят*/
                int xsize=...;
                int ysize=...;
               

                //здесь переформатирование
                //...
       
               
/*
If format is not specified (which is the default), the loader probes the file for a header to determine the file format. If format is specified, it must be one of the values returned by QImageReader::supportedImageFormats().
*/

                QImage::Format f=QImage::Format_ARGB32;
                im = QImage::fromData(mydata, &f);
               
               
   }
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #21 : 20-05-2013 09:37 » 

откуда инфа про 8 служебных байтов ?

Это из условия которое мне сказали, когда дали файл.

Где структура, которая их описывает ?

По горизонтали 720, а по вертикали 492. Заполняется картинка с лева на право с низу вверх.
То есть, пока xsize = 0,   int ysize меняется от 0 до 491. Сначала берётся первые 492 байта, затем следующие 492 байта и так далее.

Добавлено через 23 минуты и 14 секунд:
Алексей++, сделал вроде как Вы написали:

Код:
chdir("file");
QFile file("1.dat");

if (file.open(file.ReadOnly))
{
   QByteArray mydata = file.readAll();
   file.close();

   mydata.remove(0, 8);

   // здесь переформатирование (Пока не понимаю, как сделать)

   QImage::Format f = QImage::Format_ARGB32;
    im = QImage::fromData(mydata, &f);

    QPainter Tochka;
    Tochka.begin(this);

    Tochka.translate(50, 50);

    Tochka.drawImage(0, 0, im, 0, 0, 720, 492);

    Tochka.end();

Таже самая ошибка и на той же строчке кода. В чём же дело?
Можно ли обратится к QByteArray, как к двухмерному массиву? Если да, то я без проблем сделаю "переформатирование".
« Последнее редактирование: 20-05-2013 10:00 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 20-05-2013 10:34 » 

а, это я невнимательно поспотрел. Для получения указателя на начад\ло буфера данных надо вызвать метод

data()

но, блин, это из справки можно было уже и так понять ))

перейти к "двухмерности" - только вручную.  К примеру, сначала в массиве структур S идёт первая строка, потом вторая, тогда индекс структуры со строкой row и столбцом col будет равен

Код:
uint32_t i=row*Cols+col 
, где Cols - размер строки (то есть количество колонок)


Код:
S* pArrayOfS=(S*) mydata.data();
uint32_t i=5*Cols+7 ;
pArrayOfS[i]; //это ссылка на элемент S с нужным индексом (5,7)



собственно, S - это структура, описывающая один пиксел. Для конвертации будет удобно использовать похожую структуру с переставленными битовыми полями
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #23 : 20-05-2013 12:16 » 

Для получения указателя на начад\ло буфера данных надо вызвать метод

data()

Как я понял, надо в место:

Код:
im = QImage::fromData(mydata, &f);

написать:

Код:
im = QImage::fromData(mydata.data(), &f);

Но это приводит к ошибке, а именно:
invalid conversion from 'char*' to 'const uchar*'
initializing argument 1 of 'static QImage QImage::fromData(const uchar *, int, const char*)'
invalid conversion from 'QImage::Format*' to 'int'
initializing argument 2 of 'static QImage QImage::fromData(const uchar *, int, const char*)'

В добавок если я начну "переформатирование" в двухмерный массив, то я уже не смогу воспользоваться методом fromData(), который необходим для повышение скорости.
Может есть какое другое "переформатирование" которое бы в конкретном варианте подошло?
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #24 : 20-05-2013 13:36 » 

zuze, как вариант, попробуйте написать
Код:
im = QImage::fromData((const uchar*)mydata.data(), &f)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 20-05-2013 15:44 » 

zuze, ты можешь получить неконстантный указатель на буфер mydata - data(). Через него ты меняешь элементы к нужному виду (это я и назвал переформатированием), не меняя размер буфера (и, естественно, не залазя за его границы!). Потом этот объект mydata и используешь в методе QImage::fromData

Цитата
QImage   fromData ( const QByteArray & data, const char * format = 0 )
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #26 : 21-05-2013 05:36 » 

zuze, как вариант, попробуйте написать
Код:
im = QImage::fromData((const uchar*)mydata.data(), &f)

Попробовал, ошибки остались, но уменьшились, остались только:
invalid conversion from 'QImage::Format*' to 'int'
initializing argument 2 of 'static QImage QImage::fromData(const uchar *, int, const char*)'

Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #27 : 21-05-2013 05:41 » 

zuze, это потому, что там ещё длину массива надо передать. (Ты прототипы функций то гляди)

а я предлагаю использовать метод, где передаётся сразу ссылка на QByteArray
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #28 : 21-05-2013 05:53 » 

zuze, это потому, что там ещё длину массива надо передать. (Ты прототипы функций то гляди)

а я предлагаю использовать метод, где передаётся сразу ссылка на QByteArray

Я не могу понять, выбираю "QImage::fromData(const uchar *, const char*)", а при компиляции запускается "QImage::fromData(const uchar *, int, const char*)", почему же так происходит?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #29 : 21-05-2013 05:57 » 

выбираю "QImage::fromData(const uchar *, const char*)",
такой перегрузки нет. Есть только две:

Код:
QImage	fromData ( const uchar * data, int size, const char * format = 0 )
QImage fromData ( const QByteArray & data, const char * format = 0 )
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #30 : 21-05-2013 06:39 » 

Есть только две:

Код:
QImage	fromData ( const uchar * data, int size, const char * format = 0 )
QImage fromData ( const QByteArray & data, const char * format = 0 )

Тогда почему я выбираю

Код:
QImage	fromData ( const QByteArray & data, const char * format = 0 )

А выскакивает ошибка:
invalid conversion from 'char*' to 'const uchar*'
initializing argument 1 of 'static QImage QImage::fromData(const uchar *, int, const char*)'

Почему так?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #31 : 21-05-2013 06:58 » 

покажи, где ты это выбираешь ? И как ты это делаешь
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #32 : 21-05-2013 07:08 » 

покажи, где ты это выбираешь ? И как ты это делаешь

Прикрепляю картинку, как я выбираю. Если что не понятно будет я поясню.



* SelectfromData.jpg (57.18 Кб - загружено 1034 раз.)
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #33 : 21-05-2013 07:16 » 

zuze, это потому, что там ещё длину массива надо передать. (Ты прототипы функций то гляди)

а я предлагаю использовать метод, где передаётся сразу ссылка на QByteArray

Я не могу понять, выбираю "QImage::fromData(const uchar *, const char*)", а при компиляции запускается "QImage::fromData(const uchar *, int, const char*)", почему же так происходит?
Я посмотрел документацию, есть следующий функции:
Код:
QImage	fromData ( const uchar * data, int size, const char * format = 0 )
QImage fromData ( const QByteArray & data, const char * format = 0 )
функции
Код:
QImage::fromData(const uchar *, const char*)
нет, так-что попробуйте, как советовал Алексей++, либо напрямую передавать  QByteArray & data, либо узнайте его длину, через mydata.size(), что-то типа:
Код:
im = QImage::fromData((const uchar*)mydata.data(), mydata.size(), &f);
или
im = QImage::fromData(&mydata, &f);
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #34 : 21-05-2013 07:29 » 

Прикрепляю картинку, как я выбираю. Если что не понятно будет я поясню.
убил Улыбаюсь

darkelf, только в самой последней строке mydata надо без амперсенда
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #35 : 21-05-2013 07:48 » 

darkelf, только в самой последней строке mydata надо без амперсенда

да делал я так уже:

Код:
im = QImage::fromData(mydata, &f);

А в результате ошибка:
conversion from 'qbytearray' to 'const uchar*' is ambiguous
candidates are: QByteArray::operator QNotImplicitBoolCast() const <near match>
QByteArray::operator const void*() const <near match>
QByteArray::operator const char*() const <near match>

А если делаю так:

Код:
im = QImage::fromData((const uchar*)mydata.data(), mydata.size(), &f);

То всё равно ошибка:
no matching function for call to 'QImage::fromData(const uchar*, int, QImage::Format*)'
candidates are: static QImage QImage::fromData(const uchar*, int, const char*)
static QImage QImage::fromData(const QByteArray&, const char*)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #36 : 21-05-2013 07:54 » 

zuze, прицепи проект, что-то совсем непонятно
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #37 : 21-05-2013 10:14 » 

zuze, прицепи проект, что-то совсем непонятно

Прикрепляю проект. Прошу прощения, что я не могу Вам оригинал двоичного (бинарного) файла предоставить. В замен него в проекте лежит с таким же именем, расширением и количества байт файл. Я его создал лично, в нём байты произвольного значения, но для конкретной цели подойдёт этот файл.

* of.rar (39.55 Кб - загружено 1005 раз.)
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #38 : 21-05-2013 13:33 » 

zuze, попробуйте убрать параметр format вообще, похоже Qt там ожидает строку, типа "JPG", "BMP" и пр.
Код:
im = QImage::fromData(mydata);
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #39 : 21-05-2013 13:44 » 

хм, в общем, оставь так:

im = QImage::fromData(mydata, 0);

формат там задаётся как строка (например "JPG") , а если указать 0, он сам будет разбираться

И ещё - добавь реализации для слотов
    void MyExit();  
    void MyFile();

а то не сможешь собрать

Добавлено через 23 секунды:
darkelf, ага, тоже уже выяснил )
« Последнее редактирование: 21-05-2013 13:44 от Алексей1153 » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #40 : 22-05-2013 06:29 » 

Алексей++, darkelf, большое спасибо, ошибки исчезли, но к сожалению на экран ни чего не выводится, хотя должно рисоваться тоненькая линия по значениям. Прямоугольная область пока не должна рисоваться пока я не сделал "переформатирование". Я подумал может на светлом окне не видно и я сделал чёрное окно, всё равно не видно. На всякий случай прикреплю проект. По идее сейчас линия тоненькая должна рисоваться и уходить за размер окна, так как значений очень много.
И если что тут ещё приведу главный код проекта:
Код:
#include "of.h"
#include "ui_of.h"

#include <io.h>
#include <QByteArray>
#include <QFile>

#include <QPainter>
#include <QImage>

#include <QDebug>

QImage im(720, 492, QImage::Format_ARGB32);

of::of(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::of)
{
    ui->setupUi(this);

    // Для кодировки русского языка на виджетах
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale()); // Без этого кодировки БД не работает
    QTextCodec::setCodecForTr(QTextCodec::codecForName("CP-1251"));

    this->

    // Выход программы
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(MyExit()));
}
of::~of()
{
    delete ui;
}
// Открытие файла
void of::MyDraw()
{
    chdir("file");
    QFile file("1.dat");

    if (file.open(file.ReadOnly))
    {
        QByteArray mydata = file.readAll();
        file.close();

        mydata.remove(0, 8);

        //здесь переформатирование (Пока не понимаю, как сделать)

        im = QImage::fromData(mydata, 0);

        QPainter Tochka;
        Tochka.begin(this);

        Tochka.translate(50, 50);

        Tochka.drawImage(0, 0, im, 0, 0, 720, 492);

        Tochka.end();
    }
}
// Рисование
void of::paintEvent(QPaintEvent *)
{
    MyDraw();
    this->update();
}
// Выход из программы
void of::MyExit()
{
    QApplication::quit();
}

* of2.rar (374.69 Кб - загружено 1024 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #41 : 22-05-2013 06:43 » 

zuze, начнём с того, что paintEvent даже в минимуме должен выглядеть так:

Код:
void of::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    //this->update(); -- это тут нельзя точно!!!
}

если ты вынес код рисования в MyDraw(), то ты должен передать туда ссылку на  painter, чтобы иметь возможность на нём рисовать

Код:
void of::MyDraw(QPainter& painter)
{
    
}


update() в отрисовке не вызывают, это может постоянным и бессмысленным вызовом paintEvent (но не рекурсией, к счастью, как было бы в случае repaint () )

зачем ты грузишь из файла во время каждой перерисовки ? Инициализируй объект QImage один раз, потом пользуйся

переформатирование - интерпретируешь массив байтов как массив структур пикселов, затем приводишь каждый пиксел в нужный вид

Добавлено через 2 минуты и 33 секунды:
а кодировку я себе обычно ставлю "UTF-8"  (соответственно, все файлы h и cpp тоже нужно держать в этой кодировке). Не возникает проблем ни с линуксом, ни с виндой , если придётся под обе системы прект компилить
« Последнее редактирование: 22-05-2013 06:46 от Алексей++ » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #42 : 22-05-2013 10:17 » 

Алексей++, убрал this->update(), сделал открытие и чтение файла один раз. Изменил кодировку, так как в будущем с Linux предстоит работать.
Попытался сделать переформатирование, но выскочила ошибка.
Код основной программы и ошибка:

Код:
#include "of.h"
#include "ui_of.h"

#include <io.h>
#include <QByteArray>
#include <QFile>

#include <QPainter>
#include <QImage>

#include <QDebug>

QImage im(720, 492, QImage::Format_ARGB32);
QByteArray b;
struct QByteArray bstruct[492][720];
int k = 0;

of::of(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::of)
{
    ui->setupUi(this);

    // Для кодировки русского языка на виджетах
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale()); // Без этого кодировки БД не работает
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));  // ("CP-1251"));

    b = MyOpenReadFile();

    // Выход программы
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(MyExit()));
}
of::~of()
{
    delete ui;
}
// Рисование
void of::MyDraw()
{
   // здесь переформатирование
   for (int j = 0; j < 720; j++)
   {
       for (int i = 491; i >= 0; i--)
       {

           bstruct[i][j] = b[k];
           k++;
       }
   }

   im = QImage::fromData(b, 0);

   QPainter Tochka;
   Tochka.begin(this);

   Tochka.translate(50, 50);

   Tochka.drawImage(0, 0, im, 0, 0, 720, 492);

   Tochka.end();
}
// Рисование
void of::paintEvent(QPaintEvent *)
{
    MyDraw();
}
// Выход из программы
void of::MyExit()
{
    QApplication::quit();
}

// Открытие и чтенеи файла
QByteArray of::MyOpenReadFile()
{
    chdir("file");
    QFile file("1.dat");

    if (file.open(file.ReadOnly))
    {
        QByteArray mydata = file.readAll();
        file.close();

        mydata.remove(0, 8);
        return mydata;
    }
}

Ошибка в строке "bstruct[i][j] = b[k];"

invalid conversion from 'char' to 'const char*'
initializing argument of 'QByteArray& QByteArray::operator=(const char*)'

Также прикрепляю проект.

* of3.rar (376.05 Кб - загружено 1011 раз.)
« Последнее редактирование: 22-05-2013 15:56 от Алексей++ » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #43 : 22-05-2013 15:37 » 

Offtopic:
Вы столько всего и с такой скоростью пишите, что удивительно, как вы сами не путаетесь в том, какую проблему решаете.
Поставлю в угол.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #44 : 22-05-2013 15:55 » 

Dimka, смотри ЛС )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #45 : 22-05-2013 15:58 » 

zuze, опять какие-то волшебные цифры - откуда они у тебя вот так, цифрами, взяты ? ) А если картинка сменится ?

Вопрос: как выглядит результат без цикла
Цитата
 
Код:
 // здесь переформатирование
   for (int j = 0; j < 720; j++)
   {
       for (int i = 491; i >= 0; i--)
       {

           bstruct[i][j] = b[k];
           k++;
       }
   }
?
« Последнее редактирование: 22-05-2013 19:37 от Вад » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #46 : 23-05-2013 04:52 » 

zuze, опять какие-то волшебные цифры - откуда они у тебя вот так, цифрами, взяты ? ) А если картинка сменится ?


Ничего волшебного, каждая картинка берётся, только из файла имеет единый формат. Сначала первые 8 байт управляющие, а затем байты самой картинки. Само количество байт для картинки 492*720.
Первый байт после управляющих символов - это R = 1-й байт, G = 1-й байт, B = 1-й байт. Второй байт следующая точка в цветности RGB по такому же принципу.

Вопрос: как выглядит результат без цикла

Закомментировал:
Код:
for (int j = 0; j < 720; j++)
   {
       for (int i = 491; i >= 0; i--)
       {

           bstruct[i][j] = b[k];
           k++;
       }
   }

Но к сожалению, тоже ничего не рисуется.

Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #47 : 23-05-2013 05:39 » 

>>Но к сожалению, тоже ничего не рисуется.
и в отладчике ты видишь, что до этого места (до вывода картинки) дело вообще доходит, а сам объект не IsNull() ?

-------------

zuze, то есть формат пиксела у тебя такой

Код:
#pragma pack(push,1)
struct
{
  uint8_t R;
  uint8_t G;
  uint8_t B;
};
#pragma pack(pop)

?
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #48 : 23-05-2013 06:22 » 

>>Но к сожалению, тоже ничего не рисуется.
и в отладчике ты видишь, что до этого места (до вывода картинки) дело вообще доходит, а сам объект не IsNull() ?

Поставил точку останова на строчку "b = MyOpenReadFile();" в отладчике не отображаются значения. Но когда я после этой строчке написал строчку "qDebug() << b;", то вывелось всё до байта равного нуля и в символьном виде.
Когда я делал с двухмерным массивом то выводились все байты общем количеством 492*720 и в десятичном виде.
 
zuze, то есть формат пиксела у тебя такой

Код:
#pragma pack(push,1)
struct
{
  uint8_t R;
  uint8_t G;
  uint8_t B;
};
#pragma pack(pop)
?

Да формат такой. При использовании двухмерного массива этот формат надо было ещё в десятичный вид было приводить.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #49 : 23-05-2013 06:54 » 

тогда ещё вопрос:
>>Но к сожалению, тоже ничего не рисуется.
ничего - это как выглядит ? Улыбаюсь Скриншот хоть покажи

И ещё - а ты знаешь, в каком формате пикселы в файле ? Приложи его, этот файл, что ли уже
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #50 : 23-05-2013 07:12 » 

тогда ещё вопрос:
>>Но к сожалению, тоже ничего не рисуется.
ничего - это как выглядит ? Улыбаюсь Скриншот хоть покажи

Прикрепляю скриншот программы.

И ещё - а ты знаешь, в каком формате пикселы в файле ?

Конечно, в нём значения в шестнадцатеричном виде. Каждое из этих значений не меньше 00 и не больше FF. У этих значений такой диапазон значений, что бы удовлетворял модели цветности RGB.



* myprog.jpg (42.49 Кб - загружено 1029 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #51 : 23-05-2013 07:15 » 

1) то есть, фон формы закрасился белым цветом ? А без попыток вывода картинки он тоже белый ? Это важно знать, так как в первом случае выходит так, что пикселы интерпретируются как белые, а во втором вообще ничего не рисуется скорее всего

2) я про формат спросил - приведи структуру одного пиксела в твоём файле
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #52 : 23-05-2013 07:31 » 

1) то есть, фон формы закрасился белым цветом ? А без попыток вывода картинки он тоже белый ? Это важно знать, так как в первом случае выходит так, что пикселы интерпретируются как белые, а во втором вообще ничего не рисуется скорее всего

Окно всегда такое серое, даже без вывода картинки я даже делал окна чёрное, всё равно не было картинки.

2) я про формат спросил - приведи структуру одного пиксела в твоём файле

Она такая же, как Вы поняли:
 
Код:
struct
{
  uint8_t R;
  uint8_t G;
  uint8_t B;
};

Единственный нюанс тут, как я понял, что uint8_t - это unsigned char, а для указания цвета надо привести в десятичный вид, то есть, что то типа этого сделать int(uint8_t).
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #53 : 23-05-2013 07:42 » 

1) выходит, картинка просто не выводится вообще,

это у тебя где-то тут
Цитата
Tochka.drawImage(0, 0, im, 0, 0, 720, 492);

так что результат мы увидеть сейчас не сможем никакой. Добейся, чтобы в указанном тобой прямоугольнике выводилось хоть что-то из твоего объекта QImage, пусть даже это будет мусор. Скажем, так

Код:
Tochka.drawImage(QRect(20,20,100,100), im);

2) ничего приводить не нужно, uint8_t  - это уже один байт без знака
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #54 : 23-05-2013 10:00 » 

Единственный нюанс тут, как я понял, что uint8_t - это unsigned char, а для указания цвета надо привести в десятичный вид, то есть, что то типа этого сделать int(uint8_t).

Как всё запущено. Жаль
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #55 : 24-05-2013 05:11 » 

Добейся, чтобы в указанном тобой прямоугольнике выводилось хоть что-то из твоего объекта QImage, пусть даже это будет мусор. Скажем, так

Код:
Tochka.drawImage(QRect(20,20,100,100), im);

Ничего не получилось, я думаю надо сначала проверить значения хранимые в QByteArray.
Делаю так:

Код:
for (int i = 0; i < b.size(); i++)
        qDebug() << b.at(i);

А в итоге выводятся только два байта и выскакивает ошибка:
ASSERT: "i >= 0 && i < size()" in file ..\..\include/QtCore/../../src/corelib/tools/qstring.h, line 688
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.


В добавок выскакивает такое окно:
1. Название окна: Microsoft Visual C++ Runtime Library
2. Сообщение окна:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
3. Кнопка: ОК

И это случается, когда натыкается на байт со значением [00].
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #56 : 24-05-2013 05:21 » 

zuze, у тебя im нерабочий.  А то, что ты пытаешься распечатать массив с байтами - тут понятно, что будет падать
qDebug()<< пытается интерпретировать байты QByteArray как печатные символы, отсюда и ошибка. Содержимое массива можно глянуть в окне отладчика, в списке переменных. Или уж сделай функцию распечатки дампа

прицепи проект снова, что ли
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #57 : 24-05-2013 06:40 » 

zuze, у тебя im нерабочий.  А то, что ты пытаешься распечатать массив с байтами - тут понятно, что будет падать
qDebug()<< пытается интерпретировать байты QByteArray как печатные символы, отсюда и ошибка. Содержимое массива можно глянуть в окне отладчика, в списке переменных. Или уж сделай функцию распечатки дампа

Я проверил размер переменной QByteArray, всё впорядке с размером, он равен размеру файла минус 8 управляющих байт.

прицепи проект снова, что ли

Прикрепляю.

* of4.rar (376.72 Кб - загружено 951 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #58 : 24-05-2013 06:50 » 

а файл 1.dat где ?
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #59 : 24-05-2013 06:54 » 

а файл 1.dat где ?

Он лежит в "of-build-desktop\file\".
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #60 : 24-05-2013 07:04 » 

))) я эту папку всегда удаляю сразу, там только мусор Улыбаюсь Щас достану

Добавлено через 7 минут и 25 секунд:
с глобальными переменными жестяк, конечно, полный...

а по сути - QImage::fromData у тебя возвращает null

Добавлено через 1 минуту и 24 секунды:
думаю, массив нужно сначала привести к виду 24-битноцветного битмапа (BMP)

Добавлено через 12 минут и 40 секунд:
zuze, вот тебе пища для размышлений (времени у тебя вагон, как я понимаю) , разбирайся, задавай вопросы Улыбаюсь

(click to show)

* test.PNG (48.31 Кб - загружено 2047 раз.)
« Последнее редактирование: 24-05-2013 07:25 от Алексей1153 » Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #61 : 27-05-2013 07:28 » 

с глобальными переменными жестяк, конечно, полный...

Глобальные переменные это я на первое время для простоты.


думаю, массив нужно сначала привести к виду 24-битноцветного битмапа (BMP)

А не проще будет перевести QByteArray в uchar * и использовать "QImage::fromData (const uchar * data, int size, const char * format = 0)"?


Я сделал так:

Код:
//Глобально объявил

uchar *buffer;

После

Код:
b = MyOpenReadFile();

Добавил

Код:
buffer = (uchar *)b.data();
buffer = '\0';

А в место

Код:
im = QImage::fromData(b, 0);

Написал

Код:
im = QImage::fromData(buffer, 492*720,0);

Всё равно не рисуется. В чём же дело? На всякий случай прикрепляю проект.

* of5.rar (373.9 Кб - загружено 867 раз.)
« Последнее редактирование: 27-05-2013 08:07 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #62 : 27-05-2013 15:56 » 

нет, не проще. Проект я не буду смотреть , там ничего нового не увижу )

а скажи, кто формирует эти корявые исходные файлы-картинки ? Может быть, просто их вылечить до нормального формата  там, где они создаются ?
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #63 : 28-05-2013 04:50 » 

нет, не проще.

Всё понял, буду подготавливать QByteArray в нужную форму и если что спрашивать совета.

а скажи, кто формирует эти корявые исходные файлы-картинки ?

Эти файлы поставляются с выше.

Может быть, просто их вылечить до нормального формата  там, где они создаются ?

К сожалению это запрещено, по-каким причинам не знаю.

разбирайся, задавай вопросы Улыбаюсь

Код:
b = MyOpenReadFile();

QByteArray BMPFile;
BMPFile.resize(10);
BMPFile[0]  = 0x42;  // Тип файла
BMPFile[1]  = 0x4D;  // Тип файла
BMPFile[2]  = 0x35;  // Размер файла
BMPFile[3]  = 0x63;  // Размер файла
BMPFile[4]  = 0x52;  // Размер файла
BMPFile[5]  = 0x00;  // Зарезервированное место под байты равные 0x00
BMPFile[6]  = 0x00;  // Зарезервированное место под байты равные 0x00
BMPFile[7]  = 0x00;  // Зарезервированное место под байты равные 0x00
BMPFile[8]  = 0x00;  // Зарезервированное место под байты равные 0x00
BMPFile[9]  = 0x00;  // Зарезервированное место под байты равные 0x00
BMPFile[10] = 0x10; // Смещение

b.prepend(BMPFile);

Но что, то не рисуется. Наверно я неправильно заполнил BMPFile. Где там ошибка?

Заполняю QImage так:

Код:
im = QImage::fromData(b, 0);

Может тут в место "0" у второго параметра надо, чего-то другое вписывать?

Добавлено через 23 часа, 35 минут и 21 секунду:
У меня проблема с определением размера файла, где в формате BMP только красный цвет.
Я сделал его для примера, что бы понять принцип. С первыми двумя байтами всё понятно.

У меня Windows и редактор двоичных (бинарных) файлов показывает, что размер файла 1815058 байт, но в самом файле я вижу такие значения 0x12, 0xb2, 0x1b это получается 1817827 байт.

1. Откуда эти расхождения?
2. Если размер укладывается меньше чем в 4 байта, то остальные байты я должен сделать 0x00 (допустим, если у меня размер 0x12, 0xb2, то в файле размер должен указываться 0x12, 0xb2, 0x00, 0x00)?

Прикрепляю скриншёт с открытием файла в редакторе двоичных (бинарных) файлов.

* red_size.jpg (486.85 Кб - загружено 910 раз.)
« Последнее редактирование: 29-05-2013 06:55 от zuze » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #64 : 29-05-2013 07:31 » 

У меня Windows и редактор двоичных (бинарных) файлов показывает, что размер файла 1815058 байт, но в самом файле я вижу такие значения 0x12, 0xb2, 0x1b это получается 1817827 байт.

0x00 1b b2 12 == 1815058
Little endian
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #65 : 29-05-2013 07:43 » 

0x00 1b b2 12 == 1815058

Не понял ведь 0xb2 = 178, а 0x12 = 27, как это может равняться в итоге 1815058?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #66 : 29-05-2013 07:49 » 

zuze, калькулятор у тебя есть? Покалькулируй. И так у тебя 0x12 вдруг становится 27? Внимательность и еще раз внимательность! Little endian
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #67 : 29-05-2013 08:13 » 

и ещё момэнт есть: строки в BMP - составлены из 3-байтовых структур-пикселов, поэтому строка может оказаться размером, не кратным 4. Если это происходит, нужно дописать строку нулями до кратности.
Также, картинка в файле перевёрнута "вверх ногами"

на примере картинки вверху:


* Безымянный.PNG (5.88 Кб - загружено 1717 раз.)
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #68 : 29-05-2013 08:17 » 

И так у тебя 0x12 вдруг становится 27?

Это я ошибся я хотел написать, что 0x1b = 27, а это 0x12 = 18. Сейчас всё ещё лучше пересчитаю.
Всё понял надо было за раз и с право налево считать. Тогда совпадает. Большое спасибо!

Добавлено через 27 минут и 22 секунды:
Значит, если у меня файл размером 354 248 байт, то в файле будет записано 0x05 0x67 0xC8, а считаться с права налево. Я прав?
« Последнее редактирование: 29-05-2013 09:39 от zuze » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #69 : 29-05-2013 10:02 » 

Число: 0x000567C8
Байты:
  little endian: C8 67 05 00
  big endian: 00 05 67 C8

Процессоры x86 используют little endian (младший вперед). Для межплатформенных форматов часто используют «сетевой порядок байт», совпадающий с big endian (старший вперед).
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #70 : 29-05-2013 10:12 » 

Число: 0x000567C8
Байты:
little endian: C8 67 05 00
big endian: 00 05 67 C8

Процессоры x86 используют little endian (младший вперед). Для межплатформенных форматов часто используют «сетевой порядок байт», совпадающий с big endian (старший вперед).

Тогда почему в файле размер файла, если указано меньше чем четыре байта, то 0x00 указываются в конце, а по Вашему они должны быть в начале. То есть если у "00 05 67 C8", то "00" должен быть в конце, а не в начале. Даже у "Алексей++" размер стоит "96 00 00 00", а не "00 00 00 96". Что-то может я опять не так понимаю?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #71 : 29-05-2013 10:53 » 

little_endian(96 00 00 00) -> 0x00000096
Неужели это сложно?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #72 : 29-05-2013 10:57 » 

little_endian(96 00 00 00) -> 0x00000096
Неужели это сложно?

Я не в этом плане, я засомневался, что значения байт big endian 00 в начале, а не в конце, а так всё ясно.

Добавлено через 31 минуту и 58 секунд:
А как теперь вычислить значение "Смещение, с которого начинается само    изображение (растр). [Области данных]", которая 4 байта занимает?
« Последнее редактирование: 29-05-2013 11:29 от zuze » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #73 : 29-05-2013 13:22 » 

http://ru.wikipedia.org/wiki/BMP
Цитата
bfOffBits — содержит смещение в байтах от начала структуры BITMAPFILEHEADER до непосредственно битов изображения

Ты это читал? Что здесь непонятно?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #74 : 30-05-2013 04:43 » 

Что здесь непонятно?

Как до меня вчера не доходило, сегодня с утра сразу дошло - это значения количество байт перед байтами относящимися к самому изображению (то есть цвету).
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #75 : 30-05-2013 05:37 » 

Все просто. Надо лишь читать текст подряд, а не куда глаз упал. Ага
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #76 : 30-05-2013 08:17 » 

Алексей++, у меня вопрос я вроде превратил QByteArray, но тоже ничего не рисуется. Наверно, что-то не так заполнил.

В конструкторе у меня так:

Код:
b = MyOpenReadFile();

QByteArray BMPFile;
BMPFile.resize(54);

BMPFile[0]  = 0x42; // Тип файла. Указывается "B"
BMPFile[1]  = 0x4D; // Тип файла. Указывается "M"

// Считать по little-endian - младший байт располагается в памяти по меньшему адресу
// Записывать по big-endian - старший байт располагается в памяти по меньшему адресу
// (354240 + 54 = 354294)
BMPFile[2]  = 0xF6; // Размер файла
BMPFile[3]  = 0x67; // Размер файла
BMPFile[4]  = 0x05; // Размер файла
BMPFile[5]  = 0x00; // Размер файла

BMPFile[6]  = 0x00; // Зарезервированное место под байты равные 0x00
BMPFile[7]  = 0x00; // Зарезервированное место под байты равные 0x00
BMPFile[8]  = 0x00; // Зарезервированное место под байты равные 0x00
BMPFile[9]  = 0x00; // Зарезервированное место под байты равные 0x00

// Количество байт до байт относящихся к картинки
BMPFile[10] = 0x36; // Смещение
BMPFile[11] = 0x00; // Смещение
BMPFile[12] = 0x00; // Смещение
BMPFile[13] = 0x00; // Смещение

// Длина заголовка равняется всегда 40 (0х28)
BMPFile[14] = 0x28;
BMPFile[15] = 0x00;
BMPFile[16] = 0x00;
BMPFile[17] = 0x00;

// Щирина изображения, пикселы (720 пикселов)
BMPFile[18] = 0x00;
BMPFile[19] = 0x2D;
BMPFile[20] = 0x00;
BMPFile[21] = 0x00;

// Высота изображения, пикселы (492 пикселов)
BMPFile[22] = 0xEC;
BMPFile[23] = 0x01;
BMPFile[24] = 0x00;
BMPFile[25] = 0x00;

// Количество плоскостей
BMPFile[26] = 0x00;
BMPFile[27] = 0x01;

// Количество бит на пиксель (24 бит)
BMPFile[28] = 0x18;
BMPFile[29] = 0x00;

// Тип сжатия (без сжатия)
BMPFile[30] = 0x00;
BMPFile[31] = 0x00;
BMPFile[32] = 0x00;
BMPFile[33] = 0x00;

// Размер изображения в байтах (492 * 720 = 354240)
BMPFile[34] = 0xC0;
BMPFile[35] = 0x67;
BMPFile[36] = 0x05;
BMPFile[37] = 0x00;

// Горизонтальное разрешение, точки на метр
BMPFile[38] = 0x00;
BMPFile[39] = 0x00;
BMPFile[40] = 0x00;
BMPFile[41] = 0x00;

// Вертикальное разрешение, точки на метр
BMPFile[42] = 0x00;
BMPFile[43] = 0x00;
BMPFile[44] = 0x00;
BMPFile[45] = 0x00;

// Число используемых цветов (0 - максимально возможное для данной глубины цвета)
BMPFile[46] = 0x00;
BMPFile[47] = 0x00;
BMPFile[48] = 0x00;
BMPFile[49] = 0x00;

// Число основных цветов
BMPFile[50] = 0x00;
BMPFile[51] = 0x00;
BMPFile[52] = 0x00;
BMPFile[53] = 0x00;

b.prepend(BMPFile);

Остальное всё по старому. Прикрепляю проект. На всякий случай файл 1.dat лежит в "of-build-desktop\file\".


* of.zip (452.14 Кб - загружено 890 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #77 : 30-05-2013 09:39 » 

zuze, я не компьютер ) Что мешает структуру заполнить ? Она уже объявлена
http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx

тебе до пикселов нужно расположить инфу в таком порядке:
BITMAPFILEHEADER
BITMAPINFOHEADER

Код:

int sizeofpix=354240;//размер массива пикселов

BITMAPFILEHEADER  fh={0};
BITMAPINFOHEADER ih={0};

fh.bfType=0x4D42;
fh.bfOffBits=sizeof(fh)+sizeof(ih);
fh.bfSize=sizeofpix + fh.bfOffBits

ih.biSize=sizeof(ih);
ih.biWidth=ШИРИНА_В_ПИКСЕЛАХ;;
ih.biHeight=ВЫСОТА_В_ПИКСЕЛАХ;
ih.biPlanes=1;
ih.biBitCount=24;
ih.biSizeImage=sizeofpix;


эти данные засовываешь перед пикселами. Не проверял, писал прямо здесь, разбирайся ) Возможно, что-то забыл указать
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #78 : 03-06-2013 07:10 » 

Алексей++, большое спасибо. Буду разбираться.

Не хотел новую тему создавать, решил проверить по скорости я этот алгоритм. Заранее перевести все файлы в bmp методом save()

Вот код (тут показано пока преобразование только одного файла):

Код:
// Глобальные
QImage im(720, 492, QImage::Format_ARGB32);
int buffer[492][720];
char NameFiles[670][13];
char NameFiles1[670][16];
int frame = 0;
int p = 0;

void of::paintEvent(QPaintEvent *)
{
       FILE *fp;
       int size = 0;

       if (frame == 0)
       {
          fp = fopen(NameFiles[frame], "rb");

          if (fp == NULL)
            qDebug() << "Cannot open file read!";

         fseek(fp, 0, SEEK_END);
         size = ftell(fp);
         fseek(fp, size - (492*720), SEEK_SET);

         for (int j = 0; j < 720; j++)
         {
             for (int i = 491; i >= 0; i--)
             {
                 buffer[i][j] = getc(fp);
                 im.setPixel(j, i, QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba());
             }
         }
         fclose(fp);

         strcat(NameFiles1[frame], NameFiles[frame]);
         strcat(NameFiles1[frame], ".bmp");
         qDebug() << NameFiles1[frame];

         QPainter painterRect(this);
         painterRect.setBrush(QBrush(Qt::black));
         painterRect.drawRect(50, 50, 720, 492);

         QPainter Tochka;
         Tochka.begin(this);

         Tochka.translate(50, 50);
         Tochka.drawImage(0, 0, im, 0, 0, 720, 492);

         Tochka.end();

         im.save(NameFiles1[frame], "BMP");
         frame = 1;
       }
}
// Массив имён файлов
void of::MyNameFile()
{
    struct _finddata_t f;
    long int hFile;
    int k = 0;
    chdir("file");
    hFile = _findfirst("*.dat", &f);
    int KolAllFile = hFile;

    while (KolAllFile != -1)
    {
        FILE *fp = fopen(f.name, "rb");

        if (fp == NULL)
           qDebug() << "Cannot open file read!";

        strcpy(NameFiles[k], f.name);
        k++;

        fclose(fp);
        KolAllFile = _findnext(hFile, &f);
    }
    _findclose(hFile);
    qDebug() << "OK";
}

Что странно, чёрный фон рисуется, но картинка не рисуется, а следовательно и в файле записывается мусор. В чём же дело?

Как я понял, не выводится из-за этого кода:

Фон чёрный рисуется, а вот сама картинка нет, выдаётся ошибка.
Ошибка такая:
QColor::setRgb: RGB parameters out of range
Invalid parameter passed to C runtime function.
« Последнее редактирование: 03-06-2013 11:36 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #79 : 03-06-2013 18:09 » 

могу предположить, что неправильно собираешь цвет

сохрани "новую BMP" картинку в файл и погляди дамп. Думаю, всё станет видно
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #80 : 10-06-2013 07:43 » 

Мне удалось все файлы перевести в BMP.
« Последнее редактирование: 10-06-2013 07:46 от zuze » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #81 : 10-06-2013 09:07 » 

хорошо
Записан

zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #82 : 18-06-2013 08:33 » 

Хочу немного отойти от BMP файлом и попробовать сделать, как будет меняться скорость рисования, если я поменяю метод setPixel на метод bits, а к BMP файлу я обязательно вернусь.

Вот код который был:

Код:
// Глобальные
int buffer[492][720];
QImage im1(720, 492, QImage::Format_ARGB32);

// В таймере
for (int j = 0; j < 720; j++)
{
     for (int i = 491; i >= 0; i--)
     {
          buffer[i][j] = getc(fp);
          im.setPixel(j, i, QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba());
      }
}

// В paintEvent
Tochka.drawImage(0, 0, im, 0, 0, static_cast<int>((2*this->MyRadianToGradus(phi))+0.5), 492);

Картинка прекрасно рисуется с каждым срабатыванием таймера всё больше и больше появляется картинка, пока она не появится полностью.

А вот на что я пытался заменить:

Код:
// Глобальные
int buffer[492][720];
QImage im1(720, 492, QImage::Format_ARGB32);

QRgb *ptr = reinterpret_cast<QRgb *>(im.bits());

// В таймере
for (int j = 0; j < 720; j++)
{
     for (int i = 491; i >= 0; i--)
     {
          buffer[i][j] = getc(fp);
          *(ptr++) = QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba();
      }
}

// В paintEvent
Tochka.drawImage(0, 0, im, 0, 0, static_cast<int>((2*this->MyRadianToGradus(phi))+0.5), 492);

В результате появляется только часть картинки (и в добавок не уверен что правильно, так как не вижу всю картинку), которая нарисовалась при первом срабатывании таймера, а при втором срабатывании таймера ни чего не рисуется, а программа зависает и выскакивает ошибка.
Ошибка такая:
D:\QtProject\l-build-desktop\debug\l.exe завершился с кодом -1073741819

Что не так я сделал?
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #83 : 18-06-2013 08:46 » 

боюсь, что ты неправильно понимаешь метод bits
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #84 : 18-06-2013 09:14 » 

боюсь, что ты неправильно понимаешь метод bits

Он вроде указывает на начало указателя, а значит выполнятся будет быстрее, чем setPixel. Я хотел посмотреть как будет с методом bits скорость рисования происходить.
И вроде в интернете, есть какие-то примеры использования метода bits для рисования картинки.
Если я что-то не так понял поясните пожалуйста.
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #85 : 18-06-2013 09:27 » 

да хрен его знает Жаль Я тупо читаю
Цитата
Returns a pointer to the first pixel data. This is equivalent to scanLine(0).

scanLine
Цитата
Returns a pointer to the pixel data at the scanline with index i. The first scanline is at index 0.

The scanline data is aligned on a 32-bit boundary.

Warning: If you are accessing 32-bpp image data, cast the returned pointer to QRgb* (QRgb has a 32-bit size) and use it to read/write the pixel value. You cannot use the uchar* pointer directly, because the pixel format depends on the byte order on the underlying platform. Use qRed(), qGreen(), qBlue(), and qAlpha() to access the pixels.

Т.е. scanline возвращает RGB структуру

Но это указатель на копию? изображения
Все равно затем этот "буфер" нужно "сбросить" на "дисплей"
« Последнее редактирование: 18-06-2013 09:30 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #86 : 18-06-2013 10:31 » 

Вообще, форматы пикселов могут быть самые разные. И дело тут не только в Big-Endian и Little-Endian, но и в количестве битов на цветовой канал, в порядке следования цветовых каналов, наличие и положение альфа-канала; наконец, бывают индексы палитры из заголовка, бывает одноканальный grayscale с разным количеством битов, и даже встречаются форматы YCbCr видеосигнала.

Так что попытка напрямую работать с битами уместна только в одном случае: если это BMP собственного производства - что записал, то и прочитал.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #87 : 18-06-2013 10:49 » 

Но это указатель на копию? изображения
Все равно затем этот "буфер" нужно "сбросить" на "дисплей"

Метод bits возвращает массив значений из которых состоит картинка.

Но это указатель на копию? изображения
Все равно затем этот "буфер" нужно "сбросить" на "дисплей"

Да конечно придётся рисовать на дисплей возможно с помощью циклов. Я только с помощью метода bits хотел избавится от метода setPixel и лично убедится с какой скоростью будет рисоваться.
Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #88 : 25-07-2013 11:38 » 

Прошу прощения, что так долго ничего не писал был занят.

Я вот сделал метод bits() в место метода setPixel() разница по времени не такая большая получается.

Если кому интересно вот так я сделал
метод setPixel()
Код:
QImage im(720, 492, QImage::Format_ARGB32);

for (int j = 0; j < 720; j++)
{
     for (int i = 491; i >= 0; i--)
     {
          buffer[i][j] = getc(fp);
          im.setPixel(j, i, QColor(buffer[i][j], buffer[i][j], buffer[i][j], 255).rgba());
     }
}

Метод bits()
Код:
QImage im(720, 492, QImage::Format_ARGB32);
QRgb *line = reinterpret_cast<QRgb *>(im.bits());

for (int j = 0; j < 720; j++)
{
          line = (QRgb*)im.bits() + 492*720 - 720 + j;
          for (int i = 491; i >= 0; i--)
          {
                    buffer[i][j] = getc(fp);
                    line = qRgb(buffer[i][j], buffer[i][j], buffer[i][j]);
                    line = line - 720;
          }
}

Разница между кодом, где во всех циклах был использован метод setPixel() и во всех циклах был использован метод bits() составило примерно 3 секунды. Метод bits() более быстрый, но не намного.

Теперь вплотную приступаю к формату BMP файла.
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #89 : 25-07-2013 12:51 » 

а скажи-ка
line = (QRgb*)im.bits() + 492*720 - 720 + j;

(QRgb*)im.bits() - всегда возвратит одно и тоже?

Если это вычисляемая "константа" -  выноси ее за цикл.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #90 : 25-07-2013 13:00 » 

line = (QRgb*)im.bits() + 492*720 - 720 + j;

(QRgb*)im.bits() - всегда возвратит одно и тоже?

Если это вычисляемая "константа" -  выноси ее за цикл.

Согласен с Вами, лучше вынести за цикл, а в цикле обратится к переменной.
Записан
zuze
Опытный

ru
Offline Offline
Пол: Мужской
Россия, Москва


« Ответ #91 : 01-08-2013 08:10 » 

К сожалению я не могу использовать структуры BITMAPFILEHEADER, BITMAPINFOHEADER, так как программа должна без проблем пересобираться под Linux.

Я попытался сделать так:
Код:
QByteArray BMPFile;

BMPFile[0]  = 0x42; // Тип файла. Указывается "B"
BMPFile[1]  = 0x4D; // Тип файла. Указывается "M"

// Считать по little-endian - младший байт располагается в памяти по меньшему адресу
// Записывать по big-endian - старший байт располагается в памяти по меньшему адресу
BMPFile[2]  = 0x76; // Размер файла
BMPFile[3]  = 0x37; // Размер файла
BMPFile[4]  = 0x10; // Размер файла
BMPFile[5]  = 0x00; // Размер файла

BMPFile[6]  = 0x00; // Зарезервированное место под байты равные 0x00
BMPFile[7]  = 0x00; // Зарезервированное место под байты равные 0x00
BMPFile[8]  = 0x00; // Зарезервированное место под байты равные 0x00
BMPFile[9]  = 0x00; // Зарезервированное место под байты равные 0x00

// Количество байт до байт относящихся к картинки
BMPFile[10] = 0x36; // Смещение
BMPFile[11] = 0x00; // Смещение
BMPFile[12] = 0x00; // Смещение
BMPFile[13] = 0x00; // Смещение

// Длина заголовка равняется всегда 40 (0х28)
BMPFile[14] = 0x28;
BMPFile[15] = 0x00;
BMPFile[16] = 0x00;
BMPFile[17] = 0x00;

// Щирина изображения, пикселы (720 пикселов)
BMPFile[18] = 0xD0;
BMPFile[19] = 0x02;
BMPFile[20] = 0x00;
BMPFile[21] = 0x00;

// Высота изображения, пикселы (492 пикселов)
BMPFile[22] = 0xEC;
BMPFile[23] = 0x01;
BMPFile[24] = 0x00;
BMPFile[25] = 0x00;

// Количество плоскостей
BMPFile[26] = 0x01;
BMPFile[27] = 0x00;

// Количество бит на пиксель (24 бит)
BMPFile[28] = 0x18;
BMPFile[29] = 0x00;

// Тип сжатия (без сжатия)
BMPFile[30] = 0x00;
BMPFile[31] = 0x00;
BMPFile[32] = 0x00;
BMPFile[33] = 0x00;

// Размер изображения в байтах (1 062 720)
BMPFile[34] = 0x40;
BMPFile[35] = 0x37;
BMPFile[36] = 0x10;
BMPFile[37] = 0x00;

// Горизонтальное разрешение, точки на метр
BMPFile[38] = 0x00;
BMPFile[39] = 0x00;
BMPFile[40] = 0x00;
BMPFile[41] = 0x00;

// Вертикальное разрешение, точки на метр
BMPFile[42] = 0x00;
BMPFile[43] = 0x00;
BMPFile[44] = 0x00;
BMPFile[45] = 0x00;

// Число используемых цветов (0 - максимально возможное для данной глубины цвета)
BMPFile[46] = 0x00;
BMPFile[47] = 0x00;
BMPFile[48] = 0x00;
BMPFile[49] = 0x00;

// Число основных цветов
BMPFile[50] = 0x00;
BMPFile[51] = 0x00;
BMPFile[52] = 0x00;
BMPFile[53] = 0x00;

mydata1.prepend(BMPFile);

for(int i = 54; i <= mydata1.size(); i = i + 3)
{
          mydata1.insert(i+1, mydata1.at(i));
          mydata1.insert(i+1, mydata1.at(i));
}

Этот цикл зависает всю программу. Пытаюсь его сделать в отдельном потоке, но у меня пока проблема, как передать в slot переменную mydata1. Вот это я пока не понимаю.
Записан
Страниц: 1 2 3 4 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines