Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.04.08;
Скачать: CL | DM;

Вниз

Функция извлечения цветов из BMP в массив   Найти похожие ветки 

 
lyberzon ©   (2006-08-02 16:43) [0]

Привет всем!!! Ребят, подскажите плз., функцию извлечения цветовой палитры из картинки в массив, например, из элементов ТColor. Нигде не могу найти такого. Может плохо искал?


 
antonn ©   (2006-08-02 17:18) [1]

отдельно RGB из TColor?
var r, b, g:byte;
begin
r:=GetRValue(trColor); g:=GetGValue(trColor); b:=GetBValue(trColor);

или

r:=Byte(trColor);
g:=Byte(trColor shr 8);
b:=Byte(trColor shr 16);


 
antonn ©   (2006-08-02 17:18) [2]

для скорости можно воспользоваться scanline() для попиксельного пробега и получения все тех же RGB


 
Cash ©   (2006-08-02 17:34) [3]

... или для получения TColor из BMP??? (мне и самму не верится, но
мога-быть и такое)

TBitMap.Pixels[x,y: integer]: TColor, мога такое.


 
Virgo_Style ©   (2006-08-02 19:49) [4]

м.б. требуется извлечь из bmp данные об использованной палитре?


 
Степан   (2006-08-02 21:00) [5]

Я кажется нашел! Тебе надо в строну функции GetPaletteEntries рыть! Она на основе дескриптора палитры (Bitmap.Palette, так в Делфи помоему) выдает массив с ее содержимом, подробнее описано в MSDN (Windows SDK) -> Colors Overview


 
Lyberzon ©   (2006-08-03 15:15) [6]

Привет всем! Извиняюсь за долгое отсутствие. Был несказанно рад, когда увидел, что на мою просьбу откликнулись целых 4 человека.

Теперь по существу. Мне нужно извлечь из BMP задействованные цвета в массив с тем, чтобы потом я мог по выбору заменить любой выбранный цвет в картинке на другой. А с извлечением имеющейся палитры, я думаю, связываться бесполезно, т.к. некоторые форматы BMP ее не имеют. При этом алгоритм должен быть достаточно быстрым. Простое сканирование пикселей типа TBitMap.Pixels[x,y: integer]: TColor отпадает - чрезвычайно медленно. Необходимо что-то, что работало бы побыстрей.


 
Lyberzon ©   (2006-08-03 15:22) [7]

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


 
antonn ©   (2006-08-03 15:28) [8]

Lyberzon ©   (03.08.06 15:15) [6]
Простое сканирование пикселей типа TBitMap.Pixels[x,y: integer]: TColor отпадает - чрезвычайно медленно. Необходимо что-то, что работало бы побыстрей.

[2] ?


 
lyberzon ©   (2006-08-03 15:41) [9]

Я имел ввиду сканирование пикселей и сравнение их с уже занесенными в массив (если цвет текущего пикселя уже был однажды занесен в массив, то этот осуществляется переход к следующему и т.д.)


 
Jeer ©   (2006-08-03 15:44) [10]

так и непонятно, с чем проблемы - выяснить TColor пикселя или разработка собственного алгоритма сравнения чего-то с чем-то ?


 
lyberzon ©   (2006-08-03 16:09) [11]

Итак, я загружаю BMP из файла. На специальной панели отображается палитра цветов (все те цвета, из которых и состоит изображение). Я сликаю мышкой по любому цвету на панели, открывается диалог выбора цвета. Я выбираю другой цвет, и на изображении исходный цвет меняется на выбранный. Как это реализовать без использования TBitMap.Pixels[x,y: integer] ?


 
Jeer ©   (2006-08-03 16:36) [12]

Повторю - scanline ?

А алгоритм прост до неприличия:
если цвет = искомый, то цвет := выбранный


 
lyberzon ©   (2006-08-03 16:46) [13]

Ну а как с помощью scanline? Мне бы желательно код-пример. Jeer, как думаешь, за сколько времени предлагаемая реализация просчитает цвета картинки размером 1600Х1200?


 
lyberzon ©   (2006-08-03 16:47) [14]

Прошу прощения, ...как Вы думаете...?


 
Jeer ©   (2006-08-03 17:26) [15]


> как Вы думаете.


Не суть.

Важно, чтобы ты начал думать

F1 scanline

В help-e развернутый пример.

1024x768 сканируется за 20 ms на P-IV 2 GHz


 
Lyberzon ©   (2006-08-03 17:47) [16]

Спасибо. Вечером попробую...


 
Cash ©   (2006-08-03 20:13) [17]

lyberzon:
ScanLine конечно! он тебе вернет массив линии из картинки (строки по
моему...).
А там простым проходом по элементам вытягивай цвета и смотри.

Товарищ, а у вас алгоритм быстрой проверки наличия цвета есть? Простой
перебор не решит проблему за требуемое время!


 
Lyberzon ©   (2006-08-04 10:58) [18]

Вот и я о том же. Ребят, может поможете живым примером? Буду очень благодарен.


 
Jeer ©   (2006-08-04 11:29) [19]

Расскажи лучше, чем тебя 20 ms не устраивают.


 
Lyberzon ©   (2006-08-04 11:51) [20]

Да меня и это устраивает. Просто ни кто не хочет воочию показать, как это реализовать, то-есть живым примером кода.


 
Jeer ©   (2006-08-04 11:53) [21]

Зачем ?
Справку лень читать ?
набираешь в редакторе scanline
выделяешь и нажимаешь F1
Перед тобой окажется "живой" код от Borland


 
Lyberzon ©   (2006-08-04 13:21) [22]

Да, а как конкретно реализовать сравнение сосканированого цвета с цветами в массиве, и в каком виде они будут храниться в массиве? Или в каком виде удобней их хранить? И массив, подозреваю, должен быть "резиновым". Вот где загвоздка. А со сканированием мне ясно. Уважаемый Jeer, ну дайте хоть кусочек кода! :)))


 
Jeer ©   (2006-08-04 13:44) [23]

Если поможет - видимо не хочешь начать думать.

type
 TRGB = record
   b, g, r: byte;
 end;
 ARGB = array[0..1] of TRGB;
 PARGB = ^ARGB;

p: PARGB;
bmp: TBitmap;

//
// ri,gi,bi - искомый цвет
// rz,gz,bz - перезаписываемый цвет

 for y := 0 to bmp.height - 1 do
 begin
   p := bmp.scanline[y];
   for x := 0 to bmp.width - 1 do
   begin
     if (p[x].r = ri) and (p[x].g = gi) and (p[x].b = bi) then
       begin
         p[x].r  := rz;
         p[x].g := gz;
         p[x].b := bz;
       end;
   end;
 end;


 
Cash ©   (2006-08-04 14:41) [24]

Lyberzon ©   (04.08.06 13:21) [22]:
Позвольте пожалуйста поинтересоваться вашими знаниями в области
программирования (нет, это не глум, это действительно нужно для
определения того момента, с которого надо начинать эту феню).

Мне просто интересно понимание методов хранения и представления
информации, а так же знание алгоритмов и структур обработки данных.
(в частности деревья строить умеешь?)


 
Jeer ©   (2006-08-04 15:40) [25]

Cash ©   (04.08.06 14:41) [24]

В данном случае, скорее всего, надо начинать с простых вещей.
Если scanline вызвал такие затруднения, то... начинаем с понимания, что есть массив и какие они бывают.
А в лес (trees) он всегда успеет попасть.:))


 
Cash ©   (2006-08-04 16:31) [26]

Jeer ©   (04.08.06 15:40) [25]:
Да не в сканлайне дело, чел хочет поведать таинство определенного
алгоритма, который не освещен в справке вааще.


 
lyberzon ©   (2006-08-04 17:06) [27]

Ну знания мои не настоль обширны, на сколько хотелось бы. Но написать игрушку типа "Сокобан" на DelphiX мне по силам. В базах данных - абсолютный 0. И вообще, я еще учусь и многого не знаю, поэтому и обращаюсь за помощью. Прошу не судить меня строго, а за помощь огромное спасибо. Приятно осознавать, что в случае необходимости, тебе готовы помочь абсолютно незнакомые люди. Спасибо, ребята!


 
Jeer ©   (2006-08-04 17:13) [28]

lyberzon ©   (04.08.06 17:06) [27]


> тебе готовы помочь абсолютно незнакомые люди.


А тут так - и помочь и навредить тебе всегда способны апсолютно незнакомые люди.

Но, если чего - заходи.
С "расцветкой" всегда поможем:))


 
lyberzon ©   (2006-08-05 09:23) [29]

Пробовал таким способом узнать количество цветов в картинке, но увы не работает. Уважаемые спецы, что я делаю не правильно?

unit Main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, Menus;

type
 TMainForm = class(TForm)
   PaintBox1: TPaintBox;
   MainMenu1: TMainMenu;
   File1: TMenuItem;
   Opensprite1: TMenuItem;
   OpenDialog1: TOpenDialog;
   procedure FormCreate(Sender: TObject);
   procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
 private

 public
   { Public declarations }
 end;

var
 MainForm: TMainForm;
 Bitmap: TBitmap;

implementation

{$R *.dfm}

type
TRGB=record
 B,G,R: Byte;
end;
pRGB = ^TRGB;
TDynArray = array of TRGB;

var
Colors: TDynArray;

function CalculateColors(Bitmap: TBitmap): Integer;
var
i,x,y,nColors: Integer;
Dest: pRGB;

begin
Bitmap.PixelFormat:=pf24bit;
nColors:=0;
for y:=0 to Bitmap.Height-1 do
 begin
  Dest:=Bitmap.ScanLine[y];
  for x:=0 to Bitmap.Width-1 do
   begin
    with Dest^ do
     begin
      if Colors<>nil then
       begin
        for i:=0 to nColors-1 do
         begin
          if (R<>Colors[i].R) or
             (G<>Colors[i].G) or
             (B<>Colors[i].B) then
           begin
            inc(nColors);
            SetLength(Colors,nColors);
            Colors[nColors-1].R:=R;
            Colors[nColors-1].G:=G;
            Colors[nColors-1].B:=B;
           end;
         end;
       end
      else
       begin
        nColors:=1;
        SetLength(Colors,nColors);
        Colors[nColors-1].R:=R;
        Colors[nColors-1].G:=G;
        Colors[nColors-1].B:=B;
       end;
     end;
    Inc(Dest);
   end;
 end;
Result:=nColors;
end;

procedure TMainForm.Opensprite1Click(Sender: TObject);
begin
if (OpenDialog1.Execute) then
 begin
  Bitmap.LoadFromFile(OpenDialog1.FileName);
  PaintBox1.Canvas.Draw(0,0,Bitmap);
  ShowMessage(IntToStr(CalculateColors(Bitmap)));
 end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
Bitmap:=TBitmap.Create;
end;

procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
Bitmap.Free;
end;

end.


 
MBo ©   (2006-08-05 14:08) [30]


uses UQPixels;
// http://www.delphimaster.ru/articles/pixels/index.html

function GetColorCount(const PicName: string): Integer;
var
 x, y: Integer;
 c: Integer;
 qp: TQuickPixels;
 b: TBitmap;
 Bits: TBits;
begin
 Result := 0;
 b := TBitmap.Create;
 b.LoadFromFile(PicName);
 qp := TQuickPixels.Create;
 qp.Attach(b);
 Bits := TBits.Create;
 Bits.Size := $1000000;
 for y := 0 to b.Height - 1 do
   for x := 0 to b.Width - 1 do begin
     c := $FFFFFF and qp.Pixels[x, y];
     if not Bits[c] then begin
       Inc(Result);
       Bits[c] := True;
     end;
   end;
 b.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Caption := IntToStr(GetColorCount("test.bmp"));
end;


 
MBo ©   (2006-08-05 14:10) [31]

в конце функции, конечно, еще
 qp.Free;
 Bits.Free;


 
lyberzon ©   (2006-08-06 08:38) [32]

А как с помощью TQuickPixels извлеч имеющиеся в BMP цвета и поместить их в массив, с целью дальнейшего заполнения таблицы (палитры) из этого массива? Желательно использование динамического массива из элементов TColor. Уважаемый MBo, подскажите пожалуйста.


 
lyberzon ©   (2006-08-06 08:39) [33]

Хочу заметить, что цвета в массиве не должны повторяться.


 
lyberzon ©   (2006-08-06 08:42) [34]

И насчет моего кодинга. Неужели никто не может исправить мою ошибку, или хотя бы указать на нее. Народ, очень нужно!


 
Lyberzon ©   (2006-08-07 10:57) [35]


> И насчет моего кодинга. Неужели никто не может исправить
> мою ошибку, или хотя бы указать на нее. Народ, очень нужно!
>


 
Jeer ©   (2006-08-07 11:14) [36]

lyberzon ©   (06.08.06 08:42) [34]

Вариант 1.

Для фиксации цветов можно поступить так:
Завести три массива, где индекс определяется значением соответствующей цветовой составляющей:

 arR, arG, arB: array [0..255] of boolean;

Тогда фиксация наличия цвета сводится к:
arR[R] := True;
arG[G] := True;
arB[B] := True;

где R,G,B - найденные цветовые составляющие ij-пикселя

Определение числа цветов в палитре сведется к просчету числа True в каждом массиве Nr, Ng, Nb и получению Ncolors := Nr*Ng*Nb

Или, как вариант,
if not(arR[R] and arG[G] and arB[B]) then Inc(Ncolors);
и после
arR[R] := True;
arG[G] := True;
arB[B] := True;

Затем получение массива arColors: TColor :

SetLength(arColors, Ncolors);
Вложенное сканирование всех трех массивов arR,arG,arB

if (arR[i] and arG[j] and arB[k]) then begin
 arColors[m] := TColor((i shl 16) or (j shl 8) or k);
 Inc(m)
end;


 
Lyberzon ©   (2006-08-07 13:32) [37]

Решение довольно таки мудрое, уважаемый Jeer. Я так и поступлю. Мне только одно интересно, где я допустил ошибку в своем коде (см. выше)? Просто интересно...


 
MBo ©   (2006-08-07 13:42) [38]

>Jeer ©   (07.08.06 11:14) [36]
после обработки трех точек с цветами
0,0,0
1,1,1
2,2,2
цвет 0,1,2 будет считаться уже имеющимся, а это не так...


 
Cash ©   (2006-08-07 14:39) [39]

(просю прощения за отсутствие в дискуссии.)

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

Суть метода в том, чтобы добавлять в вершины дерева сами цвета (TColor),
слева меньший цвет, справа -- больший. При добавлении нового элемента
поиск его совпадений производится автоматически, т. к. мы в любом случае
должны сравнить добавляемый элемент с тем, который находится в текущей
вершине дерева. Если значение вершины совпадает с добавляемым, то
просто выходим без добавлений.

Формировать палитру можно как при проходе, так и при заполнении дерева.


 
Jeer ©   (2006-08-07 16:00) [40]

MBo ©   (07.08.06 13:42) [38]

Да, что-то меня смущало:))

Разумеется arRGB[0..255, 0..255, 0..255] of boolean
вместо трех массивов.



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

Текущий архив: 2007.04.08;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.034 c
15-1173796015
eXPell
2007-03-13 17:26
2007.04.08
Исходящие...


2-1174372869
sapsi
2007-03-20 09:41
2007.04.08
Работа с 2-мя базами


2-1174014038
Gromozeka
2007-03-16 06:00
2007.04.08
Закрытие форм


1-1171193855
Chaser
2007-02-11 14:37
2007.04.08
Программный скроллинг в ListView


2-1173951345
Quelle
2007-03-15 12:35
2007.04.08
Из шестнадцатиричного формата в текст