<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> <title>AlbumShaper: mosaic.cpp File Reference</title> <link href="tabs.css" rel="stylesheet" type="text/css"/> <link href="doxygen.css" rel="stylesheet" type="text/css"/> </head> <body> <!-- Generated by Doxygen 1.6.2 --> <div class="navigation" id="top"> <div class="tabs"> <ul> <li><a href="index.html"><span>Main Page</span></a></li> <li><a href="annotated.html"><span>Classes</span></a></li> <li class="current"><a href="files.html"><span>Files</span></a></li> </ul> </div> <div class="tabs"> <ul> <li><a href="files.html"><span>File List</span></a></li> <li><a href="globals.html"><span>File Members</span></a></li> </ul> </div> </div> <div class="contents"> <h1>mosaic.cpp File Reference</h1><code>#include <qimage.h></code><br/> <code>#include <qstring.h></code><br/> <code>#include <qapplication.h></code><br/> <code>#include <cstdlib></code><br/> <code>#include <time.h></code><br/> <code>#include <math.h></code><br/> <code>#include "<a class="el" href="mosaic_8h_source.html">mosaic.h</a>"</code><br/> <code>#include "<a class="el" href="manipulationOptions_8h_source.html">manipulationOptions.h</a>"</code><br/> <code>#include "../tools/imageTools.h"</code><br/> <code>#include "../../gui/statusWidget.h"</code><br/> <code>#include <iostream></code><br/> <div class="dynheader"> Include dependency graph for mosaic.cpp:</div> <div class="dynsection"> </div> <p><a href="mosaic_8cpp_source.html">Go to the source code of this file.</a></p> <table border="0" cellpadding="0" cellspacing="0"> <tr><td colspan="2"><h2>Classes</h2></td></tr> <tr><td class="memItemLeft" align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="structTile.html">Tile</a></td></tr> <tr><td class="memItemLeft" align="right" valign="top">struct </td><td class="memItemRight" valign="bottom"><a class="el" href="structTileSet.html">TileSet</a></td></tr> <tr><td colspan="2"><h2>Defines</h2></td></tr> <tr><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#a6403bf369550d13e1d7685c36503a46c">MAX_TILES</a> 216</td></tr> <tr><td colspan="2"><h2>Functions</h2></td></tr> <tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#adcff7718bf4fa9b179c469dbdfb1e7bf">constructColorTiles</a> (QSize tileSize)</td></tr> <tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#abaf87e675270cda9dbbdc911e4726f94">constructImageTiles</a> (QStringList files, QSize tileSize)</td></tr> <tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#a01e2afa17839fbd21afc5397952270c7">splatBestTile</a> (QImage *image, QPoint topLeftCorner, <a class="el" href="structTileSet.html">TileSet</a> *tileSet)</td></tr> <tr><td class="memItemLeft" align="right" valign="top">QImage * </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#a012c297101e169545b4ec948ddac9b23">mosaicEffect</a> (QString filename, <a class="el" href="classMosaicOptions.html">MosaicOptions</a> *options)</td></tr> <tr><td colspan="2"><h2>Variables</h2></td></tr> <tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="structTileSet.html">TileSet</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a></td></tr> <tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="structTileSet.html">TileSet</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a></td></tr> </table> <hr/><h2>Define Documentation</h2> <a class="anchor" id="a6403bf369550d13e1d7685c36503a46c"></a><!-- doxytag: member="mosaic.cpp::MAX_TILES" ref="a6403bf369550d13e1d7685c36503a46c" args="" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">#define MAX_TILES 216</td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00256">256</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> <p>Referenced by <a class="el" href="mosaic_8cpp_source.html#l00375">constructColorTiles()</a>, and <a class="el" href="mosaic_8cpp_source.html#l00413">constructImageTiles()</a>.</p> </div> </div> <hr/><h2>Function Documentation</h2> <a class="anchor" id="adcff7718bf4fa9b179c469dbdfb1e7bf"></a><!-- doxytag: member="mosaic.cpp::constructColorTiles" ref="adcff7718bf4fa9b179c469dbdfb1e7bf" args="(QSize tileSize)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">void constructColorTiles </td> <td>(</td> <td class="paramtype">QSize </td> <td class="paramname"> <em>tileSize</em></td> <td> ) </td> <td></td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00375">375</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> <p>References <a class="el" href="mosaic_8cpp_source.html#l00265">Tile::avgColor</a>, <a class="el" href="mosaic_8cpp_source.html#l00268">Tile::avgL</a>, <a class="el" href="mosaic_8cpp_source.html#l00268">Tile::avgS</a>, <a class="el" href="jpegInternal_8h_source.html#l00125">b</a>, <a class="el" href="mosaic_8cpp_source.html#l00262">Tile::image</a>, <a class="el" href="mosaic_8cpp_source.html#l00256">MAX_TILES</a>, <a class="el" href="mosaic_8cpp_source.html#l00277">TileSet::numInitialized</a>, and <a class="el" href="mosaic_8cpp_source.html#l00274">TileSet::tiles</a>.</p> <p>Referenced by <a class="el" href="mosaic_8cpp_source.html#l00290">mosaicEffect()</a>.</p> <p><div class="fragment"><pre class="fragment"><a name="l00376"></a>00376 { <a name="l00377"></a>00377 <span class="comment">//max tiles must be allocated across all colors, so find resolution we'll have for each color</span> <a name="l00378"></a>00378 <span class="comment">//channel (e.g. if max tiles is 100, 100^(1/3) ~= 4.6 so we'll use 4 unique red, green, and</span> <a name="l00379"></a>00379 <span class="comment">//blue color values for constructing tiles and use 4^3=64 tiles out of the 100 allocated</span> <a name="l00380"></a>00380 <span class="keywordtype">int</span> colorRes = (int)pow( <a class="code" href="mosaic_8cpp.html#a6403bf369550d13e1d7685c36503a46c">MAX_TILES</a>, 1.0/3 ); <a name="l00381"></a>00381 <a name="l00382"></a>00382 <span class="comment">//always include 0 and 255 so increment is always totalSpan/(count-1)</span> <a name="l00383"></a>00383 <span class="keywordtype">int</span> colorIncrement = 255 / (colorRes-1); <a name="l00384"></a>00384 <a name="l00385"></a>00385 colorIncrement = 51; <a name="l00386"></a>00386 <a name="l00387"></a>00387 <span class="comment">//create actual tiles</span> <a name="l00388"></a>00388 <span class="keywordtype">int</span> tile=0; <a name="l00389"></a>00389 <span class="keywordtype">int</span> r,g,<a class="code" href="jpegInternal_8h.html#af320905358fa78701e4cc60b6135601f">b</a>; <a name="l00390"></a>00390 <span class="keywordflow">for</span>(r=0; r<=255; r+=colorIncrement) <a name="l00391"></a>00391 { <a name="l00392"></a>00392 <span class="keywordflow">for</span>(g=0; g<=255; g+=colorIncrement) <a name="l00393"></a>00393 { <a name="l00394"></a>00394 <span class="keywordflow">for</span>(b=0; b<=255; b+=colorIncrement) <a name="l00395"></a>00395 { <a name="l00396"></a>00396 <a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.create( tileSize.width(), tileSize.height(), 32); <a name="l00397"></a>00397 <a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.fill( qRgb(r, g, b) ); <a name="l00398"></a>00398 <a name="l00399"></a>00399 <a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#accb3f9de22351962d8f3110f50363f34">avgColor</a> = QColor(r,g,b); <a name="l00400"></a>00400 <a name="l00401"></a>00401 <span class="keywordtype">int</span> h; <a name="l00402"></a>00402 QColor(r,g,b).getHsv( &h, &(<a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adc45f505b5bc1a8148462bdfcc804cd3">avgS</a>), &(<a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#a06ff4be3625f8030d80b321d9fb3acb6">avgL</a>) ); <a name="l00403"></a>00403 tile++; <a name="l00404"></a>00404 } <a name="l00405"></a>00405 } <a name="l00406"></a>00406 } <a name="l00407"></a>00407 <a name="l00408"></a>00408 <span class="comment">//setup number of initialized tiles</span> <a name="l00409"></a>00409 <a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a> = tile; <a name="l00410"></a>00410 } </pre></div></p> </div> </div> <a class="anchor" id="abaf87e675270cda9dbbdc911e4726f94"></a><!-- doxytag: member="mosaic.cpp::constructImageTiles" ref="abaf87e675270cda9dbbdc911e4726f94" args="(QStringList files, QSize tileSize)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">void constructImageTiles </td> <td>(</td> <td class="paramtype">QStringList </td> <td class="paramname"> <em>files</em>, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype">QSize </td> <td class="paramname"> <em>tileSize</em></td><td> </td> </tr> <tr> <td></td> <td>)</td> <td></td><td></td><td></td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00413">413</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> <p>References <a class="el" href="mosaic_8cpp_source.html#l00265">Tile::avgColor</a>, <a class="el" href="mosaic_8cpp_source.html#l00268">Tile::avgL</a>, <a class="el" href="mosaic_8cpp_source.html#l00268">Tile::avgS</a>, <a class="el" href="imageTools_8cpp_source.html#l00192">getImageSize()</a>, <a class="el" href="mosaic_8cpp_source.html#l00262">Tile::image</a>, <a class="el" href="mosaic_8cpp_source.html#l00256">MAX_TILES</a>, <a class="el" href="mosaic_8cpp_source.html#l00277">TileSet::numInitialized</a>, <a class="el" href="imageTools_8cpp_source.html#l00157">scaleImage()</a>, and <a class="el" href="mosaic_8cpp_source.html#l00274">TileSet::tiles</a>.</p> <p>Referenced by <a class="el" href="mosaic_8cpp_source.html#l00290">mosaicEffect()</a>.</p> <p><div class="fragment"><pre class="fragment"><a name="l00414"></a>00414 { <a name="l00415"></a>00415 <span class="comment">//--------------------------------- </span> <a name="l00416"></a>00416 <span class="comment">//setup number of initialized tiles</span> <a name="l00417"></a>00417 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a> = QMIN(files.size(), <a class="code" href="mosaic_8cpp.html#a6403bf369550d13e1d7685c36503a46c">MAX_TILES</a>); <a name="l00418"></a>00418 <span class="comment">//--------------------------------- </span> <a name="l00419"></a>00419 <span class="comment">//create file index list, we'll use this to construct a</span> <a name="l00420"></a>00420 <span class="comment">//list of indices to the randomply picked files from the master list</span> <a name="l00421"></a>00421 <span class="keywordtype">int</span>* fileIndices = <span class="keyword">new</span> <span class="keywordtype">int</span>[<a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>]; <a name="l00422"></a>00422 <span class="keywordtype">int</span>* fileIndicesUsed = <span class="keyword">new</span> <span class="keywordtype">int</span>[files.size()]; <a name="l00423"></a>00423 <span class="keywordtype">int</span> i; <a name="l00424"></a>00424 <span class="keywordflow">for</span>(i=0; i<<a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>; i++) { fileIndices[i] = -1; } <a name="l00425"></a>00425 <span class="keywordflow">for</span>(i=0; i<((int)files.size()); i++) { fileIndicesUsed[i] = 0; } <a name="l00426"></a>00426 <span class="comment">//--------------------------------- </span> <a name="l00427"></a>00427 <span class="comment">//pick the random files, updating the file indices list</span> <a name="l00428"></a>00428 <span class="keywordflow">for</span>(i=0; i<<a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>; i++) <a name="l00429"></a>00429 { <a name="l00430"></a>00430 <span class="keywordtype">double</span> percentage = ((double)rand()) / RAND_MAX; <a name="l00431"></a>00431 <span class="keywordtype">int</span> fileNum = (int) ( (files.size() - (i+1)) * percentage); <a name="l00432"></a>00432 <a name="l00433"></a>00433 <span class="comment">//correct index by offsetting by all files that have been picked before this one </span> <a name="l00434"></a>00434 <span class="keywordtype">int</span> j = 0; <a name="l00435"></a>00435 <span class="keywordtype">int</span> realFileNum = fileNum; <a name="l00436"></a>00436 <span class="keywordflow">while</span>( fileNum >= 0) <a name="l00437"></a>00437 { <a name="l00438"></a>00438 <span class="keywordflow">if</span>( fileIndicesUsed[j] == 1 ) { realFileNum++; } <a name="l00439"></a>00439 <span class="keywordflow">else</span> { fileNum--; } <a name="l00440"></a>00440 <a name="l00441"></a>00441 j++; <a name="l00442"></a>00442 } <a name="l00443"></a>00443 <a name="l00444"></a>00444 <span class="comment">//record file index into list</span> <a name="l00445"></a>00445 fileIndices[i] = realFileNum; <a name="l00446"></a>00446 fileIndicesUsed[realFileNum] = 1; <a name="l00447"></a>00447 } <a name="l00448"></a>00448 <a name="l00449"></a>00449 <span class="comment">//--------------------------------- </span> <a name="l00450"></a>00450 <span class="comment">//sort the file index list - bubble sort is fast enough right? :-)</span> <a name="l00451"></a>00451 <span class="keywordtype">int</span> j; <a name="l00452"></a>00452 <span class="keywordflow">for</span>( i=<a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>-1; i>0; i--) <a name="l00453"></a>00453 { <a name="l00454"></a>00454 <span class="keywordflow">for</span>( j=0; j<i; j++) <a name="l00455"></a>00455 { <a name="l00456"></a>00456 <span class="keywordflow">if</span>( fileIndices[j] > fileIndices[j+1] ) <a name="l00457"></a>00457 { <a name="l00458"></a>00458 <span class="keywordtype">int</span> tmp = fileIndices[j+1]; <a name="l00459"></a>00459 fileIndices[j+1] = fileIndices[j]; <a name="l00460"></a>00460 fileIndices[j] = tmp; <a name="l00461"></a>00461 } <a name="l00462"></a>00462 } <a name="l00463"></a>00463 } <a name="l00464"></a>00464 <span class="comment">//--------------------------------- </span> <a name="l00465"></a>00465 <span class="comment">//construct truncated list of files that we'll use</span> <a name="l00466"></a>00466 QStringList chosenFiles; <a name="l00467"></a>00467 QStringList::iterator it; <a name="l00468"></a>00468 <span class="keywordtype">int</span> curFileIndex = 0; <a name="l00469"></a>00469 <span class="keywordtype">int</span> nextDesiredFileIndex = 0; <a name="l00470"></a>00470 <span class="keywordflow">for</span>(it = files.begin(); it != files.end(); it++ ) <a name="l00471"></a>00471 { <a name="l00472"></a>00472 <span class="keywordflow">if</span>( curFileIndex == fileIndices[nextDesiredFileIndex] ) <a name="l00473"></a>00473 { <a name="l00474"></a>00474 chosenFiles.append( *it ); <a name="l00475"></a>00475 nextDesiredFileIndex++; <a name="l00476"></a>00476 <a name="l00477"></a>00477 <span class="keywordflow">if</span>( nextDesiredFileIndex >= <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a> ) <span class="keywordflow">break</span>; <a name="l00478"></a>00478 } <a name="l00479"></a>00479 <a name="l00480"></a>00480 curFileIndex++; <a name="l00481"></a>00481 } <a name="l00482"></a>00482 <a name="l00483"></a>00483 <span class="comment">//resetting numInitialized should not be necessary, we should have the right</span> <a name="l00484"></a>00484 <span class="comment">//number of files in chosenFiles, but as a sanity check, we'll reset it here again.</span> <a name="l00485"></a>00485 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a> = QMIN((<span class="keywordtype">int</span>)chosenFiles.size(), <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>); <a name="l00486"></a>00486 <a name="l00487"></a>00487 <span class="comment">//--------------------------------- </span> <a name="l00488"></a>00488 <span class="comment">//free up the temporary index list, it's nolonger needed since we now have an</span> <a name="l00489"></a>00489 <span class="comment">//actual list of the chosen files</span> <a name="l00490"></a>00490 <span class="keyword">delete</span> fileIndices; <a name="l00491"></a>00491 <span class="keyword">delete</span> fileIndicesUsed; <a name="l00492"></a>00492 fileIndices = NULL; <a name="l00493"></a>00493 fileIndicesUsed = NULL; <a name="l00494"></a>00494 <span class="comment">//--------------------------------- </span> <a name="l00495"></a>00495 <span class="comment">//ok, we now have a list of files we actually want to use to create tiles from, that have</span> <a name="l00496"></a>00496 <span class="comment">//been randomly chosen from the huge list we were given. now actually create the tiles</span> <a name="l00497"></a>00497 <span class="keywordtype">int</span> tile = 0; <a name="l00498"></a>00498 <a name="l00499"></a>00499 <span class="keywordflow">for</span>(it = chosenFiles.begin(); it != chosenFiles.end(); it++ ) <a name="l00500"></a>00500 { <a name="l00501"></a>00501 <span class="comment">//scale image to definately fill a tileSizeW x tileSizeH region, we'll crop down afterwards</span> <a name="l00502"></a>00502 QSize imageRes; <a name="l00503"></a>00503 <a class="code" href="imageTools_8cpp.html#a2af7f0a9c4f931ad3213c36796e95288" title="Get image dimensions.">getImageSize</a>( *it, imageRes ); <a name="l00504"></a>00504 <a name="l00505"></a>00505 <span class="keywordtype">int</span> intermediateWidth = -1; <a name="l00506"></a>00506 <span class="keywordtype">int</span> intermediateHeight = -1; <a name="l00507"></a>00507 <span class="keywordflow">if</span>( ((<span class="keywordtype">double</span>)imageRes.width()) / tileSize.width() > ((double)imageRes.height()) / tileSize.height() ) <a name="l00508"></a>00508 { <a name="l00509"></a>00509 intermediateHeight = tileSize.height(); <a name="l00510"></a>00510 intermediateWidth = (int) ( ((1.0*intermediateHeight*imageRes.width()) / imageRes.height()) + 0.5 ); <a name="l00511"></a>00511 } <a name="l00512"></a>00512 <span class="keywordflow">else</span> <a name="l00513"></a>00513 { <a name="l00514"></a>00514 intermediateWidth = tileSize.width(); <a name="l00515"></a>00515 intermediateHeight = (int) ( ((1.0*intermediateWidth*imageRes.height()) / imageRes.width()) + 0.5 ); <a name="l00516"></a>00516 } <a name="l00517"></a>00517 <a name="l00518"></a>00518 QImage scaledImage; <a name="l00519"></a>00519 <a class="code" href="imageTools_8cpp.html#a126e11984fb8124e78e3b1b68a24870c" title="Scale image and save copy to disk.">scaleImage</a>( *it, scaledImage, intermediateWidth, intermediateHeight ); <a name="l00520"></a>00520 <a name="l00521"></a>00521 <span class="comment">//scaleImage does not like to scale more than 2x, so if image is not the right size scale it up again</span> <a name="l00522"></a>00522 <span class="keywordflow">if</span>( scaledImage.width() != tileSize.width() || scaledImage.height() != tileSize.height() ) <a name="l00523"></a>00523 scaledImage = scaledImage.scale( tileSize, QImage::ScaleFree ); <a name="l00524"></a>00524 <a name="l00525"></a>00525 <span class="comment">//construct tile image</span> <a name="l00526"></a>00526 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.create( tileSize.width(), tileSize.height(), 32); <a name="l00527"></a>00527 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.fill( qRgb(255,255,255) ); <a name="l00528"></a>00528 <a name="l00529"></a>00529 <span class="comment">//crop scaledimage to tileSizeW x tileSizeH - simultaniously compute statistics about tile</span> <a name="l00530"></a>00530 <span class="keywordtype">int</span> xOffset = (scaledImage.width() - tileSize.width())/2; <a name="l00531"></a>00531 <span class="keywordtype">int</span> yOffset = (scaledImage.height() - tileSize.height())/2; <a name="l00532"></a>00532 <span class="keywordtype">int</span> x, y; <a name="l00533"></a>00533 uchar* scaledScanLine; <a name="l00534"></a>00534 uchar* croppedScanLine; <a name="l00535"></a>00535 QRgb* scaledRgb; <a name="l00536"></a>00536 QRgb* croppedRgb; <a name="l00537"></a>00537 <a name="l00538"></a>00538 <span class="keywordtype">double</span> avgR=0; <span class="keywordtype">double</span> avgG=0; <span class="keywordtype">double</span> avgB=0; <a name="l00539"></a>00539 <span class="keywordtype">double</span> avgS=0; <span class="keywordtype">double</span> avgL=0; <a name="l00540"></a>00540 <a name="l00541"></a>00541 <span class="comment">//sometimes corrupt images can get through, so this check</span> <a name="l00542"></a>00542 <span class="comment">//bulletproofs the code</span> <a name="l00543"></a>00543 <span class="keywordflow">if</span>( scaledImage.isNull() ) <a name="l00544"></a>00544 { <a name="l00545"></a>00545 avgR = avgG = avgB = 255; <a name="l00546"></a>00546 avgS = avgL = 255; <a name="l00547"></a>00547 } <a name="l00548"></a>00548 <span class="keywordflow">else</span> <a name="l00549"></a>00549 { <a name="l00550"></a>00550 <span class="keywordflow">for</span>( y=0; y<tileSize.height(); y++) <a name="l00551"></a>00551 { <a name="l00552"></a>00552 scaledScanLine = scaledImage.scanLine(y + yOffset); <a name="l00553"></a>00553 croppedScanLine = <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.scanLine(y); <a name="l00554"></a>00554 <a name="l00555"></a>00555 <span class="keywordflow">for</span>( x=0; x<tileSize.width(); x++) <a name="l00556"></a>00556 { <a name="l00557"></a>00557 scaledRgb = ((QRgb*) scaledScanLine) +x + xOffset; <a name="l00558"></a>00558 croppedRgb = ((QRgb*) croppedScanLine) + x; <a name="l00559"></a>00559 <a name="l00560"></a>00560 <span class="comment">//copy pixel color over</span> <a name="l00561"></a>00561 *croppedRgb = *scaledRgb; <a name="l00562"></a>00562 <a name="l00563"></a>00563 <span class="comment">//update statistics</span> <a name="l00564"></a>00564 QColor color( *croppedRgb ); <a name="l00565"></a>00565 <a name="l00566"></a>00566 avgR += color.red(); <a name="l00567"></a>00567 avgG += color.green(); <a name="l00568"></a>00568 avgB += color.blue(); <a name="l00569"></a>00569 <a name="l00570"></a>00570 <span class="keywordtype">int</span> h,s,l; <a name="l00571"></a>00571 color.getHsv( &h, &s, &l ); <a name="l00572"></a>00572 avgS += s; <a name="l00573"></a>00573 avgL += l; <a name="l00574"></a>00574 } <a name="l00575"></a>00575 } <a name="l00576"></a>00576 <a name="l00577"></a>00577 <span class="comment">//average red, green, blue, saturation, and luminance sums</span> <a name="l00578"></a>00578 <span class="keywordtype">int</span> pixelCount = tileSize.width()*tileSize.height(); <a name="l00579"></a>00579 avgR /= pixelCount; <a name="l00580"></a>00580 avgG /= pixelCount; <a name="l00581"></a>00581 avgB /= pixelCount; <a name="l00582"></a>00582 avgS /= pixelCount; <a name="l00583"></a>00583 avgL /= pixelCount; <a name="l00584"></a>00584 } <a name="l00585"></a>00585 <span class="comment">//store statistics </span> <a name="l00586"></a>00586 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#accb3f9de22351962d8f3110f50363f34">avgColor</a> = QColor( (<span class="keywordtype">int</span>)avgR, (<span class="keywordtype">int</span>)avgG, (<span class="keywordtype">int</span>)avgB ); <a name="l00587"></a>00587 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#adc45f505b5bc1a8148462bdfcc804cd3">avgS</a> = (int)avgS; <a name="l00588"></a>00588 <a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>.<a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[tile].<a class="code" href="structTile.html#a06ff4be3625f8030d80b321d9fb3acb6">avgL</a> = (int)avgL; <a name="l00589"></a>00589 <a name="l00590"></a>00590 <span class="comment">//move on to next tile</span> <a name="l00591"></a>00591 tile++; <a name="l00592"></a>00592 } <a name="l00593"></a>00593 <span class="comment">//--------------------------------- </span> <a name="l00594"></a>00594 } </pre></div></p> </div> </div> <a class="anchor" id="a012c297101e169545b4ec948ddac9b23"></a><!-- doxytag: member="mosaic.cpp::mosaicEffect" ref="a012c297101e169545b4ec948ddac9b23" args="(QString filename, MosaicOptions *options)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">QImage* mosaicEffect </td> <td>(</td> <td class="paramtype">QString </td> <td class="paramname"> <em>filename</em>, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"><a class="el" href="classMosaicOptions.html">MosaicOptions</a> * </td> <td class="paramname"> <em>options</em></td><td> </td> </tr> <tr> <td></td> <td>)</td> <td></td><td></td><td></td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00290">290</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> <p>References <a class="el" href="mosaic_8cpp_source.html#l00375">constructColorTiles()</a>, <a class="el" href="mosaic_8cpp_source.html#l00413">constructImageTiles()</a>, <a class="el" href="redEye__internal_8h_source.html#l00037">editedImage</a>, <a class="el" href="mosaic_8cpp_source.html#l00251">MosaicOptions::getFileList()</a>, <a class="el" href="manipulationOptions_8h_source.html#l00021">ManipulationOptions::getStatus()</a>, <a class="el" href="mosaic_8cpp_source.html#l00252">MosaicOptions::getTileSize()</a>, <a class="el" href="statusWidget_8cpp_source.html#l00119">StatusWidget::incrementProgress()</a>, <a class="el" href="redEye__internal_8h_source.html#l00031">newProgress</a>, <a class="el" href="statusWidget_8cpp_source.html#l00089">StatusWidget::showProgressBar()</a>, <a class="el" href="mosaic_8cpp_source.html#l00598">splatBestTile()</a>, <a class="el" href="redEye__internal_8h_source.html#l00021">status</a>, and <a class="el" href="redEye__internal_8h_source.html#l00028">updateIncrement</a>.</p> <p>Referenced by <a class="el" href="editingInterface_8cpp_source.html#l00834">EditingInterface::applyEffect()</a>.</p> <p><div class="fragment"><pre class="fragment"><a name="l00291"></a>00291 { <a name="l00292"></a>00292 <span class="comment">//load image</span> <a name="l00293"></a>00293 QImage* <a class="code" href="redEye__internal_8h.html#a63116a8b94b4ed0e99ddcb7f6f3bd919">editedImage</a> = <span class="keyword">new</span> QImage( filename ); <a name="l00294"></a>00294 <a name="l00295"></a>00295 <span class="comment">//convert to 32-bit depth if necessary</span> <a name="l00296"></a>00296 <span class="keywordflow">if</span>( editedImage->depth() < 32 ) <a name="l00297"></a>00297 { <a name="l00298"></a>00298 QImage* tmp = editedImage; <a name="l00299"></a>00299 editedImage = <span class="keyword">new</span> QImage( tmp->convertDepth( 32, Qt::AutoColor ) ); <a name="l00300"></a>00300 <span class="keyword">delete</span> tmp; tmp=NULL; <a name="l00301"></a>00301 } <a name="l00302"></a>00302 <a name="l00303"></a>00303 <span class="comment">//determine if busy indicators will be used</span> <a name="l00304"></a>00304 <span class="keywordtype">bool</span> useBusyIndicators = <span class="keyword">false</span>; <a name="l00305"></a>00305 <a class="code" href="classStatusWidget.html">StatusWidget</a>* <a class="code" href="redEye__internal_8h.html#a65b682074aef9e63bb1dad48c3e9e9df">status</a> = NULL; <a name="l00306"></a>00306 <span class="keywordflow">if</span>( options != NULL && options-><a class="code" href="classManipulationOptions.html#a9bc4d4123333012b705b599043406e68">getStatus</a>() != NULL ) <a name="l00307"></a>00307 { <a name="l00308"></a>00308 useBusyIndicators = <span class="keyword">true</span>; <a name="l00309"></a>00309 status = options-><a class="code" href="classManipulationOptions.html#a9bc4d4123333012b705b599043406e68">getStatus</a>(); <a name="l00310"></a>00310 } <a name="l00311"></a>00311 <a name="l00312"></a>00312 <span class="comment">//intialize seed using current time</span> <a name="l00313"></a>00313 srand( <span class="keywordtype">unsigned</span>(time(NULL)) ); <a name="l00314"></a>00314 <a name="l00315"></a>00315 <span class="comment">//determine tile size</span> <a name="l00316"></a>00316 QSize tileSize; <a name="l00317"></a>00317 <span class="keywordflow">if</span>(options == NULL) tileSize = QSize(6,6); <span class="comment">//6 is big enough to be visible, but not so blocky the image looks bad</span> <a name="l00318"></a>00318 <span class="keywordflow">else</span> tileSize =options-><a class="code" href="classMosaicOptions.html#aef9c2a6b46ac2b1e90b5dc7c94d88c34">getTileSize</a>(); <a name="l00319"></a>00319 <a name="l00320"></a>00320 <span class="comment">//construct tile set</span> <a name="l00321"></a>00321 <a class="code" href="structTileSet.html">TileSet</a>* tileSet = NULL; <a name="l00322"></a>00322 <span class="keywordflow">if</span>( options != NULL && options-><a class="code" href="classMosaicOptions.html#ab087719eafa81e81ee5d0591daf1786a">getFileList</a>().size() > 0 ) <a name="l00323"></a>00323 { <a name="l00324"></a>00324 <a class="code" href="mosaic_8cpp.html#abaf87e675270cda9dbbdc911e4726f94">constructImageTiles</a>(options-><a class="code" href="classMosaicOptions.html#ab087719eafa81e81ee5d0591daf1786a">getFileList</a>(), tileSize); <a name="l00325"></a>00325 tileSet = &<a class="code" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a>; <a name="l00326"></a>00326 } <a name="l00327"></a>00327 <span class="keywordflow">else</span> <a name="l00328"></a>00328 { <a name="l00329"></a>00329 <a class="code" href="mosaic_8cpp.html#adcff7718bf4fa9b179c469dbdfb1e7bf">constructColorTiles</a>(tileSize); <a name="l00330"></a>00330 tileSet = &<a class="code" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a>; <a name="l00331"></a>00331 } <a name="l00332"></a>00332 <a name="l00333"></a>00333 <span class="comment">//setup progress bar</span> <a name="l00334"></a>00334 <span class="keywordflow">if</span>(useBusyIndicators) <a name="l00335"></a>00335 { <a name="l00336"></a>00336 QString statusMessage = qApp->translate( <span class="stringliteral">"mosaicEffect"</span>, <span class="stringliteral">"Applying Mosaic Effect:"</span> ); <a name="l00337"></a>00337 status-><a class="code" href="classStatusWidget.html#a57d461014070b9d651c36bd157cab9c1" title="Initializes the progress bar.">showProgressBar</a>( statusMessage, 100 ); <a name="l00338"></a>00338 qApp->processEvents(); <a name="l00339"></a>00339 } <a name="l00340"></a>00340 <a name="l00341"></a>00341 <span class="comment">//update progress bar for every 1% of completion</span> <a name="l00342"></a>00342 <span class="keyword">const</span> <span class="keywordtype">int</span> <a class="code" href="redEye__internal_8h.html#a32598f506d413f48cda8e1c930dae6b3">updateIncrement</a> = (int) ( (0.01 * editedImage->width() * editedImage->height()) / <a name="l00343"></a>00343 (tileSize.width() * tileSize.height()) ); <a name="l00344"></a>00344 <span class="keywordtype">int</span> <a class="code" href="redEye__internal_8h.html#acaa08422437cae250a76ca488cbe1567">newProgress</a> = 0; <a name="l00345"></a>00345 <a name="l00346"></a>00346 <span class="comment">//iterate over each selected scanline </span> <a name="l00347"></a>00347 <span class="keywordtype">int</span> x, y; <a name="l00348"></a>00348 <span class="keywordflow">for</span>(y=0; y<editedImage->height(); y+=tileSize.height()) <a name="l00349"></a>00349 { <a name="l00350"></a>00350 <span class="keywordflow">for</span>( x=0; x<editedImage->width(); x+=tileSize.width()) <a name="l00351"></a>00351 { <a name="l00352"></a>00352 <span class="comment">//splat the best tile</span> <a name="l00353"></a>00353 <a class="code" href="mosaic_8cpp.html#a01e2afa17839fbd21afc5397952270c7">splatBestTile</a>( editedImage, QPoint(x,y), tileSet ); <a name="l00354"></a>00354 <a name="l00355"></a>00355 <span class="comment">//update status bar if significant progress has been made since last update</span> <a name="l00356"></a>00356 <span class="keywordflow">if</span>(useBusyIndicators) <a name="l00357"></a>00357 { <a name="l00358"></a>00358 newProgress++; <a name="l00359"></a>00359 <span class="keywordflow">if</span>(newProgress >= updateIncrement) <a name="l00360"></a>00360 { <a name="l00361"></a>00361 newProgress = 0; <a name="l00362"></a>00362 status-><a class="code" href="classStatusWidget.html#ade18735223ae40506c32c96b9c9c5476" title="Updates the progress bar by one step.">incrementProgress</a>(); <a name="l00363"></a>00363 qApp->processEvents(); <a name="l00364"></a>00364 } <a name="l00365"></a>00365 } <a name="l00366"></a>00366 <a name="l00367"></a>00367 } <a name="l00368"></a>00368 } <a name="l00369"></a>00369 <a name="l00370"></a>00370 <span class="comment">//return pointer to edited image</span> <a name="l00371"></a>00371 <span class="keywordflow">return</span> editedImage; <a name="l00372"></a>00372 } </pre></div></p> </div> </div> <a class="anchor" id="a01e2afa17839fbd21afc5397952270c7"></a><!-- doxytag: member="mosaic.cpp::splatBestTile" ref="a01e2afa17839fbd21afc5397952270c7" args="(QImage *image, QPoint topLeftCorner, TileSet *tileSet)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">void splatBestTile </td> <td>(</td> <td class="paramtype">QImage * </td> <td class="paramname"> <em>image</em>, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype">QPoint </td> <td class="paramname"> <em>topLeftCorner</em>, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"><a class="el" href="structTileSet.html">TileSet</a> * </td> <td class="paramname"> <em>tileSet</em></td><td> </td> </tr> <tr> <td></td> <td>)</td> <td></td><td></td><td></td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00598">598</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> <p>References <a class="el" href="mosaic_8cpp_source.html#l00265">Tile::avgColor</a>, <a class="el" href="mosaic_8cpp_source.html#l00268">Tile::avgL</a>, <a class="el" href="mosaic_8cpp_source.html#l00268">Tile::avgS</a>, <a class="el" href="mosaic_8cpp_source.html#l00262">Tile::image</a>, <a class="el" href="mosaic_8cpp_source.html#l00277">TileSet::numInitialized</a>, and <a class="el" href="mosaic_8cpp_source.html#l00274">TileSet::tiles</a>.</p> <p>Referenced by <a class="el" href="mosaic_8cpp_source.html#l00290">mosaicEffect()</a>.</p> <p><div class="fragment"><pre class="fragment"><a name="l00599"></a>00599 { <a name="l00600"></a>00600 <span class="keywordtype">int</span> x, y; <a name="l00601"></a>00601 QRgb* imageRgb; <a name="l00602"></a>00602 QRgb* tileRgb; <a name="l00603"></a>00603 uchar* imageScanLine; <a name="l00604"></a>00604 uchar* tileScanLine; <a name="l00605"></a>00605 <span class="comment">//------------------------------ </span> <a name="l00606"></a>00606 <span class="comment">//dermine boundary we'll be iterating over</span> <a name="l00607"></a>00607 <span class="keywordtype">int</span> xMin = 0; <a name="l00608"></a>00608 <span class="keywordtype">int</span> xMax = QMIN( tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[0].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.width(), image->width() - topLeftCorner.x() ); <a name="l00609"></a>00609 <span class="keywordtype">int</span> yMin = 0; <a name="l00610"></a>00610 <span class="keywordtype">int</span> yMax = QMIN( tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[0].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.height(), image->height() - topLeftCorner.y() ); <a name="l00611"></a>00611 <span class="comment">//------------------------------ </span> <a name="l00612"></a>00612 <span class="comment">//find most common hue, and average color, saturation and luminance for this portion of the image </span> <a name="l00613"></a>00613 <span class="keywordtype">double</span> avgR=0; <span class="keywordtype">double</span> avgG=0; <span class="keywordtype">double</span> avgB=0; <a name="l00614"></a>00614 <span class="keywordtype">int</span> hueHist[361]; <a name="l00615"></a>00615 <span class="keywordtype">int</span> i; <a name="l00616"></a>00616 <span class="keywordflow">for</span>(i=0; i<361; i++) { hueHist[i] = 0; } <a name="l00617"></a>00617 <span class="keywordtype">double</span> avgS=0; <span class="keywordtype">double</span> avgL=0; <a name="l00618"></a>00618 <a name="l00619"></a>00619 <span class="keywordflow">for</span>( y=yMin; y<yMax; y++) <a name="l00620"></a>00620 { <a name="l00621"></a>00621 imageScanLine = image->scanLine(y+topLeftCorner.y()); <a name="l00622"></a>00622 <span class="keywordflow">for</span>( x=xMin; x<xMax; x++) <a name="l00623"></a>00623 { <a name="l00624"></a>00624 imageRgb = ((QRgb*)imageScanLine+x+topLeftCorner.x()); <a name="l00625"></a>00625 QColor color( *imageRgb ); <a name="l00626"></a>00626 <a name="l00627"></a>00627 avgR += color.red(); <a name="l00628"></a>00628 avgG += color.green(); <a name="l00629"></a>00629 avgB += color.blue(); <a name="l00630"></a>00630 <a name="l00631"></a>00631 <span class="keywordtype">int</span> h,s,l; <a name="l00632"></a>00632 color.getHsv( &h, &s, &l ); <a name="l00633"></a>00633 hueHist[ QMIN( QMAX(h,0), 360 ) ]++; <a name="l00634"></a>00634 avgS += s; <a name="l00635"></a>00635 avgL += l; <a name="l00636"></a>00636 } <a name="l00637"></a>00637 } <a name="l00638"></a>00638 <a name="l00639"></a>00639 <span class="comment">//average red, green, blue, saturation, and luminance sums</span> <a name="l00640"></a>00640 <span class="keywordtype">int</span> pixelCount = (yMax-yMin) * (xMax-xMin); <a name="l00641"></a>00641 avgR /= pixelCount; <a name="l00642"></a>00642 avgG /= pixelCount; <a name="l00643"></a>00643 avgB /= pixelCount; <a name="l00644"></a>00644 avgS /= pixelCount; <a name="l00645"></a>00645 avgL /= pixelCount; <a name="l00646"></a>00646 <a name="l00647"></a>00647 <span class="comment">//walk through hue histogram and find most common hue</span> <a name="l00648"></a>00648 <span class="keywordtype">int</span> mostCommonHue = 0; <a name="l00649"></a>00649 <span class="keywordflow">for</span>(i=1; i<361; i++) <a name="l00650"></a>00650 { <a name="l00651"></a>00651 <span class="keywordflow">if</span>( hueHist[i] > hueHist[mostCommonHue] ) { mostCommonHue = i; } <a name="l00652"></a>00652 } <a name="l00653"></a>00653 <a name="l00654"></a>00654 <span class="comment">//------------------------------ </span> <a name="l00655"></a>00655 <span class="comment">//compute distance between this region and all initialized tiles</span> <a name="l00656"></a>00656 <span class="keywordtype">double</span>* distances = <span class="keyword">new</span> <span class="keywordtype">double</span>[tileSet-><a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>]; <a name="l00657"></a>00657 <a name="l00658"></a>00658 <span class="keywordtype">double</span> dR, dG, dB; <a name="l00659"></a>00659 <span class="keywordtype">double</span> rBar; <a name="l00660"></a>00660 <span class="keywordflow">for</span>(i=0; i<tileSet-><a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>; i++) <a name="l00661"></a>00661 { <a name="l00662"></a>00662 dR = tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[i].<a class="code" href="structTile.html#accb3f9de22351962d8f3110f50363f34">avgColor</a>.red() - avgR; <a name="l00663"></a>00663 dG = tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[i].<a class="code" href="structTile.html#accb3f9de22351962d8f3110f50363f34">avgColor</a>.green() - avgG; <a name="l00664"></a>00664 dB = tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[i].<a class="code" href="structTile.html#accb3f9de22351962d8f3110f50363f34">avgColor</a>.blue() - avgB; <a name="l00665"></a>00665 rBar = 0.5* (tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[i].<a class="code" href="structTile.html#accb3f9de22351962d8f3110f50363f34">avgColor</a>.red() + avgR); <a name="l00666"></a>00666 <a name="l00667"></a>00667 <span class="comment">//we could find the distance between this region and the tile by comparing the colors</span> <a name="l00668"></a>00668 <span class="comment">//directly as 3d points (sqrt(dR*dR + dG*dG + dB*dB)) but this would not</span> <a name="l00669"></a>00669 <span class="comment">//take into account their reltive perceptual weights. I found</span> <a name="l00670"></a>00670 <span class="comment">//some work by Thiadmer Riemersma that suggest I use this equation instead...</span> <a name="l00671"></a>00671 <span class="comment">//http://www.compuphase.com/cmetric.htm</span> <a name="l00672"></a>00672 distances[i] = ((2+(rBar/256)) * dR * dR) + <a name="l00673"></a>00673 (4 * dG * dG) + <a name="l00674"></a>00674 ((2 + ((255.0-rBar)/256)) * dB * dB); <a name="l00675"></a>00675 } <a name="l00676"></a>00676 <span class="comment">//------------------------------ </span> <a name="l00677"></a>00677 <span class="comment">//pick tile using pseudo-random distance biased approach</span> <a name="l00678"></a>00678 <a name="l00679"></a>00679 <span class="comment">//take reciprocol of all distances and find sum</span> <a name="l00680"></a>00680 <span class="keywordtype">double</span> sum = 0; <a name="l00681"></a>00681 <span class="keywordtype">double</span> epsilon = 0.000000001; <a name="l00682"></a>00682 <span class="keywordflow">for</span>(i=0; i<tileSet-><a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>; i++) <a name="l00683"></a>00683 { <a name="l00684"></a>00684 distances[i] = 1.0 / QMAX(distances[i], epsilon); <a name="l00685"></a>00685 sum += distances[i]; <a name="l00686"></a>00686 } <a name="l00687"></a>00687 <a name="l00688"></a>00688 <span class="comment">//get a random number and find appropriate tile </span> <a name="l00689"></a>00689 <span class="keywordtype">double</span> percentage = ((double)rand()) / RAND_MAX; <a name="l00690"></a>00690 <span class="keywordtype">double</span> number = sum * percentage; <a name="l00691"></a>00691 <span class="keywordtype">int</span> TILE = 0; <a name="l00692"></a>00692 sum = 0; <a name="l00693"></a>00693 <span class="keywordflow">for</span>(i =0; i<tileSet-><a class="code" href="structTileSet.html#aac330665a49d4689199da8a1a0c9eca7">numInitialized</a>; i++) <a name="l00694"></a>00694 { <a name="l00695"></a>00695 sum += distances[i]; <a name="l00696"></a>00696 <span class="keywordflow">if</span>( sum >= number) <a name="l00697"></a>00697 { <a name="l00698"></a>00698 TILE = i; <span class="keywordflow">break</span>; <a name="l00699"></a>00699 } <a name="l00700"></a>00700 } <a name="l00701"></a>00701 <a name="l00702"></a>00702 <span class="keyword">delete</span> distances; <a name="l00703"></a>00703 distances = NULL; <a name="l00704"></a>00704 <span class="comment">//------------------------------ </span> <a name="l00705"></a>00705 <span class="comment">//determine saturation and luminance multipliers</span> <a name="l00706"></a>00706 <span class="keywordtype">double</span> sInc = avgS - tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[TILE].<a class="code" href="structTile.html#adc45f505b5bc1a8148462bdfcc804cd3">avgS</a>; <a name="l00707"></a>00707 <span class="keywordtype">double</span> lInc = avgL - tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[TILE].<a class="code" href="structTile.html#a06ff4be3625f8030d80b321d9fb3acb6">avgL</a>; <a name="l00708"></a>00708 <span class="comment">//------------------------------ </span> <a name="l00709"></a>00709 <a name="l00710"></a>00710 <span class="comment">//finally, splat the tile</span> <a name="l00711"></a>00711 <span class="keywordflow">for</span>( y=yMin; y<yMax; y++ ) <a name="l00712"></a>00712 { <a name="l00713"></a>00713 <span class="comment">//iterate over each selected pixel in scanline</span> <a name="l00714"></a>00714 imageScanLine = image->scanLine( (y+topLeftCorner.y()) ); <a name="l00715"></a>00715 tileScanLine = tileSet-><a class="code" href="structTileSet.html#ad8291fa9fa299ee201def5b225c0c726">tiles</a>[TILE].<a class="code" href="structTile.html#adcff7a7b2b15451ed969e6eb77c38baa">image</a>.scanLine(y); <a name="l00716"></a>00716 <span class="keywordflow">for</span>( x=xMin; x<xMax; x++) <a name="l00717"></a>00717 { <a name="l00718"></a>00718 <span class="comment">//get the tile color</span> <a name="l00719"></a>00719 tileRgb = ((QRgb*) tileScanLine) + x;; <a name="l00720"></a>00720 QColor color( *tileRgb ); <a name="l00721"></a>00721 <a name="l00722"></a>00722 <span class="comment">//convert to hsl</span> <a name="l00723"></a>00723 <span class="keywordtype">int</span> h,s,l; <a name="l00724"></a>00724 color.getHsv( &h, &s, &l ); <a name="l00725"></a>00725 <a name="l00726"></a>00726 <span class="comment">//replace hue with the most common hue from this region of the target image</span> <a name="l00727"></a>00727 h = mostCommonHue; <a name="l00728"></a>00728 <a name="l00729"></a>00729 <span class="comment">//adjust saturation and luminance to more closely match the average values</span> <a name="l00730"></a>00730 <span class="comment">//found in this region of the target image.</span> <a name="l00731"></a>00731 s = (int)QMIN( QMAX( s+sInc, 0), 255 ); <a name="l00732"></a>00732 l = (int)QMIN( QMAX( l+lInc, 0), 255 ); <a name="l00733"></a>00733 <a name="l00734"></a>00734 <span class="comment">//convert back to rgb</span> <a name="l00735"></a>00735 color.setHsv( mostCommonHue, s, l ); <a name="l00736"></a>00736 <a name="l00737"></a>00737 <span class="comment">//splat the adjusted tile color onto the image</span> <a name="l00738"></a>00738 imageRgb = ((QRgb*)imageScanLine) + x + topLeftCorner.x(); <a name="l00739"></a>00739 <a name="l00740"></a>00740 *imageRgb = color.rgb(); <a name="l00741"></a>00741 } <a name="l00742"></a>00742 } <a name="l00743"></a>00743 <a name="l00744"></a>00744 } </pre></div></p> </div> </div> <hr/><h2>Variable Documentation</h2> <a class="anchor" id="aeae592e14c25ef303dfbb2fa68598842"></a><!-- doxytag: member="mosaic.cpp::colorTiles" ref="aeae592e14c25ef303dfbb2fa68598842" args="" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname"><a class="el" href="structTileSet.html">TileSet</a> <a class="el" href="mosaic_8cpp.html#aeae592e14c25ef303dfbb2fa68598842">colorTiles</a></td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00282">282</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> </div> </div> <a class="anchor" id="a15fb7a6ec3f4d512437d4ea50f0f02f4"></a><!-- doxytag: member="mosaic.cpp::imageTiles" ref="a15fb7a6ec3f4d512437d4ea50f0f02f4" args="" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname"><a class="el" href="structTileSet.html">TileSet</a> <a class="el" href="mosaic_8cpp.html#a15fb7a6ec3f4d512437d4ea50f0f02f4">imageTiles</a></td> </tr> </table> </div> <div class="memdoc"> <p>Definition at line <a class="el" href="mosaic_8cpp_source.html#l00283">283</a> of file <a class="el" href="mosaic_8cpp_source.html">mosaic.cpp</a>.</p> </div> </div> </div> <hr size="1"/><address style="text-align: right;"><small>Generated by <a href="http://www.doxygen.org/index.html"> <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.2 </small></address> </body> </html>