void _quicksort(int *pointlist, int n) { unsigned int i, j, ln, rn; while (n > 1) { SWAP3(pointlist, 0, n/2); for (i = 0, j = n; ; ) { do --j; while (pointlist[3*j+2] < pointlist[2]); do ++i; while (i < j && pointlist[3*i+2] > pointlist[2]); if (i >= j) break; SWAP3(pointlist, i, j); } SWAP3(pointlist, j, 0); ln = j; rn = n - ++j; if (ln < rn) { _quicksort(pointlist, ln); pointlist += 3*j; n = rn; } else { _quicksort(pointlist + 3*j, rn); n = ln; } } }
/*! This only runs for tiled images and can have up to three stages. First, Rearrange into screen-blocks (option -mLs); then into metatiles (-Mw, -Mh), then base-tiles. */ bool grit_prep_tiles(GritRec *gr) { lprintf(LOG_STATUS, "Tile preparation.\n"); // Main sizes int imgW= dib_get_width(gr->_dib), imgH= dib_get_height(gr->_dib); int tileW= gr->tileWidth, tileH= gr->tileHeight; int metaW= gr->metaWidth, metaH= gr->metaHeight; // Tiling sizes for stages int frameW=tileW*metaW, frameH=tileH*metaH; // For meta tiling bool bMeta= gr->isMetaTiled(); bool bTile= tileW*tileH > 1; // Change things for column-major ordering if(gr->bColMajor) { int lastH= imgH, tmp; if(bMeta) SWAP3(frameH, lastH, tmp); if(bTile) SWAP3(tileH, lastH, tmp); } // Meta redim if(bMeta) { lprintf(LOG_STATUS, " tiling to %dx%d tiles.\n", frameW, frameH); if(!dib_redim(gr->_dib, frameW, frameH, 0)) { lprintf(LOG_ERROR, " meta-tiling failed.\n"); return false; } } // Tile redim if(bTile) { lprintf(LOG_STATUS, " tiling to %dx%d tiles.\n", tileW, tileH); if(!dib_redim(gr->_dib, tileW, tileH, 0)) { lprintf(LOG_ERROR, " tiling failed.\n"); return false; } } lprintf(LOG_STATUS, "Tile preparation complete.\n"); return true; }
/* A simple version of quicksort; taken from Kernighan and Ritchie, page 87. Assumes 0 origin for v, number of elements = right+1 (right is index of right-most member). */ static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right) { PetscErrorCode ierr; PetscInt i,vl,last,tmp; PetscFunctionBegin; if (right <= 1) { if (right == 1) { if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp); } PetscFunctionReturn(0); } SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp); vl = L[0]; last = 0; for (i=1; i<=right; i++) { if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);} } SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp); ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr); ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(void) { int x = 5; int y = 9; printf("x = %d y = %d\n", x, y); printf("\n"); SWAP1(x, y); printf("x = %d y = %d\n", x, y); printf("\n"); SWAP2(x, y); printf("x = %d y = %d\n", x, y); printf("\n"); SWAP3(x, y); printf("x = %d y = %d\n", x, y); return 0; }
/*@ PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order; changes a pair of integer arrays to match the sorted first array. Not Collective Input Parameters: + n - number of values . I - array of integers . J - second array of integers (first array of the pair) - K - third array of integers (second array of the pair) Level: intermediate Concepts: sorting^ints with array pair .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray() @*/ PetscErrorCode PetscSortIntWithArrayPair(PetscInt n,PetscInt L[],PetscInt J[], PetscInt K[]) { PetscErrorCode ierr; PetscInt j,k,tmp,ik; PetscFunctionBegin; if (n<8) { for (k=0; k<n; k++) { ik = L[k]; for (j=k+1; j<n; j++) { if (ik > L[j]) { SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp); ik = L[k]; } } } } else { ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*! Makes sure all the settings in \a gr are valid. For example, tilemap and bitmap mode are mutually exclusive; bpp must be 1, 2, 4, 8, or 16 and more of such kind. Some things are fatal (those two are), but some can be accounted for like reversed pal start and end indices and non-aligned areas. */ bool grit_validate(GritRec *gr) { int tmp; lprintf(LOG_STATUS, "Validatating gr.\n"); // source dib MUST be loaded already! if(gr->srcDib == NULL) { lprintf(LOG_ERROR, " No input bitmap. Validation failed.\n"); return false; } if(!grit_validate_paths(gr)) return false; // --- Options --- // bpp must be 2^n; truecolor WILL be bitmaps. int bpp= gr->gfxBpp; switch(bpp) { case 0: gr->gfxBpp=8; case 1: case 2: case 4: case 8: break; case 16: case 24: case 32: gr->gfxBpp= 16; gr->mapProcMode= GRIT_EXCLUDE; // No map. REPONDER gr->palProcMode= GRIT_EXCLUDE; // No pal either. break; default: lprintf(LOG_ERROR, " Bad bpp (%d).\n", bpp); return false; } // Raw binary cannot be appended if(gr->fileType==GRIT_FTYPE_BIN && gr->bAppend) { gr->bAppend= false; lprintf(LOG_WARNING, " Can't append to binary files. Switching to override mode."); } // --- ranges --- // palette if(gr->palProcMode != GRIT_EXCLUDE) { if(gr->palStart > gr->palEnd) { lprintf(LOG_WARNING, " Palette: start (%d) > end (%d): swapping.\n", gr->palStart, gr->palEnd); SWAP3(gr->palStart, gr->palEnd, tmp); } if(gr->palStart<0) { lprintf(LOG_WARNING, " Palette: start (%d) < 0. Clamping to 0.\n", gr->palStart); gr->palStart= 0; } int nclrs= dib_get_nclrs(gr->srcDib); if(nclrs != 0 && gr->palEnd > gr->palStart+nclrs) { lprintf(LOG_WARNING, " Palette: end (%d) > #colors (%d). Clamping to %d.\n", gr->palStart+nclrs); gr->palEnd= gr->palStart+nclrs; } } if(!grit_validate_area(gr)) return false; // PONDER: issue dump for status-log? lprintf(LOG_STATUS, "Validation succeeded.\n"); return true; }
bool grit_validate_area(GritRec *gr) { int tmp; //# FIXME: consider other proc-modes? // area size if(gr->gfxProcMode != GRIT_EXCLUDE || gr->mapProcMode != GRIT_EXCLUDE) { int al, at, ar, ab; // area int aw, ah; // area size int blockW, blockH; // block size al= gr->areaLeft; at= gr->areaTop; ar= gr->areaRight; ab= gr->areaBottom; // Normalize if(al > ar) { lprintf(LOG_WARNING, " Area: left (%d) > right (%d). Swapping.\n", gr->areaLeft, gr->areaRight); SWAP3(al, ar, tmp); } if(at > ab) { lprintf(LOG_WARNING, " Area: top (%d) > bottom (%d). Swapping.\n", gr->areaTop, gr->areaBottom); SWAP3(at, ab, tmp); } if(ar == 0) ar= dib_get_width(gr->srcDib); if(ab == 0) ab= dib_get_height(gr->srcDib); aw= ar-al; ah= ab-at; // metatile size (in px) // area MUST fit at least one metatile // Tiles: either // - one meta tile // - one screenblock if in SBB layout // PONDER: non-integral metatile/sbb ?? if(gr->metaWidth < 1) gr->metaWidth = 1; if(gr->metaHeight < 1) gr->metaHeight= 1; if(gr->gfxMode == GRIT_GFX_TILE) { if(gr->tileWidth < 4) gr->tileWidth = 8; if(gr->tileHeight < 4) gr->tileHeight= 8; } else { if(gr->tileWidth < 1) gr->tileWidth = 1; if(gr->tileHeight < 1) gr->tileHeight= 1; } // Normally, the blocks are tw*mw, th*mh in size. // But for SBB-aligned maps it's a little different. if(!(gr->mapProcMode==GRIT_EXPORT && gr->mapLayout==GRIT_MAP_REG)) { blockW= gr->mtileWidth(); blockH= gr->mtileHeight(); } else blockW= blockH= 256; if(aw%blockW != 0) { lprintf(LOG_WARNING, "Non-integer tiling in width (%d vs %d)\n", aw, blockW); aw= align(aw, blockW); } if(ah%blockH != 0) { lprintf(LOG_WARNING, "Non-integer tiling in height (%d vs %d)\n", ah, blockH); ah= align(ah, blockH); } // area must be multiple of metas (rounding up here) //aw= (aw+blw-1)/blw * blw; //ah= (ah+blh-1)/blh * blh; // PONDER: but what about the image size? // *shrug* what about it? ar= al+aw; ab= at+ah; gr->areaLeft= al; gr->areaTop= at; gr->areaRight= ar; gr->areaBottom= ab; } return true; }
/*! This basically does two things. First, create a bitmap from the designated area of the source bitmap. Then, converts it 8 or 16 bpp, depending on \a gr.gfxBpp. Conversion to lower bpp is done later, when it's more convenient. The resultant bitmap is put into \a gr._dib, and will be used in later preparation. */ bool grit_prep_work_dib(GritRec *gr) { int ii, nn; RGBQUAD *rgb; lprintf(LOG_STATUS, "Work-DIB creation.\n"); // --- resize --- CLDIB *dib= dib_copy(gr->srcDib, gr->areaLeft, gr->areaTop, gr->areaRight, gr->areaBottom, false); if(dib == NULL) { lprintf(LOG_ERROR, " Work-DIB creation failed.\n"); return false; } // ... that's it? Yeah, looks like. // --- resample (to 8 or 16) --- // int dibB= dib_get_bpp(dib); // Convert to 16bpp, but ONLY for bitmaps if( gr->gfxBpp == 16 && gr->gfxMode != GRIT_GFX_TILE ) { if(dibB != 16) { lprintf(LOG_WARNING, " converting from %d bpp to %d bpp.\n", dibB, gr->gfxBpp); CLDIB *dib2= dib_convert_copy(dib, 16, 0); // If paletted src AND -pT AND NOT -gT[!] // use trans color pal[T] //# PONDER: did I fix this right? if(dibB <= 8 && gr->palHasAlpha && !gr->gfxHasAlpha) { rgb= &dib_get_pal(dib)[gr->palAlphaId]; lprintf(LOG_WARNING, " pal->true-color conversion with transp pal-id option.\n" " using color %02X%02X%02X", rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); gr->gfxHasAlpha= true; gr->gfxAlphaColor= *rgb; } dib_free(dib); if(dib2 == NULL) { lprintf(LOG_ERROR, "prep: Bpp conversion failed.\n"); return false; } dib= dib2; } // --- Dealing with 16bpp images --- // Modes: // 555 | GBA | swap R_B // 555+A=1 | NDS | swap R_B + add NDS_ALPHA // 555+A | NDS, transp | swap R_B + NDS_ALPHA if !trans-clr // src-pal + -pT -> NDS, transp // Swap palette bRGB to bBGR // And resolve -gT nn= dib_get_size_img(dib)/2; WORD *dibD2= (WORD*)dib_get_img(dib); // Single transparent color if(gr->gfxHasAlpha) { rgb= &gr->gfxAlphaColor; WORD clr= RGB16(rgb->rgbBlue, rgb->rgbGreen, rgb->rgbRed), wd; lprintf(LOG_STATUS, " converting to: 16bpp BGR, alpha=1, except for 0x%04X.\n", clr); for(ii=0; ii<nn; ii++) { wd= swap_rgb16(dibD2[ii]); dibD2[ii]= (wd == clr ? wd : wd | NDS_ALPHA); } } else if(gr->gfxMode == GRIT_GFX_BMP_A) { lprintf(LOG_STATUS, "converting to: 16bpp BGR, alpha=1.\n"); for(ii=0; ii<nn; ii++) dibD2[ii]= swap_rgb16(dibD2[ii]) | NDS_ALPHA; } else { lprintf(LOG_STATUS, "converting to: 16bpp, BGR.\n"); for(ii=0; ii<nn; ii++) dibD2[ii]= swap_rgb16(dibD2[ii]); } } else if(dibB != 8) // otherwise, convert to 8bpp { lprintf(LOG_WARNING, " converting from %d bpp to %d bpp.\n", dibB, gr->gfxBpp); if(!dib_convert(dib, 8, 0)) { dib_free(dib); lprintf(LOG_ERROR, " Bpp conversion failed.\n"); return false; } } // Palette transparency additions. if(dib_get_bpp(dib)==8) { // If gfx-trans && !pal-trans: // Find gfx-trans in palette and use that if(gr->gfxHasAlpha && !gr->palHasAlpha) { rgb= &gr->gfxAlphaColor; RGBQUAD *pal= dib_get_pal(dib); lprintf(LOG_WARNING, " tru/pal -> pal conversion with transp color option.\n" " looking for color %02X%02X%02X in palette.\n", rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); uint ii_min= 0, dist, dist_min; dist_min= rgb_dist(rgb, &pal[0]); for(ii=1; ii<256; ii++) { dist= rgb_dist(rgb, &pal[ii]); if(dist < dist_min) { ii_min= ii; dist_min= dist; } } // HACK: count 'match' only if average error is < +/-14 if(dist_min < 576) { gr->palHasAlpha= true; gr->palAlphaId= ii_min; } } // Swap alpha and pixels palette entry if(gr->palHasAlpha) { lprintf(LOG_STATUS, " Palette transparency: pal[%d].\n", gr->palAlphaId); BYTE *imgD= dib_get_img(dib); nn= dib_get_size_img(dib); for(ii=0; ii<nn; ii++) { if(imgD[ii] == 0) imgD[ii]= gr->palAlphaId; else if(imgD[ii] == gr->palAlphaId) imgD[ii]= 0; } RGBQUAD tmp, *pal= dib_get_pal(dib); SWAP3(pal[0], pal[gr->palAlphaId], tmp); } // TODO: Palette merging. if(gr->palIsShared) { lprintf(LOG_STATUS, " Palette merging\n"); nn= dib_pal_reduce(dib, &gr->shared->palRec); if(nn>PAL_MAX) lprintf(LOG_WARNING, " New palette exceeds 256. Truncating.\n"); } } dib_free(gr->_dib); gr->_dib= dib; lprintf(LOG_STATUS, "Work-DIB creation complete: %dx%d@%d.\n", dib_get_width(gr->_dib), dib_get_height(gr->_dib), dib_get_bpp(gr->_dib)); return true; }