![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Функция извлечения цветов из BMP в массив [D7, WinXP]
lyberzon © (2006-08-02 16:43:00)Привет всем!!! Ребят, подскажите плз., функцию извлечения цветовой палитры из картинки в массив, например, из элементов ТColor. Нигде не могу найти такого. Может плохо искал?
Jeer (2006-08-07 16:16:00) [1]lyberzon © (06.08.06 08:42) [34]
Как минимум:
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;
break
end;
иначе бесконечный цикл.
Jeer (2006-08-07 16:00:00) [2]MBo © (07.08.06 13:42) [38]
Да, что-то меня смущало:))
Разумеется arRGB[0..255, 0..255, 0..255] of boolean
вместо трех массивов.
Cash (2006-08-07 14:39:00) [3](просю прощения за отсутствие в дискуссии.)
А я не зря про деревья спрашивал, проблему такую я не решал, но подумал,
что с помощью структуры СДП (Случайное Дерево Поиска) время решения
этой проблемы может сократиться до приемлемых значений. Трудоемкость
поиска по СДП соответствует глубине этого дерева. Конечно с СДП есть
реальная вероятность вырождения его в список, но для данного случая,
я думаю, это мало вероятно.
Суть метода в том, чтобы добавлять в вершины дерева сами цвета (TColor),
слева меньший цвет, справа -- больший. При добавлении нового элемента
поиск его совпадений производится автоматически, т. к. мы в любом случае
должны сравнить добавляемый элемент с тем, который находится в текущей
вершине дерева. Если значение вершины совпадает с добавляемым, то
просто выходим без добавлений.
Формировать палитру можно как при проходе, так и при заполнении дерева.
MBo (2006-08-07 13:42:00) [4]>Jeer © (07.08.06 11:14) [36]
после обработки трех точек с цветами
0,0,0
1,1,1
2,2,2
цвет 0,1,2 будет считаться уже имеющимся, а это не так...
Lyberzon (2006-08-07 13:32:00) [5]Решение довольно таки мудрое, уважаемый Jeer. Я так и поступлю. Мне только одно интересно, где я допустил ошибку в своем коде (см. выше)? Просто интересно...
Jeer (2006-08-07 11:14:00) [6]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 10:57:00) [7]
> И насчет моего кодинга. Неужели никто не может исправить
> мою ошибку, или хотя бы указать на нее. Народ, очень нужно!
>
lyberzon (2006-08-06 08:42:00) [8]И насчет моего кодинга. Неужели никто не может исправить мою ошибку, или хотя бы указать на нее. Народ, очень нужно!
lyberzon (2006-08-06 08:39:00) [9]Хочу заметить, что цвета в массиве не должны повторяться.
lyberzon (2006-08-06 08:38:00) [10]А как с помощью
TQuickPixelsизвлеч имеющиеся в BMP цвета и поместить их в массив, с целью дальнейшего заполнения таблицы (палитры) из этого массива? Желательно использование динамического массива из элементовTColor. Уважаемый MBo, подскажите пожалуйста.
MBo (2006-08-05 14:10:00) [11]в конце функции, конечно, еще
qp.Free;
Bits.Free;
MBo (2006-08-05 14:08:00) [12]
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;
lyberzon (2006-08-05 09:23:00) [13]Пробовал таким способом узнать количество цветов в картинке, но увы не работает. Уважаемые спецы, что я делаю не правильно?
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.
Jeer (2006-08-04 17:13:00) [14]lyberzon © (04.08.06 17:06) [27]
> тебе готовы помочь абсолютно незнакомые люди.
А тут так - и помочь и навредить тебе всегда способны апсолютно незнакомые люди.
Но, если чего - заходи.
С "расцветкой" всегда поможем:))
lyberzon (2006-08-04 17:06:00) [15]Ну знания мои не настоль обширны, на сколько хотелось бы. Но написать игрушку типа "Сокобан" на DelphiX мне по силам. В базах данных - абсолютный 0. И вообще, я еще учусь и многого не знаю, поэтому и обращаюсь за помощью. Прошу не судить меня строго, а за помощь огромное спасибо. Приятно осознавать, что в случае необходимости, тебе готовы помочь абсолютно незнакомые люди. Спасибо, ребята!
Cash (2006-08-04 16:31:00) [16]Jeer © (04.08.06 15:40) [25]:
Да не в сканлайне дело, чел хочет поведать таинство определенного
алгоритма, который не освещен в справке вааще.
Jeer (2006-08-04 15:40:00) [17]Cash © (04.08.06 14:41) [24]
В данном случае, скорее всего, надо начинать с простых вещей.
Если scanline вызвал такие затруднения, то... начинаем с понимания, что есть массив и какие они бывают.
А в лес (trees) он всегда успеет попасть.:))
Cash (2006-08-04 14:41:00) [18]Lyberzon © (04.08.06 13:21) [22]:
Позвольте пожалуйста поинтересоваться вашими знаниями в области
программирования (нет, это не глум, это действительно нужно для
определения того момента, с которого надо начинать эту феню).
Мне просто интересно понимание методов хранения и представления
информации, а так же знание алгоритмов и структур обработки данных.
(в частности деревья строить умеешь?)
Jeer (2006-08-04 13:44:00) [19]Если поможет - видимо не хочешь начать думать.
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;
Lyberzon (2006-08-04 13:21:00) [20]Да, а как конкретно реализовать сравнение сосканированого цвета с цветами в массиве, и в каком виде они будут храниться в массиве? Или в каком виде удобней их хранить? И массив, подозреваю, должен быть "резиновым". Вот где загвоздка. А со сканированием мне ясно. Уважаемый Jeer, ну дайте хоть кусочек кода! :)))