Аукцион невиданной щедрости

Мой старый заслуженный Chieftec BA01 (возможно, я немножко ошибся с моделью) у меня свое отработал.

Если вдруг кому он нужен, забирайте. Вопрос закрыт.

Состояние:

Фотошопные кривые для фотографа

В прошлый раз мы пришли к замечательному выводу: линейные кривые из нижнего левого угла не меняют контраст изображения.

Давайте теперь разбираться с кривыми, которые контраст меняют.

Начнем, как водится, с определения:

Фотографическим контрастом кривой назовем угол наклона передаточной кривой в логарифмических (фотографических) координатах. Такими координатами могут быть:

  • Кривая "логарифм количества света" - "оптическая плотность". Это наиболее привычный вид для фотографа, в таком виде публикуются характеристические кривые пленки/бумаги. На всякий случай напомню, что фотографические стопы - это и есть логарифмическая шкала, каждый стоп соответствует изменению "количества света" вдвое.
  • Вместо оптической плотности можно рисовать логарифм яркости (или коэффициента отражения). Графики будут направлены в другую сторону, но это и вся разница.
  • Для передаточных кривых, вместо "количества света" можно рисовать входное значение.

Как мы уже заметили раньше, линейные и гамма-корректированные координаты ведут себя в логарифмах одинаково (с точностью до константы).

Перейдем теперь к простейшим случаям.

Кривые: ответ на вопрос 1

Вопрос 1 (ЖЖ-ссылка) посмотрело уже достаточно народу, а в комментариях уже практически описан ответ. Пришло время сформулировать его окончательно: Обе кривые не меняют контраст, хотя пользователю фотошопа это может быть удивительно.

Давайте двигаться постепенно и начнем с определений.

Представим себе, что у нас есть несколько снятых объектов разной яркости. Не очень темных и не очень ярких, помещающихся на линейном участке фотоматериала. Контрастом для наших целей назовем соотношение яркостей пары объектов. Нас, собственно, интересует, как этот контраст будет меняться при применении показанных на первой картинке кривых.

Фотографы и кривые: вопрос 1

Как-то тема кривых редактирования контраста не нашла того отклика, на который я надеялся. Давайте попробуем более мелкими шагами.

Вот есть две фотошоповские "кривые", первая и вторая:

В каких это (фотошоповских) координатах - несущественно, поверьте. Либо кривая по L в Lab, либо композитная кривая в каком-то RGB. Давайте для простоты считать, что это - в Adobe RGB, у этого пространства, в отличие от Lab и sRGB, нет нижнего линейного участка.

Теперь возьмем две пленки, позитивную и негативную:

Кривой контраст

Вот представим себе, значит, такую кривую, как на картинке. Вот в Lab - это просто умножение на константу. В RGB - тоже умножение на константу (если начало координат немножко подвигать).

Более того, если мы посмотрим, что происходит с интенсивностями (а не со значениями в файле) - то это опять умножение на (другую) константу: и Lab и RGB - это в первом приближении степенной закон (линейным участком в начале Lab/sRGB проще пренебречь).

Другими словами, такая вот линейная кривая в фотошопе - является линейной во всех возможных смыслах.

А теперь подпишем оси немножко иначе: пусть это будет характеристическая кривая пленки или бумаги. S-образными хвостами пренебрегаем, работаем только на линейном участке. Соответственно, по осям у нас логарифм экспозиции (то бишь линейны по стопам) и логарифм светопропускания (оптическая плотность). В этих координатах график опять линеен.

Если же мы развернем логарифмы опять к линейному, то прямые линии в "фотографических" логарифмических координатах - перестанут быть таковыми в любом пространстве редактирования, хоть в Lab, хоть в RGB, хоть в линейном.

Вот я и думаю, кто кидает фотографов, Adobe вместе с ICC и всеми прочими, или же Kodak, который характеристики фотоматериалов за сто лет выстрадал?

Popcorn + Wifi + SMB

По совету motto, спрашиваю у френдов, он обещал что среди вас будет много пользователей.

Вот есть такие Popcorn Hour разных видов, лично я дрочу приглядываюсь к A-210

Но. Я не хочу тянуть еще один проводной ethernet по дому (да и насчет свободных портов в свитче что-то сомневаюсь). Кроме того, я не хочу сувать туда диск, потому что там сразу настанет торрент-клиент, а мне их и так хватает.

То бишь задача: показывать всякие медиафайлы в миллионе форматов, но брать их по 802.11n с SMB (NFS, FTP, HTTP - любого такого, который на FreeBSD легко поднять) сервера.

Отсюда вопрос, а оно вообще в таком режиме работать будет? Кто-нибудь пробовал?

Контент - всякий. Основной контент в телеящике у нас - естественно мультики, которые обычно в чем-то low-res, но посмотреть что-то эдакое в 1080p я тоже вполне могу захотеть.

LibRaw 0.13-Beta1

Отметим завершение каникул анонсом LibRaw 0.13-Beta1.

Сегодня на экране:

  • Ускорение распаковки хаффмана за счет более правильной буферизации (а для файлов .CR2 - еще и за счет правильного пред-расчета смещений). В результате LibRaw::unpack() работает раза в полтора быстрее для .CR2 и на 20-30% быстрее для других подобных форматов (NEF, packed DNG).
  • Масса новых плюшек в demosaic packs (похоже, пора их переименовывать в feature packs):
    • Шумопонижение разных видов (подавление banding, подавление импульсного шума, выравнивание зеленых каналов).
    • Новый, более правильный, алгоритм автоподавления хроматических аберраций.
    • Правильная экспокоррекция с возможностью сохранять детали в светах (аналог compressed exposure в RPP).
    • Ускорение медианных фильтров при помощи OpenMP
  • Ну и, естественно, все фиксы из ветки 0.12
Все это благолепие - скоро в digiKam (собственно, кроме экспокоррекции - оно уже там).

OpenMP: Intel vs Visual Studio

Непонятки с производительностью OpenMP в случае VisualStudio (см. еще обсуждение в каментах) заставило разобраться.

Выяснилось, что две переменные, которые read-only и вообще объявлены как const - считаются разделяемыми. Как следствие - локи при обращении и прочие удовольствия.

После устранения этого недоразумения (#pragma omp ... private(...)) и замены _mm_store_ps() на _mm_stream_ps(), чтобы в обеих компиляторах выходной массив писался через movntps, все встало на свои места: С-шный код с powf() остается сильно быстрее у Интела т.к. он векторизует powf в _svml_powf4, а SSE-код работает с практически одинаковой скоростью.

Его пример другим наука:

#pragma omp parallel for default(none)
и явное прописывание shared/private/whatever для всех переменных.

О степенной функции, OpenMP и прочих граблях

Есть вот такое вот известное выражение, переложеное из википедии:

#define To_sRGB(q) (((q)<=0.0031308f)? 12.92f*(q) : (1+0.055f)*powf(q,1/2.4f)-0.055f)
В том смысле, что у sRGB внизу - линейный участок, а дальше степенная функция.

Если его напрямую запрограммировать (вот прямо с powf()), то в зависимости от компилятора получается от 7 Mpix/sec (Visual C++ 2010, один поток) до 100Mpix/sec (Intel Parallel Studio XE, включен OpenMP). Пиксель - это 3 компонента по 4 байта (float), то бишь гигабайт с небольшим в секунду - это максимум.

Как-то медленно.

В-принципе, бывает быстрое приближенное возведение в степень для ограниченного диапазона значений. Более того, можно просто приблизить sRGB-кривую полиномом не очень высокой степени и получить вполне приемлемый для практики результат. Но хотелось заодно решить задачу быстрого наложения произвольной кривой.

Кому война....

Кому черезвычайная ситуация, а кому - выставка ледяной скульптуры.

P.S. Света еще немножко есть....

Полна чудес могучая природа

А в SSE4.1 оказывается есть минимум-максимум для 16-битных целых. 8 штук зараз.

Хреначит 11 гигабайт в секунду, сдается мне что параллелить по ядрам дальше смысла нет, упрешься в память.

И dot-product есть, правда только для float/double.

Чешутся руки забить на владельцев AMD и всего младше Penryn, держите меня...

Убийца предсказателей переходов

      if (cr2_slice[0]) {
        jidx = jrow*jwide + jcol;
        i = jidx / (cr2_slice[1]*jh.high);
        if ((j = i >= cr2_slice[0]))
                 i  = cr2_slice[0];
        jidx -= i * (cr2_slice[1]*jh.high);
        row = jidx / cr2_slice[1+j];
        col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
      }
Для понимания контекста:
  • Этот кусок зовется на каждый пиксел и рассчитывает, куда именно поместить распакованный из CR2 пиксель (там не так просто все).
  • jidx - номер пикселя в потоке, плавно возрастает.
  • Изображение поделено на cr2_slice[0] полос шириной cr2_slice[1] и одну полосу шириной cr2_slice[2].
  • cr2_slice[0] - небольшое число, 1-3-5
  • j - соответственно - 0 или 1.

На 15 мегапикселях - 330 миллисекунд. Разворот if правильный (чтобы было не 1+j, а честно 1 или 2) - минус 70 миллисекунд. Замена на таблицу с заранее насчитанными оффсетами - минус 200 миллисекунд. Но все равно много, перемудрили в кэноне. Главное, их "слайсы" вполне можно было бы распаковывать впараллель (как они жмутся параллельными Digic-ами), если бы в RAW были бы смещения начал. Ан нет.

Pages

Subscribe to blog.lexa.ru: все статьи