SilentEye 0.4.1
|
00001 // This file is part of SilentEye. 00002 // 00003 // SilentEye is free software: you can redistribute it and/or modify 00004 // it under the terms of the GNU General Public License as published by 00005 // the Free Software Foundation, either version 3 of the License, or 00006 // (at your option) any later version. 00007 // 00008 // SilentEye is distributed in the hope that it will be useful, 00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 // GNU General Public License for more details. 00012 // 00013 // You should have received a copy of the GNU General Public License 00014 // along with SilentEye. If not, see <http://www.gnu.org/licenses/>. 00015 00016 #include "groupedimage.h" 00017 #include <moduleexception.h> 00018 #include <QDebug> 00019 00020 #include <math.h> 00021 #include <algorithm> 00022 00023 using namespace SilentEyeFramework; 00024 00025 namespace SEFormatJPEG { 00026 00027 PixelGroup::PixelGroup(QObject* parent) : QObject(parent) 00028 { 00029 setObjectName("PixelGroup"); 00030 m_logger = new Logger(this); 00031 00032 m_pixels.resize(PIXEL_GROUP_SIZE*PIXEL_GROUP_SIZE); 00033 m_miv = -1; 00034 } 00035 00036 PixelGroup::~PixelGroup() { 00037 if (!m_logger.isNull()) 00038 { 00039 delete m_logger; 00040 } 00041 00042 /*for(int i=0; i< m_pixels.size(); i++) 00043 { 00044 if (!m_pixels[i].isNull()) 00045 { 00046 delete m_pixels[i]; 00047 } 00048 }*/ 00049 } 00050 00051 QPointer<YCbCr> PixelGroup::pixel(quint8 x, quint8 y) 00052 { 00053 int index = (y * PIXEL_GROUP_SIZE) + x; 00054 00055 if (index >= PIXEL_GROUP_SIZE*PIXEL_GROUP_SIZE) 00056 { 00057 m_logger->warning("cannot get pixel: position is out of range (x:" + QString::number(x) 00058 + ",y:"+ QString::number(y) + ")"); 00059 return QPointer<YCbCr>(); 00060 } 00061 else 00062 { 00063 return m_pixels[index]; 00064 } 00065 } 00066 00067 void PixelGroup::setPixel(quint8 x, quint8 y, QPointer<YCbCr> pixel) 00068 { 00069 int index = (y * PIXEL_GROUP_SIZE) + x; 00070 00071 if (index >= PIXEL_GROUP_SIZE*PIXEL_GROUP_SIZE) 00072 { 00073 m_logger->warning("cannot set pixel: position is out of range (x:" 00074 + QString::number(x) + ",y:"+ QString::number(y) + ")"); 00075 } 00076 else 00077 { 00078 m_pixels[index] = pixel; 00079 computeMIV(); 00080 } 00081 } 00082 00083 float PixelGroup::miv() const 00084 { 00085 return m_miv; 00086 } 00087 00088 void PixelGroup::updateMivTo(float destMiv) 00089 { 00090 if (destMiv == m_miv) 00091 { 00092 return; 00093 } 00094 else if (destMiv < 0 || destMiv > 255) 00095 { 00096 m_logger->warning("Ignore MIV update> dest: " + QString::number(destMiv) + ",current: " + QString::number(m_miv)); 00097 return; 00098 } 00099 00100 qint8 tries = 0; 00101 double distance = destMiv - m_miv; 00102 do 00103 { 00104 for (int y=0; y<height(); y++) 00105 { 00106 for (int x=0; x<width(); x++) 00107 { 00108 int qx = (x < width()/2.0) ? x+1 : width() - x; 00109 int qy = (y < height()/2.0) ? y+1 : height() - y; 00110 int q = std::min(qx, qy); 00111 updatePixelMiv(pixel(x, y), (q/(width()/4.0)) * distance); 00112 } 00113 } 00114 00115 computeMIV(); 00116 tries++; 00117 00118 distance = destMiv - m_miv; 00119 00120 } while (abs(distance) > 0.1 && tries < 5); 00121 00122 if (abs(m_miv - destMiv) > 1) 00123 { 00124 m_logger->warning("MIV destination not reached> dest: " + QString::number(destMiv) 00125 + ",new: " + QString::number(m_miv)); 00126 } 00127 } 00128 00129 void PixelGroup::updatePixelMiv(QPointer<YCbCr> p, double distance) 00130 { 00131 if (!p.isNull() && p->y() != -1) 00132 { 00133 if (p->y() + distance < 0) 00134 { 00135 p->setY(0); 00136 } 00137 else if (p->y() + distance > 255) 00138 { 00139 p->setY(255); 00140 } 00141 else 00142 { 00143 p->setY(p->y() + distance); 00144 } 00145 } 00146 00147 } 00148 00149 void PixelGroup::computeMIV() 00150 { 00151 int cpt = 0; 00152 double sum = 0; 00153 00154 for (int i=0; i<PIXEL_GROUP_SIZE*PIXEL_GROUP_SIZE; i++) 00155 { 00156 QPointer<YCbCr> p = m_pixels[i]; 00157 if (!p.isNull() && p->y() >=0 && p->y() <= 255) 00158 { 00159 sum = sum + p->y(); 00160 cpt = cpt + 1; 00161 } 00162 } 00163 00164 if (cpt > 0) 00165 { 00166 m_miv = sum / cpt; 00167 //m_miv = round(sum / cpt); 00168 } 00169 else 00170 { 00171 m_miv = -1; 00172 } 00173 } 00174 00175 QString PixelGroup::toString() const 00176 { 00177 QString str = ""; 00178 for (int i=0; i<PIXEL_GROUP_SIZE*PIXEL_GROUP_SIZE; i++) 00179 { 00180 str += "[" + QString::number(i) + "|"; 00181 QPointer<YCbCr> p = m_pixels[i]; 00182 if (!p.isNull()) 00183 { 00184 str += p->toString(); 00185 } else { 00186 str += "null"; 00187 } 00188 str += "]"; 00189 } 00190 return str + "(" + QString::number(m_miv) + ")"; 00191 } 00192 00193 GroupedImage::GroupedImage(QImage& image, quint8 k, QObject* parent) : QObject(parent) 00194 { 00195 setObjectName("GroupedImage"); 00196 m_logger = new Logger(this); 00197 00198 m_initialWidth = image.width(); 00199 m_initialHeight = image.height(); 00200 m_initialFormat = image.format(); 00201 00202 if (m_initialWidth % PixelGroup::width() != 0) 00203 m_width = (int) floor((double)m_initialWidth / PixelGroup::width()) + 1; 00204 else 00205 m_width = m_initialWidth / PixelGroup::width(); 00206 00207 if (m_initialHeight % PixelGroup::height() != 0) 00208 m_height = (int) floor((double)m_initialHeight / PixelGroup::height()) + 1; 00209 else 00210 m_height = m_initialHeight / PixelGroup::height(); 00211 00212 00213 m_pg.resize(m_width*m_height); 00214 00215 compacteAndGroupImage(image, k); 00216 } 00217 00218 GroupedImage::~GroupedImage() 00219 { 00220 /*for (int i=0; i<m_pg.size(); i++) 00221 { 00222 if (!m_pg[i].isNull()) 00223 { 00224 delete m_pg[i]; 00225 } 00226 }*/ 00227 } 00228 00229 quint16 GroupedImage::width() 00230 { 00231 return m_width; 00232 } 00233 00234 quint16 GroupedImage::height() 00235 { 00236 return m_height; 00237 } 00238 00239 quint16 GroupedImage::initialWidth() 00240 { 00241 return m_initialWidth; 00242 } 00243 00244 quint16 GroupedImage::initialHeight() 00245 { 00246 return m_initialHeight; 00247 } 00248 00249 QPointer<PixelGroup> GroupedImage::pixelGroup(quint16 x, quint16 y) 00250 { 00251 return m_pg[x+(y*m_width)]; 00252 } 00253 00254 void GroupedImage::compacteAndGroupImage(QImage& image, quint8 k) { 00255 00256 m_logger->debug("Grouping image..."); 00257 for (int y = 0; y < m_initialHeight; y += PixelGroup::height()) 00258 { 00259 for (int x = 0; x < m_initialWidth; x += PixelGroup::width()) 00260 { 00261 QPointer<PixelGroup> currentPixelGroup = new PixelGroup(this); 00262 for (int pgY = 0; pgY < PixelGroup::height(); pgY++) 00263 { 00264 for (int pgX = 0; pgX < PixelGroup::width(); pgX++) 00265 { 00266 QPointer<YCbCr> ycbcr; 00267 if (x + pgX >= m_initialWidth || y + pgY >= m_initialHeight) 00268 { 00269 /*m_logger->debug("Out of bound: " 00270 + QString::number(x + pgX) 00271 + ":" 00272 + QString::number(y + pgY));*/ 00273 ycbcr = new YCbCr(-1, -1, -1, this); 00274 } 00275 else 00276 { 00277 // convert color to YCbCr and compact luminance 00278 ycbcr = new YCbCr(image.pixel(x + pgX, y + pgY), this); 00279 // compact luminance (between +K et 255-K) 00280 ycbcr->setY((double)(k + (ycbcr->y() * (128-k)/128.0) )); 00281 } 00282 currentPixelGroup->setPixel(pgX, pgY, ycbcr); 00283 } 00284 } 00285 00286 // Compute and set the current pixel group computed to the new image 00287 int giX = floor(x / (double)PixelGroup::width()); 00288 int giY = floor(y / (double)PixelGroup::height()); 00289 m_pg[giX + (giY * m_width)] = currentPixelGroup; 00290 } 00291 } 00292 m_logger->debug("Grouped image created"); 00293 } 00294 00295 QImage* GroupedImage::toImage() 00296 { 00297 m_logger->debug("Converting grouped image to rgb image..."); 00298 00299 QImage* img = new QImage(m_initialWidth, m_initialHeight, m_initialFormat); 00300 // iterate on each group 00301 for (int i=0; i<m_pg.size(); i++) 00302 { 00303 int x = (i % m_width) * PixelGroup::width(); 00304 int y = floor(i / (double)m_width) * PixelGroup::height(); 00305 00306 for (int pgY = 0; pgY < m_pg[i]->height(); pgY++) 00307 { 00308 for (int pgX = 0; pgX < m_pg[i]->width(); pgX++) 00309 { 00310 QPointer<YCbCr> pixel = m_pg[i]->pixel(pgX, pgY); 00311 // if we are in the image space 00312 if (!pixel.isNull()) 00313 { 00314 if (pixel->y() != -1 00315 && x + pgX < m_initialWidth && y + pgY < m_initialHeight) 00316 { 00317 // add current pixel to image 00318 img->setPixel(x + pgX, y + pgY, pixel->toRGB()); 00319 } 00320 } 00321 } 00322 } 00323 } 00324 00325 m_logger->debug("Grouped image converted."); 00326 00327 return img; 00328 } 00329 00330 }