Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/29: Рейтинг темы: голосов - 29, средняя оценка - 4.69
15 / 15 / 1
Регистрация: 31.12.2012
Сообщений: 101
1

Работа с отдельными пикселями

22.01.2013, 03:08. Показов 5661. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Имеется область на hdc. Надо что-то с Каждым пикселем сделать и вернуть измененный пиксель назад или на другой hdc.
Я могу написать код по схеме - в двойном цикле берешь каждый пиксель, читаешь GetPixel , раскодируешь в цвета, что хочешь делаешь, записываешь назад или на другой SetPixel . Кое-что рабочее так уже написал, НО! попиксельная обработка такая, точнее Чтение и Запись - несравнимо медленнее стандартных функций.
Как можно лучше?
Скорее всего из указателя на hdc можно как-то "выдрать" где именно в памяти все лежит и "лезть" туда напрямую, но как именно?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.01.2013, 03:08
Ответы с готовыми решениями:

Как работать с отдельными пикселями на изображении
Плиз помогите как работать с отдельными пикселями на изображении. Если точнее то я использую...

c# работа с пикселями.
бешеный проблема. Очень надо добить эту программу. Тут работа с изображениями, суть в том, что...

Работа с пикселями
1) Згенеруваты выпадкови дани що видповидають умови задачи и зберегты в текстовому редактори 2)...

Работа с пикселями
загружаю рисунок в pictureBox, беру например пиксель по координатам 10, 10 . А вот как его изменить...

7
Неэпический
18106 / 10693 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
22.01.2013, 06:18 2
Цитата Сообщение от SeaMonster Посмотреть сообщение
Скорее всего из указателя на hdc можно как-то "выдрать" где именно в памяти все лежит и "лезть" туда напрямую, но как именно?
Посмотрите в сторону DIB-секций
1
15 / 15 / 1
Регистрация: 31.12.2012
Сообщений: 101
22.01.2013, 15:47  [ТС] 3
Вроде мощная вещь, но что неправильно в таком фрагменте кода?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BITMAPINFO bmi;
  ZeroMemory(&bmi, sizeof(BITMAPINFOHEADER));
 
  bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
  bmi.bmiHeader.biWidth       = 620;
  bmi.bmiHeader.biHeight      = 200;
  bmi.bmiHeader.biPlanes      = 1;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biBitCount    = 32;
 
  DWORD *bitmapBits;
  HBITMAP bitmap = CreateDIBSection(txDC(), &bmi, DIB_RGB_COLORS, (void**)&bitmapBits, 0, 0);
Win32::SelectObject(txDC(), bitmap);
 
for (long int i1 = 0; i1<64000l; i1++){
 bitmapBits[i1] = RGB(140,2,1);
}
 
 
SetDIBitsToDevice(txDC(),0,0,320,200,0,0,  0,0,bitmapBits,&bmi,DIB_RGB_COLORS);

1. По идее то, что я написал - должно создать секцию на основе куска экрана, часть закрасить в один цвет, часть оставить как есть и снова вывести на экран.
2. На практике - создается секция заполненная нулями (черная), часть таки красится и так выводится.

Добавлено через 21 минуту
А в gdi+ есть высокоуровневые обертки для таких действий? Это же вроде gdi, так как потребовалась либа gdi32.dll чтобы откомпилить

Добавлено через 7 часов 10 минут
Попробовал создать достаточно серьезный пример
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include<stdio.h>
#include<math.h>
#include<conio.h>
#include <gdiplus.h>
#include<Graphics.h>
 
 
#include<time.h>
int printtime(){int tit=clock () / CLOCKS_PER_SEC;printf("\n t=%d",tit);} /// В общем понятно. Мелкая функция для вывода на экран времени после старта программы
 
int drawBMP_xxx(const int x1,const int y1,const int dx,const int dy,const char* name,const int regim,const int zerkalo,const double arg1,const double arg2,const double arg3,const double arg4,const double arg5,const double arg6,const double arg7,const double arg8,const double arg9){
/// Аргументы функции
//// x1,y1 - начало куда рисовать
/// dx dy - желаемый размер картинки
/// regim режим. Есть 0 - ничего особого, 1 - перекраска пикселя по матрице преобразования цветов при помощи getpixel setpixel (работает но с тормозами) и 2 - попытка сделать тоже самое при помощи DBI (Пока абсолютно не работает)
/// zerkalo если ненулевое, то картинка будет "отражена в зеркале"
/// arg1  и далее - матрица перекодирования цвета. Разумеется в таком виде не очень удобно, но интерфейс позже, пока с Ядром проблемы....
wchar_t buffer4[1000];
double cf[3][3]={{arg1,arg2,arg3},{arg4,arg5,arg6},{arg7,arg8,arg9}}; /// Матрица аргументов для преобразования цветов
static HDC htest=txCreateCompatibleDC(1024,768); /// Один раз за программу статически создаем буферный hdc
 
for(int kk=0;kk<1000;kk++){buffer4[kk]=0;}
for(int i=0;i<1000;i++){
 int v=name[i];buffer4[i]=v;if(v==0){break;}
} /// Криво, но думаю надежно преобразуем простое имя файла в формат, который принимает конструктор объекта Gdiplus::Image
 
txBitBlt(htest,0,0,dx,dy,txDC(),x1,y1); //// Копируем ту область экрана, на которой надо нарисовать, в буфер
 
 
 
Gdiplus::Graphics graphics(htest); /// Создаем "рисовалку" gdi+ чтобы она рисовала в буфер
Gdiplus::Image* m_pImage=NULL;
m_pImage=new Gdiplus::Image(buffer4); /// Загружаем из файла картинку в объект gdi+
 
if(zerkalo){m_pImage->RotateFlip(Gdiplus::Rotate180FlipY );}  /// Если задано зеркало - при помощи собственной функции gdi+ отражаем в зеркале
 
 
Gdiplus::Rect rc(0,0,dx,dy); ///Прямоугольник куда рисовать. Рисуем в начало буфера по выбранным размерам
graphics.DrawImage(                m_pImage,                        // [in] Gdiplus::Image object
     rc                                // [in] Position and dimensions
     );  //////// Рисуем загруженную картинку gdi+ в буферный hdc
if(regim==0){} /// В нулевом режиме ничего не делаем, картинка уже какая надо.
 
 
if(regim==1){
 for(int i=0;i<dx;i++){for(int j=0;j<dy;j++){
  COLORREF c_buf=Win32::GetPixel(htest,i,j);
 int r =(BYTE)(c_buf>>0);
int g = (BYTE)(c_buf>>8);
int    b = (BYTE)(c_buf>>16);
Win32::SetPixel(htest,i,j,RGB(cf[0][0]*r+cf[0][1]*g+cf[0][2]*b,cf[1][0]*r+cf[1][1]*g+cf[1][2]*b,cf[2][0]*r+cf[2][1]*g+cf[2][2]*b));
 
/// При помощи примитивной попиксельной работы с GetPixel получаем цвет каждого пикселя, раскодирывем его , преобразуем по матрице и снова рисуем.
 
}}
}
 
 
if(regim==2){
///// Пробуем работать с DIBSextion  ПОКА НЕ РАБОТАЕТ!!!
BITMAPINFO bmi;
 ZeroMemory(&bmi, sizeof(BITMAPINFOHEADER));
 
  bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
  bmi.bmiHeader.biWidth       = dx;
  bmi.bmiHeader.biHeight      = -dy;
  bmi.bmiHeader.biPlanes      = 1;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biBitCount    = 32;
 
  DWORD *bitmapBits;
  HBITMAP bitmap = CreateDIBSection(htest, &bmi, DIB_RGB_COLORS, (void**)&bitmapBits, 0, 0);
Win32::SelectObject(htest, bitmap);
/* Пока ничего не делаем, по идее должна создаваться секция на основе htest и снова рисоваться на htest , то есть внешне ничего не происходить. Но создается секция заполненная нулями!
for (long int i1 = 0; i1<64000l; i1++){
///// bitmapBits[i1] = RGB(140,2,1);
}*/
 
 
SetDIBitsToDevice(htest,0,0,dx,dy,0,0,  0,0,bitmapBits,&bmi,DIB_RGB_COLORS);
 
 
 
}
 
 
txBitBlt(txDC(),x1,y1,dx,dy,htest,0,0); /// выводим выведенную в буфер и обработанную картинку окончательно на экран
delete(m_pImage); /// не мусорим gdi+ объектами, культурно удаляем
}
 
 
 
 
 
 
 
 
 
 
 
 
int main(){
 
int gd,gm;
initgraph(&gd,&gm,""); /// Извратная инициализация полноэкранной графики
 
{
{
Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
ULONG_PTR gdiplusToken; 
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
} //// Инициализация gdi+
 
 
}
 
cleardevice();
 
for(int k=0;k<50;k++){
 
drawBMP_xxx(100,0,676,600,"Tigre039.jpg",1,0, 0,0,0 ,0.5,0.5,0.5, 0.5,0.5,0.5); /// Красим картинку в циан
drawBMP_xxx(800,0,676,600,"Tigre039.jpg",1,1, 0.33,0.33,0.33, 0.33,0.33,0.33, 0.33,0.33,0.33); //// Просто в черно-белый
printf("\n k=%d",k);printtime(); ////Показываем на экране сколько раз уже вывелось и время прошедшее с начала запуска программы
 
/////Выводим картинки много раз циклом для тестирования времени работы
}
 
getch();
 
 
 
}
Если написать именно как в примере - то все задекларированное в main работает как надо, но Большие Тормоза.
Если функциям приписать режим 0 (без обработки) то все летает, но картинки исходного цвета
Если режим 2 - то по идее должны быть исходные картинки, но на практике - черные области....
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
22.01.2013, 18:24 4
Если интересно, в соседней теме только что запустил программу, для получения скриншота рабочего стола при помощи directX. Собственно полученную поверхность можно не сохранять в качестве .bmp файла, а крутить как вам заблагорассудится (примеры есть в посте выше, той же темы)
1
15 / 15 / 1
Регистрация: 31.12.2012
Сообщений: 101
22.01.2013, 19:19  [ТС] 5
Спасибо. Но у меня мой MinGW почему-то не знает библиотеку #include <d3dx9tex.h> (#include <d3d9.h> нормально принял). Что делать?
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
22.01.2013, 19:28 6
Цитата Сообщение от SeaMonster Посмотреть сообщение
Спасибо. Но у меня мой MinGW почему-то не знает библиотеку #include <d3dx9tex.h> (#include <d3d9.h> нормально принял). Что делать?
Хм.... d3dx9tex.h отвечает за работу D3DXSaveSurfaceToFile() т.е. за сохранение поверхности в .bmp файл, если эта функция не нужна - то ее можно выбросить, и библиотеку не юзать (сам использовал только для проверки работоспособности). У меня VS2010, библиотек d3d вообще не было, качал откуда то со стороннего источника (возможно есть даже на сайте майкрософта).
1
15 / 15 / 1
Регистрация: 31.12.2012
Сообщений: 101
22.01.2013, 19:53  [ТС] 7
Хорошо, буду дальше разбираться

Добавлено через 6 минут
Гм. Осталась только одна ошибка Компиляции. Компилятор не знает GetConsoleWindow(); хотя вроде это из элементарной windows.h
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
23.01.2013, 17:39 8
Цитата Сообщение от SeaMonster Посмотреть сообщение
Хорошо, буду дальше разбираться

Добавлено через 6 минут
Гм. Осталась только одна ошибка Компиляции. Компилятор не знает GetConsoleWindow(); хотя вроде это из элементарной windows.h
В принципе прога работает и без GetConsoleWindow(), главное дать CreateDevice переменную типа HWND (насколько я понял, дескриптор окна нужен для вывода графики, а тут ничего выводить не надо, да и в консоль ее не вывести по определению )

Добавлено через 21 час 12 минут
Программа создает скриншот рабочего стола, редактирует его (в данном примере все закрашивается красным цветом) а потом сохраняет его в файл.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9tex.h>
 
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"d3d9.lib")
 
 
int main()
{
    IDirect3D9 *g_pD3D;
    HWND hWnd;
    
    IDirect3DDevice9 *g_pd3dDevice;
    IDirect3DSurface9 *pSurface;
    D3DDISPLAYMODE d3ddm;
    D3DPRESENT_PARAMETERS d3dpp;
    D3DSURFACE_DESC surfaceDesc;
    D3DLOCKED_RECT lockedRect;
 
    hWnd = GetConsoleWindow();
 
    if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) {
     printf("fail 1");
    }
    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
    printf("fail 2");
    }
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
 
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.BackBufferHeight = d3ddm.Height;
    d3dpp.BackBufferWidth = d3ddm.Width;
 
 
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                               D3DDEVTYPE_HAL, hWnd,
                               D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                               &d3dpp, &g_pd3dDevice))) {
    printf("fail 3");
    }
    
    if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(d3ddm.Width, d3ddm.Height,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
    {
        printf("fail 4");
    }
    ///////////////////////////////////////////////////////////////////////////////////////
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
    pSurface->GetDesc(&surfaceDesc);
    pSurface->LockRect(&lockedRect, 0, 0);
 
    DWORD* imageData = (DWORD*)lockedRect.pBits;
 
    for(int i = 0; i < surfaceDesc.Height; i++)
    {
        for(int j = 0; j < surfaceDesc.Width; j++)
        {
        // индекс в текстуре, обратите внимание, что мы используем шаг и
        // делим его на 4, поскольку шаг задается в байтах,
        // а каждый пиксель занимает 4 байта.
            int index = i * lockedRect.Pitch / 4 + j;
            imageData[index] = 0xffff0000; // красный цвет
        }
    }
 
    pSurface->UnlockRect();
    ///////////////////////////////////////////////////////////////////////////////////////
    D3DXSaveSurfaceToFile(L"Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);
    pSurface->Release(); 
 
    return 0;
}
Считается что видеорежим 32 бита (888+альфа)
0
23.01.2013, 17:39
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.01.2013, 17:39
Помогаю со студенческими работами здесь

Работа с пикселями в C#
Здравствуйте. Имеется приложение на C#, которое берет изображение с веб-камеры в PictureBox. На...

Работа с пикселями
Возможно ли работать с пикселями в С++? Сравнение цветов пикселей требуется Добавлено через 2...

Работа с пикселями
Я только осваиваюсь с графикой, но пока ниче не получается...Если Вам не трудно, то помогите с этой...

работа с пикселями
Помогите с кодом. Требуется загрузить любое изображение в формате BMP, далее изображение делится по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru