Pull to refresh

Comments 54

пробовал давным-давно, результаты были чем-то промежуточным между c# и c++. сейчас поленился.
Вы придумали новый логотип для Оперы… :P
UFO just landed and posted this here
Интересное у Вас решение. Зимой писал графредактор на C#, в редакторе были реализованы различные фильтры. Черно-белое изображение получал при помощи unsafe. Попробую и Ваш способ ради интереса :)
Мне тоже кажется, что unsafe будет ничуть не медленнее, хотя нужно проверить. Плюс к этому в шарпе можно использовать Parallel Extensions.

Я как раз сейчас борюсь с долгой инициализацией больших картинок в WPF. При динамическом обновлении Image-контрола картинкой размером 3000×3000 задержка в трэде рисование почти полсекунды. Что, при обновление раз в секунду, делает интерфейс не юзабельным. Никто не сталкивался с таким?
Этот контрол для быстрых обновлений не годится, как впрочем и аналогичный контрол WinForms. С размером 3000х3000 без аппаратной поддержки вообще трудно, а в WPF она видимо не подвязана (хотя и обещали нам).
Кто ж такие картинки сразу в контрол пихает, надо сначала ресайзить, потом рисовать уже нужного размера.

Или пилить на куски, грузить в текстуры и показывать через DX/OpenGL.
Вот вариант с unsafe. У меня на Pentium D 3Ггц c картинкой 3000×3000 занимает около 340 миллисекунд.

  1. Bitmap MakeBW(Bitmap source)
  2.     {
  3.       //использование промежуточных переменных ускоряет
  4.       //код в несколько раз
  5.       var width = source.Width;
  6.       var height = source.Height;
  7.  
  8.       var sourceData = source.LockBits(new Rectangle(new System.Drawing.Point(0, 0), source.Size),
  9.                        ImageLockMode.ReadOnly,
  10.                        source.PixelFormat);
  11.      
  12.       result = new Bitmap(width, height, source.PixelFormat);
  13.       var resultData = result.LockBits(new Rectangle(new System.Drawing.Point(0, 0), result.Size),
  14.                        ImageLockMode.ReadWrite,
  15.                        source.PixelFormat);
  16.  
  17.  
  18.       var sourceStride = sourceData.Stride;
  19.       var resultStride = resultData.Stride;
  20.  
  21.       var sourceScan0 = sourceData.Scan0;
  22.       var resultScan0 = resultData.Scan0;
  23.  
  24.       var resultPixelSize = resultStride / width;
  25.      
  26.       unsafe
  27.       {
  28.         for(var y = 0 ; y < height ; y++)
  29.         {
  30.           var sourceRow = (byte*)sourceScan0 + (y * sourceStride);
  31.           var resultRow = (byte*)resultScan0 + (y * resultStride);
  32.           for(var x = 0 ; x < width ; x++)
  33.           {
  34.             var v =(byte)(0.3*sourceRow[x*resultPixelSize + 2] + 0.59*sourceRow[x*resultPixelSize + 1] +
  35.                0.11*sourceRow[x*resultPixelSize]);
  36.               resultRow[ x * resultPixelSize ] = v;
  37.               resultRow[ x * resultPixelSize + 1 ] = v;
  38.               resultRow[ x * resultPixelSize + 2 ] = v;
  39.           }
  40.         }
  41.  
  42.  
  43.       }
  44.  
  45.       source.UnlockBits(sourceData);
  46.       result.UnlockBits(resultData);
  47.       return result;
  48.     }
* This source code was highlighted with Source Code Highlighter.
Не заметил сперва ваш размер картинки. С размер 360×480 — 8мс.
Молодцом. Автор не в теме (того, что все знают, что Bitmap довольно медленная обертка для работы с картинкой попиксельно)
Вместо работы с unsafe можно использовать System.Runtime.InteropServices.Marshal.Copy и получать данные в managed массиве. Скорость работы такая же, а небезопасный код не используется.
Угу. Я так же делал, все нормально работало.
А лишняя копия данных в результате не вылазит?
UFO just landed and posted this here
Возможно, но так не намного понятнее:
BitmapData resultData = result.LockBits(new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), result.Size),
                      ImageLockMode.ReadWrite,
                      System.Drawing.Imaging.PixelFormat.Format32bppArgb);


* This source code was highlighted with Source Code Highlighter.

Надо просто комментариев больше писать. :)
UFO just landed and posted this here
UFO just landed and posted this here
Еще неплохо было бы выполнять все действия в unchecked { }. Это тоже может дать небольшой прирост производительности.
Афтар — ты дизайнер и не более. Рисуй картинки и не лезь в программирование. Хочешь опустить .NET — пиши статьи на rsdn.ru, там тебе плюсики ни за хрен собачий никто ставить не станет.
Диаграмма в статье — отличный пример того, как не надо делать графики и диаграммы :)
Я вот смотрю и думаю: где же лежат мои 8мс. :) Мозг взрывает.
А можно цветную 1600 на 1200?
Сорри, в таком разнешении у меня ее нет, это картинки для айфона :)
я так понимаю это результат преобразования через ColorMatrix, да?
тогда вопрос — что со временем исполнения получилось?
писать код для проверки лениво, раз уж у вас есть код то и замерить вам легче ;)
И я не менее ленив. :) Тем более, что в моем случае производительность большой роли не играет.
Проще, мне кажется, автору данной статьи добавить еще итераций с использованием ColorMatrix (и других других улучшений из комментариев), т.к. у него уже был код для тестирования.
:)
просто подумалось, что если есть результат, то значит есть и код с помощью которого он получен :")
а так да, так надо ждать результатов от автора :)

автор, не пробовали колорМатрикс?
А вы не пробовали достать палитру из картинки, ее преобразовать в черно-белую и вставить обратно?
Это кстате тоже хорошая идея! Надо будет попробовать!
Вот-вот! Я все читаю камменты и думаю, когда уже кто-нибудь нормальный способ предложит
А что значит «нормальный»? Есть много разных способов…
Просто мне показалось, что ручной проход по всем пикселям — это не есть гуд.
Судя по количеству цветов, картинка имеет 24 или 32 бита на пиксель, следовательно палитры нет.
Полностью согласен, именно эта картинка не имеет.
Для картинки с палитрой этот код работать не будет, там данные битмапа не в RGB хранятся, а в индексах цветов.
И еще, зачем умножать, сделайте 3 массива по 256 цветов для каждого канала, где ключ — исходный цвет, а значение — цвет уже умноженный на константу. Дальше функция преобразования будет напоминать что то типа
gray_value = red[old.Red] + green[old.Green] + blue[old.Blue];
Лишних 3*256 байт памяти.
Класс! Что ни коммент то идея! Спасибо, буду тестировать!
Вопрос от дизайнера:
как делают такие фракталы вокруг буквы О?
DirectX HLSL в помощь.
В WPF шейдеры на рас подключаются к эл-там (Effect).
Всю работу делает GPU.
Оффтоп: а что было использовано для дотнета на маке? Можно ссылочку на рантайм/IDE, посмотреть хочется.
Прогуглил… Вобщем на макос нечем разрабатывать — тот же MonoDevelop даже до alpha-релизов не дошел.
ну почему? вполне дошел. Даже Helloworld можно написать. А вот дальше конечно уже *опа
o_0 взято с monodevelop.com
MonoDevelop 2.0 has been released. See the official announcement here.

March 30, 2009


если я не ошибаюсь, то моноДевелоп это форк шарпДевелопа, т.е. более-менее сносной IDE под .NET (если не сравнивать с VS :D ), неужели с ним действительно все так плачевно?!
Посмотри на его оффсайте комментарии к маковой версии ;)
Для начала стоило бы попробывать
byte rgb = (byte)(( (uint32)c.R * 5033165 + (uint32)c.G * 9898557 + (uint32)c.B * 1845494 ) >> 24)
Sign up to leave a comment.

Articles