code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>QHdrCamera: qnativecamera.h Source File</title>

<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />

<link href="search/search.css" rel="stylesheet" type="text/css"/>

QHdrCamera
    1.9.0

Main Page

Classes

Files

          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)"
               onblur="searchBox.OnSearchFieldFocus(false)"
               onkeyup="searchBox.OnSearchFieldChange(event)"/>

File List

qnativecamera.h

00001 #ifndef QNATIVECAMERA_H
00002 #define QNATIVECAMERA_H
00003
00004 #include <QDeclarativeItem>
00005 #include <QVideoFrame>
00006 #include <QCamera>
00007 #include <QCameraImageCapture>
00008 #include <QMediaRecorder>
00009
00010 QT_USE_NAMESPACE
00011
00012 class VideoSurface;
00013
00014 // Observer design pattern to provide the view finder frame for the CustomCamera
00015 // object.
00016 class FrameObserver {
00017 public:
00018     virtual bool updateFrame(const QVideoFrame &frame) = 0;
00019 };
00020
00021 class QNativeCamera : public QDeclarativeItem, FrameObserver
00022 {
00023     Q_OBJECT
00024
00025     Q_ENUMS(State)
00026
00027     // State properties
00028     Q_PROPERTY(State cameraState READ cameraState NOTIFY cameraStateChanged)
00029
00030     // Devices properties
00031     Q_PROPERTY(QStringList availableDevices READ availableDevices)
00032
00033     Q_PROPERTY(QString currentDevice READ currentDevice NOTIFY currentDeviceChanged)
00034     Q_PROPERTY(bool frontCamera READ frontCamera NOTIFY frontCameraChanged)
00035     Q_PROPERTY(bool preview READ preview WRITE setPreview)
00036     Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
00037     Q_PROPERTY(qreal exposureCompensation  READ exposureCompensation  WRITE setExposureCompensation  NOTIFY exposureCompensationChanged)
00038
00039 public:
00040
00041     enum State {
00042         ActiveState = QCamera::ActiveState,
00043         LoadedState = QCamera::LoadedState,
00044         UnloadedState = QCamera::UnloadedState
00045     };
00046
00047     explicit QNativeCamera(QDeclarativeItem *parent = 0);
00048     ~QNativeCamera();
00049
00050     QStringList availableDevices() const;
00051
00052     virtual void paint(QPainter *painter,
00053                        const QStyleOptionGraphicsItem *option,
00054                        QWidget *widget);
00055
00056     virtual bool updateFrame(const QVideoFrame &frame);
00057
00058     QSize resolution();
00059     void setResolution(QSize& value);
00060
00061     qreal exposureCompensation();
00062     void  setExposureCompensation(qreal);
00063
00064     bool preview();
00065     void setPreview(bool value);
00066
00067 protected:
00068     void destroyResources();
00069     State cameraState() const;
00070     QString currentDevice() const;
00071     bool frontCamera() const;
00072
00073 signals:
00074     void resolutionChanged(QSize resolution);
00075
00076     void digitalZoomChanged();
00077     void maximumDigitalZoomChanged();
00078
00079     void exposureCompensationChanged();
00080     void exposureModeChanged();
00081     void supportedExposureModesChanged();
00082
00083     void flashModeChanged();
00084     void supportedFlashModesChanged();
00085
00086     void locked();
00087     void lockFailed();
00088
00089     void isoValueChanged();
00090     void supportedIsoValuesChanged();
00091
00092     void imageSaved(const QString &fileName);
00093
00094     void cameraStateChanged();
00095
00096     void whiteBalanceModeChanged();
00097     void supportedWhiteBalanceModesChanged();
00098     //void sharpeningLevelChanged();
00099     //void contrastChanged();
00100
00101     void currentDeviceChanged();
00102     void frontCameraChanged();
00103
00104     //void imageAnalyzerChanged();
00105
00106 public slots:
00107     void start(const QString &device);
00108     void stop();
00109
00110     void cameraStateChanged(QCamera::State state);
00111     void handleImageSaved(int id, const QString &fileName);
00112     virtual void captureImage();
00113     virtual void imageAvailable(int,QVideoFrame);
00114     virtual void imageCaptured ( int id, const QImage & preview );
00115     virtual void imageExposed(int);
00116
00117     void emitImageSavedSignal();
00118
00119 protected:
00120     qreal m_exposureCompensation;
00121
00122     QCamera *m_camera; // Owned
00123
00124     QString m_currentDevice;
00125     bool m_frontCamera;
00126     // Still image capturing
00127     QCameraImageCapture *m_cameraImageCapture; // Owned
00128
00129     // Video capturing
00130     QMediaRecorder *m_mediaRecorder; // Owned
00131
00132     // For showing view finder image
00133     VideoSurface *m_videoSurface; // Owned
00134
00135     // For storing the latest frame
00136     unsigned int m_processedFrameCounter;
00137     unsigned int m_incomingFrameCounter;
00138     QImage m_imageFrame;
00139     QImage i_preview;
00140     bool m_preview;
00141
00142     // File to be opened in the gallery.
00143     QString m_galleryImage;
00144     QSize m_resolution;
00145 };
00146
00147 #endif // QNATIVECAMERA_H

 All Classes Functions Properties

<address class="footer">
Generated on Thu May 24 2012 22:25:56 for QHdrCamera by

 1.7.6.1
</address>


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="search.css"/>

Loading...

Searching...

No Matches

repo_name: snapshot/QHdrCamera

license: unknown


code:
var searchData=
[
  ['availabledevices',['availableDevices',['../class_q_native_camera.html#a072ef24257a0303cee1ac3bcb047b41b',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['destroyresources',['destroyResources',['../class_q_native_camera.html#aab95bb9ec64ead45e414f47bd48a7738',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['emitimagesavedsignal',['emitImageSavedSignal',['../class_q_native_camera.html#a146aaeb465ab0a0e64a790ad7a5b9ca1',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['frameobserver',['FrameObserver',['../class_frame_observer.html',1,'']]],
  ['frontcamera',['frontCamera',['../class_q_native_camera.html#ab36ab7a242df937a23c1d984066b6477',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['handleimagesaved',['handleImageSaved',['../class_q_native_camera.html#a6def766930abeef19b7a82c033bfaad5',1,'QNativeCamera']]],
  ['hdrthread',['HdrThread',['../class_hdr_thread.html',1,'']]]
];


code:
var searchData=
[
  ['paint',['paint',['../class_q_native_camera.html#a9aeab214a1c120887f57bd95a44ad6bd',1,'QNativeCamera']]],
  ['present',['present',['../class_video_surface.html#a930a2093a5da13e01e7b1f8dd39db35e',1,'VideoSurface']]]
];


code:
var searchData=
[
  ['qhdrcamera',['QHdrCamera',['../class_q_hdr_camera.html',1,'']]],
  ['qnativecamera',['QNativeCamera',['../class_q_native_camera.html',1,'']]]
];


code:
var searchData=
[
  ['start',['start',['../class_q_native_camera.html#af02f8272683ff70effccebd08368bfc7',1,'QNativeCamera::start()'],['../class_video_surface.html#adf8e48140eab4a81df4ac84151413ab1',1,'VideoSurface::start()']]],
  ['stop',['stop',['../class_q_native_camera.html#a8a63728fa3e0c9ef2c6bbf575ae40016',1,'QNativeCamera']]],
  ['supportedpixelformats',['supportedPixelFormats',['../class_video_surface.html#a4863064cd19a30e467a92ce8d4e252f9',1,'VideoSurface']]]
];


code:
var searchData=
[
  ['updateframe',['updateFrame',['../class_q_native_camera.html#a63468deb8a46f520dde1e18059379024',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['videosurface',['VideoSurface',['../class_video_surface.html',1,'VideoSurface'],['../class_video_surface.html#a51856792268280b7fef52c4321de27d9',1,'VideoSurface::VideoSurface()']]]
];


code:
var searchData=
[
  ['_7eqnativecamera',['~QNativeCamera',['../class_q_native_camera.html#abfc170b57570038fec4d887d42538567',1,'QNativeCamera']]],
  ['_7evideosurface',['~VideoSurface',['../class_video_surface.html#aecea93119c1abf87f62e0e34da5e618e',1,'VideoSurface']]]
];


code:
var searchData=
[
  ['frameobserver',['FrameObserver',['../class_frame_observer.html',1,'']]]
];


code:
var searchData=
[
  ['hdrthread',['HdrThread',['../class_hdr_thread.html',1,'']]]
];


code:
var searchData=
[
  ['videosurface',['VideoSurface',['../class_video_surface.html',1,'']]]
];


code:
var searchData=
[
  ['handleimagesaved',['handleImageSaved',['../class_q_native_camera.html#a6def766930abeef19b7a82c033bfaad5',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['videosurface',['VideoSurface',['../class_video_surface.html#a51856792268280b7fef52c4321de27d9',1,'VideoSurface']]]
];


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="search.css"/>

Loading...

Searching...

No Matches


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="search.css"/>

No Matches


code:
var searchData=
[
  ['availabledevices',['availableDevices',['../class_q_native_camera.html#a072ef24257a0303cee1ac3bcb047b41b',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['camerastate',['cameraState',['../class_q_native_camera.html#a3b610f0a042f08cd727f8dd66056c4a5',1,'QNativeCamera']]],
  ['currentdevice',['currentDevice',['../class_q_native_camera.html#af61b5ac179b61b40d20dff8c4af9b9ac',1,'QNativeCamera']]]
];


code:
var searchData=
[
  ['frontcamera',['frontCamera',['../class_q_native_camera.html#ab36ab7a242df937a23c1d984066b6477',1,'QNativeCamera']]]
];


code:
/*---------------- Search Box */

#FSearchBox {
    float: left;
}

#MSearchBox {
    white-space : nowrap;
    position: absolute;
    float: none;
    display: inline;
    margin-top: 8px;
    right: 0px;
    width: 170px;
    z-index: 102;
    background-color: white;
}

#MSearchBox .left
{
    display:block;
    position:absolute;
    left:10px;
    width:20px;
    height:19px;
    background:url('search_l.png') no-repeat;
    background-position:right;
}

#MSearchSelect {
    display:block;
    position:absolute;
    width:20px;
    height:19px;
}

.left #MSearchSelect {
    left:4px;
}

.right #MSearchSelect {
    right:5px;
}

#MSearchField {
    display:block;
    position:absolute;
    height:19px;
    background:url('search_m.png') repeat-x;
    border:none;
    width:116px;
    margin-left:20px;
    padding-left:4px;
    color: #909090;
    outline: none;
    font: 9pt Arial, Verdana, sans-serif;
}

#FSearchBox #MSearchField {
    margin-left:15px;
}

#MSearchBox .right {
    display:block;
    position:absolute;
    right:10px;
    top:0px;
    width:20px;
    height:19px;
    background:url('search_r.png') no-repeat;
    background-position:left;
}

#MSearchClose {
    display: none;
    position: absolute;
    top: 4px;
    background : none;
    border: none;
    margin: 0px 4px 0px 0px;
    padding: 0px 0px;
    outline: none;
}

.left #MSearchClose {
    left: 6px;
}

.right #MSearchClose {
    right: 2px;
}

.MSearchBoxActive #MSearchField {
    color: #000000;
}

/*---------------- Search filter selection */

#MSearchSelectWindow {
    display: none;
    position: absolute;
    left: 0; top: 0;
    border: 1px solid #90A5CE;
    background-color: #F9FAFC;
    z-index: 1;
    padding-top: 4px;
    padding-bottom: 4px;
    -moz-border-radius: 4px;
    -webkit-border-top-left-radius: 4px;
    -webkit-border-top-right-radius: 4px;
    -webkit-border-bottom-left-radius: 4px;
    -webkit-border-bottom-right-radius: 4px;
    -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
}

.SelectItem {
    font: 8pt Arial, Verdana, sans-serif;
    padding-left:  2px;
    padding-right: 12px;
    border: 0px;
}

span.SelectionMark {
    margin-right: 4px;
    font-family: monospace;
    outline-style: none;
    text-decoration: none;
}

a.SelectItem {
    display: block;
    outline-style: none;
    color: #000000;
    text-decoration: none;
    padding-left:   6px;
    padding-right: 12px;
}

a.SelectItem:focus,
a.SelectItem:active {
    color: #000000;
    outline-style: none;
    text-decoration: none;
}

a.SelectItem:hover {
    color: #FFFFFF;
    background-color: #3D578C;
    outline-style: none;
    text-decoration: none;
    cursor: pointer;
    display: block;
}

/*---------------- Search results window */

iframe#MSearchResults {
    width: 60ex;
    height: 15em;
}

#MSearchResultsWindow {
    display: none;
    position: absolute;
    left: 0; top: 0;
    border: 1px solid #000;
    background-color: #EEF1F7;
}

/* ----------------------------------- */

#SRIndex {
    clear:both;
    padding-bottom: 15px;
}

.SREntry {
    font-size: 10pt;
    padding-left: 1ex;
}

.SRPage .SREntry {
    font-size: 8pt;
    padding: 1px 5px;
}

body.SRPage {
    margin: 5px 2px;
}

.SRChildren {
    padding-left: 3ex; padding-bottom: .5em
}

.SRPage .SRChildren {
    display: none;
}

.SRSymbol {
    font-weight: bold;
    color: #425E97;
    font-family: Arial, Verdana, sans-serif;
    text-decoration: none;
    outline: none;
}

a.SRScope {
    display: block;
    color: #425E97;
    font-family: Arial, Verdana, sans-serif;
    text-decoration: none;
    outline: none;
}

a.SRSymbol:focus, a.SRSymbol:active,
a.SRScope:focus, a.SRScope:active {
    text-decoration: underline;
}

span.SRScope {
    padding-left: 4px;
}

.SRPage .SRStatus {
    padding: 2px 5px;
    font-size: 8pt;
    font-style: italic;
}

.SRResult {
    display: none;
}

DIV.searchresults {
    margin-left: 10px;
    margin-right: 10px;
}


code:
.tabs, .tabs2, .tabs3 {
    background-image: url('tab_b.png');
    width: 100%;
    z-index: 101;
    font-size: 13px;
}

.tabs2 {
    font-size: 10px;
}
.tabs3 {
    font-size: 9px;
}

.tablist {
    margin: 0;
    padding: 0;
    display: table;
}

.tablist li {
    float: left;
    display: table-cell;
    background-image: url('tab_b.png');
    line-height: 36px;
    list-style: none;
}

.tablist a {
    display: block;
    padding: 0 20px;
    font-weight: bold;
    background-image:url('tab_s.png');
    background-repeat:no-repeat;
    background-position:right;
    color: #283A5D;
    text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
    text-decoration: none;
    outline: none;
}

.tabs3 .tablist a {
    padding: 0 10px;
}

.tablist a:hover {
    background-image: url('tab_h.png');
    background-repeat:repeat-x;
    color: #fff;
    text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
    text-decoration: none;
}

.tablist li.current a {
    background-image: url('tab_a.png');
    background-repeat:repeat-x;
    color: #fff;
    text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
}


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>QHdrCamera: videosurface.h Source File</title>

<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />

<link href="search/search.css" rel="stylesheet" type="text/css"/>

QHdrCamera
    1.9.0

Main Page

Classes

Files

          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)"
               onblur="searchBox.OnSearchFieldFocus(false)"
               onkeyup="searchBox.OnSearchFieldChange(event)"/>

File List

videosurface.h

00001
00005 #ifndef VIDEOSURFACE_H
00006 #define VIDEOSURFACE_H
00007
00008 #include <QAbstractVideoSurface>
00009 #include <QVideoSurfaceFormat>
00010
00011 class FrameObserver;
00012
00013 class VideoSurface : public QAbstractVideoSurface
00014 {
00015     Q_OBJECT
00016 public:
00017     explicit VideoSurface(FrameObserver *frameObserver, QObject *parent = 0);
00018     virtual ~VideoSurface();
00019
00020     virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
00021     virtual bool present(const QVideoFrame &frame);
00022     virtual bool start(const QVideoSurfaceFormat &format);
00023
00024 protected:
00025     FrameObserver *m_frameObserver; // Not owned
00026 };
00027
00028 #endif // VIDEOSURFACE_H

 All Classes Functions Properties

<address class="footer">
Generated on Thu May 24 2012 22:25:56 for QHdrCamera by

 1.7.6.1
</address>


code:
CONFIG += mobility
CONFIG   +=thread
MOBILITY += multimedia

INCLUDEPATH += ./QHdrCamera
DEPENDPATH += ./QHdrCamera

HEADERS += \
    qnativecamera.h \
    videosurface.h \
    qhdrcamera.h

SOURCES += \
    qnativecamera.cpp \
    videosurface.cpp \
    qhdrcamera.cpp

symbian: {

    TARGET.EPOCSTACKSIZE = 0x14000
    TARGET.EPOCHEAPSIZE  = 0x20000 0x8000000

    symbian:TARGET.CAPABILITY += UserEnvironment
    symbian:TARGET.CAPABILITY += ReadUserData

    #TARGET.CAPABILITY += LocalServices ReadUserData WriteUserData UserEnvironment
}

symbian: {
        MMP_RULES += "OPTION gcce -march=armv6"
        MMP_RULES += "OPTION gcce -mfpu=vfp"
        MMP_RULES += "OPTION gcce -mfloat-abi=softfp"
        MMP_RULES += "OPTION gcce -marm"
}


code:
#include "qhdrcamera.h"
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QTimer>
#include <math.h>
#include <QMessageBox>
#include <QDebug>

#include <QScopedPointer>
#include <QSharedPointer>

qreal dt[9]={0.0,1.0,0.0,1.0,-4.0,1.0,0.0,1.0,0.0};
//qreal dt[9]={0.0,-1.0,0.0,-1.0,4.0,-1.0,0.0,-1.0,0.0};
//qreal dt[9]={-1.0,-2.0,-1.0,-2.0,12.0,-2.0,-1.0,-2.0,-1.0};
//qreal dt[9]={0.0,0.0,0.0,0.0,4.0,0.0,0.0,0.0,0.0};
QMatrix3x3 QHdrCamera::convol(dt);

QHdrCamera::QHdrCamera(QDeclarativeItem *parent) :
    QNativeCamera(parent)
   ,m_shots(3)
   ,m_exposureRange(2.0)
{
    shot.clear();
}

float QHdrCamera::brightness( const char r, const char g, const char b){
    // 255 * 0.2126 = 54,213
    // 255 * 0.7152 = 182,376
    // 255 * 0.0722 = 18,411
    return (0.2126*(float)r) + (0.7152*(float)g) + (0.0722*(float)b);
}

float QHdrCamera::gray( const float r, const float g, const float b){
    return (0.299*r + 0.587*g + 0.114*b);
}

float QHdrCamera::saturation( const float r, const float g, const float b){
    float max=r;
    float min=r;

    max = ( g > max ) ? g : max;
    max = ( b > max ) ? b : max;

    min = ( g < min ) ? g : min;
    min = ( b < min ) ? b : min;

    return (max-min);
}

void QHdrCamera::laplace(QImage& in, QImage& out){

    float sumR=0.0,sumG=0.0,sumB=0.0;
    int width = in.bytesPerLine();
    int height = in.height();
    unsigned char* inb  = in.bits();
    unsigned char* outb = out.bits();
    int pixelSize = in.depth()/8;
    int lv=0;

    for(int y=0;y<height;y++){
        for(int x=0;x<width-pixelSize;x+=pixelSize){
            sumR=0.0,sumG=0.0,sumB=0.0;
            for(int h=-1;h<2;h++){
                for(int w=-1;w<2;w++){
                    sumR+=(convol(w+1,h+1)* inb[abs(x+w)+(abs(y+h)*width)]);
                    sumG+=(convol(w+1,h+1)* inb[abs(x+w)+1+(abs(y+h)*width)]);
                    sumB+=(convol(w+1,h+1)* inb[abs(x+w)+2+(abs(y+h)*width)]);
                }
            }

            lv = QHdrCamera::gray(sumR,sumG,sumB);
            lv=(lv<256)?lv:255;
            lv=(lv>0)?lv:0;
            if(lv<70)lv=127;

            outb[x+(y*width)] = abs(lv);
            outb[x+1+(y*width)] = abs(lv);
            outb[x+2+(y*width)] = abs(lv);

        }
    }

}

int QHdrCamera::gauss(QImage& in, QImage& out, double sigma) {

    int ton = 0;
    int width  = in.bytesPerLine();
    int height = in.height();
    double l;
    double R=0.0,G=0.0,B=0.0;
    int lv;

    unsigned char* inb  = in.bits();
    unsigned char* outb = out.bits();
    int pixelSize = in.depth()/8;

    float costant = 2*pow((sigma*255),2);
    float gnu = 0.5*255;

    for(int j=0;j<height;j++){
        for(int i=0;i<width-pixelSize;i+=pixelSize){

            l= ( inb[i+(j*width)]-gnu);
            R=exp(-(l*l)/costant);
            l= ( inb[i+1+(j*width)]-gnu);
            G=exp(-(l*l)/costant);
            l= ( inb[i+2+(j*width)]-gnu);
            B=exp(-(l*l)/costant);
            lv=int(R*G*B*255);
            ton+=lv;

            lv= abs(lv);
            lv= (lv<256)?lv:255;

            //outb[i+(j*width)] = R; outb[i+1+(j*width)] = G; outb[i+2+(j*width)] = B;
            outb[i+(j*width)] = lv; outb[i+1+(j*width)] = lv; outb[i+2+(j*width)] = lv;
        }
    }

    return ton;
}

void QHdrCamera::mul(QVector<QImage*>& ins, QImage& out, int k){
    int count = ins.size();
    if( count > 1 ) {
        unsigned char* outb = out.bits();
        int width     = ins[0]->bytesPerLine();
        int height    = ins[0]->height();
        int pixelSize = ins[0]->depth()/8;
        float red=1,green=1,blue=1;

        for(int j=0;j<height;j++){
            for(int i=0;i<width-pixelSize;i+=pixelSize){
                red=1,green=1,blue=1;

                for(k=0; k < count; k++){
                    red   *= ((float)((unsigned char*)ins[k]->bits())[i+(j*width)])/255.0;
                    green *= ((float)((unsigned char*)ins[k]->bits())[i+1+(j*width)])/255.0;
                    blue  *= ((float)((unsigned char*)ins[k]->bits())[i+2+(j*width)])/255.0;
                }
                red*=(255.0+k); green*=(255.0+k); blue*=(255.0+k);

                outb[i+(j*width)] = qBound((unsigned int)0, (unsigned int)red, (unsigned int)255);
                outb[i+1+(j*width)] = qBound((unsigned int)0, (unsigned int)green, (unsigned int)255);
                outb[i+2+(j*width)] = qBound((unsigned int)0, (unsigned int)blue, (unsigned int)255);
            }
        }
    }
}

void QHdrCamera::add(QVector<QImage*>& ins, QImage& out, bool average){
    int count = ins.size();
    if( count > 1 ) {
        unsigned char* outb = out.bits();
        int width     = ins[0]->bytesPerLine();
        int height    = ins[0]->height();
        int pixelSize = ins[0]->depth()/8;
        int red=0,green=0,blue=0;

        int k = 0;

        QColor c1,c2,c3, cmax;

        for(int j=0;j<height;j++){
            for(int i=0;i<width-pixelSize;i+=pixelSize){
                red=0,green=0,blue=0;

                /*if(average) {
                    c1.setRgb( ((unsigned char*)ins[0]->bits())[i+(j*width)],
                               ((unsigned char*)ins[0]->bits())[i+1+(j*width)],
                               ((unsigned char*)ins[0]->bits())[i+2+(j*width)]
                            );
                    c2.setRgb( ((unsigned char*)ins[1]->bits())[i+(j*width)],
                               ((unsigned char*)ins[1]->bits())[i+1+(j*width)],
                               ((unsigned char*)ins[1]->bits())[i+2+(j*width)]
                            );
                    c3.setRgb( ((unsigned char*)ins[2]->bits())[i+(j*width)],
                               ((unsigned char*)ins[2]->bits())[i+1+(j*width)],
                               ((unsigned char*)ins[2]->bits())[i+2+(j*width)]
                            );
                    cmax=c1;
                    /*if( c2.saturation() > cmax.saturation()) cmax=c2;
                    if( c3.saturation() > cmax.saturation()) cmax=c3;*/

                    /*if( c2.lightness() > cmax.lightness()) cmax=c2;
                    if( c3.lightness() > cmax.lightness()) cmax=c3;*/

                    /*red += cmax.red(); green += cmax.green(); blue += cmax.blue();
                }*/

                for(k=0; k < count; k++){
                    red   += ((unsigned char*)ins[k]->bits())[i+(j*width)];
                    green += ((unsigned char*)ins[k]->bits())[i+1+(j*width)];
                    blue  += ((unsigned char*)ins[k]->bits())[i+2+(j*width)];
                }

                if(average) {
                    //red /=(count+1); green /=(count+1); blue /=(count+1);
                    red /=count; green /=count; blue /=count;
                }

                outb[i+(j*width)] = qBound((int)0, red, (int)255);
                outb[i+1+(j*width)] = qBound((int)0, green, (int)255);
                outb[i+2+(j*width)] = qBound((int)0, blue, (int)255);
            }
        }
    }
}

HdrThread::HdrThread(QImage* image,QImage* result){
    this->image = image;
    this->result = result;
}

void HdrThread::run() {
   // QString timeStamp = QDateTime::currentDateTime().toString("yyyyMMddmmsszzz");

    int width  = image->bytesPerLine();
    int height = image->height();
    int pixelSize = image->depth()/8;

    unsigned char* inb  = image->bits();
    unsigned char* outb = result->bits();

    int R = 0; int G = 0; int B = 0;
    float Rl = 0; float Gl = 0; float Bl = 0;

    //float sigma=0.2; float costant = 2*pow((sigma*255),2); float gnu = 0.5*255; float gray=0; float l=0; float lv= 0;
    int subsample=2;

    for(int j=0,sub_y=0;j<height;j++){
        for(int i=0,sub_x=0;i<width-pixelSize;i+=pixelSize){
            //R= inb[(i-(sub_x*pixelSize))+((j-sub_y)*width)]; G= inb[(i-(sub_x*pixelSize))+1+((j-sub_y)*width)]; B= inb[(i-(sub_x*pixelSize))+2+((j-sub_y)*width)];

            R= inb[i+(j*width)];G= inb[i+1+(j*width)]; B= inb[i+2+(j*width)];

            Rl = qBound(0,((inb[i+(j*width)]+inb[(i-(sub_x*pixelSize))+  ((j-sub_y)*width)])/2)   - inb[(i-(sub_x*pixelSize))+  ((j-sub_y)*width)], 255);
            Gl = qBound(0,((inb[i+1+(j*width)]+inb[(i-(sub_x*pixelSize))+1+((j-sub_y)*width)])/2) - inb[(i-(sub_x*pixelSize))+1+((j-sub_y)*width)],255);
            Bl = qBound(0,((inb[i+2+(j*width)]+inb[(i-(sub_x*pixelSize))+2+((j-sub_y)*width)])/2) - inb[(i-(sub_x*pixelSize))+2+((j-sub_y)*width)],255);

          //l= ( (float)inb[i+(j*width)]-gnu);   Rl=exp(-(l*l)/costant);
          //l= ( (float)inb[i+1+(j*width)]-gnu); Gl=exp(-(l*l)/costant);
          //l= ( (float)inb[i+2+(j*width)]-gnu); Bl=exp(-(l*l)/costant);

            outb[i+(j*width)]   = qBound(0,(int)(Rl),255);
            outb[i+1+(j*width)] = qBound(0,(int)(Gl),255);
            outb[i+2+(j*width)] = qBound(0,(int)(Bl),255);

            sub_x++; if( sub_x >= subsample) sub_x=0;
        }
        sub_y++; if( sub_y >= subsample) sub_y=0;
    }
    //result->save("C:\\Data\\Images\\athread-"+timeStamp+".jpg");
}

/*void HdrThread::run() {
    qDebug() << "thread";

    QString timeStamp = QDateTime::currentDateTime().toString("yyyyMMddmmsszzz");

    QImage tGauss(*image); tGauss.fill(0);
    QImage tLaplace(*image); tLaplace.fill(0);
    QImage tImage(*image); tImage.fill(0);

    //image->save("C:\\Data\\Images\\image-passed-"+timeStamp+".jpg");

    QVector<QImage*> vect;
    //QHdrCamera::gauss(*image, tImage);

    QHdrCamera::gauss(*image, tGauss);
    tGauss.save("C:\\Data\\Images\\gauss-"+timeStamp+".jpg");
    QHdrCamera::laplace(tGauss, tLaplace);
    tLaplace.save("C:\\Data\\Images\\laplace-"+timeStamp+".jpg");
    vect.clear(); vect.push_back(&tGauss);vect.push_back(&tLaplace);// vect.push_back(&tGauss);
    QHdrCamera::mul(vect, tImage);
    //QHdrCamera::add(vect, tImage);
    tImage.save("C:\\Data\\Images\\mul-gauss-laplace-"+timeStamp+".jpg");

    vect.clear(); vect.push_back(&tImage); vect.push_back(image);
    QHdrCamera::mul(vect, *result);

    //result->save("C:\\Data\\Images\\thread"+timeStamp+".jpg");
}*/

/*!
  Capture image with the currently set attributes.
*/
void QHdrCamera::captureImage()
{
    qDebug() << "QHdrCamera capture";
    if (!m_cameraImageCapture) {
        return;
    }

    shot.clear();
    tShot.clear();
    vFrame.clear();
    setExposureCompensation(-this->m_exposureRange);
    m_cameraImageCapture->capture();
}

void QHdrCamera::imageAvailable(int id ,QVideoFrame buffer) {

    /*if( !buffer.map(QAbstractVideoBuffer::ReadOnly) ) qDebug() << "Error during mapping";

    QImage* image = new QImage(); image->loadFromData((const uchar *)buffer.bits(), buffer.mappedBytes(), (const char *)"JPEG");
    image->save("C:\\Data\\Images\\shot"+QString::number(shot.size())+".jpg", "jpeg");

    shot.push_back(image);
    //QImage* tImage = new QImage(*image); tShot.push_back(tImage);

    buffer.unmap();*/
    vFrame.push_back(buffer);
    int shot_size = vFrame.count();

    if( shot_size < this->m_shots ){
        setExposureCompensation(-this->m_exposureRange + (shot_size*this->m_exposureRange));
        QTimer::singleShot(0, m_cameraImageCapture, SLOT(capture()));
    } else {
        setExposureCompensation(0);
        QTimer::singleShot(0, this, SLOT(process()));
    }
}

void QHdrCamera::imageCaptured ( int id, const QImage & preview ) {
    qDebug() << "QHdrCamera::imageCaptured id:" << QString::number(id);
    qDebug() << "preview.width()" << QString::number(preview.width());
    qDebug() << "preview.height()" << QString::number(preview.height());
    qDebug() << "preview.bytesPerLine()" << QString::number(preview.bytesPerLine());

    //preview.save("C:\\Data\\Images\\pippo.jpg", "jpeg");
}

void QHdrCamera::process() {

    qDebug() << "Start processing";
    emit started();

    for( int i = 0 ; i < vFrame.size(); i++ ){
        if( !vFrame[i].map(QAbstractVideoBuffer::ReadOnly) ) qDebug() << "Error during mapping";

            QImage* image = new QImage(); image->loadFromData((const uchar *)vFrame[i].bits(), vFrame[i].mappedBytes(), (const char *)"JPEG");
            //image->save("C:\\Data\\Images\\shot"+QString::number(shot.size())+".jpg", "jpeg");

            shot.push_back(image);

            vFrame[i].unmap();
    }

    QImage result(*shot[0]);// result.fill(0);
    int sz = shot.size();
    for( int i = 0 ; i < sz ; i++){
        QImage* tImage = new QImage(shot[0]->width(), shot[0]->height(), shot[0]->format()); tShot.push_back(tImage);
    }

    QVector<QImage*> vect;

   /* HdrThread* t1 = new HdrThread(shot[0], tShot[0]);
    HdrThread* t2 = new HdrThread(shot[1], tShot[1]);
    HdrThread* t3 = new HdrThread(shot[2], tShot[2]);

    qDebug() << "starting threads";
    QThreadPool::globalInstance()->start(t1);
        //QThreadPool::globalInstance()->waitForDone();
    QThreadPool::globalInstance()->start(t2);
       // QThreadPool::globalInstance()->waitForDone();
    QThreadPool::globalInstance()->start(t3);

    QThreadPool::globalInstance()->waitForDone();
    qDebug() << "All threads finished"; qDebug() << "------------";
*/
    //tImage1.save("C:\\Data\\Images\\aImage1.jpg"); tImage2.save("C:\\Data\\Images\\aImage2.jpg");  tImage3.save("C:\\Data\\Images\\aImage3.jpg");

    vect.clear(); vect.push_back(shot[0]); vect.push_back(shot[1]); vect.push_back(shot[2]);
    //vect.clear(); vect.push_back(&tImage1); vect.push_back(&tImage2); vect.push_back(&tImage3);
    emit merging();
    QHdrCamera::add(vect, result);

    /*vect.clear(); vect.push_back(tShot[0]); vect.push_back(tShot[1]); vect.push_back(tShot[2]); vect.push_back(&result);
    QHdrCamera::add(vect, result,false);
    vect.clear();*/

    QString timeStamp = QDateTime::currentDateTime().toString("yyyyMMddmmss");
    QString savePath = QDir::toNativeSeparators("C:\\Data\\Images\\hdr-"+timeStamp+".jpg");

    if( result.isNull()) qDebug() << "result image null";
    if( result.save(savePath, "jpeg") ) {
        //i_preview.load(savePath);
        i_preview = result;
        qDebug() << "Result image saved";
    } else {
        qDebug() << "Error saving result image to:"<<savePath;
    }

    QString saveOrigPath = QDir::toNativeSeparators("C:/Data/Images/hdr-original-"+timeStamp+".jpg");
    shot[1]->save(saveOrigPath);

    emit finished(savePath,saveOrigPath);

    shot.clear(); tShot.clear();
}

unsigned short QHdrCamera::shots(){
    return m_shots;
}

void QHdrCamera::setShots(unsigned short value){
    this->m_shots = value;
    emit shotsChanged(value);
}

qreal QHdrCamera::exposureRange(){
    return this->m_exposureRange;
}

void QHdrCamera::setExposureRange(qreal value){
    this->m_exposureRange=value;
    emit exposureRangeChanged(value);
}


code:
#ifndef QHDRCAMERA_H
#define QHDRCAMERA_H

#include "QNativeCamera.h"
#include <QGenericMatrix>
#include <QThreadPool>

class HdrThread :public QRunnable
{

public:
    HdrThread(QImage*,QImage*);

private:
    QImage* image;
    QImage* result;

protected:
    void run();
};

class QHdrCamera : public QNativeCamera
{
    Q_OBJECT
    Q_CLASSINFO("Author", "Sebastiano Galazzo")
    Q_CLASSINFO("Email", "sebastiano.galazzo@gmail.com")

    Q_PROPERTY(qreal exposureRange  READ exposureRange  WRITE setExposureRange  NOTIFY exposureRangeChanged)
    Q_PROPERTY(unsigned short shots  READ shots  WRITE setShots NOTIFY shotsChanged)

public:
    explicit QHdrCamera(QDeclarativeItem *parent = 0);

    unsigned short shots();
    void setShots(unsigned short value);

    qreal exposureRange();
    void setExposureRange(qreal value);

    static float brightness( const char r, const char g, const char b);
    //static float gray( const char r, const char g, const char b);
    static float gray( const float r, const float g, const float b);
    static float saturation( const float r, const float g, const float b);
    static void laplace(QImage& in, QImage& out);
    //static int gauss(QImage& in, QImage& out, double sigma=0.35);
    static int gauss(QImage& in, QImage& out, double sigma=0.2);
    static void mul(QVector<QImage*>& ins, QImage& out, int k=0);
    static void add(QVector<QImage*>& ins, QImage& out, bool average=true);

signals:
    void started();
    void finished(QString pathResultImage, QString pathOriginalImage);
    void merging();

    void shotsChanged(int value);
    void exposureRangeChanged(qreal value);

    void processedShot1();
    void processedShot2();
    void processedShot3();

public slots:
    void captureImage();

private slots:
    void process();
    void imageAvailable(int,QVideoFrame);
    void imageCaptured ( int id, const QImage & preview );

private:
    /*QImage shot1;
    QImage shot2;
    QImage shot3;*/
    QVector<QImage*> shot;
    QVector<QImage*> tShot;
    QVector<QVideoFrame> vFrame;

    /*QImage tImage1;
    QImage tImage2;
    QImage tImage3;*/

    unsigned short m_shots;
    qreal m_exposureRange;

    static QMatrix3x3 convol;
};

#endif // QHDRCAMERA_H


code:
#include "qnativecamera.h"
#include "videosurface.h"

#include <QPainter>
#include <QTimer>
#include <QDateTime>
#include <QDebug>

QNativeCamera::QNativeCamera(QDeclarativeItem *parent) :
    QDeclarativeItem(parent)
  ,m_camera(0)
  ,m_frontCamera(false)
  ,m_cameraImageCapture(0)
  ,m_mediaRecorder(0)
  ,m_videoSurface(0)
  ,m_processedFrameCounter(0)
  ,m_incomingFrameCounter(0)
  ,m_preview(false)
{
    // Important, otherwise the paint method is never called
    setFlag(QGraphicsItem::ItemHasNoContents, false);
}

/*!
  Destructor.
*/
QNativeCamera::~QNativeCamera()
{
    destroyResources();
}

/*!
  Releases and destroyes all camera resources.
*/
void QNativeCamera::destroyResources()
{
    if (m_camera) {
        m_camera->stop();
    }

    m_imageFrame = QImage();

    if (m_cameraImageCapture) {
        delete m_cameraImageCapture;
        m_cameraImageCapture = 0;
    }

    if (m_mediaRecorder) {
        delete m_mediaRecorder;
        m_mediaRecorder = 0;
    }

    delete m_camera;
    m_camera = 0;

    m_incomingFrameCounter = 0;
    m_processedFrameCounter = 0;

    m_currentDevice = "";
    emit currentDeviceChanged();
}

/*!
  Returns the list of available devices. Eg. primary camera and front camera.
*/
QStringList QNativeCamera::availableDevices() const
{
        QStringList list;
        foreach (const QByteArray array, QCamera::availableDevices()) {
            list << QString(array);
        }

        return list;
}

/*!
  Returns the state camera is currently.
*/
QNativeCamera::State QNativeCamera::cameraState() const
{
    if (!m_camera) {
        return UnloadedState;
    }

    return State(m_camera->state());
}

/*!
  Starts the camera with the given device. The available devices
  can be queried with the availableDevices method. Starting will release
  and destroy all earlier camera resources before creating new ones.
*/
void QNativeCamera::start(const QString &device)
{
    qDebug() << "Opening device: " << device;

    destroyResources();

    m_camera = new QCamera(device.toLatin1(), this);

    // Make sure the camera is in loaded state.
    //m_camera->load();

    m_videoSurface = new VideoSurface(this, m_camera);
    m_camera->setViewfinder(m_videoSurface);

    // Set the image capturing objects.
    m_cameraImageCapture = new QCameraImageCapture(m_camera);
    connect(m_cameraImageCapture,SIGNAL(imageAvailable(int,QVideoFrame)), this, SLOT(imageAvailable(int,QVideoFrame)));
    connect(m_cameraImageCapture,SIGNAL(imageCaptured(int,QImage)), this, SLOT(imageCaptured(int,QImage)));
    connect(m_cameraImageCapture,SIGNAL(imageExposed(int)), this, SLOT(imageExposed(int)));

    qDebug() << "QVideoFrame::Format_Jpeg: "<<QString::number(QVideoFrame::Format_Jpeg);
    qDebug() << "code buffer format used: "<<QString::number(m_cameraImageCapture->bufferFormat());
    //m_cameraImageCapture->setBufferFormat(QVideoFrame::Format_RGB24); // This is equivalent to QImage::Format_RGB888
    qDebug() << "code buffer format setted: "<<QString::number(m_cameraImageCapture->bufferFormat());
    //m_cameraImageCapture->setCaptureDestination( QCameraImageCapture::CaptureToFile);

    if( m_cameraImageCapture->isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer) )
        qDebug() << "QCameraImageCapture::CaptureToBuffer supported";
    else
        qDebug() << "QCameraImageCapture::CaptureToBuffer NOT supported";

    m_cameraImageCapture->setCaptureDestination( QCameraImageCapture::CaptureToBuffer);

    // The following code finds a 16:9 resolution and sets it as capture
    // resolution. The view finder image should also change to corresponding
    // aspect ratio. On some phones the view finder image does not change
    // immediately but after the first image is captured. On some other
    // phones the view finder image is correct right a way.

    // This code was commented out to prevent sudden change of aspect ratio
    // in viewfinder on some phones.

    // Find resolution that matches to device's full screen, 16:9
    QImageEncoderSettings imageSettings;
    imageSettings.setCodec("image/jpeg");

    QList<QSize> resolutions = m_cameraImageCapture->supportedResolutions();
    //QSize resolution;

    qDebug() << "supported resolutions";

    foreach (const QSize size, resolutions) {
        qDebug() << size.width() << "x" << size.height();
        /*float a = size.width() * 1.0f / (size.height() * 1.0f);
        float b = 640.0f / 360.0f;

        if (qAbs(a - b) <= 0.1f * qMin(qAbs(a), qAbs(b))) {
            resolution = size;
            break;
        }*/
    }

    QList<QVideoFrame::PixelFormat> bformats = m_cameraImageCapture->supportedBufferFormats();
    qDebug() << "QImage::Format_Invalid code: "<<QString::number(QImage::Format_Invalid);
    qDebug() << "founded "<<QString::number(bformats.count()) << "buffer formats";
    foreach (const QVideoFrame::PixelFormat format, bformats) {
        qDebug() << "PixelFormat: " << QString::number(format);
    }

    if (!m_resolution.isNull()) {
        imageSettings.setResolution(m_resolution);

        m_cameraImageCapture->setEncodingSettings(imageSettings);

    }

    // Set the video recording objects.
    m_mediaRecorder = new QMediaRecorder(m_camera);

    m_camera->load();

    // Camera API
    connect(m_camera, SIGNAL(locked()), this, SIGNAL(locked()));
    connect(m_camera, SIGNAL(lockFailed()), this, SIGNAL(lockFailed()));

    //connect(m_camera->focus(), SIGNAL(digitalZoomChanged(qreal)), this, SIGNAL(digitalZoomChanged()));
    //connect(m_camera->focus(), SIGNAL(maximumDigitalZoomChanged(qreal)),this, SIGNAL(maximumDigitalZoomChanged()));

    connect(m_camera->exposure(), SIGNAL(exposureCompensationChanged(qreal)), this, SIGNAL(exposureCompensationChanged()));
    connect(m_camera->exposure(), SIGNAL(isoSensitivityChanged(int)), this, SIGNAL(isoValueChanged()));

    connect(m_camera, SIGNAL(stateChanged(QCamera::State)), this, SLOT(cameraStateChanged(QCamera::State)));
    connect(m_camera, SIGNAL(stateChanged(QCamera::State)), this, SIGNAL(cameraStateChanged()));

    // Image capture API
    connect(m_cameraImageCapture, SIGNAL(imageSaved(int, QString)), this, SLOT(handleImageSaved(int, QString)));

    // Video recording API
    //connect(m_mediaRecorder, SIGNAL(stateChanged(QMediaRecorder::State)), this, SLOT(videoStateChanged(QMediaRecorder::State)));
    //connect(m_mediaRecorder, SIGNAL(error(QMediaRecorder::Error)), this, SLOT(handleVideoError(QMediaRecorder::Error)));

    // Set the initial capture mode to image capturing.
    m_camera->setCaptureMode(QCamera::CaptureStillImage);

    // Begin the receiving of view finder frames.
    m_camera->start();

    m_currentDevice = device;
    emit currentDeviceChanged();

    if (m_currentDevice == availableDevices()[0]) {
        m_frontCamera = false;
    }
    else {
        m_frontCamera = true;
    }

    emit frontCameraChanged();
}

/*!
  Stops the camera and releases all resources.
*/
void QNativeCamera::stop()
{
    destroyResources();
}

void QNativeCamera::imageAvailable(int id ,QVideoFrame buffer) {
    qDebug() << "QNativeCamera captured id:" << QString::number(id);
}

void QNativeCamera::imageCaptured ( int id, const QImage & preview ) {
    qDebug() << "QHdrCamera::imageCaptured id:" << QString::number(id);
}

void QNativeCamera::imageExposed(int id){
    qDebug() << "QHdrCamera::imageExposed id" << QString::number(id) ;
}

/*!
  Returns the current camera in use.
*/
QString QNativeCamera::currentDevice() const
{
    return m_currentDevice;
}

/*!
  Returns true if the secondary camera (front) is in use.
*/
bool QNativeCamera::frontCamera() const
{
    return m_frontCamera;
}

QSize QNativeCamera::resolution(){
    return m_resolution;
}

void QNativeCamera::setResolution(QSize& value){
    m_resolution = value;
    qDebug() << "Setting resolution to "<<QString::number(value.width())<<"x"<<QString::number(value.height());
}

/*!
  Paints the camera view finder frame.
*/
void QNativeCamera::paint(QPainter *painter,
                         const QStyleOptionGraphicsItem *option,
                         QWidget *widget)
{

    Q_UNUSED(option);
    Q_UNUSED(widget);

    if (!m_imageFrame.isNull()) {

        if (m_processedFrameCounter != m_incomingFrameCounter) {
            /*if (m_imageAnalyzer) {
                m_imageAnalyzer->analyze((unsigned int*)m_imageFrame.bits(),
                                         m_imageFrame.width(),
                                         m_imageFrame.height(),
                                         m_imageFrame.bytesPerLine() / 4,
                                         false);
            }*/

            m_processedFrameCounter = m_incomingFrameCounter;
        }

        QPointF upperLeft = boundingRect().center() -
                QPointF(m_imageFrame.width() / 2,
                        m_imageFrame.height() / 2);

        // Draw the black borders.
        painter->fillRect(0, 0, upperLeft.x(), boundingRect().height(),
                          Qt::black);
        painter->fillRect(upperLeft.x() + m_imageFrame.width(), 0,
                          boundingRect().right(), boundingRect().bottom(),
                          Qt::black);

        painter->drawImage(QRect(upperLeft.x(), upperLeft.y(),
                                 m_imageFrame.width(),
                                 m_imageFrame.height()), m_imageFrame);
    }
    else {
        painter->fillRect(boundingRect(), Qt::black);
        qDebug() << "frame null:" << QString::number(m_incomingFrameCounter);
    }

}

/*!
  Stores the frame as member to allow it to be processed on paint.
  Returns false when there is error, otherwise returns true.
*/
bool QNativeCamera::updateFrame(const QVideoFrame &frame)
{
    if( m_preview ) {
        if (m_processedFrameCounter != m_incomingFrameCounter) {
            // Discard frame.
            return true;
        }
        m_incomingFrameCounter++;
        m_imageFrame = i_preview.scaled(frame.width(), frame.height()).convertToFormat(QImage::Format_RGB32);
        //m_imageFrame = i_preview.convertToFormat(QImage::Format_RGB32);

        update();
        //qDebug() << "preview:" << QString::number(m_incomingFrameCounter);
    } else {
        if (!frame.isValid()) {
            qDebug() << "CustomCameras::updateFrame: Invalid frame";
            return false;
        }

        if (m_processedFrameCounter != m_incomingFrameCounter) {
            // Discard frame.
            return true;
        }

        m_incomingFrameCounter++;

        QVideoFrame f = frame;

        if (f.map(QAbstractVideoBuffer::ReadOnly)) {
            if (m_imageFrame.isNull() || m_imageFrame.width() != f.width() ||
                    m_imageFrame.height() != f.height()) {
                m_imageFrame = QImage(f.width(), f.height(), QImage::Format_RGB32);
            }

            memcpy(m_imageFrame.bits(), f.bits(), f.mappedBytes());

            f.unmap();

            update();
        }
    }

    return true;
}

/*!
  Capture image with the currently set attributes.
*/
void QNativeCamera::captureImage()
{
    qDebug() << "QNativeCamera capture";
    if (!m_cameraImageCapture) {
        return;
    }

    QString fileName =
            QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss.jpg");

    m_cameraImageCapture->capture(fileName);
}

/*!
  Handles the image saved signal. Emits imageSaved signal delayed, this must be
  done in order to be possible to stop the camera from the QML. If
  QCameraImageCapture::imageSaved signal was directly connected to the QML and
  the camera would be stopped, the applcication would crash as the stop will
  destroye the QCameraImageCapture instance.
*/
void QNativeCamera::handleImageSaved(int id, const QString &fileName)
{
    Q_UNUSED(id);

    m_galleryImage = fileName;
    i_preview.load(fileName);
    QTimer::singleShot(0, this, SLOT(emitImageSavedSignal()));
}

/*!
  Emits imageSaved signal.
*/
void QNativeCamera::emitImageSavedSignal()
{
    emit imageSaved(m_galleryImage);
}

/*!
  Gets info about the state change. When the camera is loaded we must emit
  the camera API signal in order to QML side to know about the changed camera.
*/
void QNativeCamera::cameraStateChanged(QCamera::State state)
{
    if (state == QCamera::ActiveState) {
        emit digitalZoomChanged();
        emit maximumDigitalZoomChanged();

        emit exposureCompensationChanged();
        emit exposureModeChanged();
        emit supportedExposureModesChanged();

        emit flashModeChanged();
        emit supportedFlashModesChanged();

        emit isoValueChanged();
        emit supportedIsoValuesChanged();

        emit whiteBalanceModeChanged();
        emit supportedWhiteBalanceModesChanged();
       // emit sharpeningLevelChanged();
       // emit contrastChanged();
    }
}

qreal QNativeCamera::exposureCompensation(){
    return this->m_exposureCompensation;
}

void  QNativeCamera::setExposureCompensation(qreal value){
    this->m_exposureCompensation=value;
    this->m_camera->exposure()->setExposureCompensation(this->m_exposureCompensation);
    emit exposureCompensationChanged();
    qDebug() << "QNativeCamera: exposure compensation passed:" << QString::number(value);
    qDebug() << "QNativeCamera: exposure compensation:" << QString::number(m_camera->exposure()->aperture());
}

bool QNativeCamera::preview(){
    return m_preview;
}

void QNativeCamera::setPreview(bool value){
    m_preview=value;
}


code:
#ifndef QNATIVECAMERA_H
#define QNATIVECAMERA_H

#include <QDeclarativeItem>
#include <QVideoFrame>
#include <QCamera>
#include <QCameraImageCapture>
#include <QMediaRecorder>

QT_USE_NAMESPACE

class VideoSurface;

// Observer design pattern to provide the view finder frame for the CustomCamera
// object.
class FrameObserver {
public:
    virtual bool updateFrame(const QVideoFrame &frame) = 0;
};

class QNativeCamera : public QDeclarativeItem, FrameObserver
{
    Q_OBJECT

    Q_ENUMS(State)

    // State properties
    Q_PROPERTY(State cameraState READ cameraState NOTIFY cameraStateChanged)

    // Devices properties
    Q_PROPERTY(QStringList availableDevices READ availableDevices)

    Q_PROPERTY(QString currentDevice READ currentDevice NOTIFY currentDeviceChanged)
    Q_PROPERTY(bool frontCamera READ frontCamera NOTIFY frontCameraChanged)
    Q_PROPERTY(bool preview READ preview WRITE setPreview)
    Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
    Q_PROPERTY(qreal exposureCompensation  READ exposureCompensation  WRITE setExposureCompensation  NOTIFY exposureCompensationChanged)

public:

    enum State {
        ActiveState = QCamera::ActiveState,
        LoadedState = QCamera::LoadedState,
        UnloadedState = QCamera::UnloadedState
    };

    explicit QNativeCamera(QDeclarativeItem *parent = 0);
    ~QNativeCamera();

    QStringList availableDevices() const;

    virtual void paint(QPainter *painter,
                       const QStyleOptionGraphicsItem *option,
                       QWidget *widget);

    virtual bool updateFrame(const QVideoFrame &frame);

    QSize resolution();
    void setResolution(QSize& value);

    qreal exposureCompensation();
    void  setExposureCompensation(qreal);

    bool preview();
    void setPreview(bool value);

protected:
    void destroyResources();
    State cameraState() const;
    QString currentDevice() const;
    bool frontCamera() const;

signals:
    void resolutionChanged(QSize resolution);

    void digitalZoomChanged();
    void maximumDigitalZoomChanged();

    void exposureCompensationChanged();
    void exposureModeChanged();
    void supportedExposureModesChanged();

    void flashModeChanged();
    void supportedFlashModesChanged();

    void locked();
    void lockFailed();

    void isoValueChanged();
    void supportedIsoValuesChanged();

    void imageSaved(const QString &fileName);

    void cameraStateChanged();

    void whiteBalanceModeChanged();
    void supportedWhiteBalanceModesChanged();
    //void sharpeningLevelChanged();
    //void contrastChanged();

    void currentDeviceChanged();
    void frontCameraChanged();

    //void imageAnalyzerChanged();

public slots:
    void start(const QString &device);
    void stop();

    void cameraStateChanged(QCamera::State state);
    void handleImageSaved(int id, const QString &fileName);
    virtual void captureImage();
    virtual void imageAvailable(int,QVideoFrame);
    virtual void imageCaptured ( int id, const QImage & preview );
    virtual void imageExposed(int);

    void emitImageSavedSignal();

protected:
    qreal m_exposureCompensation;

    QCamera *m_camera; // Owned

    QString m_currentDevice;
    bool m_frontCamera;
    // Still image capturing
    QCameraImageCapture *m_cameraImageCapture; // Owned

    // Video capturing
    QMediaRecorder *m_mediaRecorder; // Owned

    // For showing view finder image
    VideoSurface *m_videoSurface; // Owned

    // For storing the latest frame
    unsigned int m_processedFrameCounter;
    unsigned int m_incomingFrameCounter;
    QImage m_imageFrame;
    QImage i_preview;
    bool m_preview;

    // File to be opened in the gallery.
    QString m_galleryImage;
    QSize m_resolution;
};

#endif // QNATIVECAMERA_H


code:
/**
 * Copyright (c) 2012 Nokia Corporation.
 */

#include "videosurface.h"

#include <QtGui>
#include "qnativecamera.h"

/*!
  \class VideoSurface
  \brief Receives the frames from the camera.
*/

/*!
  Constructor.
*/
VideoSurface::VideoSurface(FrameObserver *frameObserver, QObject *parent)
    : QAbstractVideoSurface(parent),
      m_frameObserver(frameObserver)
{
    setError(QAbstractVideoSurface::NoError);
}

/*!
  Destructor.
*/
VideoSurface::~VideoSurface()
{
}

/*!
  Sets the list of supported pixel formats that we are intrested of.
*/
QList<QVideoFrame::PixelFormat> VideoSurface::supportedPixelFormats(
        QAbstractVideoBuffer::HandleType handleType) const
{
    Q_UNUSED(handleType);

    return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_ARGB32;
}

/*!
  Starts the receiving of the frames for the view finder.
*/
bool VideoSurface::start(const QVideoSurfaceFormat &format)
{
    if (isActive()) {
        stop();
    }

    if (format.frameSize().isEmpty()) {
        return false;
    }

    if (error() == QAbstractVideoSurface::NoError) {
        return QAbstractVideoSurface::start(format);
    }
    else {
        stop();

    }

    return false;
}

/*!
  Handles the just taken frame from camera and passes it to the observer.
  Returning false will stop the surface.
*/
bool VideoSurface::present(const QVideoFrame &frame)
{
    return m_frameObserver->updateFrame(frame);
}


code:
/**
 * Copyright (c) 2012 Nokia Corporation.
 */

#ifndef VIDEOSURFACE_H
#define VIDEOSURFACE_H

#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>

class FrameObserver;

class VideoSurface : public QAbstractVideoSurface
{
    Q_OBJECT
public:
    explicit VideoSurface(FrameObserver *frameObserver, QObject *parent = 0);
    virtual ~VideoSurface();

    virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
    virtual bool present(const QVideoFrame &frame);
    virtual bool start(const QVideoSurfaceFormat &format);

protected:
    FrameObserver *m_frameObserver; // Not owned
};

#endif // VIDEOSURFACE_H


code:
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

path: .gitignore


code:
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar


code:
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------

# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
#   JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
#   M2_HOME - location of maven2's installed home dir
#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
#     e.g. to debug Maven itself, use
#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------

if [ -z "$MAVEN_SKIP_RC" ] ; then

  if [ -f /usr/local/etc/mavenrc ] ; then
    . /usr/local/etc/mavenrc
  fi

  if [ -f /etc/mavenrc ] ; then
    . /etc/mavenrc
  fi

  if [ -f "$HOME/.mavenrc" ] ; then
    . "$HOME/.mavenrc"
  fi

fi

# OS specific support.  $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
  CYGWIN*) cygwin=true ;;
  MINGW*) mingw=true;;
  Darwin*) darwin=true
    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
    if [ -z "$JAVA_HOME" ]; then
      if [ -x "/usr/libexec/java_home" ]; then
        export JAVA_HOME="`/usr/libexec/java_home`"
      else
        export JAVA_HOME="/Library/Java/Home"
      fi
    fi
    ;;
esac

if [ -z "$JAVA_HOME" ] ; then
  if [ -r /etc/gentoo-release ] ; then
    JAVA_HOME=`java-config --jre-home`
  fi
fi

if [ -z "$M2_HOME" ] ; then
  ## resolve links - $0 may be a link to maven's home
  PRG="$0"

  # need this for relative symlinks
  while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
      PRG="$link"
    else
      PRG="`dirname "$PRG"`/$link"
    fi
  done

  saveddir=`pwd`

  M2_HOME=`dirname "$PRG"`/..

  # make it fully qualified
  M2_HOME=`cd "$M2_HOME" && pwd`

  cd "$saveddir"
  # echo Using m2 at $M2_HOME
fi

# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --unix "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi

# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME="`(cd "$M2_HOME"; pwd)`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi

if [ -z "$JAVA_HOME" ]; then
  javaExecutable="`which javac`"
  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
    # readlink(1) is not available as standard on Solaris 10.
    readLink=`which readlink`
    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
      if $darwin ; then
        javaHome="`dirname \"$javaExecutable\"`"
        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
      else
        javaExecutable="`readlink -f \"$javaExecutable\"`"
      fi
      javaHome="`dirname \"$javaExecutable\"`"
      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
      JAVA_HOME="$javaHome"
      export JAVA_HOME
    fi
  fi
fi

if [ -z "$JAVACMD" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  else
    JAVACMD="`\\unset -f command; \\command -v java`"
  fi
fi

if [ ! -x "$JAVACMD" ] ; then
  echo "Error: JAVA_HOME is not defined correctly." >&2
  echo "  We cannot execute $JAVACMD" >&2
  exit 1
fi

if [ -z "$JAVA_HOME" ] ; then
  echo "Warning: JAVA_HOME environment variable is not set."
fi

CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher

# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {

  if [ -z "$1" ]
  then
    echo "Path not specified to find_maven_basedir"
    return 1
  fi

  basedir="$1"
  wdir="$1"
  while [ "$wdir" != '/' ] ; do
    if [ -d "$wdir"/.mvn ] ; then
      basedir=$wdir
      break
    fi
    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
    if [ -d "${wdir}" ]; then
      wdir=`cd "$wdir/.."; pwd`
    fi
    # end of workaround
  done
  echo "${basedir}"
}

# concatenates all lines of a file
concat_lines() {
  if [ -f "$1" ]; then
    echo "$(tr -s '\n' ' ' < "$1")"
  fi
}

BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
  exit 1;
fi

##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Found .mvn/wrapper/maven-wrapper.jar"
    fi
else
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
    fi
    if [ -n "$MVNW_REPOURL" ]; then
      jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
    else
      jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
    fi
    while IFS="=" read key value; do
      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
      esac
    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Downloading from: $jarUrl"
    fi
    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
    if $cygwin; then
      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
    fi

    if command -v wget > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found wget ... using wget"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
        else
            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
        fi
    elif command -v curl > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found curl ... using curl"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            curl -o "$wrapperJarPath" "$jarUrl" -f
        else
            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
        fi

    else
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Falling back to using Java to download"
        fi
        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
        # For Cygwin, switch paths to Windows format before running javac
        if $cygwin; then
          javaClass=`cygpath --path --windows "$javaClass"`
        fi
        if [ -e "$javaClass" ]; then
            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Compiling MavenWrapperDownloader.java ..."
                fi
                # Compiling the Java class
                ("$JAVA_HOME/bin/javac" "$javaClass")
            fi
            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                # Running the downloader
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Running MavenWrapperDownloader.java ..."
                fi
                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
            fi
        fi
    fi
fi
##########################################################################################
# End of extension
##########################################################################################

export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
  echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"

# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --path --windows "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi

# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS

WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain

exec "$JAVACMD" \
  $MAVEN_OPTS \
  $MAVEN_DEBUG_OPTS \
  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
  "-Dmaven.home=${M2_HOME}" \
  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

path: mvnw


code:
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements.  See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership.  The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License.  You may obtain a copy of the License at
@REM
@REM    https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied.  See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------

@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM     e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------

@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%

@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")

@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre

@setlocal

set ERROR_CODE=0

@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal

@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome

echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error

:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init

echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error

@REM ==== END VALIDATION ====

:init

@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.

set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir

set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir

:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir

:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"

:endDetectBaseDir

IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig

@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%

:endReadAdditionalConfig

SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain

set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"

FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)

@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
    if "%MVNW_VERBOSE%" == "true" (
        echo Found %WRAPPER_JAR%
    )
) else (
    if not "%MVNW_REPOURL%" == "" (
        SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
    )
    if "%MVNW_VERBOSE%" == "true" (
        echo Couldn't find %WRAPPER_JAR%, downloading it ...
        echo Downloading from: %DOWNLOAD_URL%
    )

    powershell -Command "&{"^
		"$webclient = new-object System.Net.WebClient;"^
		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
		"}"^
		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
		"}"
    if "%MVNW_VERBOSE%" == "true" (
        echo Finished downloading %WRAPPER_JAR%
    )
)
@REM End of extension

@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*

%MAVEN_JAVA_EXE% ^
  %JVM_CONFIG_MAVEN_PROPS% ^
  %MAVEN_OPTS% ^
  %MAVEN_DEBUG_OPTS% ^
  -classpath %WRAPPER_JAR% ^
  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end

:error
set ERROR_CODE=1

:end
@endlocal & set ERROR_CODE=%ERROR_CODE%

if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost

@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause

if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%

cmd /C exit /B %ERROR_CODE%


code:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.9</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.kubyshka</groupId>
	<artifactId>kubyshka</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>kubyshka</name>
	<description>Java Spring Boot applications to monitor your savings.</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.32</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mustache</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>


code:
package com.kubyshka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class KubyshkaApplication {

	public static void main(String[] args) {
		SpringApplication.run(KubyshkaApplication.class, args);
	}

}


code:
package com.kubyshka.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
    }

}


code:
package com.kubyshka.config;

import com.kubyshka.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/", "/css/**", "/fonts/**", "/images/**", "/js/**", "/plugins/**").permitAll()
                    .anyRequest().authenticated()
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/savings", true)
                    .permitAll()
                .and()
                    .logout()
                    .logoutSuccessUrl("/")
                    .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService)
                .passwordEncoder(NoOpPasswordEncoder.getInstance());
    }
}


code:
package com.kubyshka.controller;

import com.kubyshka.entity.Saving;
import com.kubyshka.entity.User;
import com.kubyshka.repositories.SavingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.Set;

@Controller
public class MainController {
    @Autowired
    private SavingRepository savingRepository;

    @GetMapping("/")
    public String home(Map<String, Object> model) {
        return "home";
    }

    @GetMapping("/savings")
    public String savingPage(
            @AuthenticationPrincipal User user,
            Model model) {
        Set<Saving> savings = user.getSavings();
        model.addAttribute("savings", savings);
        return "savings";
    }

    @GetMapping("/editsavings")
    public String editSavingPage(Map<String, Object> model) {
        Iterable<Saving> savings = savingRepository.findAll();
        model.put("savings", savings);
        return "editsavings";
    }

    @RequestMapping("/updatesavings")
    public String updateSaving(Map<String, Object> model) {
        Iterable<Saving> savings = savingRepository.findAll();
        model.put("savings", savings);
        return "editsavings";
    }

    @GetMapping("/addsavings")
    public String addSavingPage(Map<String, Object> model) {
        return "addsavings";
    }

    @PostMapping("/addsavings")
    public String addSaving(
            @AuthenticationPrincipal User user,
            @RequestParam String saving_name,
            @RequestParam Float amount,
            @RequestParam String currency_name,
            @RequestParam String saving_type,
            Map<String, Object> model) {
        Saving saving = new Saving(saving_name, amount, currency_name, saving_type, user);
        savingRepository.save(saving);
        return "redirect:/savings";
    }
}


code:
package com.kubyshka.controller;

import com.kubyshka.entity.Role;
import com.kubyshka.entity.User;
import com.kubyshka.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.Collections;
import java.util.Map;

@Controller
public class RegistrationController {
    @Autowired
    private UserRepository userRepository;
    @GetMapping("/registration")
    public String registration() {
        return "registration";
    }
    @PostMapping("/registration")
    public String addUser(User user, Map<String, Object> model) {
        User userFromDB = userRepository.findByUsername(user.getUsername());
        if (userFromDB != null) {
            model.put("message", "Такой пользователь уже зарегистрирован!");
            return "registration";
        }
        user.setActive(true);
        user.setRoles(Collections.singleton(Role.USER));
        userRepository.save(user);

        return "redirect:/login";
    }
}


code:
package com.kubyshka.entity;

import org.springframework.security.core.GrantedAuthority;

public enum Role implements GrantedAuthority {
    USER;

    @Override
    public String getAuthority() {
        return name();
    }
}


code:
package com.kubyshka.entity;

import javax.persistence.*;

@Entity
public class Saving {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String saving_name;

    private Float amount;

    private String currency_name;

    private String saving_type;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id")
    private User author;

    public Saving() {
    }

    public Saving(String saving_name, Float amount, String currency_name, String saving_type, User user) {
        this.author = user;
        this.saving_name = saving_name;
        this.amount = amount;
        this.currency_name = currency_name;
        this.saving_type = saving_type;
    }

    public String getAuthorName() {
        return author != null ? author.getUsername() : "<ничьё>";
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getSaving_name() {
        return saving_name;
    }

    public void setSaving_name(String saving_name) {
        this.saving_name = saving_name;
    }

    public Float getAmount() {
        return amount;
    }

    public void setAmount(Float amount) {
        this.amount = amount;
    }

    public String getCurrency_name() {
        return currency_name;
    }

    public void setCurrency_name(String currency_name) {
        this.currency_name = currency_name;
    }

    public String getSaving_type() {
        return saving_type;
    }

    public void setSaving_type(String saving_type) {
        this.saving_type = saving_type;
    }

    public User getAuthor() {
        return author;
    }

    public void setAuthor(User author) {
        this.author = author;
    }
}


code:
package com.kubyshka.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import java.util.Collection;
import java.util.Set;

@Entity
@Table(name = "usr")
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String username;
    private String password;
    private boolean active;

    @ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
    @CollectionTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"))
    @Enumerated(EnumType.STRING)
    private Set<Role> roles;

    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Saving> savings;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return isActive();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return getRoles();
    }

    public Set<Saving> getSavings() {
        return savings;
    }

    public void setSavings(Set<Saving> savings) {
        this.savings = savings;
    }
}


code:
package com.kubyshka.repositories;

import com.kubyshka.entity.Saving;
import org.springframework.data.repository.CrudRepository;

public interface SavingRepository extends CrudRepository<Saving, Long> {

}


code:
package com.kubyshka.repositories;

import com.kubyshka.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}


code:
package com.kubyshka.service;

import com.kubyshka.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findByUsername(username);
    }
}


code:
# ????
spring.jpa.hibernate.ddl-auto=update
# Параметры БД
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/kubyshka_db
spring.datasource.username=kubyshka_user
spring.datasource.password=flVxaW2Uwo6MleFUbFwiRsLH9SO-ID
# Подключения драйвера jdbc
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Создаем БД сами, а ее структуру spring формирует сам
spring.jpa.generate-ddl=true
#Для корректного отображения кирилицы
server.servlet.encoding.force=true

spring.mustache.servlet.expose-request-attributes=true


code:
@charset "UTF-8";

@font-face {
  font-family: "pct";
  src:url("fonts/pct.eot");
  src:url("fonts/pct.eot?#iefix") format("embedded-opentype"),
    url("fonts/pct.woff") format("woff"),
    url("fonts/pct.ttf") format("truetype"),
    url("fonts/pct.svg#pct") format("svg");
  font-weight: normal;
  font-style: normal;

}

[data-icon]:before {
  font-family: "pct" !important;
  content: attr(data-icon);
  font-style: normal !important;
  font-weight: normal !important;
  font-variant: normal !important;
  text-transform: none !important;
  speak: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

[class^="pct-"]:before,
[class*=" pct-"]:before {
  font-family: "pct" !important;
  font-style: normal !important;
  font-weight: normal !important;
  font-variant: normal !important;
  text-transform: none !important;
  speak: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.pct-arrow1:before {
  content: "\61";
}
.pct-arrow2:before {
  content: "\62";
}
.pct-arrow3:before {
  content: "\63";
}
.pct-arrow4:before {
  content: "\64";
}
.pct-chat1:before {
  content: "\65";
}
.pct-chat2:before {
  content: "\66";
}
.pct-chat3:before {
  content: "\67";
}
.pct-chat4:before {
  content: "\68";
}
.pct-loader1:before {
  content: "\69";
}
.pct-arrow-sharp1:before {
  content: "\6a";
}
.pct-arrow-sharp2:before {
  content: "\6b";
}
.pct-arrow-sharp3:before {
  content: "\6c";
}
.pct-arrow-sharp4:before {
  content: "\6d";
}


code:
@font-face {
  font-family: "feather";
  src: url('../fonts/feather.eot?t=1501841394106'); /* IE9*/
  src: url('../fonts/feather.eot?t=1501841394106#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('../fonts/feather.woff?t=1501841394106') format('woff'), /* chrome, firefox */
  url('../fonts/feather.ttf?t=1501841394106') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
  url('../fonts/feather.svg?t=1501841394106#feather') format('svg'); /* iOS 4.1- */
}

.feather {
  /* use !important to prevent issues with browser extensions that change fonts */
  font-family: 'feather' !important;
  speak: none;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;

  /* Better Font Rendering =========== */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-alert-octagon:before { content: "\e81b"; }

.icon-alert-circle:before { content: "\e81c"; }

.icon-activity:before { content: "\e81d"; }

.icon-alert-triangle:before { content: "\e81e"; }

.icon-align-center:before { content: "\e81f"; }

.icon-airplay:before { content: "\e820"; }

.icon-align-justify:before { content: "\e821"; }

.icon-align-left:before { content: "\e822"; }

.icon-align-right:before { content: "\e823"; }

.icon-arrow-down-left:before { content: "\e824"; }

.icon-arrow-down-right:before { content: "\e825"; }

.icon-anchor:before { content: "\e826"; }

.icon-aperture:before { content: "\e827"; }

.icon-arrow-left:before { content: "\e828"; }

.icon-arrow-right:before { content: "\e829"; }

.icon-arrow-down:before { content: "\e82a"; }

.icon-arrow-up-left:before { content: "\e82b"; }

.icon-arrow-up-right:before { content: "\e82c"; }

.icon-arrow-up:before { content: "\e82d"; }

.icon-award:before { content: "\e82e"; }

.icon-bar-chart:before { content: "\e82f"; }

.icon-at-sign:before { content: "\e830"; }

.icon-bar-chart-2:before { content: "\e831"; }

.icon-battery-charging:before { content: "\e832"; }

.icon-bell-off:before { content: "\e833"; }

.icon-battery:before { content: "\e834"; }

.icon-bluetooth:before { content: "\e835"; }

.icon-bell:before { content: "\e836"; }

.icon-book:before { content: "\e837"; }

.icon-briefcase:before { content: "\e838"; }

.icon-camera-off:before { content: "\e839"; }

.icon-calendar:before { content: "\e83a"; }

.icon-bookmark:before { content: "\e83b"; }

.icon-box:before { content: "\e83c"; }

.icon-camera:before { content: "\e83d"; }

.icon-check-circle:before { content: "\e83e"; }

.icon-check:before { content: "\e83f"; }

.icon-check-square:before { content: "\e840"; }

.icon-cast:before { content: "\e841"; }

.icon-chevron-down:before { content: "\e842"; }

.icon-chevron-left:before { content: "\e843"; }

.icon-chevron-right:before { content: "\e844"; }

.icon-chevron-up:before { content: "\e845"; }

.icon-chevrons-down:before { content: "\e846"; }

.icon-chevrons-right:before { content: "\e847"; }

.icon-chevrons-up:before { content: "\e848"; }

.icon-chevrons-left:before { content: "\e849"; }

.icon-circle:before { content: "\e84a"; }

.icon-clipboard:before { content: "\e84b"; }

.icon-chrome:before { content: "\e84c"; }

.icon-clock:before { content: "\e84d"; }

.icon-cloud-lightning:before { content: "\e84e"; }

.icon-cloud-drizzle:before { content: "\e84f"; }

.icon-cloud-rain:before { content: "\e850"; }

.icon-cloud-off:before { content: "\e851"; }

.icon-codepen:before { content: "\e852"; }

.icon-cloud-snow:before { content: "\e853"; }

.icon-compass:before { content: "\e854"; }

.icon-copy:before { content: "\e855"; }

.icon-corner-down-right:before { content: "\e856"; }

.icon-corner-down-left:before { content: "\e857"; }

.icon-corner-left-down:before { content: "\e858"; }

.icon-corner-left-up:before { content: "\e859"; }

.icon-corner-up-left:before { content: "\e85a"; }

.icon-corner-up-right:before { content: "\e85b"; }

.icon-corner-right-down:before { content: "\e85c"; }

.icon-corner-right-up:before { content: "\e85d"; }

.icon-cpu:before { content: "\e85e"; }

.icon-credit-card:before { content: "\e85f"; }

.icon-crosshair:before { content: "\e860"; }

.icon-disc:before { content: "\e861"; }

.icon-delete:before { content: "\e862"; }

.icon-download-cloud:before { content: "\e863"; }

.icon-download:before { content: "\e864"; }

.icon-droplet:before { content: "\e865"; }

.icon-edit-2:before { content: "\e866"; }

.icon-edit:before { content: "\e867"; }

.icon-edit-1:before { content: "\e868"; }

.icon-external-link:before { content: "\e869"; }

.icon-eye:before { content: "\e86a"; }

.icon-feather:before { content: "\e86b"; }

.icon-facebook:before { content: "\e86c"; }

.icon-file-minus:before { content: "\e86d"; }

.icon-eye-off:before { content: "\e86e"; }

.icon-fast-forward:before { content: "\e86f"; }

.icon-file-text:before { content: "\e870"; }

.icon-film:before { content: "\e871"; }

.icon-file:before { content: "\e872"; }

.icon-file-plus:before { content: "\e873"; }

.icon-folder:before { content: "\e874"; }

.icon-filter:before { content: "\e875"; }

.icon-flag:before { content: "\e876"; }

.icon-globe:before { content: "\e877"; }

.icon-grid:before { content: "\e878"; }

.icon-heart:before { content: "\e879"; }

.icon-home:before { content: "\e87a"; }

.icon-github:before { content: "\e87b"; }

.icon-image:before { content: "\e87c"; }

.icon-inbox:before { content: "\e87d"; }

.icon-layers:before { content: "\e87e"; }

.icon-info:before { content: "\e87f"; }

.icon-instagram:before { content: "\e880"; }

.icon-layout:before { content: "\e881"; }

.icon-link-2:before { content: "\e882"; }

.icon-life-buoy:before { content: "\e883"; }

.icon-link:before { content: "\e884"; }

.icon-log-in:before { content: "\e885"; }

.icon-list:before { content: "\e886"; }

.icon-lock:before { content: "\e887"; }

.icon-log-out:before { content: "\e888"; }

.icon-loader:before { content: "\e889"; }

.icon-mail:before { content: "\e88a"; }

.icon-maximize-2:before { content: "\e88b"; }

.icon-map:before { content: "\e88c"; }

.icon-map-pin:before { content: "\e88e"; }

.icon-menu:before { content: "\e88f"; }

.icon-message-circle:before { content: "\e890"; }

.icon-message-square:before { content: "\e891"; }

.icon-minimize-2:before { content: "\e892"; }

.icon-mic-off:before { content: "\e893"; }

.icon-minus-circle:before { content: "\e894"; }

.icon-mic:before { content: "\e895"; }

.icon-minus-square:before { content: "\e896"; }

.icon-minus:before { content: "\e897"; }

.icon-moon:before { content: "\e898"; }

.icon-monitor:before { content: "\e899"; }

.icon-more-vertical:before { content: "\e89a"; }

.icon-more-horizontal:before { content: "\e89b"; }

.icon-move:before { content: "\e89c"; }

.icon-music:before { content: "\e89d"; }

.icon-navigation-2:before { content: "\e89e"; }

.icon-navigation:before { content: "\e89f"; }

.icon-octagon:before { content: "\e8a0"; }

.icon-package:before { content: "\e8a1"; }

.icon-pause-circle:before { content: "\e8a2"; }

.icon-pause:before { content: "\e8a3"; }

.icon-percent:before { content: "\e8a4"; }

.icon-phone-call:before { content: "\e8a5"; }

.icon-phone-forwarded:before { content: "\e8a6"; }

.icon-phone-missed:before { content: "\e8a7"; }

.icon-phone-off:before { content: "\e8a8"; }

.icon-phone-incoming:before { content: "\e8a9"; }

.icon-phone:before { content: "\e8aa"; }

.icon-phone-outgoing:before { content: "\e8ab"; }

.icon-pie-chart:before { content: "\e8ac"; }

.icon-play-circle:before { content: "\e8ad"; }

.icon-play:before { content: "\e8ae"; }

.icon-plus-square:before { content: "\e8af"; }

.icon-plus-circle:before { content: "\e8b0"; }

.icon-plus:before { content: "\e8b1"; }

.icon-pocket:before { content: "\e8b2"; }

.icon-printer:before { content: "\e8b3"; }

.icon-power:before { content: "\e8b4"; }

.icon-radio:before { content: "\e8b5"; }

.icon-repeat:before { content: "\e8b6"; }

.icon-refresh-ccw:before { content: "\e8b7"; }

.icon-rewind:before { content: "\e8b8"; }

.icon-rotate-ccw:before { content: "\e8b9"; }

.icon-refresh-cw:before { content: "\e8ba"; }

.icon-rotate-cw:before { content: "\e8bb"; }

.icon-save:before { content: "\e8bc"; }

.icon-search:before { content: "\e8bd"; }

.icon-server:before { content: "\e8be"; }

.icon-scissors:before { content: "\e8bf"; }

.icon-share-2:before { content: "\e8c0"; }

.icon-share:before { content: "\e8c1"; }

.icon-shield:before { content: "\e8c2"; }

.icon-settings:before { content: "\e8c3"; }

.icon-skip-back:before { content: "\e8c4"; }

.icon-shuffle:before { content: "\e8c5"; }

.icon-sidebar:before { content: "\e8c6"; }

.icon-skip-forward:before { content: "\e8c7"; }

.icon-slack:before { content: "\e8c8"; }

.icon-slash:before { content: "\e8c9"; }

.icon-smartphone:before { content: "\e8ca"; }

.icon-square:before { content: "\e8cb"; }

.icon-speaker:before { content: "\e8cc"; }

.icon-star:before { content: "\e8cd"; }

.icon-stop-circle:before { content: "\e8ce"; }

.icon-sun:before { content: "\e8cf"; }

.icon-sunrise:before { content: "\e8d0"; }

.icon-tablet:before { content: "\e8d1"; }

.icon-tag:before { content: "\e8d2"; }

.icon-sunset:before { content: "\e8d3"; }

.icon-target:before { content: "\e8d4"; }

.icon-thermometer:before { content: "\e8d5"; }

.icon-thumbs-up:before { content: "\e8d6"; }

.icon-thumbs-down:before { content: "\e8d7"; }

.icon-toggle-left:before { content: "\e8d8"; }

.icon-toggle-right:before { content: "\e8d9"; }

.icon-trash-2:before { content: "\e8da"; }

.icon-trash:before { content: "\e8db"; }

.icon-trending-up:before { content: "\e8dc"; }

.icon-trending-down:before { content: "\e8dd"; }

.icon-triangle:before { content: "\e8de"; }

.icon-type:before { content: "\e8df"; }

.icon-twitter:before { content: "\e8e0"; }

.icon-upload:before { content: "\e8e1"; }

.icon-umbrella:before { content: "\e8e2"; }

.icon-upload-cloud:before { content: "\e8e3"; }

.icon-unlock:before { content: "\e8e4"; }

.icon-user-check:before { content: "\e8e5"; }

.icon-user-minus:before { content: "\e8e6"; }

.icon-user-plus:before { content: "\e8e7"; }

.icon-user-x:before { content: "\e8e8"; }

.icon-user:before { content: "\e8e9"; }

.icon-users:before { content: "\e8ea"; }

.icon-video-off:before { content: "\e8eb"; }

.icon-video:before { content: "\e8ec"; }

.icon-voicemail:before { content: "\e8ed"; }

.icon-volume-x:before { content: "\e8ee"; }

.icon-volume-2:before { content: "\e8ef"; }

.icon-volume-1:before { content: "\e8f0"; }

.icon-volume:before { content: "\e8f1"; }

.icon-watch:before { content: "\e8f2"; }

.icon-wifi:before { content: "\e8f3"; }

.icon-x-square:before { content: "\e8f4"; }

.icon-wind:before { content: "\e8f5"; }

.icon-x:before { content: "\e8f6"; }

.icon-x-circle:before { content: "\e8f7"; }

.icon-zap:before { content: "\e8f8"; }

.icon-zoom-in:before { content: "\e8f9"; }

.icon-zoom-out:before { content: "\e8fa"; }

.icon-command:before { content: "\e8fb"; }

.icon-cloud:before { content: "\e8fc"; }

.icon-hash:before { content: "\e8fd"; }

.icon-headphones:before { content: "\e8fe"; }

.icon-underline:before { content: "\e8ff"; }

.icon-italic:before { content: "\e900"; }

.icon-bold:before { content: "\e901"; }

.icon-crop:before { content: "\e902"; }

.icon-help-circle:before { content: "\e903"; }

.icon-paperclip:before { content: "\e904"; }

.icon-shopping-cart:before { content: "\e905"; }

.icon-tv:before { content: "\e906"; }

.icon-wifi-off:before { content: "\e907"; }

.icon-minimize:before { content: "\e88d"; }

.icon-maximize:before { content: "\e908"; }

.icon-gitlab:before { content: "\e909"; }

.icon-sliders:before { content: "\e90a"; }

.icon-star-on:before { content: "\e90b"; }

.icon-heart-on:before { content: "\e90c"; }