Initial support for scripting.
[studio:studio.git] / imageitem.cpp
1 /*
2 Copyright (c) 2010 Henrik Abelsson <henrik@abelsson.com>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <iostream>
28 #include <algorithm>
29 #include <cfloat>
30 #include <QtGui>
31 #include "imageitem.h"
32 #include "main.h"
33
34 #ifdef COV_INTERNAL
35 #include <etf/etf.h>
36 #include <etf/image.h>
37 #include <etf/ops/all.h>
38
39 #include <hive/session.h>
40
41 #include <bee/param/parser.h>
42 #include <bee/contrast.h>
43 #include <bee/enhancement.h>
44 #endif
45
46 ImageItem::ImageItem(MainWindow *mw, int width, int height, ImageFormat fmt, QString filename):
47         m_fileName(filename),m_width(width),m_height(height),m_mw(mw), m_format(fmt)
48 {  
49     m_histogram = new int[256];
50
51     setAcceptHoverEvents(true);
52     setFlags(QGraphicsItem::ItemIsMovable |
53              QGraphicsItem::ItemIsSelectable);
54
55     loadData(m_fileName);
56     setCurMaxValue(m_maxValue);
57     setCurMinValue(m_minValue);
58     mapDataToDisplay();
59     setTransformOriginPoint(boundingRect().center());
60
61 }
62
63 ImageItem::~ImageItem()
64 {
65     delete[] m_histogram;
66 }
67
68 void ImageItem::loadData(QString filename)
69 {
70     QFile file(filename);
71
72
73     if (!file.open(QIODevice::ReadOnly)) {
74         QMessageBox::warning(0,"Warning",QString("Couldn't open file '%1'").arg(m_fileName));
75         return;
76     }
77
78     // read indata
79     QByteArray fileData = file.readAll();
80
81     m_pixels = new float[m_height * m_width];
82     m_originalPixels =  new float[m_height * m_width];
83     switch (m_format) {
84     case F32: {
85             const float *floatPixels = reinterpret_cast<const float*>(fileData.constData());
86             int i=0;
87             memcpy(m_pixels, floatPixels, sizeof(float)*m_height*m_width);
88         } break;
89     case U16: {
90             const unsigned short *u16Pixels = reinterpret_cast<const unsigned short*>(fileData.constData());
91             int i=0;
92             for(int y = 0 ; y < m_height; y++)
93                 for(int x = 0 ; x < m_width; x++)
94                     m_pixels[y*m_width+x] = u16Pixels[i++];
95
96         }break;
97     case S16: {
98             const signed short *s16Pixels = reinterpret_cast<const signed short*>(fileData.constData());
99             int i=0;
100             for(int y = 0 ; y < m_height; y++)
101                 for(int x = 0 ; x < m_width; x++)
102                     m_pixels[y*m_width+x] = s16Pixels[i++];
103         } break;
104     case U8: {
105             const unsigned char *u8Pixels = reinterpret_cast<const unsigned char*>(fileData.constData());
106             int i=0;
107             for(int y = 0 ; y < m_height; y++)
108                 for(int x = 0 ; x < m_width; x++)
109                     m_pixels[y*m_width+x] = u8Pixels[i++];
110         } break;
111     }
112
113     memcpy(m_originalPixels, m_pixels, sizeof(float)*m_height*m_width);
114
115     // convert to host byte order.
116     /*
117         for(int i = 0; i < width*height; i++)
118         {
119             tmp.f = floatPixels[i];
120             tmp.i = tmp.i; // ntohl(tmp.i);
121             floatPixels[i] = tmp.f;
122         }
123         */
124     // find out pixel value range
125     m_minValue = FLT_MAX;
126     m_maxValue = -FLT_MAX;
127     float sum = 0.0f;
128     for(int y = 0 ; y < m_height; y++) {
129         for(int x = 0 ; x < m_width; x++) {
130             float pixel = m_pixels[y*m_width+x];
131             sum += pixel;
132             m_minValue = qMin(m_minValue, pixel);
133             m_maxValue = qMax(m_maxValue, pixel);
134         }
135     }
136     m_avgValue = sum/(m_width*m_height);
137
138 }
139
140 void ImageItem::applyContrast(XMLNode xmlParams)
141 {
142     // TODO: Plugin to call specific processing here..
143     mapDataToDisplay();
144 }
145
146 QRectF ImageItem::boundingRect() const
147 {
148     return QRectF(0,0,m_width,m_height+20);
149 }
150
151 void ImageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
152 {
153     Q_UNUSED(option);
154     Q_UNUSED(widget);
155
156     if (isSelected())
157         painter->setPen(QColor(0,0,255));
158     else
159         painter->setPen(QColor(0,0,0));
160     QString name = m_fileName.section('/',-1);
161     painter->drawText(0,10,name);
162     painter->drawPixmap(QRect(0,15,m_width,m_height),m_pixmap);
163 }
164
165 void ImageItem::mapDataToDisplay()
166 {
167     float max = getCurMaxValue();
168     float min = getCurMinValue();
169     //std::cout << "mapping to " << min << " " << max << std::endl;
170     uint8_t *intPixels = new uint8_t[m_width*m_height];
171
172     if (min < m_minValue)
173         min = m_minValue;
174     if (max > m_maxValue)
175         max = m_maxValue;
176
177     float range = max - min;
178     float offset = -min;
179     float scale_factor = 255.0f/range;
180
181     for(int i=0;i<256;i++)
182         m_histogram[i]=0;
183
184     QImage image(intPixels,m_width,m_height,QImage::Format_Indexed8);
185     image.setNumColors(256);
186
187     // scale to 8 bit range.
188     for(int y = 0 ; y < m_height; y++) {
189         for(int x = 0 ; x < m_width; x++) {
190             float p = m_pixels[y*m_width+x];
191             if (p > max)
192                 p = max;
193             if (p < min)
194                 p = min;
195
196             uint8_t val = (uint8_t)((p + offset) * scale_factor);
197             image.setPixel(x,y,val);
198             m_histogram[val]++;
199         }
200     }
201
202     // convert to Qt image and set up color map
203
204
205     QVector<QRgb> colorTable(256);
206     for(int i=0;i<256;i++)
207         colorTable[i] = QColor(i,i,i).rgb();
208
209     image.setColorTable(colorTable);
210
211     m_pixmap = QPixmap::fromImage(image);
212
213     update(0,0,m_width,m_height);
214 }
215
216 QVariant ImageItem::itemChange(GraphicsItemChange change, const QVariant &value)
217 {
218     if (change == QGraphicsItem::ItemSelectedHasChanged) {
219         if (value.toBool())
220             setZValue(zValue()+1);
221         else
222             setZValue(zValue()-1);
223     }
224
225     return value;
226 }
227
228 void ImageItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
229 {
230     int x,y;
231
232     x = event->pos().x();
233     y = event->pos().y() - 16;
234
235     if (y < 0)
236         y = 0;
237
238     if (y >= m_height)
239         y = m_height - 1;
240  
241     if (x < 0)
242         x = 0;
243
244     if (x >= m_width)
245         x = m_width - 1;
246
247
248
249     float value = m_pixels[y+m_width+x];
250     QString str = QString("Position: (%1, %2) value: %3 ").arg(x).arg(y).arg(value);
251
252     if (m_mw)
253         m_mw->setStatusText(str);
254 }