Russian Qt Forum
Ноябрь 01, 2024, 16:40 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: преобразование в 8-bit grayscale  (Прочитано 10955 раз)
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);
}
Можно ли это как-нибудь исправить?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Ноябрь 08, 2012, 07:47 »

Не сочтите что придираюсь, но если Вы исходный имедж менять не собирались, то пишите const
Код
C++ (Qt)
QImage convertToGray(const QImage &img)
 

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

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #2 : Ноябрь 08, 2012, 10:25 »

А поворачиваете как?
Записан
alexey11111
Гость
« Ответ #3 : Ноябрь 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, то все получается ок. Но тогда трехканальное изображение получается...
« Последнее редактирование: Ноябрь 08, 2012, 14:44 от alexey11111 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Ноябрь 08, 2012, 15:40 »

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

А чего ж Вы про масштаб-то молчали? Это важно, надо поворачивать бОльшую картинку, поэтому если увеличиваете то это надо делать до поворота
Записан
alexey11111
Гость
« Ответ #5 : Ноябрь 08, 2012, 15:47 »

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

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

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

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Ноябрь 08, 2012, 18:30 »

Да тут дело не в jpg, похоже - когда вывожу на  QLabel просмотр получается именно то, что после сохранения. Т.е. сохраняется-то как раз корректно.
Ну и хорошо. Тогда гляньте что у Вас в QImage::colorTable
Записан
alexey11111
Гость
« Ответ #7 : Ноябрь 08, 2012, 18:50 »

Да тут дело не в jpg, похоже - когда вывожу на  QLabel просмотр получается именно то, что после сохранения. Т.е. сохраняется-то как раз корректно.
Ну и хорошо. Тогда гляньте что у Вас в QImage::colorTable
Посмотрел. Получилось r, g, b по нулям.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 08, 2012, 21:00 »

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

Я взял Ваш имедж good, загрузил, перевел в 32 потом опять в 8 - результат 1:1
Скинтье "хороший но 3-х канальный" имедж

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

Здесь же - та же картинка, но в 8 битах.
« Последнее редактирование: Ноябрь 08, 2012, 21:25 от alexey11111 » Записан
alexey11111
Гость
« Ответ #10 : Ноябрь 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);
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.188 секунд. Запросов: 23.