📄 cimage.cpp
字号:
/*************************************************************************** CPicture.cpp The Picture class (c) 2000-2003 Beno顃 Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __CIMAGE_CPP#include <string.h>#include <qpixmap.h>#include <qbitmap.h>#include <qpicture.h>#include <qnamespace.h>#include <qdict.h>#include <qpainter.h>#include <qwmatrix.h>#include "gambas.h"#include "CPicture.h"#include "CImage.h"//#if QT_VERSION < 0x030100//#include <X11/Xlib.h>//#endifstatic void create(CIMAGE **pimage){ static GB_CLASS class_id = NULL; if (!class_id) class_id = GB.FindClass("Image"); GB.New((void **)pimage, class_id, NULL, NULL);}const char *CIMAGE_get_format(QString path){ int pos; pos = path.findRev('.'); if (pos < 0) return NULL; path = path.mid(pos + 1).lower(); if (path == "png") return "PNG"; else if (path == "jpg" || path == "jpeg") return "JPEG"; else if (path == "gif") return "GIF"; else if (path == "bmp") return "BMP"; else if (path == "xpm") return "XPM"; else return NULL;}bool CIMAGE_load_image(QImage &p, char *path, long lenp){ char *addr; long len; bool ok = false; if (!GB.LoadFile(path, lenp, &addr, &len)) { ok = p.loadFromData((const uchar *)addr, (uint)len); if (ok) { //create((CIMAGE **)&_object); if (p.depth() < 32) p = p.convertDepth(32); p.setAlphaBuffer(true); } GB.ReleaseFile(&addr, len); } return ok;}#if 0static void create_new(CPICTURE **ppict){ *ppict = NULL; create(ppict);}static bool load(CPICTURE **ppict, char *file){ FORMAT_MATCH *fmt; bool ok; char *addr; long len; CPICTURE *pict; //qDebug("Loading %s", file); if (GB.LoadFile(file, 0, &addr, &len)) return true; QImage p; ok = p.loadFromData((const uchar *)addr, (uint)len); if (ok) { GB.New((void **)ppict, class_id, NULL, NULL); create(ppict); pict = *ppict; clear(pict); pict->image = new QImage; //qDebug("%s: w = %d h = %d", file, p.width(), p.height()); if (p.depth() < 32) { //qDebug("Convert to depth 32"); *(pict->image) = p.convertDepth(32); //delete pict->image; //pict->image = p; } else *(pict->image) = p; pict->image->setAlphaBuffer(true); } GB.ReleaseFile(&addr, len); if (!ok) GB.Error("Unable to load image"); //qDebug("Loading %s => %s", file, ok ? "OK" : "*ERR*"); return !ok;}static CPICTURE *get_picture(char *key){ CPICTURE *pict; pict = dict[key]; if (!pict) { create_new(&pict); if (load(&pict, key)) { GB.Unref((void **)&pict); return NULL; } // Optimize for using in the interface if (get_type(pict) == TYPE_IMAGE) set_type(pict, TYPE_PIXMAP); GB.Ref(pict); dict.insert(key, pict); } return pict;}static void set_picture(char *key, CPICTURE *new_pict){ CPICTURE *pict; pict = dict[key]; if (!pict) GB.Unref((void **)&pict); if (new_pict) dict.replace(key, new_pict);}static void flush_picture(){ QDictIterator<CPICTURE> it(dict); CPICTURE *pict; while (it.current()) { //delete it.current()->pixmap; pict = it.current(); GB.Unref((void **)&pict); ++it; }}static int get_width(CPICTURE *_object){ if (CPICTURE_is_pixmap(THIS)) return THIS->pixmap->width(); else if (CPICTURE_is_image(THIS)) return THIS->image->width(); else if (CPICTURE_is_picture(THIS)) return THIS->picture->boundingRect().width(); else return 0;}static int get_height(CPICTURE *_object){ if (CPICTURE_is_pixmap(THIS)) return THIS->pixmap->height(); else if (CPICTURE_is_image(THIS)) return THIS->image->height(); else if (CPICTURE_is_picture(THIS)) return THIS->picture->boundingRect().height(); else return 0;}CPICTURE *CPICTURE_grab(int wid){ CPICTURE *pict; #if QT_VERSION >= 0x030100 if (wid == 0) wid = QPaintDevice::x11AppRootWindow(); #else if (wid == 0) wid = RootWindow(QPaintDevice::x11AppDisplay(), QPaintDevice::x11AppScreen()); #endif create_new(&pict); pict->pixmap = new QPixmap(); *pict->pixmap = QPixmap::grabWindow(wid); return pict;}void CPICTURE_update_mask(CPICTURE *_object){ if (THIS->pixmap && THIS->pixmap->hasAlpha()) THIS->pixmap->setMask(THIS->pixmap->createHeuristicMask());}#endif/******************************************************************************* Image*******************************************************************************/BEGIN_METHOD(CIMAGE_new, GB_INTEGER w; GB_INTEGER h) int w, h; THIS->image = new QImage(); w = VARGOPT(w, 0); h = VARGOPT(h, 0); if (h <= 0) h = w; else if (w <= 0) w = h; if (w > 0 && h > 0) { THIS->image->create(w, h, 32); THIS->image->setAlphaBuffer(true); }END_METHODBEGIN_METHOD_VOID(CIMAGE_free) delete THIS->image; THIS->image = 0;END_METHODBEGIN_PROPERTY(CIMAGE_picture) CPICTURE *pict; GB.New((void **)&pict, GB.FindClass("Picture"), NULL, NULL); pict->pixmap->convertFromImage(*(THIS->image)); GB.ReturnObject(pict);END_PROPERTYBEGIN_METHOD(CIMAGE_resize, GB_INTEGER width; GB_INTEGER height) if (THIS->image->isNull()) { THIS->image->create(VARG(width), VARG(height), 32); THIS->image->setAlphaBuffer(true); } else { QImage img = THIS->image->copy(0, 0, VARG(width), VARG(height)); delete THIS->image; THIS->image = new QImage(img); }END_METHODBEGIN_PROPERTY(CIMAGE_width) GB.ReturnInteger(THIS->image->width());END_PROPERTYBEGIN_PROPERTY(CIMAGE_height) GB.ReturnInteger(THIS->image->height());END_PROPERTYBEGIN_PROPERTY(CIMAGE_depth) if (READ_PROPERTY) GB.ReturnInteger(THIS->image->depth()); else { if (!THIS->image->isNull()) { int depth = VPROP(GB_INTEGER); if (depth != THIS->image->depth()) { QImage img = THIS->image->convertDepth(depth); if (!img.isNull()) { delete THIS->image; THIS->image = new QImage(img); } } } }END_PROPERTYBEGIN_METHOD(CIMAGE_load, GB_STRING path) QImage p; if (CIMAGE_load_image(p, STRING(path), LENGTH(path))) *(THIS->image) = p; else GB.Error("Unable to load image");END_METHODBEGIN_METHOD(CIMAGE_save, GB_STRING path) QString path = TO_QSTRING(GB.FileName(STRING(path), LENGTH(path))); bool ok = false; const char *fmt = CIMAGE_get_format(path); if (!fmt) { GB.Error("Unknown format"); return; } ok = THIS->image->save(path, fmt); if (!ok) GB.Error("Unable to save picture");END_METHODBEGIN_METHOD_VOID(CIMAGE_clear) delete THIS->image; THIS->image = new QImage();END_METHODBEGIN_METHOD(CIMAGE_fill, GB_INTEGER col) //bool a; int col = VARG(col); //a = THIS->image->hasAlphaBuffer(); THIS->image->setAlphaBuffer(false); col ^= 0xFF000000; THIS->image->fill(col); THIS->image->setAlphaBuffer(true);END_METHODBEGIN_METHOD(CIMAGE_copy, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h) CIMAGE *img; int x = VARGOPT(x, 0); int y = VARGOPT(y, 0); int w = VARGOPT(w, THIS->image->width()); int h = VARGOPT(h, THIS->image->height()); create(&img); img->image->create(w, h, 32); bool a = THIS->image->hasAlphaBuffer(); THIS->image->setAlphaBuffer(false); bitBlt(img->image, 0, 0, THIS->image, x, y, w, h); THIS->image->setAlphaBuffer(a); img->image->setAlphaBuffer(a); GB.ReturnObject(img);END_METHODBEGIN_METHOD(CIMAGE_stretch, GB_INTEGER width; GB_INTEGER height; GB_BOOLEAN smooth) CIMAGE *img; QImage stretch; create(&img); if (VARGOPT(smooth, TRUE)) *(img->image) = THIS->image->smoothScale(VARG(width), VARG(height)); else *(img->image) = THIS->image->scale(VARG(width), VARG(height)); GB.ReturnObject(img);END_METHODBEGIN_METHOD_VOID(CIMAGE_flip) CIMAGE *img; create(&img); *(img->image) = THIS->image->mirror(true, false); GB.ReturnObject(img);END_METHODBEGIN_METHOD_VOID(CIMAGE_mirror) CIMAGE *img; create(&img); *(img->image) = THIS->image->mirror(false, true); GB.ReturnObject(img);END_METHODBEGIN_METHOD(CIMAGE_rotate, GB_FLOAT angle) CIMAGE *img; QWMatrix mat; create(&img); mat.rotate(VARG(angle)); *(img->image) = THIS->image->xForm(mat); GB.ReturnObject(img);END_METHODBEGIN_METHOD(CIMAGE_replace, GB_INTEGER src; GB_INTEGER dst) uint x, y, src, dst; THIS->image->setAlphaBuffer(true); src = VARG(src) ^ 0xFF000000; dst = VARG(dst) ^ 0xFF000000; for (y = 0; y < (uint)THIS->image->height(); y++) for (x = 0; x < (uint)THIS->image->width(); x++) { if (THIS->image->pixel(x, y) != src) continue; THIS->image->setPixel(x, y, dst); }END_METHOD/******************************************************************************* .ImagePixels*******************************************************************************/BEGIN_METHOD(CIMAGE_pixels_get, GB_INTEGER x; GB_INTEGER y) int col; int x, y; //unsigned char r, g, b, a; x = VARG(x); y = VARG(y); if (!THIS->image->valid(x, y)) { GB.ReturnInteger(-1); return; } col = THIS->image->pixel(x, y) ^ 0xFF000000; GB.ReturnInteger(col); #if 0 a = (col >> 24); //qDebug("[%d,%d] = (%d %d %d) / %d", x, y, r, g, b, a); if (!THIS->image->hasAlphaBuffer() || a == 255) GB.ReturnInteger( col & 0xFFFFFF); else if (a == 0) GB.ReturnInteger(-1); else { r = col & 0xFF; g = (col >> 8) & 0xFF; b = (col >> 16) & 0xFF; r = 255 - ((255 - r) * a) / 255; g = 255 - ((255 - g) * a) / 255; b = 255 - ((255 - b) * a) / 255; GB.ReturnInteger(r + (g << 8) + (b << 16)); } #endifEND_METHODBEGIN_METHOD(CIMAGE_pixels_put, GB_INTEGER col; GB_INTEGER x; GB_INTEGER y) int x, y; int col; x = VARG(x); y = VARG(y); if (!THIS->image->valid(x, y)) return; col = VARG(col) ^ 0xFF000000; THIS->image->setPixel(x, y, col);END_METHOD#if 0BEGIN_PROPERTY(CPICTURE_pixels_data) GB.ReturnInteger((long)THIS->image->bits());END_PROPERTY#endifGB_DESC CImageDesc[] ={ GB_DECLARE("Image", sizeof(CIMAGE)), //GB_STATIC_METHOD("_exit", NULL, CPICTURE_flush, NULL), //GB_CONSTANT("None", "i", TYPE_NONE), //GB_CONSTANT("Bitmap", "i", TYPE_PIXMAP), //GB_CONSTANT("Pixmap", "i", TYPE_PIXMAP), //GB_CONSTANT("Vector", "i", TYPE_PICTURE), //GB_CONSTANT("Metafile", "i", TYPE_PICTURE), //GB_CONSTANT("Image", "i", TYPE_IMAGE), GB_METHOD("_new", NULL, CIMAGE_new, "[(Width)i(Height)i]"), GB_METHOD("_free", NULL, CIMAGE_free, NULL), GB_METHOD("_get", "i", CIMAGE_pixels_get, "(X)i(Y)i"), GB_METHOD("_put", NULL, CIMAGE_pixels_put, "(Color)i(X)i(Y)i"), //GB_STATIC_METHOD("_get", "Picture", CPICTURE_get, "(Path)s"), //GB_STATIC_METHOD("_put", NULL, CPICTURE_put, "(Picture)Picture;(Path)s"), //GB_STATIC_METHOD("Flush", NULL, CPICTURE_flush, NULL), //GB_PROPERTY("Type", "i<Picture,None,Pixmap,Image,Metafile>", CPICTURE_type), GB_PROPERTY_READ("Width", "i", CIMAGE_width), GB_PROPERTY_READ("Height", "i", CIMAGE_height), GB_PROPERTY("Depth", "i", CIMAGE_depth), GB_METHOD("Load", NULL, CIMAGE_load, "(Path)s"), GB_METHOD("Save", NULL, CIMAGE_save, "(Path)s"), GB_METHOD("Resize", NULL, CIMAGE_resize, "(Width)i(Height)i"), GB_METHOD("Clear", NULL, CIMAGE_clear, NULL), GB_METHOD("Fill", NULL, CIMAGE_fill, "(Color)i"), GB_METHOD("Replace", NULL, CIMAGE_replace, "(OldColor)i(NewColor)i"), //GB_METHOD("Mask", NULL, CPICTURE_mask, "[(Color)i]"), GB_METHOD("Copy", "Image", CIMAGE_copy, "[(X)i(Y)i(Width)i(Height)i]"), GB_METHOD("Stretch", "Image", CIMAGE_stretch, "(Width)i(Height)i[(Smooth)b]"), GB_METHOD("Flip", "Image", CIMAGE_flip, NULL), GB_METHOD("Mirror", "Image", CIMAGE_mirror, NULL), GB_METHOD("Rotate", "Image", CIMAGE_rotate, "(Angle)f"), GB_PROPERTY_READ("Picture", "Picture", CIMAGE_picture), //GB_PROPERTY_SELF("Pixels", ".ImagePixels"), //GB_PROPERTY_SELF("Colors", ".PictureColors"), GB_END_DECLARE};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -