/*! \note Still very unsafe, but I need to redo everything later anyway. */ void grs_run(GritShared *grs, GritRec *gr_base) { // Make sure we have shared data. if( grs->dib==NULL && grs->palRec.data==NULL) { lprintf(LOG_WARNING, "No shared data to run with!\n"); return; } // Make copy of gr_base for flags, etc GritRec *gr= grit_alloc(); grs_free(gr->shared); grit_copy_options(gr, gr_base); grit_copy_strings(gr, gr_base); // Attach shared data gr->shared= grs; strrepl(&gr->symName, grs->symName); strrepl(&gr->dstPath, grs->dstPath); if(grs->dib == NULL) { // Palette only. Create new dib. gr->srcDib= dib_alloc(16, 16, 8, NULL); memset(dib_get_pal(gr->srcDib), 0, PAL_MAX*RGB_SIZE); memcpy(dib_get_pal(gr->srcDib), grs->palRec.data, rec_size(&grs->palRec)); } else gr->srcDib= dib_clone(grs->dib); // NOTE: aliasing screws up deletion later; detach manually. gr->_dib= gr->srcDib; // Run for shared gr do { if(!grit_validate(gr)) break; bool grit_prep_gfx(GritRec *gr); bool grit_prep_shared_pal(GritRec *gr); if(gr->gfxProcMode != GRIT_EXCLUDE) grit_prep_gfx(gr); if(gr->palProcMode != GRIT_EXCLUDE) grit_prep_shared_pal(gr); if(gr->bExport) grit_export(gr); } while(0); gr->_dib= NULL; // Detach shared data and delete gr gr->shared= NULL; grit_free(gr); }
/*! \param dib valid HBITMAP * \return initialized CLDIB; NULL on failure. */ CLDIB *dib_from_hbm(HBITMAP hbm) { if(hbm == NULL) return NULL; BITMAP bm; GetObject(hbm, sizeof(BITMAP), &bm); CLDIB *dib= dib_alloc(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, NULL); if(dib == NULL) return NULL; // The WinXP GetDIBits somehow overwrites biClrUsed // Hack to fix that BITMAPINFOHEADER *bmih= dib_get_hdr(dib); int nclrs= bmih->biClrUsed; HDC hdc = GetDC(NULL); GetDIBits(hdc, hbm, 0, dib_get_height(dib), dib_get_img(dib), dib_get_info(dib), DIB_RGB_COLORS); ReleaseDC(NULL, hdc); bmih->biClrUsed= nclrs; // man, this is f@%#@%g weak return dib; }
// 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; }
/*! Similar to \c dib_clone, but can crop the image too. The * boundaries of the new bitmap need not fit inside the source; the * outside parts will be zeroed. * \param src Source bitmap. * \param ll Left of rectangle. * \param tt Top of rectangle. * \param rr Right of rectangle. * \param bb Bottom of rectangle. * \param bClip If \c true, the rectangle will be clipped to the * dimensions of \c src. * \return Copied and cropped bitmap. */ CLDIB *dib_copy(CLDIB *src, int ll, int tt, int rr, int bb, bool bClip) { if(src==NULL || ll==rr || tt==bb) return NULL; int srcW= dib_get_width(src); int srcH= dib_get_height(src); int srcB= dib_get_bpp(src); int srcP= dib_get_pitch(src); // Normalize rect if(rr<ll) { int tmp=ll; ll=rr; rr=tmp; } if(bb<tt) { int tmp=tt; tt=bb; bb=tmp; } // Clip if requested if(bClip) { if(ll<0) ll= 0; if(tt<0) tt= 0; if(rr>srcW) rr= srcW; if(bb>srcH) bb= srcH; } int dstW= rr-ll, dstH= bb-tt; CLDIB *dst= dib_alloc(dstW, dstH, srcB, NULL, true); if(dst==NULL) return NULL; dib_pal_cpy(dst, src); // set base src,dst pointers int dstP= dib_get_pitch(dst); BYTE *srcL= dib_get_img(src), *dstL= dib_get_img(dst); if(ll>=0) // set horz base srcL += ll*srcB>>3; else
// Yes, you can use LoadImage too, but that creates a device // dependent bitmap and you want to stay the fsck away from those. bool CBmpFile::Load(const char *fpath) { FILE *fp= fopen(fpath, "rb"); CLDIB *dib= NULL; try { if(!fp) throw CImgFile::sMsgs[ERR_NO_FILE]; BITMAPFILEHEADER bmfh; fread(&bmfh, sizeof(BITMAPFILEHEADER), 1,fp); // Whoa, not a bitmap, back off if(bmfh.bfType != BMP_TYPE) // 4D42h = "BM". throw CImgFile::sMsgs[ERR_FORMAT]; BITMAPINFOHEADER bmih; bool bCore; // check for bm version first :( fread(&bmih, 4, 1, fp); if(bmih.biSize == sizeof(BITMAPCOREHEADER)) // crap! v2.x BMP { bCore= true; bmih.biSize= BMIH_SIZE; WORD wd; fread(&wd, 2,1,fp); bmih.biWidth= wd; fread(&wd, 2,1,fp); bmih.biHeight= wd; fread(&bmih.biPlanes, 2,1,fp); fread(&bmih.biBitCount, 2,1,fp); memset(&bmih.biCompression, 0, BMIH_SIZE-sizeof(BITMAPCOREHEADER)); } else // normal v3.0 BMP fread(&bmih.biWidth, BMIH_SIZE-4, 1, fp); if(bmih.biPlanes > 1) // no color planes, plz throw sMsgs[ERR_BMP_PLANES]; if(bmih.biCompression != BI_RGB) // no compression either throw sMsgs[ERR_BMP_CPRS]; int dibP, dibHa, dibS; dibHa= abs(bmih.biHeight); dibP= dib_align(bmih.biWidth, bmih.biBitCount); dibS= dibP*dibHa; // set manually, just to be sure bmih.biSizeImage= dibS; // ditto for ClrUsed if(bmih.biBitCount <=8 && bmih.biClrUsed == 0) bmih.biClrUsed= 1<<bmih.biBitCount; // now we set-up the full bitmap dib= dib_alloc(bmih.biWidth, dibHa, bmih.biBitCount, NULL, true); if(dib == NULL) throw CImgFile::sMsgs[ERR_ALLOC]; // read the palette fread(dib_get_pal(dib), RGB_SIZE, bmih.biClrUsed, fp); // read image fread(dib_get_img(dib), dibS, 1, fp); if(bmih.biHeight>=0) // -> TD image dib_vflip(dib); } // </try> catch(const char *msg) { SetMsg(msg); dib_free(dib); dib= NULL; } if(fp) fclose(fp); if(!dib) return false; // if we're here we've succeeded SetMsg(CImgFile::sMsgs[ERR_NONE]); dib_free(Attach(dib)); SetBpp(dib_get_bpp(dib)); SetPath(fpath); return true; }
// xxx_load(const char *fname, PDIBDATA *ppdib, IMG_FMT_INFO *pifi) bool CTgaFile::Load(const char *fpath) { FILE *fp= fopen(fpath, "rb"); CLDIB *dib= NULL; TGAHDR hdr; try { if(!fp) throw CImgFile::sMsgs[ERR_NO_FILE]; fread(&hdr, sizeof(TGAHDR), 1, fp); // ignore image desc (if any) fseek(fp, hdr.id_len, SEEK_CUR); int imgW, imgH, imgB, imgP; imgW= hdr.width; imgH= hdr.height; imgB= hdr.img_bpp; imgP= dib_align(imgW, imgB); // Set-up the full bitmap dib= dib_alloc(imgW, imgH, imgB, NULL, true); if(dib == NULL) throw CImgFile::sMsgs[ERR_ALLOC]; // === get color map === if(hdr.has_table) { if(!tga_read_pal(dib, &hdr, fp)) throw sMsgs[ERR_TGA_BADPAL]; } int ii; int tgaP= (imgW*imgB+7)/8; BYTE *imgD= dib_get_img(dib); switch(hdr.type) { case TGA_BW: case TGA_PAL: case TGA_true: for(ii=0; ii<imgH; ii++) fread(&imgD[ii*imgP], 1, tgaP, fp); break; case TGA_BW_RLE: case TGA_PAL_RLE: case TGA_true_RLE: tga_unrle(dib, &hdr, fp); break; default: throw sMsgs[ERR_TGA_VERSION]; } // TGA's are bottom-up by default, flip if necessary if(~hdr.img_desc & TGA_VFLIP) dib_vflip(dib); } // </try> catch(const char *msg) { SetMsg(msg); dib_free(dib); dib= NULL; } // cleanup if(!dib) return false; // if we're here we've succeeded SetMsg(CImgFile::sMsgs[ERR_NONE]); dib_free(Attach(dib)); SetBpp(dib_get_bpp(dib)); SetPath(fpath); return true; }