Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.12.2013, 14:54   #1
Winexcel
Форумчанин
 
Регистрация: 26.08.2013
Сообщений: 187
Сообщение ScanLine, градация серого.

Всем привет, опять при изучении delphi запнулся, на коварной функции BitMap'а - ScanLine, хотелось бы чтобы кто нибудь пояснил следующие строчки кода:
Код:
procedure TForm1.Gray(var Clip: TBitmap);
var
 p0: PByteArray;
 x, y: Integer;
begin
1) for y:=0 to Clip.Height-1 do  begin
2)   p0:=Clip.ScanLine[y];
3)   for x:=0 to Clip.Width-1 do
    begin
4)     p0[x*3+1]:=p0[x*3];
5)     p0[x*3+2]:=p0[x*3];
    end;
 end;
end;
Как я понял:
1)Перебираем все Y по переданному объекту Bitmap
2)В массив байтов, при это X[N]:=8 мы получаем все коды X по Y.
3)Начинаем перебирать каждый X
4)Здесь творится что-то не понятное
5)Тут тоже

Взято из книги Библия делфи, Фленов очень мало чего написал по этому поводу, я непонимаю почему мы умножаем на 3, видимому потому что картинка pixelformat:=24bit, а X:=8, почему после этого мы прибавляем ещё и +1,+2:
Код:
x*3+1;
x*3+2


Это как я понял есть:
У RGB если все три цвета ранвы то это будет градация серого. Но почему именно так? Кто может, и кому не сложно, разжуйте пожалуйста . Заранее огромное спасибо.

пысы загрузка картинки:

Код:
 if OpenPictureDialog1.Execute then
  begin
   Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
   SavedImage.Assign(Image1.Picture.Bitmap);
   SavedImage.PixelFormat:=pf24bit;
  end;
градация:

Код:
var
 bmp:TBitmap;
begin
 bmp:=TBitmap.Create;
 bmp.Assign(SavedImage);
 Gray(bmp);
 Image1.Picture.Bitmap.Assign(bmp);

Последний раз редактировалось Winexcel; 13.12.2013 в 14:57.
Winexcel вне форума Ответить с цитированием
Старый 14.12.2013, 08:20   #2
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Цитата:
Сообщение от Winexcel
Взято из книги Библия делфи, Фленов очень мало чего написал по этому поводу, я непонимаю почему мы умножаем на 3, видимому потому что картинка pixelformat:=24bit, а X:=8, почему после этого мы прибавляем ещё и +1,+2:
Именно так.
У Флёнова не рассмотрен обычный метод работы со сканлайном, как делает большинство (ибо так гораздо понятнее), а именно через ^(array[0..N] of TRGBTriple), у него сделано через обычные нетипизированные указатели - var p0: PByteArray;
Чтобы работать с битмапом, надо знать , что для 24битного битмапа данные идут подряд так: 1я строка пикселей по байту на компонент - ргбргбргбргбргб и т.д. в количестве: ширина картинки - пикселей и ширина *3 в байтах, потом новая строка пикселей (сразу подряд) и так пока все строки не закончатся (высота битмапа).

Обычно берут цикл , в нём берут сканлайн первой строки, и получают указатель на начало этой строки байт. Если указатель взять типизированный, то можно в следующем цикле по пикселям обращаться к Trgbtriple и её компонентам без заморочек. Но тут сделано проще - для внутреннего цикла текущий пиксель вычисляется каждый раз со смещением на 3 байта, через умножение, давая и начало пикселя и байт под красный цвет, а через добавление 1 и 2 осуществляется доступ к зелёной и синей компонентам пикселя.

Грейскейл картинки при этом делается странным алгоритмом - синий и зелёный приравниваются красному. Возможно, оно и даёт определённый результат, но общепринятая формула http://ru.wikipedia.org/wiki/Оттенки_серого т.е. надо прочитать все 3 компонента пикселя, вычислить по формуле значение и его присвоить всем компонентам пикселя.

Вот мой пример работы со сканлайном http://programmersforum.ru/showpost....&postcount=628 обсуждение касательно этого примера в той теме выше.

Последний раз редактировалось phomm; 14.12.2013 в 08:25.
phomm вне форума Ответить с цитированием
Старый 17.12.2013, 11:29   #3
Winexcel
Форумчанин
 
Регистрация: 26.08.2013
Сообщений: 187
По умолчанию

Ура, нашлось время на продолжение обучения, решил сделать эксперимент:
Код:
var
p0:PByteArray;
x,y:integer;
begin
memo1.Clear;
Img.Assign(Image1.Picture.Bitmap);
Img.PixelFormat:=pf24bit;
y:=0;
p0:=Img.ScanLine[y];
for x:=0 to img.Width do
memo1.Lines.Add(inttostr(p0[x]));
showmessage(inttostr(memo1.Lines.count));
Вывел в мемо я значит все цвета пикселей по y:=0 вот что получилось:
Код:
255
0
255
255
0
255
255
0
255
213
204
199
255
0
255
255
0
На сколько я понимаю, Memo1.lines.count должно делится на 3, в моём случае получилось число 17.

Цитата:
Чтобы работать с битмапом, надо знать , что для 24битного битмапа данные идут подряд так: 1я строка пикселей по байту на компонент - ргбргбргбргбргб и т.д. в количестве: ширина картинки - пикселей и ширина *3 в байтах, потом новая строка пикселей (сразу подряд) и так пока все строки не закончатся (высота битмапа).
Чтобы получить первый верхний(левый) пиксель картинки, получается что мы должны 0*3?

Цитата:
Грейскейл картинки при этом делается странным алгоритмом - синий и зелёный приравниваются красному. Возможно, оно и даёт определённый результат, но общепринятая формула http://ru.wikipedia.org/wiki/Оттенки_серого т.е. надо прочитать все 3 компонента пикселя, вычислить по формуле значение и его присвоить всем компонентам пикселя.
Читал где-то что в Windows не RGB а BGR.
Winexcel вне форума Ответить с цитированием
Старый 17.12.2013, 12:09   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
На сколько я понимаю, Memo1.lines.count должно делится на 3, в моём случае получилось число 17.
ширина имга 17 пикселей, не так ли?
(точнее 16)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 17.12.2013, 14:55   #5
Winexcel
Форумчанин
 
Регистрация: 26.08.2013
Сообщений: 187
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
ширина имга 17 пикселей, не так ли?
(точнее 16)
Да, 16x16, но что это даёт?
Winexcel вне форума Ответить с цитированием
Старый 17.12.2013, 15:04   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Сообщение от Winexcel Посмотреть сообщение
Да, 16x16, но что это даёт?
вы забыли что размер пикселей у вас не один байт?
вы же считаете что пиксель это байт.

потому и предпочитают работать через RGBTriple и тп.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 17.12.2013, 15:41   #7
Winexcel
Форумчанин
 
Регистрация: 26.08.2013
Сообщений: 187
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
вы забыли что размер пикселей у вас не один байт?
вы же считаете что пиксель это байт.

потому и предпочитают работать через RGBTriple и тп.
В коде выше, видимо что-то пошло не так, раз вывело 17, презапустил среду, и тот-же код выдал в мемо другой результат, теперь всё встало на свои места, с размером картинки 16x16 мне выдало 48 строк, каждые три строки это и есть пиксель(надеюсь я правильно понял), так к примеру первый пиксель - 0*3 - R
0*3+1 - G
0*3+2 - B
(или же наоборот BGR). С форматом pf32bit аналогично, очень рад что спустя столько времени понял .
Теперь ещё хотелось бы уточнить: почему используется именно RGB? И можем ли мы использовать такие цветовые модели как: CMYK, HSB?
Winexcel вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
JPEG градация серого BARNEY Мультимедиа в Delphi 2 24.02.2016 22:11
ScanLine ijonhson C++ Builder 1 28.03.2013 06:31
Работа со ScanLine ofx C++ Builder 1 22.08.2012 20:36
работа с градиентом серого frosti Общие вопросы C/C++ 1 24.04.2012 19:59
Оттенки серого yulia Мультимедиа в Delphi 4 02.12.2008 15:50