bool SingleRemap::apply() { const GfxRemap32 *const gfxRemap32 = g_sci->_gfxRemap32; const uint8 remapStartColor = gfxRemap32->getStartColor(); // Blocked colors are not allowed to be used as target // colors for the remap bool blockedColors[236]; Common::fill(blockedColors, blockedColors + remapStartColor, false); const bool *const paletteCycleMap = g_sci->_gfxPalette32->getCycleMap(); const int16 blockedRangeCount = gfxRemap32->getBlockedRangeCount(); if (blockedRangeCount) { const uint8 blockedRangeStart = gfxRemap32->getBlockedRangeStart(); Common::fill(blockedColors + blockedRangeStart, blockedColors + blockedRangeStart + blockedRangeCount, true); } for (uint i = 0; i < remapStartColor; ++i) { if (paletteCycleMap[i]) { blockedColors[i] = true; } } // NOTE: SSCI did a loop over colors here to create a // new array of updated, unblocked colors, but then // never used it bool updated = false; for (uint i = 1; i < remapStartColor; ++i) { int distance; if (!_idealColorsChanged[i] && !_originalColorsChanged[_remapColors[i]]) { continue; } if ( _idealColorsChanged[i] && _originalColorsChanged[_remapColors[i]] && _matchDistances[i] < 100 && colorDistance(_idealColors[i], _originalColors[_remapColors[i]]) <= _matchDistances[i] ) { continue; } const int16 bestColor = matchColor(_idealColors[i], _matchDistances[i], distance, blockedColors); if (bestColor != -1 && _remapColors[i] != bestColor) { updated = true; _remapColors[i] = bestColor; _matchDistances[i] = distance; } } return updated; }
void moFlatlandColorPairFinderModule::applyFilter(IplImage *src) { ///////////////////////////////////////////////////////////////////////////////////// //Step 1 get gray version of input, retain colored version ///////////////////////////////////////////////////////////////////////////////////// //Step 2 pass gray along normally to contour finder. this->clearBlobs(); //imagePreprocess(src); //cvCopy(src, this->output_buffer); cvCvtColor(src, this->output_buffer, CV_RGB2GRAY); CvSeq *contours = 0; cvFindContours(this->output_buffer, this->storage, &contours, sizeof(CvContour), CV_RETR_CCOMP); cvDrawContours(this->output_buffer, contours, cvScalarAll(255), cvScalarAll(255), 100); //cvCircle(this->output_buffer, /* the dest image */ // cvPoint(110, 60), 35, /* center point and radius */ // cvScalarAll(255), /* the color; red */ // 1, 8, 0); // Consider each contour a blob and extract the blob infos from it. int size; int min_size = this->property("min_size").asInteger(); int max_size = this->property("max_size").asInteger(); CvSeq *cur_cont = contours; ///////////////////////////////////////////////////////////////////////////////////// //Step 3 check window around contour centers and find color //clear the console? //system("cls"); //system("clear"); //clrscr(); //printf("\033[2J"); //std::cout << std::string( 100, '\n' ); std::vector<ColoredPt> cPts; //printf("==================================\n"); int blobi = 0; while (cur_cont != 0) { CvRect rect = cvBoundingRect(cur_cont, 0); size = rect.width * rect.height; //printf(":: %d\n", size); if ((size >= min_size) && (size <= max_size)) { //TODO use a Vector double red = 0; double green = 0; double blue = 0; int blobColor = 0; //in reality, probably could filter heavily and just look at 1 pixel, or at least a very small window // [!!!] for (int x = rect.x; x < rect.x + rect.width; x++) { for (int y = rect.y; y < rect.y + rect.height; y++) { int blueVal = ( ((uchar*)(src->imageData + src->widthStep*y))[x*3+0] ); int greenVal = ( ((uchar*)(src->imageData + src->widthStep*y))[x*3+1] ); int redVal = ( ((uchar*)(src->imageData + src->widthStep*y))[x*3+2] ); double colorNorm = 1.0;//sqrt((blueVal*blueVal) + (greenVal*greenVal) + (redVal * redVal)); //weight dark pixels less double weight = 1.0;//(1.0*blueVal + greenVal + redVal) / (1.5 * 255.0); if (weight > 1) { weight = 1; } if (colorNorm > 0) { red += weight*redVal/colorNorm; green += weight*greenVal/colorNorm; blue += weight*blueVal/colorNorm; } } } //the channel totals //printf("%d : %f\n%f\n%f\n\n",blobi , red, green, blue); blobi++; if (red > green && red > blue) { blobColor = RED; } if (blue > green && blue > red) { blobColor = BLUE; } if (green > red && green > blue) { blobColor = GREEN; } blobColor = matchColor(red, green, blue); // Draw a letter corresponding to the LED color CvFont font; cvInitFont(&font, CV_FONT_HERSHEY_PLAIN, .7f, .7f, 0, 1, CV_AA); if (blobColor == RED) { cvPutText(this->output_buffer, "R", cvPoint(rect.x + rect.width / 2.0, rect.y + rect.height / 2.0), &font, cvScalar(255, 255, 255, 0)); } else if (blobColor == GREEN) { cvPutText(this->output_buffer, "G", cvPoint(rect.x + rect.width / 2.0, rect.y + rect.height / 2.0), &font, cvScalar(255, 255, 255, 0)); } else if (blobColor == BLUE) { cvPutText(this->output_buffer, "B", cvPoint(rect.x + rect.width / 2.0, rect.y + rect.height / 2.0), &font, cvScalar(255, 255, 255, 0)); } else if (blobColor == WHITE) { cvPutText(this->output_buffer, "Y", cvPoint(rect.x + rect.width / 2.0, rect.y + rect.height / 2.0), &font, cvScalar(255, 255, 255, 0)); } /*moDataGenericContainer *blob = new moDataGenericContainer(); blob->properties["implements"] = new moProperty("pos,size"); blob->properties["x"] = new moProperty((rect.x + rect.width / 2) / (double) src->width ); blob->properties["y"] = new moProperty((rect.y + rect.height / 2) / (double) src->height ); blob->properties["width"] = new moProperty(rect.width); blob->properties["height"] = new moProperty(rect.height); blob->properties["color"] = new moProperty(blobColor); this->blobs->push_back(blob);*/ struct ColoredPt thisPt; thisPt.x = (rect.x + rect.width / 2);// / (double) src->width; thisPt.y = (rect.y + rect.height / 2);// / (double) src->height; thisPt.color = blobColor; cPts.push_back(thisPt); } cur_cont = cur_cont->h_next; } ///////////////////////////////////////////////////////////////////////////////////// //Step 4 iterate over blobs again, to find close pairs //TODO Currently, this algorithm assumes the best, and does nothing to ensure robustness/smoothness //e.g. add a distance threshold (would need to be "settable" in a Gui) int nPlayersFound = 0; //Init the adjacency list int MAX_N_LIGHTS = 20; // TODO! more lights may need to be identified for field markers! int pairs[MAX_N_LIGHTS]; for ( int i = 0; i < MAX_N_LIGHTS; i++ ) { pairs[i] = -1; } //printf("+++++++++++++++++++++++++++++++++++++++++\n"); // map out closest pairs of lights. //TODO need to iterate through blobs and throw out obviously non-player-light blobs. (big blobs) //TODO //TODO //TODO //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // In more realistic scenarios, an arbitrary number of lights is likely to appear! // Need to account for this! //! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! for ( int i = 0; i < cPts.size() && i < MAX_N_LIGHTS; i++ ) // dynamically allocate pairs based on number of lights? { if(pairs[i] == -1) { double minDist = 1000000;//distances are < 1, so should be OK. int closestIdx = -1; for ( int j = i; j < cPts.size() && j < MAX_N_LIGHTS; j++ ) { if (j != i) { double x1 = cPts[i].x; double y1 = cPts[i].y; double x2 = cPts[j].x; double y2 = cPts[j].y; double distance = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); if (distance < minDist) { minDist = distance; closestIdx = j; } } } if (closestIdx >= 0) { pairs[i] = closestIdx; pairs[closestIdx] = -9999; //designate as 'slave' point. nPlayersFound ++; //printf("%d ___ %d\n",i, pairs[i]); } } else { } } //printf("==================================\n"); //for ( int i = 0; i < cPts.size(); i++ ) //{ // printf("%d ___ %d\n", i, pairs[i]); //} /////////////////////////////////////// // Clear the player list ////////////// moDataGenericList::iterator pit; for ( pit = this->players->begin(); pit != this->players->end(); pit++ ) { delete (*pit); } this->players->clear(); // look at pair colors and determine player number for (int i = 0; i < MAX_N_LIGHTS; i++) { if (pairs[i] >= 0) { //printf("%d ___ %d\n",pairs[i], pairs[i]); int color1 = cPts[i].color; int color2 = cPts[pairs[i]].color; //write a function to choose the player int playerIdx = getPlayerIndex(color1, color2); std::ostringstream labelStream; labelStream << playerIdx; /*if ((color1 == 0 && color2 == 2) || (color2 == 0 && color1 == 2)) //red and blue { label = "1"; } else if ((color1 == 0 && color2 == 1) || (color2 == 0 && color1 == 1)) //red and green { label = "2"; }*/ double avX = (cPts[i].x + cPts[pairs[i]].x)/2; double avY = (cPts[i].y + cPts[pairs[i]].y)/2; CvFont font; cvInitFont(&font, CV_FONT_HERSHEY_PLAIN, 1.7f, 1.7f, 0, 1, CV_AA); cvPutText(this->output_buffer, labelStream.str().c_str(), cvPoint(avX, avY), &font, cvScalar(255, 255, 255, 0)); /*moDataGenericContainer *player = new moDataGenericContainer(); player->properties["implements"] = new moProperty("pos"); player->properties["x"] = new moProperty(avX / src->width); player->properties["y"] = new moProperty(avY / src->height); player->properties["blob_id"] = new moProperty(playerIdx); std::string implements = player->properties["implements"]->asString(); // Indicate that the blob has been tracked, i.e. blob_id exists. implements += ",tracked"; player->properties["implements"]->set(implements); this->players->push_back(player);*/ //->properties["blob_id"]->set(old_id); } } //Add in some fake players, so I don't have to have the lights out to test the connection. double debugX = .5 + .25 * sin(2*3.14 * frameCounter / 200); if (frameCounter % 2 == 0) { moDataGenericContainer *player = new moDataGenericContainer(); player->properties["implements"] = new moProperty("pos"); player->properties["x"] = new moProperty(debugX); player->properties["y"] = new moProperty(.75); player->properties["blob_id"] = new moProperty(0); std::string implements = player->properties["implements"]->asString(); // Indicate that the blob has been tracked, i.e. blob_id exists. implements += ",tracked"; player->properties["implements"]->set(implements); moDataGenericContainer *player2 = new moDataGenericContainer(); player2->properties["implements"] = new moProperty("pos"); player2->properties["x"] = new moProperty(1 - debugX); player2->properties["y"] = new moProperty(.75); player2->properties["blob_id"] = new moProperty(1); player2->properties["implements"]->set(implements); this->players->push_back(player); this->players->push_back(player2); } frameCounter = (frameCounter + 1) % 200; this->output_data->push(this->players); }
TestCase::IterateResult ReadPixelsCase::iterate (void) { const tcu::RenderTarget& renderTarget = m_context.getRenderTarget(); tcu::PixelFormat pixelFormat = renderTarget.getPixelFormat(); int targetWidth = renderTarget.getWidth(); int targetHeight = renderTarget.getHeight(); int x = 0; int y = 0; int imageWidth = 0; int imageHeight = 0; deRandom rnd; deRandom_init(&rnd, deInt32Hash(m_curIter)); switch (m_curIter) { case 0: // Fullscreen x = 0; y = 0; imageWidth = targetWidth; imageHeight = targetHeight; break; case 1: // Upper left corner x = 0; y = 0; imageWidth = targetWidth / 2; imageHeight = targetHeight / 2; break; case 2: // Lower right corner x = targetWidth / 2; y = targetHeight / 2; imageWidth = targetWidth - x; imageHeight = targetHeight - y; break; default: x = deRandom_getUint32(&rnd) % (targetWidth - 1); y = deRandom_getUint32(&rnd) % (targetHeight - 1); imageWidth = 1 + (deRandom_getUint32(&rnd) % (targetWidth - x - 1)); imageHeight = 1 + (deRandom_getUint32(&rnd) % (targetHeight - y - 1)); break; } Surface resImage(imageWidth, imageHeight); Surface refImage(imageWidth, imageHeight); Surface diffImage(imageWidth, imageHeight); int r = (int)(deRandom_getUint32(&rnd) & 0xFF); int g = (int)(deRandom_getUint32(&rnd) & 0xFF); int b = (int)(deRandom_getUint32(&rnd) & 0xFF); tcu::clear(refImage.getAccess(), tcu::IVec4(r, g, b, 255)); glClearColor(r/255.0f, g/255.0f, b/255.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glu::readPixels(m_context.getRenderContext(), x, y, resImage.getAccess()); GLU_CHECK_MSG("glReadPixels() failed."); RGBA colorThreshold = pixelFormat.getColorThreshold(); RGBA matchColor(0, 255, 0, 255); RGBA diffColor(255, 0, 0, 255); bool isImageOk = true; for (int j = 0; j < imageHeight; j++) { for (int i = 0; i < imageWidth; i++) { RGBA resRGBA = resImage.getPixel(i, j); RGBA refRGBA = refImage.getPixel(i, j); bool isPixelOk = compareThreshold(refRGBA, resRGBA, colorThreshold); diffImage.setPixel(i, j, isPixelOk ? matchColor : diffColor); isImageOk = isImageOk && isPixelOk; } } if (isImageOk) m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); else { m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); TestLog& log = m_testCtx.getLog(); log << TestLog::ImageSet("Result", "Resulting framebuffer") << TestLog::Image("Result", "Resulting framebuffer", resImage) << TestLog::Image("Reference", "Reference image", refImage) << TestLog::Image("DiffMask", "Failing pixels", diffImage) << TestLog::EndImageSet; } return (++m_curIter < m_numIters) ? CONTINUE : STOP; }
int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) { return matchColor(r, g, b) & 0xFF; }
bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { uint16 res; bool paletteChanged = false; for (int i = 1; i < 255; i++) { // skip unused colors if (!newPalette->colors[i].used) continue; // forced palette merging or dest color is not used yet if (force || (!_sysPalette.colors[i].used)) { _sysPalette.colors[i].used = newPalette->colors[i].used; if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { _sysPalette.colors[i].r = newPalette->colors[i].r; _sysPalette.colors[i].g = newPalette->colors[i].g; _sysPalette.colors[i].b = newPalette->colors[i].b; paletteChanged = true; } newPalette->mapping[i] = i; continue; } // is the same color already at the same position? -> match it directly w/o lookup // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) if ((_sysPalette.colors[i].r == newPalette->colors[i].r) && (_sysPalette.colors[i].g == newPalette->colors[i].g) && (_sysPalette.colors[i].b == newPalette->colors[i].b)) { newPalette->mapping[i] = i; continue; } // check if exact color could be matched res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b); if (res & 0x8000) { // exact match was found newPalette->mapping[i] = res & 0xFF; continue; } int j = 1; // no exact match - see if there is an unused color for (; j < 256; j++) { if (!_sysPalette.colors[j].used) { _sysPalette.colors[j].used = newPalette->colors[i].used; _sysPalette.colors[j].r = newPalette->colors[i].r; _sysPalette.colors[j].g = newPalette->colors[i].g; _sysPalette.colors[j].b = newPalette->colors[i].b; newPalette->mapping[i] = j; paletteChanged = true; break; } } // if still no luck - set an approximate color if (j == 256) { newPalette->mapping[i] = res & 0xFF; _sysPalette.colors[res & 0xFF].used |= 0x10; } } if (!forceRealMerge) _sysPalette.timestamp = g_system->getMillis() * 60 / 1000; return paletteChanged; }
bool GameLogic_match::matchColors(int pos,bool ishelp){ m_match_ignore_pos.clear(); m_match_clear_pos.clear(); m_match_new_gem_type.clear(); int color = m_gems[pos]->getColor(); matchColor(pos); bool hasBombs = false; if (m_match_clear_pos.size()>0) { if (!ishelp) { Combo(); } hasBombs = true; } if (m_match_new_gem_type.size()>1) { vector<NewSpcialGemInfos*>::iterator it; for ( it= m_match_new_gem_type.begin();it<m_match_new_gem_type.end();it++) { NewSpcialGemInfos* infos = *it; if (infos->gem_area_count==0) { m_match_new_gem_type.erase(it); it--; } } } for (unsigned int i=0; i<m_match_clear_pos.size();i++) { if (ishelp) { m_gems[m_match_clear_pos[i]]->showHelpAnim(); }else{ Bomb(m_match_clear_pos[i]); } } // if (m_match_clear_pos.size()>0) { // CCLOG("clear_count %ld",m_match_clear_pos.size()); // } // // for (int i=0; i<m_match_new_gem_type.size(); i++) { // cout<<"gem_v_count "<<m_match_new_gem_type[i]->gem_v_count // <<" gem_h_count "<<m_match_new_gem_type[i]->gem_h_count // <<" gem_area_count "<<m_match_new_gem_type[i]->gem_area_count // <<" gem_magic_count "<<m_match_new_gem_type[i]->gem_magic_count // <<" pos "<<m_match_new_gem_type[i]->pos; // } // return hasBombs; if (ishelp) { return hasBombs; } for (unsigned int i=0; i< m_match_new_gem_type.size(); i++) { NewSpcialGemInfos* infos = m_match_new_gem_type[i]; if (!m_gems[infos->pos]->isEmpty()) { continue; } if (!m_blocks[infos->pos]->canInsertGem()) { continue; } for (int j=0; j<infos->gem_area_count; j++) { int _p; if (m_gems[infos->pos]->isEmpty()) { _p = infos->pos; }else{ _p = getEmptyPosRound(infos->pos); } if (_p!=-1) { m_gems[_p]->create(GEM_AREA*10+color); showSeaHurt(200, _p); if (G::g_game_mode == GAMEMODE_SEA) { G::G_Add_Achievement_Complete(35); } achieve_count->combine_count++; } } for (int j=0; j<infos->gem_magic_count; j++) { int _p; if (m_gems[infos->pos]->isEmpty()) { _p = infos->pos; }else{ _p = getEmptyPosRound(infos->pos); } if (_p!=-1) { m_gems[_p]->create(GEM_MAGIC*10+GEM_COLOR_NOCOLOR); G::G_Add_Achievement_Complete(8); achieve_count->create_magic_count++; achieve_count->combine_count++; showSeaHurt(200, _p); if (G::g_game_mode == GAMEMODE_SEA) { G::G_Add_Achievement_Complete(35); } } } for (int j=0; j<infos->gem_h_count; j++) { int _p; if (m_gems[infos->pos]->isEmpty()) { _p = infos->pos; }else{ _p = getEmptyPosRound(infos->pos); } if (_p!=-1) { m_gems[_p]->create(GEM_H*10+color); showSeaHurt(200, _p); if (G::g_game_mode == GAMEMODE_SEA) { G::G_Add_Achievement_Complete(35); } achieve_count->combine_count++; } } for (int j=0; j<infos->gem_v_count; j++) { int _p; if (m_gems[infos->pos]->isEmpty()) { _p = infos->pos; }else{ _p = getEmptyPosRound(infos->pos); } if (_p!=-1) { m_gems[_p]->create(GEM_V*10+color); showSeaHurt(200, _p); if (G::g_game_mode == GAMEMODE_SEA) { G::G_Add_Achievement_Complete(35); } achieve_count->combine_count++; } } } m_match_ignore_pos.clear(); m_match_clear_pos.clear(); m_match_new_gem_type.clear(); return hasBombs; }
void GameLogic_match::matchColor(int pos){ if (isMatchIgnorePos(pos)){ return; } m_match_ignore_pos.push_back(pos); if (pos >= BLOCK_NUM_WH||pos<0) { return; } if (!m_blocks[pos]->isMatchColor()) { return; } if (m_gems[pos]->isEmpty()) { return; } if (m_gems[pos] ->IsMoving()) { return; } if (m_gems[pos]->HasBee()) { return; } if (m_gems[pos]->getColor() == GEM_COLOR_NOCOLOR) {//无色宝石不参与匹配 return; } vector<int> _hPos; vector<int> _vPos; _hPos.push_back(pos); _vPos.push_back(pos); int _ofx = -1; while (true) {//左 int tmpx = pos%BLOCK_NUM_W; int tmpy = pos/BLOCK_NUM_W; tmpx += _ofx; if (tmpx<0) { break; } int tmpPos = tmpy*BLOCK_NUM_W+tmpx; if (!IsMatchColor(pos, tmpPos)) { break; } _hPos.push_back(tmpPos); // _hcount++; // hGems->addObject(m_gems[tmpPos]); _ofx--; } _ofx = 1; while (true) {//右 int tmpx = pos%BLOCK_NUM_W; int tmpy = pos/BLOCK_NUM_W; tmpx += _ofx; if (tmpx>=BLOCK_NUM_W) { break; } int tmpPos = tmpy*BLOCK_NUM_W+tmpx; if (!IsMatchColor(pos, tmpPos)) { break; } _hPos.push_back(tmpPos); // _hcount++; // hGems->addObject(m_gems[tmpPos]); _ofx++; } int _ofy = -1; while (true) {//上 int tmpx = pos%BLOCK_NUM_W; int tmpy = pos/BLOCK_NUM_W; tmpy += _ofy; if (tmpy<0) { break; } int tmpPos = tmpy*BLOCK_NUM_W+tmpx; if (!IsMatchColor(pos, tmpPos)) { break; } _vPos.push_back(tmpPos); // _vcount++; // vGems->addObject(m_gems[tmpPos]); _ofy--; } _ofy = 1; while (true) {//下 int tmpx = pos%BLOCK_NUM_W; int tmpy = pos/BLOCK_NUM_W; tmpy += _ofy; if (tmpy>=BLOCK_NUM_H) { break; } int tmpPos = tmpy*BLOCK_NUM_W+tmpx; if (!IsMatchColor(pos, tmpPos)) { break; } _vPos.push_back(tmpPos); // _vcount++; // vGems->addObject(m_gems[tmpPos]); _ofy++; } if (_vPos.size()<3) { _vPos.clear(); } if (_hPos.size()<3) { _hPos.clear(); } AddMatchClearPos(_vPos); AddMatchClearPos(_hPos); NewSpcialGemInfos* infos = new NewSpcialGemInfos(pos); if (_vPos.size()>=3&&_hPos.size()>=3) { infos->gem_area_count++; } if (_vPos.size()>=5) { infos->gem_magic_count++; }else if(_vPos.size()>=4){ infos->gem_h_count++; } if (_hPos.size()>=5) { infos->gem_magic_count++; }else if(_hPos.size()>=4){ infos->gem_v_count++; } if (infos->hasNewSpecialGem()) { if (infos->gem_area_count==0) { if (m_match_new_gem_type.size()==0) { m_match_new_gem_type.push_back(infos); } }else{ m_match_new_gem_type.push_back(infos); } } for (unsigned int i=0; i<_vPos.size(); i++) { matchColor(_vPos[i]); } for (unsigned int i=0; i<_hPos.size(); i++) { matchColor(_hPos[i]); } _vPos.clear(); _hPos.clear(); }