/*! Converts palette to 16bit GBA colors, compresses it and fills in \a gr._palRec. */ bool grit_prep_pal(GritRec *gr) { lprintf(LOG_STATUS, "Palette preparation.\n"); int ii, nclrs, palS; COLOR *palOut; RGBQUAD *palIn; nclrs= gr->palEnd - gr->palStart; if(dib_get_nclrs(gr->_dib) < nclrs && nclrs != 0) nclrs= dib_get_nclrs(gr->_dib); palS= nclrs*sizeof(COLOR); palOut= (COLOR*)malloc(palS); palIn= &dib_get_pal(gr->_dib)[gr->palStart]; for(ii=0; ii<nclrs; ii++) palOut[ii]= RGB16(palIn[ii].rgbBlue, palIn[ii].rgbGreen, palIn[ii].rgbRed); RECORD rec= { 2, palS/2, (BYTE*)palOut }; if( BYTE_ORDER == BIG_ENDIAN ) data_byte_rev(rec.data, rec.data, rec_size(&rec), 2); // Attach and compress palette grit_compress(&rec, &rec, gr->palCompression); rec_alias(&gr->_palRec, &rec); lprintf(LOG_STATUS, "Palette preparation complete.\n"); return true; }
BOOL CxpGbaDlg::OnInitDialog() { ASSERT(mpDib); int nclrs= dib_get_nclrs(mpDib); if(nclrs > 0 && mPalStart+mPalCount>nclrs) { mPalStart= 0; mPalCount= nclrs; } if(moAreaSize != 0) { mAreaLeft= 0; mAreaWidth= dib_get_width(mpDib); mAreaTop=0; mAreaHeight= dib_get_height(mpDib); } if(mbSymChk == FALSE) mSymName= mDstTitle; CDialog::OnInitDialog(); OnPalChk(); OnGfxChk(); OnMapChk(); UpdateObj(); UpdateMap(); UpdateArea(); GetDlgItem(IDC_VAR_NAME)->EnableWindow(mbSymChk); //UpdateSummary(); return TRUE; }
//! Initialize palette and gfx-related functions from the DIB. bool grit_init_from_dib(GritRec *gr) { if(gr == NULL) return false; CLDIB *dib= gr->srcDib; if(dib == NULL) { lprintf(LOG_ERROR, "No bitmap to initialize GritRec from.\n"); return false; } int nclrs = dib_get_nclrs(dib); gr->palEnd= ( nclrs ? nclrs : 256 ); if(dib_get_bpp(dib) > 8) gr->gfxBpp= 16; else gr->gfxBpp= dib_get_bpp(dib); gr->areaRight= dib_get_width(dib); gr->areaBottom=dib_get_height(dib); return true; }
// CHK: unpadded works // DESC: redimensions/(un)tiles a dib into a column of tiles with // dimensions dstW x tileH. Can also work in reverse (if srcW<dstW) // NOTE: padding pixels may cause problems CLDIB *dib_redim_copy(CLDIB *src, int dstW, int tileH, int tileN) { if(src == NULL) return NULL; int srcW, srcH, srcB, srcP; dib_get_attr(src, &srcW, &srcH, &srcB, &srcP); // Force byte alignment if( (dstW*srcB&7) ) return NULL; // setup redim int srcR= srcW*srcB>>3, dstR= dstW*srcB>>3; // bytes/row RECORD srcRec= { srcR, srcH, dib_get_img(src) }; RECORD dstRec= { dstR, 0, 0 }; int ii; BYTE *srcD= NULL; if(srcR&3) // depad for src { srcD= (BYTE*)malloc(srcR*srcH); if(srcD == NULL) return NULL; for(ii=0; ii<srcH; ii++) memcpy(&srcD[ii*srcR], &srcRec.data[ii*srcP], srcR); srcRec.data= srcD; } bool bOK= data_redim(&srcRec, &dstRec, tileH, tileN); SAFE_FREE(srcD); if(!bOK) return NULL; CLDIB *dst= dib_alloc(dstW, dstRec.height, srcB, NULL, dib_is_topdown(src)); if(dst == NULL) return NULL; int dstH= dib_get_height(dst); // bytes/row int dstP= dib_get_pitch(dst); BYTE *dstD= dib_get_img(dst); if(dstR&3) // repad for dst { for(ii=0; ii<dstH; ii++) memcpy(&dstD[ii*dstP], &dstRec.data[ii*dstR], dstP); } else memcpy(dstD, dstRec.data, dstP*dstH); SAFE_FREE(dstRec.data); memcpy(dib_get_pal(dst), dib_get_pal(src), dib_get_nclrs(src)*RGB_SIZE); return dst; }
bool CBmpFile::Save(const char *fpath) { FILE *fp= NULL; bool bOK= true;; try { if(!mDib) throw CImgFile::sMsgs[ERR_GENERAL]; fp = fopen(fpath, "wb"); if(!fp) throw CImgFile::sMsgs[ERR_NO_FILE]; BITMAPINFOHEADER bmih= *dib_get_hdr(mDib); int dibH= dib_get_height2(mDib), dibHa= dib_get_height(mDib); int dibP= dib_get_pitch(mDib), dibPa= dibP; int dibS= dibHa*dibPa, nclrs= dib_get_nclrs(mDib); bmih.biHeight= dibHa; bmih.biSizeImage= dibS; // fill in fileheader BITMAPFILEHEADER bmfh; bmfh.bfType= BMP_TYPE; bmfh.bfOffBits= sizeof(BITMAPFILEHEADER)+BMIH_SIZE+nclrs*RGB_SIZE; bmfh.bfSize= bmfh.bfOffBits + dibS; bmfh.bfReserved1= bmfh.bfReserved2= 0; // write down header fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, fp); fwrite(&bmih, BMIH_SIZE, 1, fp); // write down palette fwrite(dib_get_pal(mDib), RGB_SIZE, nclrs, fp); // write down rows, with possible flipping BYTE *dibL= dib_get_img(mDib); if(dibH<0) { dibL += (dibHa-1)*dibPa; dibP= -dibP; } for(int iy=0; iy<dibHa; iy++) fwrite(dibL+iy*dibP, dibPa, 1, fp); } catch(const char *msg) { SetMsg(msg); bOK= false; } if(fp) fclose(fp); return bOK; }
/*! 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; }
// === LOAD HELPERS =================================================== static bool tga_read_pal(CLDIB *dib, const TGAHDR *hdr, FILE *fp) { // no palette, 's fair if(hdr->has_table == 0) return true; // writer of this file is an idiot // PONDER: is pal_len the size of the whole thing, or // counting from pal_start? // I'm assuming the latter if(hdr->pal_len <= hdr->pal_start) return false; int ii; int clrS= (hdr->pal_bpp != 15 ? (hdr->pal_bpp/8) : 2); int palN= hdr->pal_len, palS= palN*clrS; BYTE *palD= (BYTE*)malloc(palN*clrS); fread(palD, clrS, palN-hdr->pal_start, fp); RGBQUAD *dibPal= dib_get_pal(dib); memset(dibPal, 0, dib_get_nclrs(dib)*RGB_SIZE); if(palN>dib_get_nclrs(dib)) palN= dib_get_nclrs(dib); switch(hdr->pal_bpp) // damn these different options :( { case 16: for(ii=hdr->pal_start; ii<palN; ii++) { WORD rgb16= ((WORD*)palD)[ii]; dibPal[ii].rgbRed= ((rgb16>>10)&31)*255/31; dibPal[ii].rgbGreen= ((rgb16>> 5)&31)*255/31; dibPal[ii].rgbBlue= ((rgb16 )&31)*255/31; } break; case 24: for(ii=hdr->pal_start; ii<palN; ii++) { TGA_BGR rgb24= ((TGA_BGR*)palD)[ii]; dibPal[ii].rgbRed= rgb24.red; dibPal[ii].rgbGreen= rgb24.green; dibPal[ii].rgbBlue= rgb24.blue; } break; case 32: for(ii=hdr->pal_start; ii<palN; ii++) { TGA_BGRA rgb32= ((TGA_BGRA*)palD)[ii]; dibPal[ii].rgbRed= rgb32.red; dibPal[ii].rgbGreen= rgb32.green; dibPal[ii].rgbBlue= rgb32.blue; } break; default: SAFE_FREE(palD); return false; } // clean up SAFE_FREE(palD); return true; }
bool CTgaFile::Save(const char *fpath) { int ii, iy; FILE *fp= NULL; bool bOK= true; try { if(!mDib) throw CImgFile::sMsgs[ERR_GENERAL]; fp = fopen(fpath, "wb"); if(!fp) throw CImgFile::sMsgs[ERR_NO_FILE]; int imgW= dib_get_width(mDib); int imgH= dib_get_height(mDib), imgHs= dib_get_height2(mDib); int imgP= dib_get_pitch(mDib); int imgB= dib_get_bpp(mDib); int imgS= imgH*imgP, nclrs= dib_get_nclrs(mDib); TGAHDR hdr; memset(&hdr, 0, sizeof(TGAHDR)); if(imgB==1) hdr.type= TGA_BW; else if(imgB <= 8) hdr.type= TGA_PAL; else hdr.type= TGA_true; if(imgB<=8) // paletted { hdr.has_table= 1; hdr.pal_len= dib_get_nclrs(mDib); hdr.pal_bpp= 24; } else // true color hdr.has_table=0; hdr.width= imgW; hdr.height= imgH; hdr.img_bpp= imgB; hdr.img_desc= 0; fwrite(&hdr, 1, sizeof(TGAHDR), fp); // write palette if(imgB <= 8) { RGBQUAD *pal= dib_get_pal(mDib); for(ii=0; ii<hdr.pal_len; ii++) fwrite(&pal[ii], 1, 3, fp); } // TGA should be bottom up: BYTE *imgL= dib_get_img(mDib); if(dib_is_topdown(mDib)) { imgL += imgP*(imgH-1); imgP= -imgP; } // write image (not RLEd, because that's awful to do) int tgaP= (imgW*imgB+7)/8; for(iy=0; iy<imgH; iy++) fwrite(&imgL[iy*imgP], 1, tgaP, fp); } catch(const char *msg) { SetMsg(msg); bOK= false; } if(fp) fclose(fp); return bOK; }