Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2005.07.11;
Скачать: [xml.tar.bz2];

Вниз

Алгоритм преобразования монохромного изображения   Найти похожие ветки 

 
Штотоносец   (2005-03-11 20:28) [0]

Не знаю как точно сказать. Вообщем есть монохромное изображение и надо его преобразовать в 2, 4, 8 и т.д. цветное, т.е. градацией серого. Во. Вроде понятно объяснил :)


 
Virgo_Style ©   (2005-03-11 20:31) [1]

Осредняй значение яркости в некоторой области каждой точки, нормируй... И смотри, в какой диапазон попадает...


 
YurikGL ©   (2005-03-11 20:31) [2]

Чего во что преобразовать то надо? Цветное->монохромное или монохромное->цветное? Вророе, вроде как, нельзя. А первое - формулу я как-то яндексом в свое время нашел...


 
TUser ©   (2005-03-11 20:32) [3]

Не не понятно.
В монохромном изображении размера n*m есть m*n бит информации. Ты хочешь преобразовать его в изображение того же размера, но большей цветности, так? Там информации больше. Откуда брать занчения дополнительных бит.


 
YurikGL ©   (2005-03-11 20:32) [4]

тьфу... прочитал

> 2, 4, 8 и т.д. цветно"е

по науке, делается это методами кластеризации...


 
YurikGL ©   (2005-03-11 20:33) [5]


> Штотоносец   (11.03.05 20:28)  

можно поискать как Image-ready гифы делает...


 
Штотоносец   (2005-03-11 20:37) [6]

Нет не цветное, а как бы серое 8\ Всмысле если двухцветное, то это черный и белый, если 4, то белый, черный и две градации серого. Всего, максимально, какбы 256 градаций. Изображение-то монохромное, т.е. серое и то, что колор получить никак я понимаю, вообщем это и не надо.


 
YurikGL ©   (2005-03-11 20:49) [7]

Тебе нужны методы кластеризации.
Кратко, суть в том, что произвольное множество точек делится на заранее заданное (в твоем случае) количество "сгущений". Результатом применения метода будут центры "сгущений". Дальше, вычисляя расстояние между конкретной точкой и центрами "сгущений" заменяем эту точку центром ближайшего "сгущения". Не уверен, что эти методы можно в инете нарыть, на на лабах такие рассчеты мы делали.


 
Штотоносец   (2005-03-11 21:01) [8]

Да уж, мудрено. А может у кого завалялся исходничек?


 
Virgo_Style ©   (2005-03-11 21:02) [9]


> Да уж, мудрено

Мне тоже так показалось :-) А чем [1] не устраивает?


 
Штотоносец   (2005-03-11 21:05) [10]

Так там, помоему, еще мудреней :)


 
YurikGL ©   (2005-03-11 21:09) [11]


> А чем [1] не устраивает?


есть у тебя картинка, где реально используются цвета
0,1,2,10,11,12,230,231,232,250,251,252.
Нужно к 4-м цветам преобразовать на основании чего будещ диапазоны цветов выбирать?


 
Virgo_Style ©   (2005-03-11 21:50) [12]

Да, я, кажется, неправ :-) Это для Черный+Белый -> градации серого, а вопрос, как я теперь понял, о снижении цветности? Тогда молчу :-)


 
TUser ©   (2005-03-11 21:50) [13]


> YurikGL ©

я понимаю - тут обратная задачав. воссановить информацию из изображения, где эта инфа потеряна. низя ...


 
Virgo_Style ©   (2005-03-11 22:11) [14]

TUser ©   (11.03.05 21:50) [13]
Хм. Автор! Объясните народу - информацию надо потерять или найти? Градации серого - в меньшее количество градаций серого, или же B&W - в градации?
:-)


 
Штотоносец   (2005-03-11 23:52) [15]

Так, попробую. В ПАМЯТИ хранится изображение. Монохромное - 256 градаций. В зависимости от положения бегунка, на форму выводится изображение преобразованное с оригинала (в памяти). Поэтому восстановление потерянной информации не подразумевается из-за отсутствие таковой =)


 
XProger ©   (2005-03-12 04:30) [16]

Штотоносец, дык тебе уменьшение кол-ва байт на пиксель нужно? ;)


 
XProger ©   (2005-03-12 04:31) [17]

т.е. бит?
Допустим было изображение 8 бит на киксель урезали стало 7 бит ... 1 бита на пиксель. С потерей качества разумеется.


 
Fenik   (2005-03-12 12:05) [18]

Ты в баню?
Нет, я в баню.
Ааа, я думал, что ты в баню.


 
Штотоносец   (2005-03-12 13:19) [19]

Допустим есть изображение, у которого каждый Image2.Canvas.Pixels[w,h] равен некоему колору, в момнохроме от 0..255, точнее например RGB(0,0,0), это черный, а RGB(255,255,255), это белый.
Понятно, что если просто уменьшать это значение, то при двухцветности, рисунок станет просто черным, да это будет видно и раньше.

Я понимаю, что YurikGL [7] высказал верную идею, но у меня возникают проблемы с ее реализацией, точнее на проблемы, а я не знаю даже как начать.


 
Virgo_Style ©   (2005-03-12 15:08) [20]

Самое дубовое решение - разбить диапазон 0..255 на поддиапазоны в нужном количестве. Например
0..128   - это цвет (0+128)/2
128..255 - это цвет (128+255)/2
Куда попадает твой серый - тем цветом он и станет.
Чуть менее дубовое - считать средний цвет для каждого диапазона.
Но это все равно дубово, а если надо хорошо - тогда [7]


 
Штотоносец   (2005-03-12 15:13) [21]

К сожалению мне надо уехать, а буду я в воскресенье вечером, тогда и продолжим.


 
Fenik   (2005-03-12 19:38) [22]

Ладно уж, даю грубый вариант:


procedure SetGrayScale(Bitmap: TBitmap; Value: Byte);
var Pixel: pRGBTriple;
   x, y, n: Integer;
   A: array [Byte] of Byte;
begin
 if Value > 1 then begin
   A[0] := 0;
   A[255] := 255;
   for x := 1 to 254 do begin
     case Value of
       2: A[x] := Byte(x>127)*255;
       3..127: begin
         n := Round(256/(Value-1));
         n := Round(x/n)*n;
         if n <= 255 then A[x] := n
                     else A[x] := 255;
       end;
       else A[x] := x;
     end;
   end;
 end
 else
   FillChar(A, SizeOf(A), 0);
   
 for y := 0 to Bitmap.Height - 1 do begin
   Pixel := Bitmap.ScanLine[y];
   for x := 0 to Bitmap.Width - 1 do begin
     with Pixel^ do begin
       rgbtBlue  := A[rgbtBlue];
       rgbtGreen := A[rgbtGreen];
       rgbtRed   := A[rgbtRed];
     end;
     Inc(Pixel);
   end;
 end;
end;


 
Fenik   (2005-03-12 20:04) [23]

Забыл:
n := Round(256/(Value-1));
можно вынести из цикла :)


 
Штотоносец   (2005-03-14 18:16) [24]

У меня по YurikGL [7] получилось следующее;

procedure Tfrm_Main.GetGrayScale(Value:Integer);
var
 i,w,h:integer;
 a,c:Real;
 b:byte;
begin
 w:=0;
 h:=0;
 if value<>256 then a:=256/value;
 for i:=1 to Length(ArrByteImg) do begin
   b:=ArrByteImg[i-1];
   if value<>256 then begin
     c:=Ceil(b/a);
     if (b-a*c)>(a/2) then c:=Floor(b/(a+1));
     b:=Round(c*a);
     if (b=0) and (c<>0) then dec(b);
   end;
   Image2.Canvas.Pixels[w,h]:=b shl 16 + b shl 8 + b;
   inc(w);
   if w=Image2.Width then begin
     w:=0;
     inc(h);
   end;
 end;
end;


Единственная проблема в то, что при 2-х цветности получаются 128 и 255, т.е. белый и серый, а не черный.
Посмотрите пожалуйста в чем проблема.

Да, вот еще. ArrByteImg это ArrByteImg:array of byte;

 a:=0;
 SetLength(ArrByteImg,Image2.Height*Image2.Width-1);
 for h:=0 to Image2.Height-1 do begin
   for w:=0 to Image2.Width-1 do begin
     ArrByteImg[a]:=GetRValue(Image2.Canvas.Pixels[w,h]);
     inc(a);
   end;
 end;


 
Fenik   (2005-03-14 19:13) [25]

Это че за лабуда? :))
Я тебе процедуру дал? Дал.
Ты скорость работы сравнивал со своим произведением? Сомневаюсь.
Короче, не парься и возьми мою функцию. Правь в ней первоначальное заполнение массива по своему усмотрению и всё. Для двух цветов там как тебе надо работает.
Не забудь только Bitmap.PixelFormat := pf24Bit;


 
Штотоносец   (2005-03-14 19:24) [26]

Fenik [25]
Послушай, я не лабы пишу и мне завтра это не здавать, я для себя пишу, так сказать для общего развития, поэтому хочеться самому =)
Если хочешь помочь, так лучше укажи на ошибки, объясни, если не влом, а то; "Это че за лабуда?". Ты типа лох, я тебе все дал, а ты типа, даже просто код скопировать не можешь. Так можно инерпретировать твои слова. А это обидно.


 
Fenik   (2005-03-14 19:34) [27]

Прости, не хотел обидеть. Там вообще-то смайлы.. :)
Вместо Canvas.Pixels целесообразней использовать ScanLine. Это первое. (Выигрыш в скорости офигенный)
А второе - это че за лабуда? :))))) Шутю.
Ты можешь объяснить, зачем тебе понадобилсся какой-то массив пикселей ArrByteImg?
Вообще прокомментируй свой код.
Потом посмотри внимательно на мой и подумай, что в нем тебе не понятно. Короче - смотри, думай и спрашивай.


 
dmk ©   (2005-03-14 21:23) [28]

Вот тебе еще немного кода. Преобразование BiLevel в Grayscale.
Преобразует 8 BiLevel-строк в 1 Grayscale.
Кстати! Потрясная скорость!

Только для этого надо сначала подсчитать
кол-во бит в кубике 8х8 и занести их в массив из
которого эта процедура выборку делает.
Я делаю это в секции Initialization

function Bit(TestByte, TestBit:Integer):boolean;
asm
  bt    eax, edx
  setc  al
  and   eax, 0FFh
end;

Function BitsCount(v:byte):byte;
var
 c:    Byte;
 res:  Integer;
 
begin
Res := 0;

For c := 0 to 7 do If Bit(v,c) then Inc(Res, 32);

If Res > 255 then Res := 255;
Result := Byte(Res);
end;

procedure InitHalphtoneBits;
var
 Counter:Byte;

begin
 For Counter := 0 to 255 do HBitsArray[Counter] := BitsCount(Counter);
 HBitsArray[0] := 0;
 HBitsArray[255] := 255;
 HBitsArrayAddr := DWord(Addr(HBitsArray[0])); //&#204;&#224;&#241;&#241;&#232;&#226; &#239;&#238;&#228;&#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#231;&#237;&#224;&#247;&#229;&#237;&#232;&#233;
end;

procedure TImageStream.HalftoneLine(InputAddress, OutputAddress, Len:DWord);
var
 FStart:       DWord;
 FPos:         DWord;
 FNewStart:    DWord;
 FNewPos:      DWord;

 //...
 FLineSize:    DWord;
 FLinePos:     DWord;

 //...
 FSum:         DWord;
 FHMem:        DWord;

begin
 FStart        := InputAddress;
 FHMem         := HBitsArrayAddr; //&#204;&#224;&#241;&#241;&#232;&#226; &#239;&#238;&#228;&#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#231;&#237;&#224;&#247;&#229;&#237;&#232;&#233;
 FLineSize     := Len;

 //...
 FNewStart     := OutputAddress;
 FNewPos       := 0;
 FPos          := 0;

 //...
 asm
      push       edi
      push       esi
      push       ebx

      mov        edx, FStart           {&#205;&#224;&#247;&#224;&#235;&#252;&#237;&#251;&#233; &#224;&#228;&#240;&#229;&#241; &#226; bitmap &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#232;}
      add        edx, FPos             {&#207;&#238;&#231;&#232;&#246;&#232;&#255; &#226; bitmap &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#232;}
      mov        edi, FNewStart        {&#205;&#224;&#247;&#224;&#235;&#252;&#237;&#251;&#233; &#224;&#228;&#240;&#229;&#241; &#226; grayscale &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#232;}
      add        edi, FNewPos          {&#207;&#238;&#231;&#232;&#246;&#232;&#255; &#226; grayscale &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#232;}
      mov        esi, FHMem            {&#209;&#242;&#224;&#240;&#242;&#238;&#226;&#251;&#233; &#224;&#228;&#240;&#229;&#241; &#226; &#236;&#224;&#241;&#241;&#232;&#226;&#229; &#239;&#238;&#228;&#241;&#247;&#232;&#242;&#224;&#237;&#237;&#251;&#245; &#231;&#237;&#224;&#247;&#229;&#237;&#232;&#233;}
      mov        ecx, FLineSize        {&#228;&#235;&#232;&#237;&#224; &#241;&#234;&#224;&#237;-&#235;&#232;&#237;&#232;&#232;}
      mov        ebx, ecx
      mov        FLinePos, 0

@@Cyc: mov        FSum, 0
      xor        eax, eax

   {0}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx, ebx

   {1}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx,ebx

   {2}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx,ebx

   {3}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx,ebx

   {4}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx,ebx

   {5}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx,ebx

   {6}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax
      add        edx,ebx

   {7}mov        al, [edx]
      mov        al, [esi+eax]
      add        FSum, eax

      mov        eax, FSum
      shr        ax, 3

      mov        [edi], al  //&#199;&#224;&#239;&#232;&#241;&#252; &#241;&#243;&#236;&#236;&#251; &#226; grayscale &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#229;
      inc        edi

      mov        edx, FStart  //&#200;&#241;&#245;&#238;&#228;&#237;&#251;&#233; &#224;&#228;&#240;&#229;&#241;
      add        edx, FPos
      inc        FLinePos
      add        edx, FLinePos

      loop       @@Cyc
      //...
      pop        ebx
      pop        esi
      pop        edi
     end;

end;


 
Fenik   (2005-03-14 21:33) [29]

Ну всё, завалили парня кодом :)))


 
YurikGL ©   (2005-03-14 21:33) [30]


> Fenik   (12.03.05 19:38) [22]

Я в [11] пример привел, который методом деления "в лоб" не решается.

Автору:
Посмотри http://www.megaputer.ru/content/production/pa/_polyanalyst_info.html#5_05

Алгоритм кластеризации в твоем случае, примерно такой:
Пусть нам надо представить все в 4-х цветах. Тогда, делим всю область пополам т.е. цвета меньше 127,5 и больше 127,5 т.е. граница между двумя кластерами будет 127.5. Далее сдвигаем эту границу в сторону с большим количеством точек до тех пор, когда точек с обоих сторон не станет поровну. Далее, каждый получившийся кластер делим аналогичным способом пополам. После этого у нас в каждом из 4-х кластеров поровну точек (или почти поровну). Берем за новые цвета средние арифметические значений точек в каждом кластере и заменяем точки каждого кластера полученным значением.

Конечно, будут и пограничные значения и разное количество точек в кластерах, но общий алгоритм может быть такой. Ситуацию [11] он должен обработать корректно. Хотя существуют ситуации, которые и этот алгоритм обработает некорректно. Например значения
1,1,1,1,1,1, 200,201,202. разделить на 4 цвета. Для учета таких ситуаций надо еще много чего считать.

Хотя в университете нам вроде давали гораздо более оптимальные алогоритмы, но это надо в лекциях рыться :-)


 
Fenik   (2005-03-14 21:40) [31]

>YurikGL ©  (14.03.05 21:33) [30]
>Я в [11] пример привел, который методом деления "в лоб" не решается.

Я понимаю и полностью поддерживаю.
Поэтому и написал "грубый вариант". Просто как пример.


 
dmk ©   (2005-03-14 21:58) [32]

А если хочешь с RGB работать, что крайне непонятно для меня,
сначала конвертни Bitmap-строку в RGB. Также сначала
создай RGB-представление битов.

//&#207;&#240;&#238;&#246;&#229;&#228;&#243;&#240;&#224; &#241;&#238;&#231;&#228;&#224;&#229;&#242; &#236;&#224;&#241;&#241;&#232;&#226; &#238;&#242;&#238;&#225;&#240;&#224;&#230;&#224;&#254;&#249;&#232;&#233; &#225;&#232;&#242;&#251; &#226; RGB &#239;&#240;&#229;&#228;&#241;&#242;&#224;&#226;&#235;&#229;&#237;&#232;&#232;
//&#207;&#240;&#232;&#236;&#229;&#240;: (10001111) = ($00000000 $00FFFFFF $00FFFFFF $00FFFFFF $00000000 $00000000 $00000000 $00000000)
//&#200;&#241;&#239;&#238;&#235;&#252;&#231;&#243;&#229;&#242;&#241;&#255; &#228;&#235;&#255; &#239;&#240;&#238;&#240;&#232;&#241;&#238;&#226;&#234;&#232; &#239;&#240;&#232; &#225;&#232;&#242;&#237;&#238;&#241;&#242;&#232; 1 Bpp
//&#204;&#224;&#241;&#241;&#232;&#226; &#231;&#224;&#237;&#232;&#236;&#224;&#229;&#242; 8&#202;&#225;
Procedure TImageStream.InitRgbMapOfBits;
var
 Counter:      Byte; //&#209;&#247;&#229;&#242;&#247;&#232;&#234; &#225;&#224;&#233;&#242;&#238;&#226;
 bc:           Byte; //&#209;&#247;&#229;&#242;&#247;&#232;&#234; &#225;&#232;&#242;&#238;&#226;

begin
 For Counter := 0 to 255 do
   begin
     For bc := 0 to 7 do
       If Bit(Counter, bc) then
          FRGBBitsArray[Counter].Cell[7 - bc] := clWhite else
          FRGBBitsArray[Counter].Cell[7 - bc] := clBlack;
   end;

 //&#192;&#228;&#240;&#229;&#241; &#237;&#224;&#247;&#224;&#235;&#224; &#236;&#224;&#241;&#241;&#232;&#226;&#224;
 FRGBBitsAddr := DWord(Addr(FRGBBitsArray[0].Cell[0]));
 RgbBits := FRgbBitsAddr;
end;


 
dmk ©   (2005-03-14 22:02) [33]

Procedure ConvertBitmapScLineToRgb(ImgLineAddr:DWord; DBufferLineAddr:DWord; NumberBits:DWord; StartBit:Byte);
var
 SrcAddr:            DWord;
 DestAddr:           DWord;
 BitsOffs:           DWord; //&#209;&#236;&#229;&#249;&#229;&#237;&#232;&#229; &#226; &#236;&#224;&#241;&#241;&#232;&#226;&#229; RGBBits
 FBitsLen:           DWord; //&#196;&#235;&#232;&#237;&#224; &#234;&#238;&#239;&#232;&#240;&#243;&#229;&#236;&#238;&#233; &#255;&#247;&#229;&#233;&#234;&#232;
 FBitsStart:         DWord; //&#205;&#224;&#247;&#224;&#235;&#238; &#226; &#255;&#247;&#229;&#233;&#234;&#229;
 FTotalBits:         DWord;
 FFirstBitsLen:      DWord;
 FLastBitsLen:       DWord;
 FBitsForCycle:      DWord;

begin
   //&#192;&#228;&#240;&#229;&#241; &#241;&#234;&#224;&#237;-&#235;&#232;&#237;&#232;&#232; &#226; &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#232;
   SrcAddr := ImgLineAddr;

   //&#192;&#228;&#240;&#229;&#241; &#241;&#234;&#224;&#237;-&#235;&#232;&#237;&#232;&#232; &#226; &#234;&#238;&#237;&#229;&#247;&#237;&#238;&#236; &#225;&#243;&#244;&#229;&#240;&#229;
   DestAddr := DBufferLineAddr;

   //&#202;&#238;&#235;-&#226;&#238; &#225;&#232;&#242;&#238;&#226; &#226; &#241;&#234;&#224;&#237;-&#235;&#232;&#237;&#232;&#232;
   FTotalBits := NumberBits;

   //&#208;&#224;&#241;&#247;&#229;&#242; &#241;&#236;&#229;&#249;&#229;&#237;&#232;&#255; &#226; &#225;&#224;&#233;&#242;&#229;, &#242;.&#234;. &#239;&#232;&#234;&#241;&#229;&#235;&#252; &#236;&#238;&#230;&#229;&#242; &#237;&#224;&#247;&#232;&#237;&#224;&#242;&#241;&#255; &#226; &#225;&#224;&#233;&#242;&#229; &#227;&#228;&#229; &#243;&#227;&#238;&#228;&#237;&#238;
   FBitsStart := StartBit;

   //&#196;&#235;&#255; &#246;&#232;&#234;&#235;&#224; &#225;&#232;&#242;&#238;&#226; &#237;&#229;&#242;
   FBitsForCycle := 0;

   //&#196;&#235;&#255; &#239;&#238;&#241;&#235;&#229;&#228;&#237;&#229;&#227;&#238; &#225;&#224;&#233;&#242;&#224; &#242;&#238;&#230;&#229; &#237;&#229;&#242;
   FLastBitsLen := 0;

   //&#197;&#241;&#235;&#232; &#228;&#235;&#232;&#237;&#224; &#236;&#229;&#237;&#252;&#248;&#229; &#226;&#238;&#241;&#252;&#236;&#232; &#239;&#232;&#234;&#241;&#229;&#235;&#238;&#226;(&#225;&#224;&#233;&#242;&#224;)
   If FTotalBits < 8 then
     begin
       //&#229;&#241;&#235;&#232; &#237;&#224;&#247;&#224;&#235;&#252;&#237;&#251;&#233; &#225;&#232;&#242; &#237;&#229; &#237;&#243;&#235;&#229;&#226;&#238;&#233;
       If StartBit <> 0 then
         begin
           //&#209;&#247;&#232;&#242;&#224;&#229;&#236;, &#247;&#242;&#238; &#228;&#235;&#232;&#237;&#224; &#246;&#229;&#239;&#238;&#247;&#234;&#232; &#226; &#239;&#229;&#240;&#226;&#238;&#236; &#225;&#224;&#233;&#242;&#229;
           //&#240;&#224;&#226;&#237;&#224; &#238;&#241;&#242;&#224;&#226;&#248;&#232;&#236;&#241;&#255; &#225;&#232;&#242;&#224;&#236;
           FFirstBitsLen := 8 - StartBit;
           //&#205;&#243; &#224; &#229;&#241;&#235;&#232; &#228;&#235;&#232;&#237;&#224; &#238;&#241;&#242;&#224;&#226;&#248;&#232;&#245;&#241;&#255; &#225;&#232;&#242;&#238;&#226;
           //&#236;&#229;&#237;&#252;&#248;&#229; &#228;&#235;&#232;&#237;&#251; &#226;&#245;&#238;&#228;&#237;&#238;&#233; &#246;&#229;&#239;&#238;&#247;&#234;&#232;
           //&#242;&#238; &#241;&#225;&#240;&#224;&#241;&#251;&#226;&#224;&#229;&#236; &#228;&#235;&#232;&#237;&#243; &#239;&#229;&#240;&#226;&#238;&#233; &#246;&#229;&#239;&#238;&#247;&#234;&#232;
           //&#234; &#226;&#245;&#238;&#228;&#237;&#238;&#236;&#243; &#234;&#238;&#235;-&#226;&#243;
           If FFirstBitsLen > FTotalBits then FFirstBitsLen := FTotalBits;
           //&#197;&#241;&#235;&#232; &#234;&#238;&#235;-&#226;&#238; &#225;&#232;&#242;&#238;&#226; &#226; &#239;&#229;&#240;&#226;&#238;&#236; &#225;&#224;&#233;&#242;&#229;
           //&#236;&#229;&#237;&#252;&#248;&#229; &#247;&#229;&#236; &#226;&#241;&#229;&#227;&#238;, &#242;&#238;
           //&#239;&#240;&#238;&#232;&#241;&#245;&#238;&#228;&#232;&#242; &#239;&#229;&#240;&#229;&#245;&#238;&#228; &#226; &#241;&#235;&#229;&#228;&#243;&#254;&#249;&#232;&#233; &#225;&#224;&#233;&#242;
           If FFirstBitsLen < FTotalBits then
             FLastBitsLen := FTotalBits - FFirstBitsLen;
         end//If aX <> 0 then
        else
         begin
           //&#196;&#235;&#232;&#237;&#224; &#239;&#229;&#240;&#226;&#238;&#233; &#246;&#229;&#239;&#238;&#247;&#234;&#232;
           FFirstBitsLen := FTotalBits;
         end;
     end//If FTotalBits < 8
    else//&#197;&#241;&#235;&#232; &#234;&#238;&#235;-&#226;&#238; &#225;&#232;&#242;&#238;&#226; &#225;&#238;&#235;&#252;&#248;&#229; 8


 
dmk ©   (2005-03-14 22:02) [34]

begin
       //&#229;&#241;&#235;&#232; &#237;&#224;&#247;&#224;&#235;&#252;&#237;&#251;&#233; &#225;&#232;&#242; &#237;&#229; &#237;&#243;&#235;&#229;&#226;&#238;&#233;
       If StartBit <> 0 then
         begin
           //&#209;&#247;&#232;&#242;&#224;&#229;&#236;, &#247;&#242;&#238; &#228;&#235;&#232;&#237;&#224; &#246;&#229;&#239;&#238;&#247;&#234;&#232; &#226; &#239;&#229;&#240;&#226;&#238;&#236; &#225;&#224;&#233;&#242;&#229;
           //&#240;&#224;&#226;&#237;&#224; &#238;&#241;&#242;&#224;&#226;&#248;&#232;&#236;&#241;&#255; &#225;&#232;&#242;&#224;&#236;
           FFirstBitsLen := 8 - StartBit;
           //&#207;&#238;&#241;&#236;&#238;&#242;&#240;&#232;&#236;. &#209;&#234;&#238;&#235;&#234;&#238; &#230;&#229; &#225;&#232;&#242;&#238;&#226; &#238;&#241;&#242;&#224;&#235;&#238;&#241;&#252;?
           Dec(FTotalBits,FFirstBitsLen);
           //&#197;&#241;&#235;&#232; &#238;&#241;&#242;&#224;&#235;&#238;&#241;&#252; 8 &#232;&#235;&#232; &#236;&#229;&#237;&#252;&#248;&#229; &#242;&#238;
           If FTotalBits <= 8 then
             begin
               //&#196;&#235;&#255; &#246;&#232;&#234;&#235;&#224; &#225;&#232;&#242;&#238;&#226; &#237;&#229;&#242;
               FBitsForCycle := 0;
               //&#206;&#237;&#232; &#226;&#241;&#229; &#228;&#235;&#255; &#239;&#238;&#241;&#235;&#229;&#228;&#237;&#229;&#227;&#238; &#239;&#232;&#234;&#241;&#229;&#235;&#224;
               FLastBitsLen := FTotalBits;
             end
            else//&#229;&#241;&#235;&#232; &#238;&#241;&#242;&#224;&#235;&#238;&#241;&#252; &#225;&#238;&#235;&#252;&#248;&#229; &#225;&#232;&#242;&#238;&#226;
             begin
               //&#196;&#235;&#232;&#237;&#224; &#246;&#229;&#239;&#238;&#247;&#234;&#232; &#226; &#239;&#238;&#241;&#235;&#229;&#228;&#237;&#229;&#236; &#225;&#224;&#233;&#242;&#229;
               FLastBitsLen := FTotalBits mod 8;
               //&#224; &#228;&#235;&#255; &#246;&#232;&#234;&#235;&#224; &#247;&#242;&#238;-&#242;&#238; &#232;&#236;&#229;&#229;&#236;
               FBitsForCycle := FTotalBits - FLastBitsLen;
             end;//else
         end//If aX <> 0
        else//&#197;&#241;&#235;&#232; &#226;&#241;&#229; &#230;&#229; &#239;&#232;&#234;&#241;&#229;&#235;&#251; &#237;&#224;&#247;&#232;&#237;&#224;&#254;&#242;&#241;&#255; &#241; 0-&#227;&#238; &#225;&#232;&#242;&#224;
         begin
           //&#210;&#238; &#239;&#229;&#240;&#226;&#251;&#233; &#225;&#224;&#233;&#242; &#239;&#238;&#235;&#237;&#251;&#233;
           FFirstBitsLen := 0;
           //&#202;&#238;&#235;-&#226;&#238; &#225;&#224;&#233;&#242; &#228;&#235;&#255; &#246;&#232;&#234;&#235;&#224;
           FBitsForCycle := (FTotalBits shr 3) shl 3;  
           //&#202;&#238;&#235;-&#226;&#238; &#225;&#232;&#242; &#226; &#239;&#238;&#241;&#235;&#229;&#228;&#237;&#229;&#236; &#225;&#224;&#233;&#242;&#229;
           FLastBitsLen := FTotalBits - FBitsForCycle;
         end;
     end;//If FTotalBits >= 8

   If FFirstBitsLen <> 0 then
     begin
      //&#234;&#238;&#235;-&#226;&#238; &#225;&#232;&#242;&#238;&#226; &#240;&#224;&#226;&#237;&#238; 8 - &#239;&#238;&#239;&#240;&#224;&#226;&#234;&#224; &#237;&#224; &#237;&#224;&#247;&#224;&#235;&#238; &#225;&#232;&#242;&#224;
      FBitsLen := FFirstBitsLen;

      //&#209;&#236;&#229;&#249;&#229;&#237;&#232;&#229; &#226; &#236;&#224;&#241;&#241;&#232;&#226;&#229; RGBBits
      asm
        mov     eax, SrcAddr
        mov     al, [eax]                 //&#215;&#232;&#242;&#224;&#229;&#236; &#239;&#232;&#234;&#241;&#229;&#235;
        and     eax, $000000FF            //&#206;&#247;&#232;&#241;&#242;&#232;&#236; &#241;&#242;&#224;&#240;&#248;&#232;&#229; 3 &#225;&#224;&#233;&#242;&#224; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224; EAX
        and     al, gvIndexedMask         //&#206;&#242;&#234;&#235;&#254;&#247;&#229;&#237; &#235;&#232; &#234;&#224;&#237;&#224;&#235;? &#210;&#229;&#239;&#229;&#240;&#252; &#226; AL 8 &#239;&#232;&#234;&#241;&#229;&#235;&#238;&#226; &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#255;
        shl     eax, 5                    //&#211;&#236;&#237;&#238;&#230;&#224;&#229;&#236; &#237;&#224; 32, &#242;.&#234;. &#253;&#235;&#229;&#236;&#229;&#237;&#242; &#236;&#224;&#241;&#241;&#232;&#226;&#224; - &#253;&#242;&#238; 32 &#225;&#224;&#233;&#242;&#224;
        mov     BitsOffs, eax
      end;

      //&#202;&#238;&#239;&#232;&#240;&#243;&#229;&#236; RGB &#225;&#224;&#233;&#242;&#251; &#226; &#234;&#238;&#237;&#229;&#247;&#237;&#251;&#233; &#225;&#243;&#244;&#229;&#240;
      MoveBytes(RgbBits + BitsOffs + (FBitsStart shl 2), DestAddr, FBitsLen shl 2);
      //&#209;&#236;&#229;&#249;&#224;&#229;&#236;&#241;&#255; &#234; &#241;&#235;&#229;&#228;&#243;&#254;&#249;&#229;&#236;&#243; &#225;&#224;&#233;&#242;&#243; &#226; &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#232;
      Inc(SrcAddr);
      //&#209;&#236;&#229;&#249;&#224;&#229;&#236;&#241;&#255; &#234; &#241;&#235;&#229;&#228;&#243;&#254;&#249;&#232;&#236; &#225;&#232;&#242;&#224;&#236; &#226; &#236;&#224;&#241;&#241;&#232;&#226;&#229; RGBBits
      Inc(DestAddr,FBitsLen shl 2);
    end;


 
dmk ©   (2005-03-14 22:02) [35]

If FBitsForCycle <> 0 then
     begin
       While FBitsForCycle <> 0 do
         begin
           //&#209;&#236;&#229;&#249;&#229;&#237;&#232;&#229; &#226; &#236;&#224;&#241;&#241;&#232;&#226;&#229; RGBBits
           asm
             mov     eax, SrcAddr
             mov     al, [eax]                 //&#215;&#232;&#242;&#224;&#229;&#236; &#239;&#232;&#234;&#241;&#229;&#235;
             and     eax, $000000FF            //&#206;&#247;&#232;&#241;&#242;&#232;&#236; &#241;&#242;&#224;&#240;&#248;&#232;&#229; 3 &#225;&#224;&#233;&#242;&#224; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224; EAX
             and     al, gvIndexedMask         //&#206;&#242;&#234;&#235;&#254;&#247;&#229;&#237; &#235;&#232; &#234;&#224;&#237;&#224;&#235;? &#210;&#229;&#239;&#229;&#240;&#252; &#226; AL 8 &#239;&#232;&#234;&#241;&#229;&#235;&#238;&#226; &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#255;
             shl     eax, 5                    //&#211;&#236;&#237;&#238;&#230;&#224;&#229;&#236; &#237;&#224; 32, &#242;.&#234;. &#253;&#235;&#229;&#236;&#229;&#237;&#242; &#236;&#224;&#241;&#241;&#232;&#226;&#224; - &#253;&#242;&#238; 32 &#225;&#224;&#233;&#242;&#224;
             mov     BitsOffs, eax
           end;

           MoveBytes(RgbBits + BitsOffs, DestAddr, 32);
           Inc(SrcAddr);
           Inc(DestAddr,32);
           Dec(FBitsForCycle,8);
         end;//While
     end;

   If FLastBitsLen <> 0 then
     begin
       //&#209;&#236;&#229;&#249;&#229;&#237;&#232;&#229; &#226; &#236;&#224;&#241;&#241;&#232;&#226;&#229; RGBBits
       asm
         mov     eax, SrcAddr
         mov     al, [eax]                 //&#215;&#232;&#242;&#224;&#229;&#236; &#239;&#232;&#234;&#241;&#229;&#235;
         and     eax, $000000FF            //&#206;&#247;&#232;&#241;&#242;&#232;&#236; &#241;&#242;&#224;&#240;&#248;&#232;&#229; 3 &#225;&#224;&#233;&#242;&#224; &#240;&#229;&#227;&#232;&#241;&#242;&#240;&#224; EAX
         and     al, gvIndexedMask         //&#206;&#242;&#234;&#235;&#254;&#247;&#229;&#237; &#235;&#232; &#234;&#224;&#237;&#224;&#235;? &#210;&#229;&#239;&#229;&#240;&#252; &#226; AL 8 &#239;&#232;&#234;&#241;&#229;&#235;&#238;&#226; &#232;&#231;&#238;&#225;&#240;&#224;&#230;&#229;&#237;&#232;&#255;
         shl     eax, 5                    //&#211;&#236;&#237;&#238;&#230;&#224;&#229;&#236; &#237;&#224; 32, &#242;.&#234;. &#253;&#235;&#229;&#236;&#229;&#237;&#242; &#236;&#224;&#241;&#241;&#232;&#226;&#224; - &#253;&#242;&#238; 32 &#225;&#224;&#233;&#242;&#224;
         mov     BitsOffs, eax
       end;

       MoveBytes(RgbBits + BitsOffs, DestAddr, (FLastBitsLen shl 2));
     end;//If
end;


 
Fenik   (2005-03-14 22:25) [36]

>dmk ©

Блин, ну ты даешь. Человеку нужен алгоритм, красивый четкий наглядный код. А не секреты оптимизации графики инструментами встроенного ассемблера. Учится он ещё, понимаешь? =)


 
Штотоносец   (2005-03-14 23:21) [37]

YurikGL ©   (14.03.05 21:33) [30]

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

procedure Tfrm_Main.GetGrayScale(Value:Integer);
var
 i,w,h:integer;
 a,c:Real;
 b:byte;
begin
 w:=0;
 h:=0;
 a:=255/value;
 for i:=1 to Length(ArrByteImg) do begin
   b:=ArrByteImg[i-1];
   c:=Round(b/a);
   if (b-a*c)>(a/2) then c:=Round(b/(a+1));
   b:=Round(c*a);
   Image2.Canvas.Pixels[w,h]:=b shl 16 + b shl 8 + b;
   inc(w);
   if w=Image2.Width then begin
     w:=0;
     inc(h);
   end;
 end;
end;


Остается теперь оптимизацией заняться =)


 
dmk ©   (2005-03-14 23:49) [38]

2 Fenik
Я не волшебник, я только учусъ (C) Золушка
Ну а вдруг ему интересно?! =)


 
Штотоносец   (2005-03-14 23:55) [39]


dmk ©   (14.03.05 23:49) [38]
Ну а вдруг ему интересно?! =)


Да вообщем интересно, но с такими коментариями, код сложнее воспринимается =)


 
dmk ©   (2005-03-15 00:52) [40]

Так черещз блокнот скопируй и шрифт поменяй.
Все читается =)


 
Fenik   (2005-03-15 17:44) [41]

> Штотоносец  (14.03.05 23:21) [37]
> Остается теперь оптимизацией заняться =)


procedure SetGrayScale(Bitmap: TBitmap; Value: Byte);
var Pixel: pRGBTriple;
   X, Y: Integer;
   A, A_2, B: Double;
   ByteTable: array [Byte] of Byte;
begin
 Bitmap.PixelFormat := pf24Bit;
 if Value > 1 then begin
   A := 255/(Value-1);
   A_2 := A/2;
   for X := 0 to 255 do begin
     B := A * Round(X/A);
     if (X - B) > A_2
       then ByteTable[X] := Round(A*Round(X/(A+1)))
       else ByteTable[X] := Round(X);
   end;
 end
 else
   FillChar(ByteTable, SizeOf(ByteTable), 0);

 for Y := 0 to Bitmap.Height - 1 do begin
   Pixel := Bitmap.ScanLine[Y];
   for X := 0 to Bitmap.Width - 1 do begin
     with Pixel^ do begin
       rgbtBlue  := ByteTable[rgbtBlue];
       rgbtGreen := ByteTable[rgbtGreen];
       rgbtRed   := ByteTable[rgbtRed];
     end;
     Inc(Pixel);
   end;
 end;
end;


Тестирование - http://fenik.nm.ru/Gray.zip
Но этот алгоритм не умный, так сказать. Так как - [11].
Возьми например какртинку http://fenik.nm.ru/UGADAY.JPG и установи 3 цвета. В итоге лажа. Нужен умный алгоритм, который будет анализировать распределение цветов и в соответствии с этим подбирать опорные точки.


 
Fenik   (2005-03-15 18:53) [42]

Упс, опечаточка, вместо строки -
   else ByteTable[X] := Round(X)
нужно
   else ByteTable[X] := Round(B)

В тесте тоже исправить.
Это я перед отправкой решил подправить, понимаешь.. :))


 
Fenik   (2005-03-15 19:19) [43]

> Штотоносец

Кстати, я проверил ситуации (b-a*c)>(a/2) никогда не возникает.
Поэтому всё заполнение таблицы сводится к

   A := 255/(Value-1);
   for X := 0 to 255 do
     ByteTable[X] := Round(A * Round(X/A));


Тест я перезакачал. Можешь проверить.
Вот такая оптимизация. :))


 
Fenik   (2005-03-15 19:39) [44]

Блин, да это ж почти тоже самое, что и я первый раз писал "грубый вариант". -))



Страницы: 1 2 вся ветка

Форум: "Media";
Текущий архив: 2005.07.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.64 MB
Время: 0.043 c
14-1118253491
redlord
2005-06-08 21:58
2005.07.11
teamspeak2 живой базар


3-1117141875
Zahar
2005-05-27 01:11
2005.07.11
Помогите с SQL-запросом.


14-1118309693
КаПиБаРа
2005-06-09 13:34
2005.07.11
Помогите решить практическую задачу


3-1116938513
Вольный Стрелок
2005-05-24 16:41
2005.07.11
Возврат данных (не набора) из ХП


4-1116431908
George
2005-05-18 19:58
2005.07.11
SolidWorks





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский