diff --git a/CMakeLists.txt b/CMakeLists.txt index bce3a1b..8254d52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,10 +14,12 @@ message(STATUS "----- GTK2_LINK_LIBRARIES: ${GTK2_LINK_LIBRARIES}") include_directories(${GTK2_INCLUDE_DIRS}) link_directories(${GTK2_LIBRARY_DIRS}) list(APPEND FC_DEP_LIBS ${GTK2_LIBRARIES}) +list(APPEND FC_DEP_LIBS freeimage) set(commom_src Rgba.cc Raster.cc + Image.cc ) add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 564adb8..c1cd2e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,6 @@ +add_executable(draw_image draw_image.cc ${commom_src}) +target_link_libraries (draw_image ${FC_DEP_LIBS}) + add_executable(draw_triangle draw_triangle.cc ${commom_src}) target_link_libraries (draw_triangle ${FC_DEP_LIBS}) diff --git a/src/Image.cc b/src/Image.cc new file mode 100644 index 0000000..5ac0adf --- /dev/null +++ b/src/Image.cc @@ -0,0 +1,37 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: Image.cc + * Author: Blobt + * + * Created on February 10, 2020, 5:55 PM + */ + +#include "Image.h" +#include + +Image::Image(int width, int height, void* data) { + if (width == 0 || height == 0 || data == 0) { + _width = 0; + _height = 0; + _pixel = 0; + } else { + _width = width; + _height = height; + _pixel = new unsigned int[width * height]; + memcpy(_pixel, data, width * height * sizeof (unsigned int)); + } +} + +Image::~Image() { + delete [] _pixel; +} + +Rgba Image::pixelAt(int x, int y) const { + return Rgba(_pixel[y * _width + x]); +} + diff --git a/src/Image.h b/src/Image.h new file mode 100644 index 0000000..86adb6a --- /dev/null +++ b/src/Image.h @@ -0,0 +1,77 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: Image.h + * Author: Blobt + * + * Created on February 10, 2020, 5:55 PM + */ + +#ifndef IMAGE_H +#define IMAGE_H +#include "Rgba.h" +#include "FreeImage.h" +#include "stdio.h" + +class Image { +public: + Image(int width, int height, void* data); + virtual ~Image(); + + int width() const { + return _width; + } + + int height() const { + return _height; + } + + Rgba pixelAt(int x, int y) const; + + static Image* loadFromFile(const char* fileName) { + + //检查文件类型 + FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0); + if (fifmt == FIF_UNKNOWN) { + return 0; + } + + + //获取 + FIBITMAP* dib = FreeImage_Load(fifmt, fileName, 0); + + //转换 + FIBITMAP* temp = dib; + dib = FreeImage_ConvertTo32Bits(dib); + FreeImage_Unload(temp); + + + BYTE* pixels = (BYTE*) FreeImage_GetBits(dib); + int width = FreeImage_GetWidth(dib); + int height = FreeImage_GetHeight(dib); + + //颜色为数调换 + for (int i = 0; i < width * height * 4; i += 4) { + BYTE temp = pixels[i]; + pixels[i] = pixels[i + 2]; + pixels[i + 2] = temp; + } + + + Image* image = new Image(width, height, (void*) pixels); + FreeImage_Unload(dib); + + return image; + + } +private: + int _width; + int _height; + unsigned int* _pixel; +}; +#endif /* IMAGE_H */ + diff --git a/src/Raster.cc b/src/Raster.cc index e35c11f..200bd49 100644 --- a/src/Raster.cc +++ b/src/Raster.cc @@ -13,6 +13,7 @@ #include "Rgba.h" #include "Raster.h" +#include "Image.h" #include #include #include @@ -35,11 +36,13 @@ void Raster::drawPoint(int x, int y, Rgba color, int pointSize) { switch (pointSize) { case 1: setPixel(x, y, color); + break; case 2: setPixel(x, y, color); setPixel(x + 1, y, color); setPixel(x, y + 1, color); setPixel(x + 1, y + 1, color); + break; case 3: setPixel(x - 1, y - 1, color); setPixel(x, y - 1, color); @@ -52,6 +55,7 @@ void Raster::drawPoint(int x, int y, Rgba color, int pointSize) { setPixel(x - 1, y + 1, color); setPixel(x, y + 1, color); setPixel(x + 1, y + 1, color); + break; } } @@ -163,13 +167,13 @@ void Raster::drawSpan(const Span &span) { Rgba color; float length = span.xEnd - span.xStart; - - + + int startX = tmax(span.xStart, 0); int endX = tmin(span.xEnd, _width); - + float scale = (startX - span.xStart) / length; - + //优化3 x轴越界处理 for (int i = startX; i <= endX; i++) { color = colorLerp(span.color1, span.color2, (float) (i - startX) / length); @@ -339,6 +343,22 @@ void Raster::drawRect(const int2* points, const Rgba* colors) { } } +void Raster::drawImage(int startX, int startY, const Image* image) { + /*越界部分不描画*/ + int left = tmax(startX, 0); + int bottom = tmax(startY, 0); + + int right = tmin(startX + image->width(), _width); + int top = tmin(startY + image->height(), _height); + + for (int x = left; x < right; x++) { + for (int y = bottom; y < top; y++) { + Rgba color = image->pixelAt(x - left, y - bottom); + drawPoint(x, y, color); + } + } +} + int Raster::size() { return _width * _height * sizeof (Rgba); } diff --git a/src/Raster.h b/src/Raster.h index 6d7eccb..45d5212 100644 --- a/src/Raster.h +++ b/src/Raster.h @@ -16,6 +16,7 @@ #include "common.h" #include "Rgba.h" +#include "Image.h" enum DRAWMODE { DM_POINTS = 0, @@ -94,6 +95,7 @@ public: void drawArray(DRAWMODE mode, const float2* points, size_t count); void drawFilledRect(int startX, int startY, int width, int height); void drawRect(const int2* points, const Rgba* colors); + void drawImage(int startX, int startY, const Image* image); int size(); void clean(); bool setPixel(int x, int y, Rgba color); diff --git a/src/Rgba.cc b/src/Rgba.cc index 51ebfe4..c99bf47 100644 --- a/src/Rgba.cc +++ b/src/Rgba.cc @@ -24,6 +24,10 @@ Rgba::Rgba(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { _a = a; } +Rgba::Rgba(unsigned int rgba) { + _color = rgba; +} + bool operator==(Rgba &left, Rgba &right) { return left._a == right._a && left._b == right._b && left._g == right._g && left._r == right._r; } @@ -35,7 +39,7 @@ bool operator!=(Rgba &left, Rgba &right) { Rgba::operator unsigned() { unsigned int ret; - unsigned char* p = (unsigned char*)&ret; + unsigned char* p = (unsigned char*) &ret; p[0] = _r; p[1] = _g; p[2] = _b; @@ -43,14 +47,14 @@ Rgba::operator unsigned() { //bitset<32> set = ret; //cout << set << endl; - + return ret; } Rgba::operator int() { int ret; - unsigned char* p = (unsigned char*)&ret; + unsigned char* p = (unsigned char*) &ret; p[0] = _r; p[1] = _g; p[2] = _b; @@ -62,7 +66,7 @@ Rgba::operator int() { Rgba::operator long() { long ret; - unsigned char* p = (unsigned char*)&ret ; + unsigned char* p = (unsigned char*) &ret; p[0] = _r; p[1] = _g; p[2] = _b; diff --git a/src/Rgba.h b/src/Rgba.h index 1b20422..b7ae512 100644 --- a/src/Rgba.h +++ b/src/Rgba.h @@ -19,16 +19,25 @@ class Rgba { public: Rgba(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 0); + Rgba(unsigned int rgba); friend bool operator==(Rgba &left, Rgba &right); friend bool operator!=(Rgba &left, Rgba &righe); operator unsigned(); operator int(); operator long(); public: - unsigned char _r; - unsigned char _g; - unsigned char _b; - unsigned char _a; + + /*这里使用了联合,可以是类能使用unsigned int 直接赋值*/ + union { + + struct { + unsigned char _r; + unsigned char _g; + unsigned char _b; + unsigned char _a; + }; + unsigned int _color; + }; }; inline Rgba colorLerp(const Rgba& color1, const Rgba& color2, float step) { diff --git a/src/draw_image.cc b/src/draw_image.cc new file mode 100644 index 0000000..a7dfd08 --- /dev/null +++ b/src/draw_image.cc @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include "Rgba.h" +#include "Raster.h" +#include "common.h" +#include "Image.h" + +using namespace std; + + +gint height = 500; +gint width = 500; + +Raster raster(width, height); + +unsigned char* makeBitmap() { + raster.clean(); + + Image* image = Image::loadFromFile("/home/blobt/Documents/dev/cpp/3dbase/build/bin/12.jpg"); + + raster.drawImage(25, 25, image); + + return (unsigned char*) raster.buffer; +} + +void render(GtkWidget *widget) { + //允许窗口可以绘图 + gtk_widget_set_app_paintable(widget, TRUE); + gtk_widget_realize(widget); + gtk_widget_queue_draw(widget); + + //模拟一张图片 + unsigned char* data = makeBitmap(); + + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, NULL, NULL); + + GdkPixmap *pixmap = NULL; + + gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, NULL, 128); + + gdk_window_set_back_pixmap(widget->window, pixmap, FALSE); + + g_object_unref(pixbuf); + g_object_unref(pixmap); + //delete data; +} + +int main(int argc, char* argv[]) { + + gtk_init(&argc, &argv); + + //创建窗口 + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_size_request(window, width, height); + + gtk_window_set_title(GTK_WINDOW(window), "Gtk testing"); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS); + + //窗口关闭时候,关闭程序 + g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + //设置渲染 + g_signal_connect(window, "expose-event", G_CALLBACK(render), window); + + + gtk_widget_show_all(window); + gtk_main(); + + return 0; +}