Skip to content

Instantly share code, notes, and snippets.

@gununu
Created July 12, 2010 15:32
Show Gist options
  • Save gununu/472593 to your computer and use it in GitHub Desktop.
Save gununu/472593 to your computer and use it in GitHub Desktop.
boost::gil preview library for windows
/*
Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef GUNUNU_GIL_PREVIEW_HPP
#define GUNUNU_GIL_PREVIEW_HPP
#include <windows.h>
#pragma comment(lib, "user32")
#pragma comment(lib, "gdi32")
#include <memory>
#include <boost/gil/gil_all.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
class gilpreview {
public:
gilpreview(): hwnd_(NULL), updated(false) {
thr.reset(new boost::thread(boost::bind(&gilpreview::run, this)));
}
~gilpreview(){
thr->join();
}
template <typename View>
void operator << (const View& v) {
boost::gil::bgr8_image_t tmp;
tmp.recreate(v.dimensions(), 4);
boost::gil::copy_and_convert_pixels(v, view(tmp));
{ boost::mutex::scoped_lock lock(mtx);
img.swap(tmp);
updated = false;
}
refresh();
}
private:
static LPCTSTR classname() { return _T("gilprev c"); }
static LPCTSTR propname() { return _T("gilprev p"); }
static LPCTSTR title() { return _T("gil preview"); }
void run() {
WNDCLASSEX wc = {sizeof(WNDCLASSEX)};
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = classname();
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
wc.lpfnWndProc = &gilpreview::WindowProc;
RegisterClassEx(&wc);
HWND hwnd = CreateWindow(classname(), title(), WS_VISIBLE|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,50,50, NULL, NULL, 0, 0);
{ boost::mutex::scoped_lock lock(mtx);
hwnd_ = hwnd;
}
SetProp(hwnd, propname(), (HANDLE)this);
refresh();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_PAINT: {
RECT rc = {};
GetWindowRect(hwnd, &rc);
gilpreview* p = (gilpreview*)GetProp(hwnd, propname());
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
int w,h;
{ boost::mutex::scoped_lock lock(p->mtx);
w = p->img.width();
h = p->img.height();
BITMAPINFO info = {sizeof(BITMAPINFOHEADER)};
info.bmiHeader.biWidth = w;
info.bmiHeader.biHeight = -h;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 24;
info.bmiHeader.biCompression = BI_RGB;
SetDIBitsToDevice(hdc, 0,0,w,h, 0,0, 0, h,
(void*)boost::gil::interleaved_view_get_raw_data(view(p->img)), &info, DIB_RGB_COLORS);
}
if (w < rc.right) {
RECT r = {};
r.left = rc.right;
r.right = w;
r.bottom = h;
FillRect(hdc, &r, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
}
if (h < rc.bottom) {
RECT b = {};
b.top = h;
b.bottom = rc.bottom;
b.right = rc.right;
FillRect(hdc, &b, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
}
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
RemoveProp(hwnd, propname());
PostQuitMessage(0);
break;
case WM_ERASEBKGND: break;
default: return DefWindowProc(hwnd, uMsg, wParam, lParam);
};
return 0;
}
void refresh() {
boost::gil::bgr8_image_t::point_t dim;
HWND hwnd;
{ boost::mutex::scoped_lock lock(mtx);
dim = img.dimensions();
hwnd = hwnd_;
if (!hwnd || updated)
return;
updated = true;
}
if (!IsZoomed(hwnd)) {
RECT rc = {};
rc.right = dim.x;
rc.bottom = dim.y;
WINDOWINFO wi;
GetWindowInfo(hwnd, &wi);
AdjustWindowRect(&rc, wi.dwStyle, FALSE);
POINT pt = {};
ClientToScreen(hwnd, &pt);
rc.left += pt.x;
rc.right += pt.x;
rc.top += pt.y;
rc.bottom += pt.y;
MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
}
InvalidateRect(hwnd, NULL, FALSE);
}
private:
HWND hwnd_;
bool updated;
boost::gil::bgr8_image_t img;
std::auto_ptr<boost::thread> thr;
boost::mutex mtx;
};
#endif GUNUNU_GIL_PREVIEW_HPP
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/io/jpeg_io.hpp>
#include "gilpreview.hpp"
int main()
{
boost::gil::rgb8_image_t img;
boost::gil::jpeg_read_image("image.jpg", img);
gilpreview pv;
pv << view(img); //display image
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment