
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.52] |
![]() |
|
Сообщ.
#1
,
|
|
|
Имеется цветной рисунок нужно из него сделать черно-белый.
![]() |
Сообщ.
#2
,
|
|
|
![]() ![]() int r = 0, g = 0, b = 0, color = 0; for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { r = ptr[x]; //Получаем g = ptr[x+1]; //значения b = ptr[x+2]; //каналов color = (r + g + b) / 3; //Выссчитываем среднее значение ptr[x] = color; ptr[x+1] = color; ptr[x+2] = color; } } (с) Мяут ![]() |
Сообщ.
#3
,
|
|
|
Noer, этот вариант неправильный. Правильно - использовать компоненту Y(яркость) кодировки YUV.
Примеры - здесь: http://sources.ru/builder/faq/027.html или здесь: RGB to YUV и обратно |
Сообщ.
#4
,
|
|
|
trainer, Ну код же вроде пашет, а с ссылок этих я например не понял как сделать серую картинку...
|
Сообщ.
#5
,
|
|
|
Цитата int r = 0, g = 0, b = 0, color = 0; for(int y = 0; y < Image->Height; y++){ ptr = (Byte*)Image->ScanLine[y]; for (int x = 0; x < Image->Width * 3; x+=3) { r = ptr[x]; //Получаем g = ptr[x+1]; //значения b = ptr[x+2]; //каналов color = (r + g + b) / 3; //Выссчитываем среднее значение ptr[x] = color; ptr[x+1] = color; ptr[x+2] = color; } } Мне кажется, что это преобразование не в черно-белое, а в серое. Цитата а с ссылок этих я например не понял как сделать серую картинку... Солидарен c NoeR |
Сообщ.
#6
,
|
|
|
Вообщето в моем понимание серое это считаеться черно-белое или тебе надо чисто только черный и только белый ?
|
Сообщ.
#7
,
|
|
|
Цитата NoeR @ Он использует неправильный алгоритм определения яркости(оттенка серого). Ну код же вроде пашет |
Сообщ.
#8
,
|
|
|
Да, мне надо чисто только черный и только белый.
|
Сообщ.
#9
,
|
|
|
Черно-белый:
(Можно и через сканлайны) ![]() ![]() int Height = Image->Picture->Bitmap->Height; int Width = Image->Picture->Bitmap->Width; byte Luminance = 128; byte Color[3]; byte ColorMid; for(int y = 0; y < Height; y++) { for(int x = 0; x < Width; x++) { Color[0] = GetRValue(Image->Picture->Bitmap->Canvas->Pixels[x][y]); Color[1] = GetGValue(Image->Picture->Bitmap->Canvas->Pixels[x][y]); Color[2] = GetBValue(Image->Picture->Bitmap->Canvas->Pixels[x][y]); ColorMid = Gray(ptr[x], ptr[x+1], ptr[x+2]); if(ColorMid < Luminance) Image->Picture->Bitmap->Canvas->Pixels[x][y] = 0x000000; else Image->Picture->Bitmap->Canvas->Pixels[x][y] = 0xFFFFFF; } } Оттенки серого: ![]() ![]() int Height = Image->Picture->Bitmap->Height; int Width = Image->Picture->Bitmap->Width*3; byte ColorMid; byte* ptr; for(int y = 0; y < Height; y++) { ptr = (byte*) Image->Picture->Bitmap->ScanLine[y]; for(int x = 0; x < Width; x+=3) { ColorMid = Gray(ptr[x], ptr[x+1], ptr[x+2]); ptr[x+2] = ColorMid; ptr[x+1] = ColorMid; ptr[x] = ColorMid; } } Где Gray определено как Y: ![]() ![]() #define Gray(R, G, B) (R*.257 + G*.504+B*.098+16.) ЗЫ. NoeR, стравьте копирайты ![]() |
Сообщ.
#10
,
|
|
|
Цитата ЗЫ. NoeR, стравьте копирайты У Вас слишком высокая самооценка, я поставил копирайт! |
Сообщ.
#11
,
|
|
|
Сори. Просто тут совсем запарился. Извини - больще не повториться
![]() |
Сообщ.
#12
,
|
|
|
Цитата Мяут-Настоящий @ У фотошопа есть отличия притом я их вижу невооруженным глазомГде Gray определено как Y: #define Gray(R, G, B) (R*.257 + G*.504+B*.098+16.) Фотошоп сделал более контрастно |
Сообщ.
#13
,
|
|
|
Цитата gastroler @ Да, мне надо чисто только черный и только белый. А свойство TBitmap::Monochrome в true не пробовал выставить? |
Сообщ.
#14
,
|
|
|
Подскажите, пожалуйста, недоделанному программисту, если это код перевода цветного изображения в оттенки серого:
int Height = Image->Picture->Bitmap->Height; int Width = Image->Picture->Bitmap->Width*3; byte ColorMid; byte* ptr; for(int y = 0; y < Height; y++) { ptr = (byte*) Image->Picture->Bitmap->ScanLine[y]; for(int x = 0; x < Width; x+=3) { ColorMid = Gray(ptr[x], ptr[x+1], ptr[x+2]); ptr[x+2] = ColorMid; ptr[x+1] = ColorMid; ptr[x] = ColorMid; } } То, где окончание? То есть как на форму вывести результат - фото в оттенках серого? |
Сообщ.
#15
,
|
|
|
Цитата Klaribel @ Подскажите, пожалуйста, Тут подразумевается, что на форме есть уже компонент Image, в него уже загружена картинка, а этот код вставлен в обработчик кнопки. |
Сообщ.
#16
,
|
|
|
Хм, ну это понятно. Расскажу подробней.
У меня есть компоненты Image1 и Image2 и есть кнопка, по нажатию которой картинка Image1 должна становиться серой и выводиться в Image2. Вставляю код в обработчик кнопки и.... из Image1 исчезает картинка, в Image2 ничего не появляется. Подразумеваю, что что-то все таки не так) |
Сообщ.
#17
,
|
|
|
Ну можно вот так попробывать сделать ч\б. ТОлько по непонятной причине ч\б становится только часть фото.
![]() ![]() int Lowpass(BYTE Image[][256], int x, int y) { int Mask[3][3] = {{1, 1, 1,}, {1, 1, 1}, {1, 1, 1}}; int i, j, sum=0; for (j=-1; j<=1; j++) for (i=-1; i<=1; i++) sum += Image[x+i][y+j]*Mask[i+1][j+1]; return INT(sum/9.0); } void __fastcall TForm1::Button1Click(TObject *Sender) { BYTE ImageData[256][256], *LinePtr; BYTE Output[256][256]; int x, y; for (y=0; y<=255; y++) { LinePtr = (BYTE *) Image1->Picture->Bitmap->ScanLine[y]; for (x=0; x<=255; x++) ImageData[x][y] = LinePtr[x]; } for (y=1; y<=254; y++) for (x=1; x<=254; x++) Output[x][y] = Lowpass(ImageData, x, y); for (y=0; y<=255; y++) { LinePtr = (BYTE *) Image1->Picture->Bitmap->ScanLine[y]; for (x=0; x<=255; x++) LinePtr[x] = Output[x][y]; } Image1->Refresh(); } |
Сообщ.
#18
,
|
|
|
Спасибо за идею, однако не получается.
Выскакивает окно project project1.exe raised exception class EInvalid Graphic Operation with message "Scan line index out of range". Process stopped.... |
Сообщ.
#19
,
|
|
|
Цитата Klaribel @ Выскакивает окно Загрузи фото другого размера. И обязательно bmp |
Сообщ.
#20
,
|
|
|
А если мне именно надо jpg и именно такого размера (160х128)?=)
|
Сообщ.
#21
,
|
|
|
ну попробуй сначала загрузить bmp такого размера
|
Сообщ.
#22
,
|
|
|
Ну да, bmp и большего размера прога обрабатывает, но действительно только маленькую часть. С jpg, пределанный в bmp и большего, и такого же размера работать отказывается:(
|
Сообщ.
#23
,
|
|
|
Кстати, я так и не понял почему не обрабатывается вся фото. Выдернул кусок кода из проекта просто. Но раньше то работал же.
Может кто-то подскажет почему так происходит. |
![]() |
Сообщ.
#24
,
|
|
Если в Image1 загружен не bmp-формат (jpg, png и т.д.) то можно просто скопировать эту картинку в промежуточный bmp, его "засерить" и заасайнить его уже в Image2.
![]() ![]() // копирование в промежуточный bitmap Graphics::TBitmap* bitmap = new Graphics::TBitmap(); bitmap->Width = Image1->Width; bitmap->Height = Image1->Height; BitBlt(bitmap->Canvas->Handle, 0, 0, bitmap->Width, bitmap->Height, Form1->Canvas->Handle, Image1->Left, Image1->Top, SRCCOPY); // "засеривание" промежуточного bitmap'а bitmap->PixelFormat = pf24bit; for (int y = bitmap->Height - 1; y >= 0; --y) { TRGBTriple* scanLine = (TRGBTriple*)bitmap->ScanLine[y]; for (int x = bitmap->Width - 1; x >= 0; --x) { const BYTE gray = 0.222 * scanLine[x].rgbtRed + 0.707 * scanLine[x].rgbtGreen + 0.071 * scanLine[x].rgbtBlue; scanLine[x].rgbtGreen = gray; scanLine[x].rgbtRed = gray; scanLine[x].rgbtBlue = gray; } } // копирование промежуточного bitmap'а в Image2 Image2->Picture->Assign(bitmap); delete bitmap; Но если картинка не на форме (а на панели например, к канве которой доступа напрямую нет) или поверх картинки какие-то контролы - то тогда сложнее будет. Добавлено Цитата Kamenev_D @ Кстати, я так и не понял почему не обрабатывается вся фото У тебя вообще какой-то код кучерявый.. Какие-то три цикла и почему только до 255(254)?! Добавлено о.. прикольно. Знаю как прорисовать Image в любой девайсконтекст (именно прорисовать а не скопировать уже прорисованный). вместо ![]() ![]() BitBlt(bitmap->Canvas->Handle, 0, 0, bitmap->Width, bitmap->Height, Form1->Canvas->Handle, Image1->Left, Image1->Top, SRCCOPY); надо просто ![]() ![]() Image1->Perform(WM_PAINT, (WPARAM)bitmap->Canvas->Handle, 0); и отпадает проблема парента, и возможных контролов поверх картинки... Image1 вообще невидимым может быть! Добавлено Так-с... После всего вышло что можно и вообще без промежуточного битмапа ![]() Сразу прорисовать Image1 в Image2 и потом последний "засерить": ![]() ![]() Image2->Picture->Bitmap->PixelFormat = pf24bit; Image2->Picture->Bitmap->Width = Image1->Width; Image2->Picture->Bitmap->Height = Image1->Height; Image1->Perform(WM_PAINT, (WPARAM)Image2->Picture->Bitmap->Canvas->Handle, 0); for (int y = Image2->Picture->Bitmap->Height - 1; y >= 0; --y) { TRGBTriple* scanLine = (TRGBTriple*)Image2->Picture->Bitmap->ScanLine[y]; for (int x = Image2->Picture->Bitmap->Width - 1; x >= 0; --x) { const BYTE gray = 0.222 * scanLine[x].rgbtRed + 0.707 * scanLine[x].rgbtGreen + 0.071 * scanLine[x].rgbtBlue; scanLine[x].rgbtGreen = gray; scanLine[x].rgbtRed = gray; scanLine[x].rgbtBlue = gray; } } Работает ![]() |
Сообщ.
#25
,
|
|
|
Всем спасибо, завтра попробую, сегодня уже сил нет=)
|
Сообщ.
#26
,
|
|
|
Спасибо огромное! РАБОТАЕТ!
![]() |
Сообщ.
#27
,
|
|
|
подскажите ещё одному начинающему программисту, возможно ли провернуть фильтр сепии?
пробовал менять формулу серого на формулу коричневого и сепии, но как-то не очень получалось... подскажите плиз) Добавлено откуда формула серого такая? #define Gray(R, G, B) (R*.257 + G*.504+B*.098+16.) есть формулы других цветов? |
Сообщ.
#28
,
|
|
|
Цитата donotlies @ Откуда там у тебя +16. - это нам не известно. Это очевидно вычисление яркости точки, отображать ее можно в оттенках хоть серого, хоть красного или зеленого. Каких таких других цветов? откуда формула серого такая? #define Gray(R, G, B) (R*.257 + G*.504+B*.098+16.) есть формулы других цветов? |
![]() |
Сообщ.
#29
,
|
|
Цитата donotlies @ откуда формула серого такая? #define Gray(R, G, B) (R*.257 + G*.504+B*.098+16.) А от куда ты ее взял? На Википедии приведены такие весовые коэффициенты: 0,222 0,707 и 0,071 |
Сообщ.
#30
,
|
|
|
donotlies
Это история старая. Во времена когда создавалось телевидение... Во общем формула отсюда. http://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf Chow Википедия не достоверный источник. Но такая формула тоже существует. А по поводу того какая из них правильная отвечу просто. Во первых не понятно откуда взялась картинка и формат её хранения и способ вывода. Так что с успехом можно применять любую. Но вроде как стандарт CIE преобладает. Так что надо следовать ихним рекомендациям. |
Сообщ.
#31
,
|
|
|
я её взял с первой страницы этой темы...
|
Сообщ.
#32
,
|
|
|
Цитата Klaribel @ А если мне именно надо jpg и именно такого размера (160х128)?=) Для *.jpg можна использовать TJPEGImage. #include <Jpeg.hpp> //----------------- TJPEGImage *tJpg=new TJPEGImage; //----------------- |