Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: jatsuk от Сентябрь 20, 2011, 15:14



Название: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 20, 2011, 15:14
Помогите люди

Есть изображение bmp
QImage image(fileName);

Нужно его сохранить бинарно.
При диалоге сохранения выбираю название
fileNamesave="111.bmp"


Облазил весь форум .. куча тем про бинарное сохранения, но в основном сохраняют текст...
Нашел что то похожее, но помоему это бред. НА выходе файл bmp размером 64 , который просит открыть фотошопом, а при стандартном просмотре ошибка.


Код:
 QFile file (fileNamesave);
                if (file.open(QIODevice::WriteOnly )){

                    QTextStream out(stdout);
                    QTextCodec *concodec = QTextCodec::codecForName("CP-866");
                    out.setCodec(concodec);



                   QDataStream stream(&file);
                   stream.setVersion(QDataStream::Qt_4_7);
                   stream << image;
                  }


     file.close();


Нашел более адекватный вариант, перевести это изображение в QByteArray и сохранить.
Незнаю правильно ли я это сделал... но на выходе файл 4 байта (Где то читал что они  и так должны туда писаться следовательно ничего не записалось ;))

Код:
 QByteArray ba;

image.loadFromData(ba);
//image.loadFromData(QByteArray::fromBase64(ba));


 QFile file (fileNamesave);
            if (file.open(QIODevice::WriteOnly )){

                QTextStream out(stdout);
                QTextCodec *concodec = QTextCodec::codecForName("CP-866");
                out.setCodec(concodec);

               QDataStream stream(&file);
               stream.setVersion(QDataStream::Qt_4_7);
               stream << ba;
              }
file.close();

Так как сохранить это изображение так ???


Название: Re: QImage в QDataStream
Отправлено: Пантер от Сентябрь 20, 2011, 15:18
bool QImage::save ( QIODevice * device, const char * format = 0, int quality = -1 ) const


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 20, 2011, 15:43
спс, но нужно бинарно сохранить
Пишу кодирование

Так ка вы сказали уже сохранял, но возникла проблемма
QImage image2(width_im, height_im, QImage::Format_RGB32);
bool saved = image2.save(fileNamesave, "BMP");

Изображение из которого сохранялось весило 157, а новое стало 468


Название: Re: QImage в QDataStream
Отправлено: Пантер от Сентябрь 20, 2011, 16:13
Исходное видимо jpg было? Читай про графические форматы .


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 20, 2011, 16:25
Исходное было bmp RGB32, про форматы уже читал.

Но лучше бы подсказал, что в коде не так, как бинарно сохранить. А то на быдлере сделано а в Qt сделать не могу


Название: Re: QImage в QDataStream
Отправлено: slim от Сентябрь 20, 2011, 17:41
Попробуй для начала открыть файл как бинарный, а не WriteOnly, для этого используй параметры для открытия 'wb'


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 21, 2011, 11:44
Зачем мне его окрывать как бинарный ?? люди и так пишут вроде работает

Придумал способ, сложно нудно, но думаю можно....

Суть такова - изображение это набор точек rgb.

В моей программе эти точки уже считаны.
Что если перевести каждую точку в двоичное число и прям так сохранить ???
Подскажите что лучше использовать?

QByteArray ba; и его потом
  QDataStream stream(&file);
               stream.setVersion(QDataStream::Qt_4_7);
               stream << ba;

Так получится ?


Название: Re: QImage в QDataStream
Отправлено: slim от Сентябрь 21, 2011, 13:04
>> Зачем мне его окрывать как бинарный ??

потомучто у тебя могут встретиться разные групы символов, например "\n"  в текстовом и бинарном виде эти символо транслируються по разному! Вообщем, бинарные данны в текстовый файл сохранять ерись.


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 22, 2011, 11:55
Я записываю int числа только, откуда там такое )


Название: Re: QImage в QDataStream
Отправлено: Prm от Сентябрь 22, 2011, 12:53
 QImage::save и есть бинарное сохранение. Пантер правильно сказал, косяк в форматах. Тренеруйтесь на реальном файле, не надо велосипед изобретать.


Название: Re: QImage в QDataStream
Отправлено: Igors от Сентябрь 22, 2011, 13:03
Нужно его сохранить бинарно.
"бинарно" всего лишь значит "нечитабельно", поэтому трудно догадаться что нужно  :)
Неясно почему Вы не хотите использовать QImage::save. Ну ладно, то Ваше дело, тогда изобретите свой формат, напр

Код
C++ (Qt)
QFile file(file);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QDataStream strm(&file);
strm << image.width() << image.height();  
file.write((const char *) image.bits(), qint64(image.bytesPerLine()) * image.height());
}
 
Это извращение может иметь смысл если хочется читать image максимально быстро, ну или он не должен просматриваться сторонним вьюером


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 23, 2011, 13:22
Сделал через save всё таки.
С форматами так и не разобрался, но сделал следуещее:
Сохранил мой BMP со всеми теми же пикселями в новый BMP QImage::Format_RGB32 (было 176 стало 468)
Далее использовал уже новое  изображение (весом 468), его пиксели изменял и всё норм теперь оно не стало больше весить , всё равно 468...

А на счёт изобретения велосипеда... Это первая лаба по кодированию (1 стадия алгоритма JPEG, мы свой дмипег пишем. RGB в YCrCb ).
И этот файл нужно было бинарно сохранить в файл, чтобы последующие программы (в которых остальные части алгоритма) считывали данные из бинарного файла и продолжали свои дейтсвия...

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

P.S. 3 дня убил на то, чтобы понять почему изображение восстанавливается в неправильном цвете ;)
оказалось, что на сайте  (http://algolist.manual.ru/compress/image/fractal/algcomp3.php) неправильный RGB в YCrCb алгоритм написан. Вторая и 3 строчка перепутана. и нет знака минуса перер 0.0168.... на остальных сайтах вроде нормально. Это так, вдруг кто нибудь подобное будет делать )

Спасибо всем за идеи


Название: Re: QImage в QDataStream
Отправлено: LisandreL от Сентябрь 23, 2011, 13:51
Сохранил мой BMP со всеми теми же пикселями в новый BMP QImage::Format_RGB32 (было 176 стало 468)
Дайте оригинальный bmp посмотреть.
Может он не 32 битный или с RLE сжатем (последнего встречается редко и поддерживается не всеми программами, но формат допускает).


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 23, 2011, 14:58
Запись в файл сделал...  просто записав все 3 параметра цветности через пробел в TXT. Думаю этого хватит )

Код:
QFile file("fail.txt");
             if ( !file.open(QIODevice::WriteOnly) )
                 return;
   QTextStream stream(&file);
   for (int i=0; i<height_im; i++)
   for (int j=0; j<width_im; j++)    {
   int rint= red[i][j];
   int gint= green[i][j];
   int bint= blue[i][j];
   QString rtxt = QString::number(rint);
   QString gtxt = QString::number(gint);
   QString btxt = QString::number(bint);
   stream << rtxt << " ";
   stream << gtxt<< " ";
   stream << btxt << " ";
   }


Вот BMP файлы...

Первый это сохраненное в пейнте как 256 цветный рисунок bmp (http://itmode.ru/Mysor/paint.bmp)
Второй qt QImage::Format_RGB32 (http://itmode.ru/Mysor/qt.bmp)

Я думал , что это одно и то же.... но это похоже не так )


Название: Re: QImage в QDataStream
Отправлено: Igors от Сентябрь 23, 2011, 17:31
Запись в файл сделал...  просто записав все 3 параметра цветности через пробел в TXT. Думаю этого хватит )
Надо было просто сказать напр "держу изображение в своем формате/массивах" - а не морочить людям голову с QImage который здесь ни при чем. Ну а с текстом зачем связались? Не жалко машины и места на диске?

Код
C++ (Qt)
 int rowSize = sizeof(red[0][0]) * width_im;
 for (int i=0; i<height_im; i++) {
    file.write((char *) &red[i][0], rowSize);
    file.write((char *) &green[i][0], rowSize);
    file.write((char *) &blue[i][0], rowSize);
 }
 
И слово "бинарный" больше не употребляйте


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Сентябрь 28, 2011, 09:34
И всё же пришлось делать бинарный (
Через txt не проканало, я наконец понял что преподу нужно...

Судь такова сохранить эти 3 массива в .bin, ( чтобы размер картинки был равен = этого массива )

Код:
 int TotalSize=width_im *height_im;

     FILE *out = fopen("array.bin", "wb");  // Открыть файл
  fwrite(red, TotalSize, 1, out);
        fclose(out);    // Закрыть файл

P.S. Извиняюсь перед человеком, который сказал про fwrite и  wb , а я этот вариант не принял...

Сохраняю в этом примере только красную составляющую цвета..

В итоге всё сохраняется, весит также, короче всё ок, но !!! при восстановлении из этого бинарного файла происходят какие то помехи.
Рисунок приложу

Считываю вот так
Код:
 int height_im = 400;
    int width_im = 400;
int TotalSize=width_im *height_im;
int Y [height_im][width_im];

   FILE *in = fopen("array.bin", "rb");   // Открыть файл
    fread(Y, TotalSize, 1, in);   // Прочитать данные
    fclose(in);    // Закрыть файл


1) Значения вроде  записываются правильные (проверял, сохранив как бмп картинку)
2) Ошибки эти возникают всегда в одних местах...

[img="http://itmode.ru/Mysor/ddd.bmp"][/img]


Название: Re: QImage в QDataStream
Отправлено: jatsuk от Октябрь 01, 2011, 14:25
Вроде разобрался, не  так я записывал...

раньше было  fwrite(red, TotalSize, 1, out);
где в роли TotalSize был размер изображения - тоесть 400*400= 160к

fwrite(red, sizeof(red), 1, out);

sizeof(red) - размер массива.

странно, я думал эти значения одинаковы. В итоге картинка bmp  весит 468, а бинарник 1875 - ровно в 4 раза больше

Погуглил и понял , что просто массив int , а  int - 4 байта, поэтому и больше в 4 раза.
Попробую сохранить как char, чтобы весило нормально