Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: alexey11111 от Ноябрь 07, 2012, 23:09



Название: преобразование в 8-bit grayscale
Отправлено: alexey11111 от Ноябрь 07, 2012, 23:09
Добрый вечер.
Есть такая проблема. Если взять некоторую RGB-картинку, изменить ее размер и преобразовать в 8 битный grayscale формат и сохранить в jpg файл, то все сохраняется нормально, без дефектов (см. картинку good.jpg). А вот если картинку еще и повернуть (вокруг центра), а потом преобразовать в оттенки серого, то файл сохраняется со значительной потерей качества (см картинку bad.jpg). Если же картинку не преобразовывать в Format_Indexed8, а просто поменять значения пикселей на серые, тот все сохраняется нормально. Но в этом случае получается трехканальное изображение, а мне нужно одноканальное.
Преобразование в grayscale делаю так:
 
Код:
QImage convertToGray(QImage &img)
{
    QImage converted = img;
    QRgb col;
    int gray;
    int width  = img.width();
    int height = img.height();\
    for (int i = 0; i < width; ++i)
    {
        for (int j = 0; j < height; ++j)
        {
            col = img.pixel(i, j);
            gray = qGray(col);
            converted.setPixel(i, j, qRgb(gray, gray, gray));
        }
    }
    return converted.convertToFormat(QImage::Format_Indexed8);
}
Можно ли это как-нибудь исправить?


Название: Re: преобразование в 8-bit grayscale
Отправлено: Igors от Ноябрь 08, 2012, 07:47
Не сочтите что придираюсь, но если Вы исходный имедж менять не собирались, то пишите const
Код
C++ (Qt)
QImage convertToGray(const QImage &img)
 

Код
C++ (Qt)
return converted.convertToFormat(QImage::Format_Indexed8);
 
Давайте сначала отсечем сохранение в файл. Значит до convertToFormat если показать имедж - он Вас устраивает. Хорошо, а после convertToFormat ?


Название: Re: преобразование в 8-bit grayscale
Отправлено: LisandreL от Ноябрь 08, 2012, 10:25
А поворачиваете как?


Название: Re: преобразование в 8-bit grayscale
Отправлено: alexey11111 от Ноябрь 08, 2012, 14:40
Не сочтите что придираюсь, но если Вы исходный имедж менять не собирались, то пишите const
Код
C++ (Qt)
QImage convertToGray(const QImage &img)
 

Код
C++ (Qt)
return converted.convertToFormat(QImage::Format_Indexed8);
 
Давайте сначала отсечем сохранение в файл. Значит до convertToFormat если показать имедж - он Вас устраивает. Хорошо, а после convertToFormat ?

Насчет const Вы абсолютно правы.
По поводу конвертации Вы не совсем так поняли: обе картинки (bad и good) - это Format_Indexed8. Только good - это картинка к которой не был поворот применен - просто перевел в 8 битный формат, а bad получена после применения вращения, а затем перевода в 8 бит.
Короче говоря, полная последовательность такая:
1. поворот картинки вокруг центра:
Код:
QTransform trans = QTransform().translate(cent.x(), cent.y()).rotate(-_rotat).translate(-cent.x(), -cent.y());
QImage targImg = sourceImg.transformed(trans);
2. Изменение размера картинки:
Код:
targImg = targImg.scaled(128,128, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 
3. Конвертация в 8-бит grayscale
4. сохранение в .jpg

Так вот, если исключить первый пункт (вращение), то получаем нормальную (good) картинку, а если нет, то bad. И еще такой момент: если в 3-м пункте просто первести картинку в оттенки серого, но не менять формат на indexed_8, то все получается ок. Но тогда трехканальное изображение получается...


Название: Re: преобразование в 8-bit grayscale
Отправлено: Igors от Ноябрь 08, 2012, 15:40
Так вот, если исключить первый пункт (вращение), то получаем нормальную (good) картинку, а если нет, то bad. И еще такой момент: если в 3-м пункте просто первести картинку в оттенки серого, но не менять формат на indexed_8, то все получается ок. Но тогда трехканальное изображение получается...
jpg - дело темное, качество он теряет (вопрос насколько). Я бы (временно, для отладки) заменил на png и посмотрел - или бы вывел сам и посмотрел.

А чего ж Вы про масштаб-то молчали? Это важно, надо поворачивать бОльшую картинку, поэтому если увеличиваете то это надо делать до поворота


Название: Re: преобразование в 8-bit grayscale
Отправлено: alexey11111 от Ноябрь 08, 2012, 15:47
Так вот, если исключить первый пункт (вращение), то получаем нормальную (good) картинку, а если нет, то bad. И еще такой момент: если в 3-м пункте просто первести картинку в оттенки серого, но не менять формат на indexed_8, то все получается ок. Но тогда трехканальное изображение получается...
jpg - дело темное, качество он теряет (вопрос насколько). Я бы (временно, для отладки) заменил на png и посмотрел - или бы вывел сам и посмотрел.

А чего ж Вы про масштаб-то молчали? Это важно, надо поворачивать бОльшую картинку, поэтому если увеличиваете то это надо делать до поворота

Да тут дело не в jpg, похоже - когда вывожу на  QLabel просмотр получается именно то, что после сохранения. Т.е. сохраняется-то как раз корректно.
Что касается поворотов, то я не могу делать сначала rescale, поскольку финальная картинка вырезается из из большой путем вращения. Помните, Вы же мне пару дней назад с этим помогали?
Короче, хз...


Название: Re: преобразование в 8-bit grayscale
Отправлено: Igors от Ноябрь 08, 2012, 18:30
Да тут дело не в jpg, похоже - когда вывожу на  QLabel просмотр получается именно то, что после сохранения. Т.е. сохраняется-то как раз корректно.
Ну и хорошо. Тогда гляньте что у Вас в QImage::colorTable


Название: Re: преобразование в 8-bit grayscale
Отправлено: alexey11111 от Ноябрь 08, 2012, 18:50
Да тут дело не в jpg, похоже - когда вывожу на  QLabel просмотр получается именно то, что после сохранения. Т.е. сохраняется-то как раз корректно.
Ну и хорошо. Тогда гляньте что у Вас в QImage::colorTable
Посмотрел. Получилось r, g, b по нулям.


Название: Re: преобразование в 8-bit grayscale
Отправлено: Igors от Ноябрь 08, 2012, 21:00
Я взял Ваш имедж good, загрузил, перевел в 32 потом опять в 8 - результат 1:1
Скинтье "хороший но 3-х канальный" имедж


Название: Re: преобразование в 8-bit grayscale
Отправлено: alexey11111 от Ноябрь 08, 2012, 21:19
Я взял Ваш имедж good, загрузил, перевел в 32 потом опять в 8 - результат 1:1
Скинтье "хороший но 3-х канальный" имедж

Вот, например. Здесь просто значения пикселей перевел в оттенки серого, но без конвертации в indexed_8

Здесь же - та же картинка, но в 8 битах.


Название: Re: преобразование в 8-bit grayscale
Отправлено: alexey11111 от Ноябрь 08, 2012, 23:39
Все, решил проблему.
Здесь все оказалось хитрее: если угол поворота в объекте QTransform равен нулю, то исходный QImage имеет формат Format_RGB32. Как только к изображению применяется трансформация с углом поворота, отличным от нуля, то трансформированное изображение автоматически конвертируется в Format_ARGB32_Premultiplied, т.е. добавляется альфа-канал. Поэтому, если из Format_ARGB32_Premultiplied конвертировать сразу в Format_Indexed8, то преобразование учитывает альфа-канал и получается артефакт. Поэтому, надо сначала избавиться от альфы, а потом конвертировать в 8 бит:
Код:
QImage target =convertToGray(source).convertToFormat(QImage::Format_RGB32).
                      convertToFormat(QImage::Format_Indexed8);