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 < 4); 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::compactImage(QImage& image, quint8 k) 00255 { 00256 //QImage* img = new QImage(image.width(), image.height(), image.format()); 00257 for (int y=0; y<image.height(); y++) 00258 { 00259 for (int x=0; x<image.width(); x++) 00260 { 00261 QPointer<YCbCr> ycbcr = new YCbCr(image.pixel(x, y)); 00262 compactPixel(ycbcr, k); 00263 image.setPixel(x, y, ycbcr->toRGB()); 00264 delete ycbcr; 00265 } 00266 } 00267 } 00268 00269 void GroupedImage::compacteAndGroupImage(QImage& image, quint8 k) { 00270 00271 m_logger->debug("Grouping image..."); 00272 for (int y = 0; y < m_initialHeight; y += PixelGroup::height()) 00273 { 00274 for (int x = 0; x < m_initialWidth; x += PixelGroup::width()) 00275 { 00276 QPointer<PixelGroup> currentPixelGroup = new PixelGroup(this); 00277 for (int pgY = 0; pgY < PixelGroup::height(); pgY++) 00278 { 00279 for (int pgX = 0; pgX < PixelGroup::width(); pgX++) 00280 { 00281 QPointer<YCbCr> ycbcr; 00282 if (x + pgX >= m_initialWidth || y + pgY >= m_initialHeight) 00283 { 00284 /*m_logger->debug("Out of bound: " 00285 + QString::number(x + pgX) 00286 + ":" 00287 + QString::number(y + pgY));*/ 00288 ycbcr = new YCbCr(-1, -1, -1, this); 00289 } 00290 else 00291 { 00292 // convert color to YCbCr and compact luminance 00293 ycbcr = new YCbCr(image.pixel(x + pgX, y + pgY), this); 00294 //compactPixel(ycbcr, k); 00295 } 00296 currentPixelGroup->setPixel(pgX, pgY, ycbcr); 00297 } 00298 } 00299 00300 // Compute and set the current pixel group computed to the new image 00301 int giX = floor(x / (double)PixelGroup::width()); 00302 int giY = floor(y / (double)PixelGroup::height()); 00303 m_pg[giX + (giY * m_width)] = currentPixelGroup; 00304 } 00305 } 00306 m_logger->debug("Grouped image created"); 00307 } 00308 00310 void GroupedImage::compactPixel(QPointer<YCbCr> ycbcr, quint8 k) 00311 { 00312 ycbcr->setY((double)(k + (ycbcr->y() * (128-k)/128.0) )); 00313 } 00314 00315 QImage* GroupedImage::toImage() 00316 { 00317 m_logger->debug("Converting grouped image to rgb image..."); 00318 00319 QImage* img = new QImage(m_initialWidth, m_initialHeight, m_initialFormat); 00320 // iterate on each group 00321 for (int i=0; i<m_pg.size(); i++) 00322 { 00323 int x = (i % m_width) * PixelGroup::width(); 00324 int y = floor(i / (double)m_width) * PixelGroup::height(); 00325 00326 for (int pgY = 0; pgY < m_pg[i]->height(); pgY++) 00327 { 00328 for (int pgX = 0; pgX < m_pg[i]->width(); pgX++) 00329 { 00330 QPointer<YCbCr> pixel = m_pg[i]->pixel(pgX, pgY); 00331 // if we are in the image space 00332 if (!pixel.isNull()) 00333 { 00334 if (pixel->y() != -1 00335 && x + pgX < m_initialWidth && y + pgY < m_initialHeight) 00336 { 00337 // add current pixel to image 00338 img->setPixel(x + pgX, y + pgY, pixel->toRGB()); 00339 } 00340 } 00341 } 00342 } 00343 } 00344 00345 m_logger->debug("Grouped image converted."); 00346 00347 return img; 00348 } 00349 00350 }