⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.cc

📁 c++的guiQt做的开发
💻 CC
📖 第 1 页 / 共 2 页
字号:
/** @file ImageView - class for manipulating the image*/#include "image.h"#include <stdlib.h>#include <QApplication>#include <QClipboard>#include <QFileInfo>#include <QPainter>#include <QPixmap>#include "aconf.h"#include "argb.h"#define cimg_debug 0#include <CImg.h>#include <math.h>#include <settings.h>#include <assert.h>#include <limits>#include <exception>namespace gui {using namespace std;using namespace cimg_library;/** Which pixel type will be used for one channel? Using unsigned char mean 8bit per channel (32bit per RGBA),       unsigned short is 16bit per channel (64bit per RGBA), unsigned int, unsigned long,float or double may be used for even more precision*/typedef unsigned char Pixel;/** Convert RGB image to grayscale Assumes R, G and B channels are of equal weight. Alpha channel (if any) is untouched. If image have less than three channels, it is also untouched. @param img image to convert */template<class T> void grayscale(CImg<T> &img) { if (img.dimv()<3) return; for (int x=0;x<img.dimx();x++) {  for (int y=0;y<img.dimy();y++) {   typename cimg::superset<T,long>::type val=img(x,y,0)+img(x,y,1)+img(x,y,2);   img(x,y,0)=img(x,y,1)=img(x,y,2)=val/3;  } }}/** Return grayscale version of current image See \see grayscale for more info @param in source image */template<class T> CImg<T> get_grayscale(const CImg<T> &in) { CImg<T> img=in; grayscale(img); return img;}/** Convert image to different amount of channels It is assumed that:<br>  1 channels is greyscale<br>  2 channels is greyscale with alpha<br>  3 channels is RGB<br>  4 channels is RGB with alpha<br>  5+ channels is RGB with alpha, rest of channels is ignored/filled with zero<br> @param in Image to convert @param channels Desired number of channels*/template<class T> void convert_channels(CImg<T> &in,int channels) { int dv=in.dimv(); int xy=in.dimx()*in.dimy(); if (channels==dv) return;//Nothing to convert if (channels>dv) {  //Raising number of channels  in.resize(-100,-100,-100,channels,0);  if (dv==2 && channels==4) {   //LA -> RGBA   T *g=in.ptr(0,0,0,1);   T *a=in.ptr(0,0,0,3);   //Copy alpha from "green"   for (int x=0;x<xy;x++) { //memcpy?    a[x]=g[x];   }  }  if ((dv==1 || dv==3) && channels==4) {   //L/RGB -> RGBA   //Set alpha to opaque   T *a=in.ptr(0,0,0,3);   for (int x=0;x<xy;x++) {    a[x]=pixel_limits<T>::full();   }  }  if (dv<=2 && channels>=3) {   //LX -> RGBX   T *r=in.ptr(0,0,0,0);   T *g=in.ptr(0,0,0,1);   T *b=in.ptr(0,0,0,2);   for (int x=0;x<xy;x++) { //memcpy?    g[x]=b[x]=r[x];   }  }  if (dv==1 && channels==2) {   //L -> LA   //Set alpha to opaque   T *a=in.ptr(0,0,0,1);   for (int x=0;x<xy;x++) {    a[x]=pixel_limits<T>::full();   }  } } if (channels<dv) {  //Lowering number of channels  if (dv>=3 && channels<=2) {   //RGB->greyscale   T *r=in.ptr(0,0,0,0);   T *g=in.ptr(0,0,0,1);   T *b=in.ptr(0,0,0,2);   for (int x=0;x<xy;x++) {    typename cimg::superset<T,long>::type val=r[x]+g[x]+b[x];    r[x]=val/3;   }   if (dv>=4 && channels==2) {    //RGBA -> LA    T *a=in.ptr(0,0,0,3);    //Copy alpha to "green"    for (int x=0;x<xy;x++) { //memcpy?     g[x]=a[x];    }   }   if (dv==3 && channels==2) {    //RGB -> LA    //Set alpha to opaque    for (int x=0;x<xy;x++) {     g[x]=pixel_limits<T>::full();    }   }  }  in.resize(-100,-100,-100,channels,0); }}/** Class hiding implementation details (and avoiding to include CImg.h (which takes quite long to compile) in the header)*/class ImagePrivate {public: /** constructor */ ImagePrivate() {  undoValid=false;  pixdata=NULL;  pix_x=0;  pix_y=0;  pix_w=0;  pix_h=0; } /** destructor */ ~ImagePrivate() {  if (pixdata) free(pixdata); } /** function to call when image is changed - flush some internal variables */ void imageChanged() {  if (pixdata) free(pixdata);  pixdata=NULL; } /**  Set name of image  @param name filename of image */ void setName(const QString &name) {  imgName=name;  if (name.isNull()) {   imgFullName=QString::null;  } else {   imgFullName=QFileInfo(name).absoluteFilePath();  } }public: /** Image itself */ CImg<Pixel> i; /** Image used for undo function */ CImg<Pixel> iUndo; /** Image original name */ QString imgName; /** Image original name with full path */ QString imgFullName; /** True if iUndo contain something valid */ bool undoValid; /** Pixel data for currently shown image */ int *pixdata; /** X offset of pixdata */ int pix_x; /** Y offset of pixdata */ int pix_y; /** Width of pixdata */ int pix_w; /** Height of pixdata */ int pix_h;};/** Code block to insert before running image operation */#define OP_BEGIN try { beforeOp();/** Code block to insert after running image operation */#define OP_END d->imageChanged();} catch (CImgException &e) { stdErrorHandler(e); }/** constructor of Image @param name Name of image to load*/Image::Image(const QString &name) { d=new ImagePrivate(); loadImage(name);}/** constructor of Image @param px Pixmap to create image from*/Image::Image(QPixmap px) { d=new ImagePrivate(); QImage i=px.toImage().convertToFormat(QImage::Format_RGB32); load(i);}/** constructor of Image @param im QImage to create image from*/Image::Image(QImage im) { d=new ImagePrivate(); load(im);}/** Load internally image data from given QImage @param i image to load*/void Image::load(QImage i) { int wx=i.width(); int wy=i.height(); if (i.format()==QImage::Format_ARGB32_Premultiplied) i=i.convertToFormat(QImage::Format_ARGB32); QImage::Format fmt=i.format(); if (fmt!=QImage::Format_RGB32 && fmt!=QImage::Format_ARGB32) {  i=i.convertToFormat(QImage::Format_RGB32); } fmt=i.format(); bool rgba=(fmt==QImage::Format_ARGB32); if (rgba) {  d->i.assign(wx,wy,1,4);//RGBA } else {  d->i.assign(wx,wy,1,3);//RGBA } int *pixeldata=(int *)i.bits(); size_t pd=0; Pixel *r,*g,*b,*a; r=d->i.ptr(0,0,0,0); g=d->i.ptr(0,0,0,1); b=d->i.ptr(0,0,0,2); if (rgba) a=d->i.ptr(0,0,0,3); size_t sz=wx*wy; ARGB<Pixel> rgb; assert(sizeof(ARGB<Pixel>)==sizeof(int)); if (rgba) {  for (pd=0;pd<sz;pd++) {   rgb.argb=pixeldata[pd];   r[pd]=rgb.r;   g[pd]=rgb.g;   b[pd]=rgb.b;   a[pd]=rgb.a;  } } else {  for (pd=0;pd<sz;pd++) {   rgb.argb=pixeldata[pd];   r[pd]=rgb.r;   g[pd]=rgb.g;   b[pd]=rgb.b;  } } d->setName(QString::null); clearUndo(); d->imageChanged();}/** Return true if undo is to be used, false otherwise*/bool Image::useUndo() { return globalSettings->readBool("undo",true);}/** Return true if undo can be used, false otherwise*/bool Image::haveUndo() { return d->iUndo.dimx()>0;}/** Replace image contents with new one @param name name of image*/void Image::loadImage(const QString &name) { try {  d->i.assign(name.toLocal8Bit().data());  d->setName(name);  clearUndo();  d->imageChanged(); } catch (CImgException &e) {  stdErrorHandler(e); } catch (std::exception &e) {  stdErrorHandler(e); }}/** Save image to file on disk @param name name of image*/void Image::saveImage(const QString &name) { try {  d->i.save(name.toLocal8Bit().data());  d->setName(name); } catch (CImgException &e) {  stdErrorHandler(e); } catch (std::exception &e) {  stdErrorHandler(e); }}/** Standard error handler called when exception from CImg is thrown @param e exception*/void Image::stdErrorHandler(cimg_library::CImgException &e) { errorMessage=QString::fromAscii(e.message);}/** Standard error handler called when exception not from CImg is thrown @param e exception*/void Image::stdErrorHandler(std::exception &e) { errorMessage=QString::fromAscii(e.what());}/** Get and clear error message(s)*/QString Image::error() { QString e=errorMessage; errorMessage=QString::null; return e;}/** handler to be run before any operation*/void Image::beforeOp() { if (useUndo()) {  d->iUndo=d->i;  d->undoValid=true; }}/** Explicitly clear contents of undo buffer*/void Image::clearUndo() { d->iUndo.assign(); d->undoValid=false;}/** Perform undo - undo Last operation Another undo will act as re-do, another as "undo again" and so on ...*/void Image::undo() { if (!d->undoValid) return; CImg<Pixel> tmp; /** \todo swap images more effectively? */ tmp=d->i; d->i=d->iUndo; d->iUndo=tmp;}/** Rotate image by arbitrary angle @param angle Angle to rotate*/void Image::rotate(float angle) { OP_BEGIN  d->i.rotate(angle); OP_END}/** Resize image to new size @param x new image width @param y new image height @param interp Resizing type  - -1 = no interpolation : raw memory resizing.  - 0 = no interpolation : additional space is filled with 0.  - 1 = bloc interpolation (nearest point).  - 2 = moving average interpolation.  - 3 = linear interpolation.  - 4 = grid interpolation.  - 5 = bi-cubic interpolation. @param border_condition Behavior at image borders*/void Image::resize(int x,int y,int interp/*=1*/,int border_condition/*=-1*/) { OP_BEGIN  d->i.resize(x,y,-100,-100,interp,border_condition); OP_END}/** Return image value at specified point @param x X coordinate @param y Y coordinate @param c Image channel */int Image::value(int x,int y,int c) { return d->i(x,y,0,c);}/** Return image value at specified point as hexadecimal @param x X coordinate @param y Y coordinate @param c Image channel */QString Image::valueHex(int x,int y,int c) { int v=d->i(x,y,0,c); QString n=QString::number(v,16).toUpper(); for(unsigned int i=n.length();i<sizeof(Pixel)*2;i++) {  n="0"+n; } return n;}/** Crop image, replace image by its sub-region @param x1 X-coordinate of the upper-left crop rectangle corner. @param y1 Y-coordinate of the upper-left crop rectangle corner. @param x2 X-coordinate of the lower-right crop rectangle corner. @param y2 Y-coordinate of the lower-right crop rectangle corner. @param border_condition type of border condition if some of the desired region is outside the image.*/void Image::crop(int x1,int y1,int x2,int y2,bool border_condition/*=false*/) { OP_BEGIN  d->i.crop(x1,y1,x2,y2,border_condition); OP_END}/** Pixel-wise multiplication of image by given value, in all channels @param value Value to multiply with all pixels*/void Image::multiply(float value) { OP_BEGIN  d->i*=value; OP_END}/** Pixel-wise negative in all channels*/void Image::negative() { OP_BEGIN  d->i=numeric_limits<Pixel>::max()-d->i; OP_END}/** Addition of given value to all image pixels, in all channels @param value Value to add to all pixels*/void Image::add(int value) { OP_BEGIN

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -