s464967_przetwarzanie_obraz.../examples/example_win32_directx11/main.cpp

963 lines
31 KiB
C++

// Dear ImGui: standalone example application for DirectX 11
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#include "imgui.h"
#include "imgui_impl_win32.h"
#include "imgui_impl_dx11.h"
#include <d3d11.h>
#include <tchar.h>
#include "implot.h"
#include <array>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
struct Pixel {
int x;
int y;
float value;
Pixel(int x, int y, float value) : x(x), y(y), value(value) {}
};
static ID3D11Device* g_pd3dDevice = nullptr;
static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
static IDXGISwapChain* g_pSwapChain = nullptr;
static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
unsigned char* ImageData(const char* filename, int &width, int &height, int &channels)
{
unsigned char* image_data = stbi_load(filename, &width, &height, &channels, 4);
return image_data;
}
bool LoadTextureFromFile(unsigned char* image_data, int image_width, int image_height, ID3D11ShaderResourceView** out_srv)
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = image_width;
desc.Height = image_height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
ID3D11Texture2D *pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = image_data;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, out_srv);
pTexture->Release();
return true;
}
#undef max;
#undef min;
#include <algorithm>
#include <iostream>
#include <cmath>
#include <vector>
#include <queue>
//void watershedSegmentation(unsigned char* image, int width, int height) {
// const float INFINITY = std::numeric_limits<float>::max();
//
// int* labels = new int[width * height];
// for (int i = 0; i < width * height; ++i) {
// labels[i] = -1;
// }
//
// float* copy = new float[width * height];
// for (int i = 0; i < width * height; ++i) {
// copy[i] = static_cast<float>(image[i]);
// }
//
// std::priority_queue<Pixel, std::vector<Pixel>, [](const Pixel& p1, const Pixel& p2) {
// return p1.value < p2.value;
// }> queue;
//
// for (int i = 0; i < width * height; ++i) {
// queue.push(Pixel(i % width, i / width, copy[i]));
// }
//
// while (!queue.empty()) {
// Pixel pixel = queue.top();
// queue.pop();
//
// int x = pixel.x;
// int y = pixel.y;
// int index = y * width + x;
//
// for (int i = -1; i <= 1; ++i) {
// for (int j = -1; j <= 1; ++j) {
// int nx = x + i;
// int ny = y + j;
// int nIndex = ny * width + nx;
//
// if (nx >= 0 && nx < width && ny >= 0 && ny < height && labels[nIndex] != -1) {
// if (labels[index] == -1) {
// labels[index] = labels[nIndex];
// } else if (labels[index] != labels[nIndex]) {
// labels[index] = -2;
// }
// }
// }
// }
//
// if (labels[index] == -1) {
// labels[index] = index;
//
// copy[index] = INFINITY;
//
// for (int i = -1; i <= 1; ++i) {
// for (int j = -1; j <= 1; ++j) {
// int nx = x + i;
// int ny = y + j;
// int nIndex = ny * width + nx;
//
// if (nx >= 0 && nx < width && ny >= 0 && ny < height && labels[nIndex] == -1) {
// queue.push(Pixel(nx, ny, copy[nIndex]));
// }
// }
// }
// }
// }
//
// for (int i = 0; i < width * height; ++i) {
// if (labels[i] == -2) {
// image[i] = static_cast<unsigned char>(INFINITY);
// }
// }
//
// delete[] labels;
// delete[] copy;
//}
//
void dilation(unsigned char* image, int width, int height) {
int structuringElement[3][3] = {
{0, 255, 0},
{255, 255, 255},
{0, 255, 0}
};
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int maxPixelValue = 0;
for (int j = -1; j <= 1; ++j) {
for (int i = -1; i <= 1; ++i) {
if (x + i >= 0 && x + i < width && y + j >= 0 && y + j < height) {
int imagePixelValue = image[(y + j) * width + (x + i)];
int structuringElementValue = structuringElement[j + 1][i + 1];
int newPixelValue = imagePixelValue + structuringElementValue;
if (newPixelValue > maxPixelValue) {
maxPixelValue = newPixelValue;
}
}
}
}
image[y * width + x] = static_cast<unsigned char>(maxPixelValue > 255 ? 255 : maxPixelValue);
}
}
}
void erosion(unsigned char* image, int width, int height) {
int structuringElement[3][3] = {
{0, 255, 0},
{255, 255, 255},
{0, 255, 0}
};
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
int minPixelValue = 255;
for (int j = -1; j <= 1; ++j) {
for (int i = -1; i <= 1; ++i) {
if (x + i >= 0 && x + i < width && y + j >= 0 && y + j < height) {
int imagePixelValue = image[(y + j) * width + (x + i)];
int structuringElementValue = structuringElement[j + 1][i + 1];
int newPixelValue = imagePixelValue - structuringElementValue;
if (newPixelValue < minPixelValue) {
minPixelValue = newPixelValue;
}
}
}
}
image[y * width + x] = static_cast<unsigned char>(minPixelValue < 0 ? 0 : minPixelValue);
}
}
}
void hitAndMiss(unsigned char* image, int width, int height) {
int structuringElement1[3][3] = {
{0, 0, 0},
{255, 255, 0},
{0, 255, 0}
};
int structuringElement2[3][3] = {
{255, 255, 255},
{0, 0, 255},
{0, 0, 0}
};
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
bool match1 = true;
bool match2 = true;
for (int j = -1; j <= 1; ++j) {
for (int i = -1; i <= 1; ++i) {
if (x + i >= 0 && x + i < width && y + j >= 0 && y + j < height) {
int imagePixelValue = image[(y + j) * width + (x + i)];
int structuringElement1Value = structuringElement1[j + 1][i + 1];
int structuringElement2Value = structuringElement2[j + 1][i + 1];
if (structuringElement1Value == 255 && imagePixelValue != 255) {
match1 = false;
}
if (structuringElement2Value == 255 && imagePixelValue != 0) {
match2 = false;
}
}
}
}
image[y * width + x] = (match1 && match2) ? 255 : 0;
}
}
}
void thickening(unsigned char* image, int width, int height) {
int structuringElement[3][3] = {
{0, 255, 0},
{255, 255, 255},
{0, 255, 0}
};
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (image[y * width + x] == 255) {
for (int j = -1; j <= 1; ++j) {
for (int i = -1; i <= 1; ++i) {
if (x + i >= 0 && x + i < width && y + j >= 0 && y + j < height) {
int structuringElementValue = structuringElement[j + 1][i + 1];
if (structuringElementValue == 255) {
image[(y + j) * width + (x + i)] = 255;
}
}
}
}
}
}
}
}
void thinning(unsigned char* image, int width, int height) {
int structuringElement[3][3] = {
{0, 255, 0},
{255, 255, 255},
{0, 255, 0}
};
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (image[y * width + x] == 255) {
bool match = true;
for (int j = -1; j <= 1; ++j) {
for (int i = -1; i <= 1; ++i) {
if (x + i >= 0 && x + i < width && y + j >= 0 && y + j < height) {
int imagePixelValue = image[(y + j) * width + (x + i)];
int structuringElementValue = structuringElement[j + 1][i + 1];
if (structuringElementValue == 255 && imagePixelValue != 255) {
match = false;
break;
}
}
}
if (!match) {
break;
}
}
image[y * width + x] = match ? 255 : 0;
}
}
}
}
void rgbToHsl(float r, float g, float b, float &_h, float &_s, float &_l)
{
r /= 255.f;
g /= 255.f;
b /= 255.f;
float max = std::max({r, g, b});
float min = std::min({r, g, b});
float h, s, l = (max + min) / 2.f;
if(max - min < .001f)
{
h = s = 0.f;
}
else
{
float d = max - min;
s = l > 0.5f ? d / (2.f - max - min) : d / (max + min);
if (max - r < .001f)
{
h = (g - b) / d + (g < b ? 6.f : 0.f);
}
else if (max - g < .001f)
{
h = (b - r) / d + 2.f;
}
else if (max - b < .001f)
{
h = (r - g) / d + 4.f;
}
h /= 6;
}
_h = h;
_s = s;
_l = l;
}
void hslToRgb(float h, float s, float l, int &_r, int &_g, int &_b){
float r, g, b = 0.f;
if(s < .001f)
{
r = g = b = l;
}
else
{
auto hue2rgb = [](float p, float q, float t) {
if (t < 0) t += 1.f;
if (t > 1) t -= 1.f;
if (t < 1.f / 6.f) return p + (q - p) * 6.f * t;
if (t < 1.f / 2.f) return q;
if (t < 2.f / 3.f) return p + (q - p) * (2.f / 3.f - t) * 6.f;
return p;
};
float q = l < 0.5f ? l * (1.f + s) : l + s - l * s;
float p = 2.f * l - q;
r = hue2rgb(p, q, h + 1.f/3.f);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1.f/3.f);
}
_r = std::clamp(int(r * 255), 0, 255);
_g = std::clamp(int(g * 255), 0, 255);
_b = std::clamp(int(b * 255), 0, 255);
}
void InvertImageColors(unsigned char* imageData, int width, int height)
{
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int index = (y * width + x) * 4;
imageData[index] = 255 - imageData[index];
imageData[index + 1] = 255 - imageData[index + 1];
imageData[index + 2] = 255 - imageData[index + 2];
}
}
}
void Sepia(unsigned char* imageData, int width, int height)
{
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int index = (y * width + x) * 4;
imageData[index] = int(std::min((imageData[index] * .393f) + (imageData[index + 1] * .769f) + (imageData[index + 2] * .189f), 255.f));
imageData[index + 1] = int(std::min((imageData[index] * .349f) + (imageData[index + 1] * .686f) + (imageData[index + 2] * .168f), 255.f));
imageData[index + 2] = int(std::min((imageData[index] * .272f) + (imageData[index + 1] * .534f) + (imageData[index + 2] * .131f), 255.f));
}
}
}
void Saturation(unsigned char* imageData, int width, int height, float scale)
{
float h, s, l = 0.f;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int index = (y * width + x) * 4;
int r = imageData[index];
int b = imageData[index + 1];
int g = imageData[index + 2];
rgbToHsl(r, g, b, h, s, l);
s *= scale;
hslToRgb(h, s, l, r, g, b);
imageData[index] = r;
imageData[index + 1] = g;
imageData[index + 2] = b;
}
}
}
void Light(unsigned char* imageData, int width, int height, float scale)
{
float h, s, l = 0.f;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int index = (y * width + x) * 4;
int r = imageData[index];
int b = imageData[index + 1];
int g = imageData[index + 2];
rgbToHsl(r, g, b, h, s, l);
l *= scale;
hslToRgb(h, s, l, r, g, b);
imageData[index] = r;
imageData[index + 1] = g;
imageData[index + 2] = b;
}
}
}
std::array<std::array<float, 7>, 7> KernelFunction(float sigma)
{
const int kernel_size = 7;
std::array<std::array<float, 7>, 7> kernel;
float sum = 0.0f;
for (int i = 0; i < kernel_size; i++) {
for (int j = 0; j < kernel_size; j++) {
int x = i - kernel_size / 2;
int y = j - kernel_size / 2;
kernel[i][j] = exp(-(x * x + y * y) / (2 * sigma * sigma));
sum += kernel[i][j];
}
}
for (int i = 0; i < kernel_size; i++) {
for (int j = 0; j < kernel_size; j++) {
kernel[i][j] /= sum;
}
}
return kernel;
}
void GaussianKernel(unsigned char* imageData, int width, int height, int channels, int kernel_size, std::array<std::array<float, 7>, 7> kernel)
{
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int c = 0; c < channels; c++) {
float sum = 0.0f;
for (int i = 0; i < kernel_size; i++) {
for (int j = 0; j < kernel_size; j++) {
int px = x + i - kernel_size / 2;
int py = y + j - kernel_size / 2;
if (px < 0 || px >= width || py < 0 || py >= height) {
continue;
}
sum += kernel[i][j] * imageData[(py * width + px) * channels + c];
}
}
imageData[(y * width + x) * channels + c] = (unsigned char)sum;
}
}
}
}
unsigned char* greyScale(const unsigned char* image, unsigned char* grayscaleImage, int width, int height, int numChannels) {
for (int i = 0; i < width * height; ++i) {
unsigned char r = image[i * numChannels];
unsigned char g = image[i * numChannels + 1];
unsigned char b = image[i * numChannels + 2];
grayscaleImage[i] = static_cast<unsigned char>(0.2989 * r + 0.587 * g + 0.114 * b);
}
return grayscaleImage;
}
void binaryTransform(unsigned char* grayscaleImage, unsigned char* binaryImage, int width, int height, int threshold) {
for (int i = 0; i < width * height; ++i) {
binaryImage[i] = (grayscaleImage[i] > threshold) ? 255 : 0;
}
}
//void binaryTransform(const unsigned char* image, unsigned char* binaryImage, int threshold, int width, int height, int channels)
//{
// for (int i = 0; i < width * height; i++) {
// unsigned char brightness = 0.2126f * image[i * channels] + 0.7152f * image[i * channels + 1] + 0.0722f * image[i * channels + 2];
//
// if (brightness < threshold) {
// binaryImage[i] = 0;
// }
// else {
// binaryImage[i] = 255;
// }
// }
//}
int calculateOtsuThreshold(const unsigned char* image, int width, int height) {
int histogram[256] = {0};
for (int i = 0; i < width * height; ++i) {
histogram[image[i]]++;
}
int totalPixels = width * height;
float sum = 0.0;
for (int i = 0; i < 256; ++i) {
sum += i * histogram[i];
}
float sumB = 0.0;
int wB = 0;
int wF = 0;
float maxVariance = 0.0;
int threshold = 0;
for (int i = 0; i < 256; ++i) {
wB += histogram[i];
if (wB == 0) continue;
wF = totalPixels - wB;
if (wF == 0) break;
sumB += i * histogram[i];
float meanB = sumB / wB;
float meanF = (sum - sumB) / wF;
float betweenVariance = wB * wF * (meanB - meanF) * (meanB - meanF);
if (betweenVariance > maxVariance) {
maxVariance = betweenVariance;
threshold = i;
}
}
return threshold;
}
void hough_transform(const unsigned char* input_image, int width, int height, int threshold, unsigned char* hough_image, int channel)
{
int hough_width = 2 * (width + height);
int hough_height = 180;
int* hough_space = new int[hough_width * hough_height];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (input_image[(y * width + x)] > threshold)
{
for (int theta = 0; theta < hough_height; theta++)
{
double angle = theta * (3.14 / 180.0);
int rho = static_cast<int>((x * cos(angle)) + (y * sin(angle)));
rho += (hough_width / 2);
hough_space[(theta * hough_width) + rho]++;
}
}
}
}
int max_value = 0;
for (int i = 0; i < hough_width * hough_height; i++)
{
if (hough_space[i] > max_value)
{
max_value = hough_space[i];
}
}
hough_image = new unsigned char[hough_width * hough_height * channel];
for (int y = 0; y < hough_height; y++)
{
for (int x = 0; x < hough_width; x++)
{
int value = static_cast<int>(255.0 * hough_space[(y * hough_width) + x] / max_value);
hough_image[3 * (y * hough_width + x)] = value;
hough_image[3 * (y * hough_width + x) + 1] = value;
hough_image[3 * (y * hough_width + x) + 2] = value;
}
}
delete[] hough_space;
}
int main(int, char**)
{
WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
::RegisterClassExW(&wc);
HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX11 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 1;
}
::ShowWindow(hwnd, SW_SHOWDEFAULT);
::UpdateWindow(hwnd);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImPlot::CreateContext();
//ImPlot::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
ImGui::StyleColorsDark();
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
bool main_window = true;
bool show_another_window = false;
bool image_window = false;
bool histogram = false;
char image_location[MAX_PATH] = {};
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
bool negative = false;
bool sepia = false;
bool saturation = false;
bool blure = false;
float scaleS = 0.f;
bool light = false;
float scaleL = 0.f;
float sigma = 2.0f;
bool binary = false;
bool hough = false;
bool thining = false;
bool thick = false;
bool hitmiss = false;
bool erosi = false;
bool dil = false;
bool done = false;
int* colorR = nullptr;
int* colorG = nullptr;
int* colorB = nullptr;
static float sliderValue = 0.5f;
float xMin = 0;
float xMax = 256 * sliderValue;
while (!done)
{
MSG msg;
while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
if (msg.message == WM_QUIT)
done = true;
}
if (done)
break;
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
if (main_window)
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("App");
ImGui::InputText("Image location", image_location, sizeof(image_location), image_window ? ImGuiInputTextFlags_ReadOnly : 0);
if (!image_window)
{
if (ImGui::Button("Load Image"))
image_window = true;
}
else
{
if (ImGui::Button("Close Image"))
image_window = false;
if (colorR != NULL && colorB != NULL && colorG != NULL)
{
delete[] colorR;
delete[] colorG;
delete[] colorB;
colorR = NULL;
colorG = NULL;
colorB = NULL;
}
}
ImGui::End();
}
if (image_window)
{
int my_image_width = 0;
int my_image_height = 0;
int my_image_channels = 0;
unsigned char* image_data = ImageData(image_location, my_image_width, my_image_height, my_image_channels);
unsigned char* grayscaleImage = new unsigned char[my_image_width * my_image_height * my_image_channels];
unsigned char* binaryImage = new unsigned char[my_image_width * my_image_height * my_image_channels];
unsigned char* hough_image = nullptr;
if (colorR == NULL && colorB == NULL && colorG == NULL) {
colorR = new int[256];
colorG = new int[256];
colorB = new int[256];
int place = 0;
for (int i = 0; i < my_image_width * my_image_height * my_image_channels; i += my_image_channels) {
colorR[image_data[i]]++;
colorG[image_data[i + 1]]++;
colorB[image_data[i + 2]]++;
}
}
if (negative)
{
InvertImageColors(image_data, my_image_width, my_image_height);
}
if (sepia)
{
Sepia(image_data, my_image_width, my_image_height);
}
if (saturation)
{
Saturation(image_data, my_image_width, my_image_height, scaleS);
}
if (light)
{
Light(image_data, my_image_width, my_image_height, scaleL);
}
if (blure)
{
GaussianKernel(image_data, my_image_width, my_image_height, my_image_channels, 7, KernelFunction(sigma));
}
if (binary)
{
binaryTransform(greyScale(image_data, grayscaleImage, my_image_width, my_image_height, my_image_channels), binaryImage, my_image_width, my_image_height, calculateOtsuThreshold(image_data, my_image_width, my_image_height));
}
if (hough)
{
hough_transform(image_data, my_image_width, my_image_height, 125, hough_image, my_image_channels);
}
if (thining)
{
thinning(image_data, my_image_width, my_image_height);
}
if (thick)
{
thickening(image_data, my_image_width, my_image_height);
}
if (hitmiss)
{
hitAndMiss(image_data, my_image_width, my_image_height);
}
if (erosi)
{
erosion(image_data, my_image_width, my_image_height);
}
if (dil)
{
dilation(image_data, my_image_width, my_image_height);
}
if (histogram)
{
ImGui::Begin("Histogram");
float xMin = 0;
float xMax = 256 * sliderValue;
/*ImPlot::SetNextPlotLimitsX(xMin, xMax, ImGuiCond_Always);*/
if (ImPlot::BeginPlot("RGB Histogram")) {
ImPlot::PlotHistogram("Red", colorR, 256);
ImPlot::PlotHistogram("Green", colorG, 256);
ImPlot::PlotHistogram("Blue", colorB, 256);
ImPlot::EndPlot();
}
ImGui::SliderFloat("X-axis Range", &sliderValue, 0.0f, 1.0f);
ImGui::End();
}
if (!image_data)
{
ImGui::Begin("Error");
ImGui::Text("Wrong path");
if (ImGui::Button("Ok"))
image_window = false;
ImGui::End();
}
else
{
ID3D11ShaderResourceView* my_texture = NULL;
if (binary == TRUE) {
bool ret = LoadTextureFromFile(binaryImage, my_image_width, my_image_height, &my_texture);
delete[] binaryImage;
delete[] grayscaleImage;
stbi_image_free(image_data);
}
else if (hough == TRUE) {
bool ret = LoadTextureFromFile(hough_image, my_image_width, my_image_height, &my_texture);
delete[] hough_image;
stbi_image_free(image_data);
}
else {
bool ret = LoadTextureFromFile(image_data, my_image_width, my_image_height, &my_texture);
stbi_image_free(image_data);
}
ImGui::Begin("Image window");
ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
ImGui::End();
ImGui::Begin("Histograms");
ImGui::Checkbox("RGB", &histogram);
ImGui::End();
ImGui::Begin("Operatory");
ImGui::Checkbox("Dylacja", &dil);
ImGui::Checkbox("Erozja", &erosi);
ImGui::Checkbox("Hit and Miss", &hitmiss);
ImGui::Checkbox("Pogrubianie", &thick);
ImGui::Checkbox("Thining", &thining);
ImGui::End();
ImGui::Begin("Filters");
ImGui::Checkbox("Negative", &negative);
ImGui::Checkbox("Sepia", &sepia);
ImGui::Checkbox("Saturation", &saturation);
ImGui::SameLine();
ImGui::SliderFloat(" ", &scaleS, 0.f, 1.f);
ImGui::Checkbox("Light", &light);
ImGui::SameLine();
ImGui::SliderFloat(" ", &scaleL, 0.f, 1.f);
ImGui::Checkbox("Blure", &blure);
ImGui::SameLine();
ImGui::SliderFloat(" ", &sigma, 0.f, 10.f);
ImGui::Checkbox("Binaryzacja", &binary);
ImGui::Checkbox("Hough transform", &hough);
ImGui::End();
}
}
ImGui::Render();
const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
g_pSwapChain->Present(1, 0);
}
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImPlot::DestroyContext();
ImGui::DestroyContext();
CleanupDeviceD3D();
::DestroyWindow(hwnd);
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 0;
}
bool CreateDeviceD3D(HWND hWnd)
{
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res == DXGI_ERROR_UNSUPPORTED)
res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res != S_OK)
return false;
CreateRenderTarget();
return true;
}
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
}
void CreateRenderTarget()
{
ID3D11Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
pBackBuffer->Release();
}
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
}
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != nullptr && wParam != SIZE_MINIMIZED)
{
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU)
return 0;
break;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}