Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/184: Рейтинг темы: голосов - 184, средняя оценка - 4.79
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696

Вывод изображения WinAPI

11.01.2011, 17:21. Показов 34830. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Нужно сделать что-то типа графического редоктора, который накладывает фильтры на изображения. С алгоритмами я знаком, на C# уже написал приложение(для "посмотреть как оно будет"), но нужно всё сделать на WinAPI. Подскажите, как с помощью WinAPI:
1) получить изображение из файла
2) иметь возможность получить/изменить цвет определенного пикселя
3) отобразить полученное изображение в окне
4) сохранить его в файл
Буду очень признателен за код, если никого не затруднит.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.01.2011, 17:21
Ответы с готовыми решениями:

Вывод изображения в WinAPI
Вот не получается загрузить картинку Делаю по примеру найденому здесь на форуме Но у меня не находит файл #include <windows.h> ...

Вывод изображения из файла в окно (Winapi)
делаю так но выводит белый фон case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hdc = BeginPaint(hWnd,...

Visual Studio 2008, WinAPI - Вывод изображения
Как вывести изображение на форму? В гугле искал, но там что-то ничего того,что я могу понять не нашёл =( Понял только , что...

23
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
12.01.2011, 22:30  [ТС]
Неужели никто не может помочь?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
12.01.2011, 23:34
Лучший ответ Сообщение было отмечено как решение

Решение

body90, выводилка картинки в окошке есть, может пригодится...
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
#include <windows.h>
    
LRESULT CALLBACK PictViewWndProc(HWND, UINT, UINT, LONG);
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow){
    HWND hWnd;
    WNDCLASS WndClass;
    MSG Msg;
    char szClassName[] = "PictView";
    
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = PictViewWndProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance = hInstance;
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    WndClass.lpszMenuName = NULL;
    WndClass.lpszClassName = szClassName;
    
    if ( ! RegisterClass(&WndClass) ){
        MessageBox(NULL, "Can't register class", "Error", MB_OK);
        return 0;
    }
    
    hWnd = CreateWindow(szClassName, "Picture View", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 
        CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
    if ( ! hWnd ){
        MessageBox(NULL, "Can't create window", "Error", MB_OK);
        return 0;
    }
    
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    
    while ( GetMessage(&Msg, NULL, 0, 0) ){
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}
 
LRESULT CALLBACK PictViewWndProc(HWND hWnd, UINT Message, UINT wParam, LONG lParam){
    HDC hDC, hCompatibleDC;
    PAINTSTRUCT PaintStruct;
    HANDLE hBitmap, hOldBitmap;
    RECT Rect;
    BITMAP Bitmap;
    
    switch ( Message ){
    case WM_PAINT :
        hDC = BeginPaint(hWnd, &PaintStruct);
        hBitmap = LoadImage(NULL, "picture.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
        hCompatibleDC = CreateCompatibleDC(hDC);
        hOldBitmap = SelectObject(hCompatibleDC, hBitmap);
        GetClientRect(hWnd, &Rect);
        StretchBlt(hDC, 0, 0, Rect.right, Rect.bottom, hCompatibleDC, 0, 0, Bitmap.bmWidth, 
            Bitmap.bmHeight, SRCCOPY);
        SelectObject(hCompatibleDC, hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hCompatibleDC);
        EndPaint(hWnd, &PaintStruct);
        return 0;
    case WM_DESTROY :
        PostQuitMessage(0);
        return 0;
    }
    
    return DefWindowProc(hWnd, Message, wParam, lParam);
}
picture.bmp должен в одной папке с программой лежать.
8
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
13.01.2011, 14:02  [ТС]
А как получать и задавать цвет точки в изображении?

Добавлено через 13 часов 49 минут
Хоть функции для получения и задания цвета точки в битмапе скажите
0
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
15.01.2011, 05:47  [ТС]
Как связать HBITMAP и GetPixel()/SetPixel?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
15.01.2011, 11:21
body90, на MSDN-ской странице с описанием GetPixel есть ссылки внизу
Bitmaps Overview
Bitmap Functions
там ничего интересного не нашлось?
На сколько я понимаю, hDC - это хендл контекста устройства (того самого, на которое изображение выводится)
Цитата Сообщение от easybudda Посмотреть сообщение
hDC = BeginPaint(hWnd, &PaintStruct);
2
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
15.01.2011, 11:55  [ТС]
Цитата Сообщение от easybudda Посмотреть сообщение
На сколько я понимаю, hDC - это хендл контекста устройства (того самого, на которое изображение выводится)
А как получить HDC изображения (битмапа)
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
15.01.2011, 12:55
Цитата Сообщение от body90 Посмотреть сообщение
А как получить HDC изображения (битмапа)
Не, Вы немного не правильно себе это представляете... Пиксели нужно искать уже не в картинке, а в том объекте, в который Вы её загрузили.
Цитата Сообщение от easybudda Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
case WM_PAINT :
  hDC = BeginPaint(hWnd, &PaintStruct);
  hBitmap = LoadImage(NULL, "picture.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
  hCompatibleDC = CreateCompatibleDC(hDC);
  hOldBitmap = SelectObject(hCompatibleDC, hBitmap);
  GetClientRect(hWnd, &Rect);
  StretchBlt(hDC, 0, 0, Rect.right, Rect.bottom, hCompatibleDC, 0, 0, Bitmap.bmWidth, 
  Bitmap.bmHeight, SRCCOPY);
  SelectObject(hCompatibleDC, hOldBitmap);
  DeleteObject(hBitmap);
  DeleteDC(hCompatibleDC);
  EndPaint(hWnd, &PaintStruct);
  return 0;
Вот этот кусок разберите, станет немного понятнее, что искать нужно...
2
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
15.01.2011, 13:05  [ТС]
Тут понятно. Выводит картинку в окно. Но разве правильно будет применять фильтры к картинке, которая уже нарисована в окне? Тем более как я ее потом сохраню в файл? Получить цвет пикселя из окна или экрана я могу. Но как это сделать для изображения? Не может быть, что только по байтам всё читать. Может как-то с помощью GDI+ можно?
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
15.01.2011, 20:57
body90, а чем GetPixel() не устраивает?
Если все таки не устраивает, то читаем про формат .bmp. Можно просто считывать байты прям из картинки, значение байт - есть цвета картинки в формате RGB. Но там не с первого байта читать надо, в общем почитайте, я на память не помню.

Добавлено через 2 минуты
Нет, там даже не в RGB, сейчас в википедии глянул. Советую, там достаточно информации.
1
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
15.01.2011, 21:01  [ТС]
Цитата Сообщение от Kastaneda Посмотреть сообщение
body90, а чем GetPixel() не устраивает?
Меня вообще больше чем устраивает. Но я не знаю как им воспользоваться. Как работать с помощью GetPixel() с HBITMAP?
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
15.01.2011, 21:09
GetPixel() считывает цвет пикселя в определенных координатах экрана. С HBITMAP его ни как не используешь. Тут смотря для каких целей нужен цвет пикселя, может и GetPixel() подойдет.
Если мне не изменяет память, то прототип выглядет так GetPixel(HDC DC,DWORD X, DWORD Y)

Добавлено через 1 минуту
например
C++
1
2
HDC dc=GetDC(0);
COLORREF clrf=GetPixel(dc,0,0);
получаем цвет пикселя в левом верхнем углу экрана (не зависимо от того, какое окно открыто)
1
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
15.01.2011, 21:18  [ТС]
В том то и проблема, что мне нужно накладывать фильтры на изображение. Я его загружаю, а дальше мне надо получать цвет каждой точки и работать с ним. Совсем не хочется работать с байтами. Тем более на сколько я помню там еще всё зависит от цветовой палитры.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
15.01.2011, 21:24
Цитата Сообщение от body90 Посмотреть сообщение
мне нужно накладывать фильтры на изображение
Тогда наверно напрямую с байтами, GetPixel() тут не очень удобно использовать. С байтами работать не так страшно, как кажется) Нужно просто понять структуру файла, а дальше совсем просто)
1
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
16.01.2011, 00:55  [ТС]
Приложение нужно подстраивать под разные палитры? А как быть со сжатием?

Добавлено через 11 минут
Для начала попробую сделать всё же чтение по байтам для 24-байтного изображения. Можете помочь с кодом: как узнать высоту, ширину и с какого места начинаются байты изображения?

Добавлено через 2 часа 40 минут
Кстати, а с помощью GDI+ никак нельзя получать цвет пикселей?
0
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
16.01.2011, 19:59  [ТС]
Вот попытался загрузить изображение с помощью GDI+ и нарисовать его. Подскажите, почему ничего не рисуется? Что я пропустил?
Вложения
Тип файла: rar GDI.rar (848.5 Кб, 56 просмотров)
0
 Аватар для body90
467 / 344 / 19
Регистрация: 26.05.2009
Сообщений: 2,696
20.01.2011, 20:51  [ТС]
Неужели всем так тяжело посмотреть и сказать в чем проблема?

Добавлено через 17 часов 2 минуты
Всё, нашел в чем проблема: не инициализировал GDI+. Спасибо всем, кто не ответил!
0
230 / 0 / 1
Регистрация: 15.06.2011
Сообщений: 4
15.06.2011, 18:42
Лучший ответ Сообщение было отмечено как решение

Решение

Не стану создавать новую тему.
В примере из третьего поста в обработчике WM_PAINT каждый раз создается битмап и загружается из файла picture.bmp.
А вот тут утверждается, что выбранный объект надо удалять после использования.
Зачем это нужно? Не будет ли правильнее создать битмап и хендл глобальными переменными, загрузить изображение в winmain и удалить их в обработчике закрытия окна, например?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
15.06.2011, 23:19
Цитата Сообщение от lavrentiy Посмотреть сообщение
Не будет ли правильнее создать битмап и хендл глобальными переменными, загрузить изображение в winmain и удалить их в обработчике закрытия окна, например?
Да может так и лучше... Пример из книжки по winapi, наверняка многое "за уши притянуто"...
3
 Аватар для xAtom
935 / 760 / 299
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
16.06.2011, 15:34
Лучший ответ Сообщение было отмечено как решение

Решение

Вот такой вариант работы с файлом BMP. Покажу не большой пример как быстро получить доступ к массиву пикселов без обращения медленной функции режима ядра SetPixel/SetPixelV - но с ними тоже интересно поработать но медленно, при получение массива пикселей возможно быстро организовать разнообразные фильтры, сглаживания Гауссого, Лапласа, резкости и т.п.

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
// Глобальные объекты
HBITMAP    bit     = NULL;
HDC          dc      = NULL;
BYTE*       buffer = NULL;
DWORD     bsize   = 0U;
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
 
    switch (message) {
    case WM_DESTROY: {  // Событие возникает при уничтожение окна
 
        if(buffer)
             delete[] buffer;
        buffer = NULL;
        DeleteObject(bit);
        DeleteDC(dc);
        PostQuitMessage(0);
    } break;
    case WM_CREATE: {  // создание совместимого контекста и объект битмап из файла
 
bit = (HBITMAP) ::LoadImage((HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE),  "X:\\atom.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    BITMAP b;
           ZeroMemory(&b, sizeof(BITMAP));
    GetObject(bit, sizeof(BITMAP), (LPVOID)&b);
    bsize = b.bmWidth * b.bmHeight * b.bmBitsPixel;
           buffer = new  BYTE[ bsize ];
           dc = ::CreateCompatibleDC( GetDC(hWnd) );
 
if(! bit)
    MessageBox(hWnd, "Ошибка при загрузки файла !!!", "BITMAP ERROR", MB_OK | MB_ICONERROR);
 
} break;
case WM_PAINT: {   // Рисование в окне
 
    BeginPaint(hWnd, &ps);
 
    if(bit) {
          BITMAP b;
          ZeroMemory(&b, sizeof(BITMAP));
          GetObject(bit, sizeof(BITMAP), (LPVOID)&b);
          SelectObject(dc, bit);
          BitBlt(ps.hdc, 0, 0, b.bmWidth, b.bmHeight,  dc, 0, 0, SRCCOPY);
    }
 
    EndPaint(hWnd, &ps);
 
    } break;
case WM_LBUTTONDOWN: {  // при щёлкание левой кнокпи мыши изображение будет светлеть
                 
     if(buffer) {
        GetBitmapBits(bit, bsize, (LPVOID) buffer);
        for(DWORD  i = 0; i < bsize; i++) 
             *((buffer) + i) = min( *((buffer) + i) + 10, 255);
                            
        SetBitmapBits(bit, bsize, (CONST VOID*) buffer);
        RECT  rect;
        GetClientRect(hWnd, &rect);
        InvalidateRect(hWnd, &rect, FALSE);
    }
                            
} break;
case WM_RBUTTONDOWN: {  // при щёлкание правой кнопки мыши изображение будет темнеть
 
         if(buffer) {
    GetBitmapBits(bit, bsize, (LPVOID) buffer);
 
    for(DWORD  i = 0; i < bsize; i++) 
          *((buffer) + i) = max( *((buffer) + i) - 10, 55);
                            
    SetBitmapBits(bit, bsize, (CONST VOID*) buffer);
    RECT  rect;
    GetClientRect(hWnd, &rect);
    InvalidateRect(hWnd, &rect, FALSE);
       }
} break;
case WM_KEYDOWN: {  // Нажмите на любую клавишу, изображение станет чёрно-белым 
         //  чёрно белое изображение
       // Медленный доступ к пикселам, обусловлен переключение в режим ядра gdi
      BITMAP b;
      ZeroMemory(&b, sizeof(BITMAP));
      GetObject(bit, sizeof(BITMAP), (LPVOID)&b);
     for(DWORD x = 0U; x < b.bmWidth; x++) {
    for(DWORD  y = 0U; y < b.bmHeight; y++) {
        COLORREF  color = GetPixel(dc, x, y);
        color = RGB( color, color, color);   
        SetPixelV(dc, x, y, color);
    }
    }         
    RECT  rect;
    GetClientRect(hWnd, &rect);
    InvalidateRect(hWnd, &rect, FALSE);
 } break;
 default:
    return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.06.2011, 15:34
Помогаю со студенческими работами здесь

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

Поворот bmp изображения на 90 градусов winapi
8) Написать программу, которая читает с диска *.bmp файл и выводит его в окно приложения. При помощи потока организовать поворот...

Вывод изображения поверх другого изображения
Привет, как правильнее сделать такую манипуляцию нужно на картинке вывести справа вверху КРАСНЫЙ КРУГ как на изображении которое...

Сохранение изображения jpg/png в базу данных средствами С++ и WinAPI с последующим извлечением оного из БД
Можно ли с использованием C++ на winApi сохранить изображение (png,jpeg) в какую нибудь переменную , потом сохранить все это в MysQL , а...

Вывод изображения с БД и размер изображения
&lt;div id=&quot;block-3&quot; &lt;?php $query = mysql_query(&quot;SELECT * FROM table_photos&quot; ,$link); $array = mysql_fetch_array($query); do { ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru