static void test_arrays (ROI roi) { const float *a = (const float *)imgA.localpixels(); ASSERT(a); const float *b = (const float *)imgB.localpixels(); ASSERT(b); float *r = (float *)imgR.localpixels(); ASSERT(r); for (int x = 0; x < size; ++x) r[x] = a[x] * a[x] + b[x]; }
ImageBuf * SMT::reconstructBig() { if( verbose )cout << "INFO: Reconstructing Big\n"; ImageBuf *tileBuf = NULL; //Load tilemap from SMF ImageBuf *tilemapBuf = NULL; if( is_smf( tilemapFile ) ) { SMF sourcesmf(tilemapFile); tilemapBuf = sourcesmf.getTilemap(); } // Else load tilemap from image if( !tilemapBuf ) { tilemapBuf = new ImageBuf( tilemapFile ); tilemapBuf->read(0,0,false,TypeDesc::UINT); if( !tilemapBuf->initialized() ) { delete tilemapBuf; if( !quiet )printf("ERROR: %s cannot be loaded.\n", tilemapFile.c_str()); return NULL; } } //TODO Else load tilemap from csv unsigned int *tilemap = (unsigned int *)tilemapBuf->localpixels(); int xtiles = tilemapBuf->spec().width; int ztiles = tilemapBuf->spec().height; // allocate enough data for our large image ImageSpec bigSpec( xtiles * tileRes, ztiles * tileRes, 4, TypeDesc::UINT8 ); ImageBuf *bigBuf = new ImageBuf( "big", bigSpec ); // Loop through tile index for( int z = 0; z < ztiles; ++z ) { for( int x = 0; x < xtiles; ++x ) { int tilenum = tilemap[z * xtiles + x]; tileBuf = getTile(tilenum); int xbegin = tileRes * x; int ybegin = tileRes * z; ImageBufAlgo::paste(*bigBuf, xbegin, ybegin, 0, 0, *tileBuf); delete [] (unsigned char *)tileBuf->localpixels(); delete tileBuf; if( verbose )printf("\033[0GINFO: Processing tile %i of %i.", z * xtiles + x, xtiles * ztiles ); } } cout << endl; delete tilemapBuf; if( is_smf( tilemapFile ) ) delete [] tilemap; return bigBuf; }
static void test_arrays_like_image_multithread (ROI roi) { const float *a = (const float *)imgA.localpixels(); ASSERT(a); const float *b = (const float *)imgB.localpixels(); ASSERT(b); float *r = (float *)imgR.localpixels(); ASSERT(r); int nchannels = imgA.nchannels(); for (int y = roi.ybegin; y < roi.yend; ++y) { for (int x = roi.xbegin; x < roi.xend; ++x) { int i = (y*xres + x) * nchannels; for (int c = 0; c < nchannels; ++c) r[i+c] = a[i+c] * a[i+c] + b[i+c]; } } }
static void test_arrays_like_image (ROI roi) { const float *a = (const float *)imgA.localpixels(); ASSERT(a); const float *b = (const float *)imgB.localpixels(); ASSERT(b); float *r = (float *)imgR.localpixels(); ASSERT(r); int nchannels = imgA.nchannels(); for (int y = 0; y < yres; ++y) { for (int x = 0; x < xres; ++x) { int i = (y*xres + x) * nchannels; for (int c = 0; c < nchannels; ++c) r[i+c] = a[i+c] * a[i+c] + b[i+c]; } } }
static void test_arrays_simd4 (ROI roi) { const float *a = (const float *)imgA.localpixels(); ASSERT(a); const float *b = (const float *)imgB.localpixels(); ASSERT(b); float *r = (float *)imgR.localpixels(); ASSERT(r); int x, end4 = size - (size&3); for (x = 0; x < end4; x += 4, a += 4, b += 4, r += 4) { simd::vfloat4 a_simd(a), b_simd(b); *(simd::vfloat4 *)r = a_simd * a_simd + b_simd; } for ( ; x < size; ++x, ++a, ++b, ++r) { *r = a[0]*a[0] + b[0]; } }
ImageBuf::ImageBuf (const ImageBuf &src) : m_name(src.m_name), m_fileformat(src.m_fileformat), m_nsubimages(src.m_nsubimages), m_current_subimage(src.m_current_subimage), m_current_miplevel(src.m_current_miplevel), m_nmiplevels(src.m_nmiplevels), m_spec(src.m_spec), m_nativespec(src.m_nativespec), m_pixels(src.m_pixels), m_localpixels(src.m_localpixels), m_clientpixels(src.m_clientpixels), m_spec_valid(src.m_spec_valid), m_pixels_valid(src.m_pixels_valid), m_badfile(src.m_badfile), m_orientation(src.m_orientation), m_pixelaspect(src.m_pixelaspect), m_imagecache(src.m_imagecache), m_cachedpixeltype(src.m_cachedpixeltype), m_deepdata(src.m_deepdata) { if (src.localpixels()) { // Source had the image fully in memory (no cache) if (src.m_clientpixels) { // Source just wrapped the client app's pixels ASSERT (0 && "ImageBuf wrapping client buffer not yet supported"); } else { // We own our pixels // Make sure our localpixels points to our own owned memory. m_localpixels = &m_pixels[0]; } } else { // Source was cache-based or deep // nothing else to do } }
static void test_arrays_like_image_simd_multithread (ROI roi) { const float *a = (const float *)imgA.localpixels(); ASSERT(a); const float *b = (const float *)imgB.localpixels(); ASSERT(b); float *r = (float *)imgR.localpixels(); ASSERT(r); int nchannels = imgA.nchannels(); for (int y = roi.ybegin; y < roi.yend; ++y) { for (int x = roi.xbegin; x < roi.xend; ++x) { int i = (y*xres + x) * nchannels; simd::vfloat4 a_simd, b_simd, r_simd; a_simd.load (a+i, 3); b_simd.load (b+i, 3); r_simd = a_simd * a_simd + b_simd; r_simd.store (r+i, 3); } } }
ImageBuf * SMT::collateBig() { if( verbose )cout << "INFO: Collating Big\n"; if( !loadFile.compare("") ) { if( !quiet )cout << "ERROR: No SMT Loaded." << endl; return NULL; } // OpenImageIO ImageBuf *tileBuf = NULL; // Allocate Image size large enough to accomodate the tiles, int collateStride = ceil(sqrt(header.nTiles)); int bigRes = collateStride * header.tileRes; ImageSpec bigSpec(bigRes, bigRes, 4, TypeDesc::UINT8 ); ImageBuf *bigBuf = new ImageBuf( "big", bigSpec); // Loop through tiles copying the data to our image buffer for(int i = 0; i < header.nTiles; ++i ) { // Pull data tileBuf = getTile(i); int dx = header.tileRes * (i % collateStride); int dy = header.tileRes * (i / collateStride); ImageBufAlgo::paste(*bigBuf, dx, dy, 0, 0, *tileBuf); delete [] (unsigned char *)tileBuf->localpixels(); delete tileBuf; if( verbose )printf("\033[0GINFO: Processing tile %i of %i.", i, header.nTiles ); } if( verbose ) cout << endl; return bigBuf; }
bool SMT::save() { // Make sure we have some source images before continuing if( sourceFiles.size() == 0) { if( !quiet )cout << "ERROR: No source images to convert" << endl; return true; } // Build SMT Header // ////////////////////// char filename[256]; sprintf(filename, "%s.smt", outPrefix.c_str()); if( verbose ) printf("\nINFO: Creating %s\n", filename ); fstream smt( filename, ios::binary | ios::out ); if( !smt.good() ) { cout << "ERROR: fstream error." << endl; return true; } SMTHeader header; header.tileRes = tileRes; header.tileType = tileType; if( verbose ) { cout << " Version: " << header.version << endl; cout << " nTiles: n/a\n"; printf( " tileRes: (%i,%i)%i.\n", tileRes, tileRes, 4); cout << " tileType: "; if( tileType == DXT1 ) cout << "DXT1" << endl; cout << " tileSize: " << tileSize << " bytes" << endl; } smt.write( (char *)&header, sizeof(SMTHeader) ); smt.close(); // setup size for index dimensions int tcx = width * 16; // tile count x int tcz = length * 16; // tile count z unsigned int *indexPixels = new unsigned int[tcx * tcz]; // Load source image if( verbose )cout << "INFO: Loading Source Image(s)\n"; ImageBuf *bigBuf = buildBig(); ImageSpec bigSpec = bigBuf->spec(); // Process decals if( !decalFile.empty() ) { if( verbose )cout << "INFO: Processing decals\n"; pasteDecals( bigBuf ); } // Swizzle channels if( verbose )cout << "INFO: Swizzling channels\n"; ImageBuf fixBuf; int map[] = { 2, 1, 0, 3 }; ImageBufAlgo::channels( fixBuf, *bigBuf, 4, map ); bigBuf->copy( fixBuf ); fixBuf.clear(); // Process Tiles if( verbose )cout << "INFO: Processing tiles\n"; // Time reporting vars timeval t1, t2; double elapsedTime; deque<double> readings; double averageTime = 0; double intervalTime = 0; // Loop vars int totalTiles = tcx * tcz; int currentTile; // Tile Vars ROI roi; ImageSpec tileSpec(tileRes, tileRes, 4, TypeDesc::UINT8 ); // Comparison vars bool match; bool yee = false; unsigned int i; string hash; vector<string> hashTable; TileBufListEntry *listEntry; deque<TileBufListEntry *> tileList; // Open smt file for writing tiles smt.open(filename, ios::binary | ios::out | ios::app ); // loop through tile columns for ( int z = 0; z < tcz; z++) { // loop through tile rows for ( int x = 0; x < tcx; x++) { currentTile = z * tcx + x + 1; gettimeofday(&t1, NULL); // pull a region of the big image to use as a tile. roi.xbegin = x * tileRes; roi.xend = x * tileRes + tileRes; roi.ybegin = z * tileRes; roi.yend = z * tileRes + tileRes; roi.zbegin = 0; roi.zend = 1; roi.chbegin = 0; roi.chend = 4; ImageBuf tempBuf; ImageBufAlgo::crop( tempBuf, *bigBuf, roi ); ImageBuf *tileBuf = new ImageBuf( filename, tileSpec, tempBuf.localpixels() ); // reset match variables match = false; i = nTiles; if( cnum < 0) { // no attempt at reducing tile sizes i = nTiles; } else if( cnum == 0) { // only exact matches will be referenced. hash = ImageBufAlgo::computePixelHashSHA1( *tileBuf ); for( i = 0; i < hashTable.size(); ++i ) { if( !hashTable[i].compare( hash ) ) { match = true; break; } } if( !match ) hashTable.push_back( hash ); } else if( !yee ) { //Comparison based on numerical differences of pixels listEntry = new TileBufListEntry; listEntry->image.copy(*tileBuf); listEntry->tileNum = nTiles; ImageBufAlgo::CompareResults result; deque< TileBufListEntry * >::iterator it; for(it = tileList.begin(); it != tileList.end(); it++ ) { TileBufListEntry *listEntry2 = *it; ImageBufAlgo::compare( *tileBuf, listEntry2->image, cpet, 1.0f, result); //TODO give control on tweaking matching if((int)result.nfail < cnet) { match = true; i = listEntry2->tileNum; delete listEntry; break; } } if( !match ) { tileList.push_back(listEntry); if((int)tileList.size() > cnum) { delete tileList[0]; tileList.pop_front(); } } } else { //FIXME uncomment when OpenImageIO gets upgraded to v3 /* listEntry = new TileBufListEntry; listEntry->image.copy(*tileBuf); listEntry->tileNum = nTiles; ImageBufAlgo::CompareResults result; deque< TileBufListEntry * >::iterator it; for(it = tileList.begin(); it != tileList.end(); it++ ) { TileBufListEntry *listEntry2 = *it; ImageBufAlgo::compare_yee( *tileBuf, listEntry2->image, result, 1.0f, 1.0f ); if(result.nfail == 0) { match = true; i = listEntry2->tileNum; break; } } if( !match ) { tileList.push_back(listEntry); if((int)tileList.size() > 32) tileList.pop_front(); }*/ } // write tile to file. if( !match ) { unsigned char *std = (unsigned char *)tileBuf->localpixels(); // process into dds NVTTOutputHandler *nvttHandler = new NVTTOutputHandler(tileSize); nvtt::InputOptions inputOptions; inputOptions.setTextureLayout( nvtt::TextureType_2D, tileRes, tileRes ); inputOptions.setMipmapData( std, tileRes, tileRes ); nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(nvtt::Format_DXT1a); nvtt::OutputOptions outputOptions; outputOptions.setOutputHeader(false); outputOptions.setOutputHandler( nvttHandler ); nvtt::Compressor compressor; if( slow_dxt1 ) compressionOptions.setQuality(nvtt::Quality_Normal); else compressionOptions.setQuality(nvtt::Quality_Fastest); compressor.process(inputOptions, compressionOptions, outputOptions); smt.write( nvttHandler->buffer, tileSize ); delete nvttHandler; nTiles +=1; } delete tileBuf; // Write index to tilemap indexPixels[currentTile-1] = i; gettimeofday(&t2, NULL); // compute and print the elapsed time in millisec elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms readings.push_back(elapsedTime); if(readings.size() > 1000)readings.pop_front(); intervalTime += elapsedTime; if( verbose && intervalTime > 1 ) { for(unsigned int i = 0; i < readings.size(); ++i) averageTime+= readings[i]; averageTime /= readings.size(); intervalTime = 0; printf("\033[0G %i of %i %%%0.1f complete | %%%0.1f savings | %0.1fs remaining.", currentTile, totalTiles, (float)currentTile / totalTiles * 100, (float)(1 - (float)nTiles / (float)currentTile) * 100, averageTime * (totalTiles - currentTile) / 1000); } } } hashTable.clear(); if( verbose ) cout << endl; smt.close(); // retroactively fix up the tile count. smt.open(filename, ios::binary | ios::in | ios::out ); smt.seekp( 20); smt.write( (char *)&nTiles, 4); smt.close(); // Save tileindex ImageOutput *imageOutput; sprintf( filename, "%s_tilemap.exr", outPrefix.c_str() ); imageOutput = ImageOutput::create(filename); if( !imageOutput ) { delete [] indexPixels; return true; } ImageSpec tilemapSpec( tcx, tcz, 1, TypeDesc::UINT); imageOutput->open( filename, tilemapSpec ); imageOutput->write_image( TypeDesc::UINT, indexPixels ); imageOutput->close(); delete imageOutput; delete [] indexPixels; return false; }
IplImage * ImageBufAlgo::to_IplImage (const ImageBuf &src) { #ifdef USE_OPENCV ImageBuf tmp = src; ImageSpec spec = tmp.spec(); // Make sure the image buffer is initialized. if (!tmp.initialized() && !tmp.read(tmp.subimage(), tmp.miplevel(), true)) { DASSERT (0 && "Could not initialize ImageBuf."); return NULL; } int dstFormat; TypeDesc dstSpecFormat; if (spec.format == TypeDesc(TypeDesc::UINT8)) { dstFormat = IPL_DEPTH_8U; dstSpecFormat = spec.format; } else if (spec.format == TypeDesc(TypeDesc::INT8)) { dstFormat = IPL_DEPTH_8S; dstSpecFormat = spec.format; } else if (spec.format == TypeDesc(TypeDesc::UINT16)) { dstFormat = IPL_DEPTH_16U; dstSpecFormat = spec.format; } else if (spec.format == TypeDesc(TypeDesc::INT16)) { dstFormat = IPL_DEPTH_16S; dstSpecFormat = spec.format; } else if (spec.format == TypeDesc(TypeDesc::HALF)) { dstFormat = IPL_DEPTH_32F; // OpenCV does not support half types. Switch to float instead. dstSpecFormat = TypeDesc(TypeDesc::FLOAT); } else if (spec.format == TypeDesc(TypeDesc::FLOAT)) { dstFormat = IPL_DEPTH_32F; dstSpecFormat = spec.format; } else if (spec.format == TypeDesc(TypeDesc::DOUBLE)) { dstFormat = IPL_DEPTH_64F; dstSpecFormat = spec.format; } else { DASSERT (0 && "Unknown data format in ImageBuf."); return NULL; } IplImage *ipl = cvCreateImage(cvSize(spec.width, spec.height), dstFormat, spec.nchannels); if (!ipl) { DASSERT (0 && "Unable to create IplImage."); return NULL; } size_t pixelsize = dstSpecFormat.size() * spec.nchannels; // Account for the origin in the line step size, to end up with the // standard OIIO origin-at-upper-left: size_t linestep = ipl->origin ? -ipl->widthStep : ipl->widthStep; bool converted = convert_image(spec.nchannels, spec.width, spec.height, 1, tmp.localpixels(), spec.format, spec.pixel_bytes(), spec.scanline_bytes(), 0, ipl->imageData, dstSpecFormat, pixelsize, linestep, 0); if (!converted) { DASSERT (0 && "convert_image failed."); cvReleaseImage(&ipl); return NULL; } // OpenCV uses BGR ordering if (spec.nchannels == 3) { cvCvtColor(ipl, ipl, CV_RGB2BGR); } else if (spec.nchannels == 4) { cvCvtColor(ipl, ipl, CV_RGBA2BGRA); } return ipl; #else return NULL; #endif }
bool SMF::saveGrass() { if( verbose )cout << "INFO: saveGrass\n"; SMFEHGrass *grassHeader = NULL; for( unsigned int i = 0; i < extraHeaders.size(); ++i ) { if( extraHeaders[ i ]->type == 1 ) grassHeader = reinterpret_cast<SMFEHGrass *>( extraHeaders[ i ] ); } if( !grassHeader )return true; ImageBuf *imageBuf = NULL; ROI roi( 0, width * 16, 0, length * 16, 0, 1, 0, 1); ImageSpec imageSpec(roi.xend, roi.yend, roi.chend, TypeDesc::UINT8 ); if( is_smf(grassFile) ) { // Load from SMF SMF sourcesmf(grassFile); imageBuf = sourcesmf.getGrass(); } if( !imageBuf ) { // Load image file imageBuf = new ImageBuf( grassFile ); imageBuf->read( 0, 0, false, TypeDesc::UINT8 ); if( imageBuf->initialized() ) { delete imageBuf; imageBuf = NULL; } } if( !imageBuf ) { // Generate blank imageBuf = new ImageBuf( "grass", imageSpec ); } imageSpec = imageBuf->specmod(); ImageBuf fixBuf; // Fix the number of channels if( imageSpec.nchannels != roi.chend ) { int map[] = {0}; ImageBufAlgo::channels(fixBuf, *imageBuf, roi.chend, map ); imageBuf->copy( fixBuf ); fixBuf.clear(); } // Fix the Dimensions if ( imageSpec.width != roi.xend || imageSpec.height != roi.yend ) { if( verbose ) printf( "\tWARNING: %s is (%i,%i), wanted (%i, %i) Resampling.\n", typeFile.c_str(), imageSpec.width, imageSpec.height, roi.xend, roi.yend); ImageBufAlgo::resample(fixBuf, *imageBuf, false, roi); imageBuf->copy( fixBuf ); fixBuf.clear(); } unsigned char *pixels = (unsigned char *)imageBuf->localpixels(); char filename[256]; sprintf( filename, "%s.smf", outPrefix.c_str() ); if( verbose )printf( " Source: %s.\n", grassFile.c_str() ); fstream smf(filename, ios::binary | ios::in | ios::out); smf.seekp(grassHeader->grassPtr); smf.write( (char *)pixels, imageBuf->spec().image_bytes() ); smf.close(); delete imageBuf; if( is_smf( grassFile ) ) delete [] pixels; return false; }
bool SMF::saveTilemap() { if( verbose )cout << "INFO: saveTilemap\n"; char filename[256]; sprintf( filename, "%s.smf", outPrefix.c_str() ); fstream smf(filename, ios::binary | ios::in | ios::out); smf.seekp(tilesPtr); // Tiles Header int nTileFiles = smtList.size(); smf.write( (char *)&nTileFiles, 4); smf.write( (char *)&nTiles, 4); if(verbose)printf( " %i tiles referenced in %i files\n", nTiles, nTileFiles ); // SMT Names for(unsigned int i = 0; i < smtList.size(); ++i) { if( verbose )printf( "\t%i %s\n", smtTiles[i], smtList[i].c_str() ); smf.write( (char *)&smtTiles[i], 4); smf.write( smtList[i].c_str(), smtList[i].size() +1 ); } // Dimensions of displacement map. ImageBuf *imageBuf = NULL; ROI roi( 0, width * 16, // xbegin, xend 0, length * 16, // ybegin, yend 0, 1, // zbegin, zend 0, 1); // chbegin, chend ImageSpec imageSpec( roi.xend, roi.yend, roi.chend, TypeDesc::UINT ); if( is_smf(tilemapFile) ) { // Load from SMF SMF sourcesmf(tilemapFile); imageBuf = sourcesmf.getTilemap(); } if( !imageBuf ) { // load image file imageBuf = new ImageBuf( tilemapFile ); imageBuf->read( 0, 0, false, TypeDesc::UINT ); if( !imageBuf->initialized() ) { delete imageBuf; imageBuf = NULL; } } if( !imageBuf ) { // Generate blank imageBuf = new ImageBuf( "tilemap", imageSpec ); for ( unsigned int i = 0; i < imageSpec.image_pixels(); ++i ) ((unsigned int *)imageBuf->localpixels())[ i ] = i; } imageSpec = imageBuf->specmod(); ImageBuf fixBuf; // Fix the number of channels if( imageSpec.nchannels != roi.chend ) { int map[] = {0}; ImageBufAlgo::channels(fixBuf, *imageBuf, roi.chend, map); imageBuf->copy(fixBuf); fixBuf.clear(); } // Fix the size // FIXME image should never be resized, instead tiling either from an edge or centred. if ( imageSpec.width != roi.xend || imageSpec.height != roi.yend ) { if( verbose ) printf( "\tWARNING: %s is (%i,%i), wanted (%i, %i), Resampling.\n", tilemapFile.c_str(), imageSpec.width, imageSpec.height, roi.xend, roi.yend ); ImageBufAlgo::resample(fixBuf, *imageBuf, false, roi); imageBuf->copy(fixBuf); fixBuf.clear(); } unsigned int *pixels = (unsigned int *)imageBuf->localpixels(); // write the data to the smf smf.write( (char *)pixels, imageBuf->spec().image_bytes() ); smf.close(); delete imageBuf; if( is_smf( tilemapFile ) ) delete [] pixels; return false; }
bool SMF::saveMetal() { if( verbose )cout << "INFO: saveMetal\n"; // Dimensions of displacement map. ImageBuf *imageBuf = NULL; ROI roi( 0, width * 32, // xbegin, xend 0, length * 32, // ybegin, yend 0, 1, // zbegin, zend 0, 1); // chbegin, chend ImageSpec imageSpec( roi.xend, roi.yend, roi.chend, TypeDesc::UINT8 ); if( is_smf(metalFile) ) { // Load from smf SMF sourcesmf(metalFile); imageBuf = sourcesmf.getMetal(); } if( !imageBuf ) { //load from image imageBuf = new ImageBuf(metalFile); imageBuf->read( 0, 0, false, TypeDesc::UINT8 ); if( !imageBuf->initialized() ) { delete imageBuf; imageBuf = NULL; } } if( !imageBuf ) { // Generate blank imageBuf = new ImageBuf( "metal", imageSpec ); } imageSpec = imageBuf->specmod(); ImageBuf fixBuf; // Fix the number of channels if( imageSpec.nchannels != roi.chend ) { int map[] = {0}; ImageBufAlgo::channels(fixBuf, *imageBuf, roi.chend, map); imageBuf->copy(fixBuf); fixBuf.clear(); } // Fix the size if ( imageSpec.width != roi.xend || imageSpec.height != roi.yend ) { if( verbose ) printf( "\tWARNING: %s is (%i,%i), wanted (%i, %i), Resampling.\n", metalFile.c_str(), imageSpec.width, imageSpec.height, roi.xend, roi.yend ); ImageBufAlgo::resample(fixBuf, *imageBuf, true, roi); imageBuf->copy(fixBuf); fixBuf.clear(); } unsigned char *pixels = (unsigned char *)imageBuf->localpixels(); char filename[256]; sprintf( filename, "%s.smf", outPrefix.c_str() ); fstream smf(filename, ios::binary | ios::in | ios::out); smf.seekp(metalPtr); // write the data to the smf smf.write( (char *)pixels, imageBuf->spec().image_bytes() ); smf.close(); delete imageBuf; if( is_smf( metalFile ) ) delete [] pixels; return false; }
bool SMF::saveMinimap() { if( verbose )cout << "INFO: saveMinimap\n"; char filename[256]; sprintf( filename, "%s.smf", outPrefix.c_str() ); fstream smf(filename, ios::binary | ios::in | ios::out); smf.seekp(minimapPtr); unsigned char *pixels; if( is_smf(minimapFile) ) { // Copy from SMF pixels = new unsigned char[MINIMAP_SIZE]; ifstream inFile(minimapFile.c_str(), ifstream::in); inFile.seekg(header.minimapPtr); inFile.read( (char *)pixels, MINIMAP_SIZE); inFile.close(); smf.write( (char *)pixels, MINIMAP_SIZE); smf.close(); delete [] pixels; return false; } //OpenImageIO ROI roi( 0, 1024, 0, 1024, 0, 1, 0, 4); ImageSpec imageSpec( roi.xend, roi.yend, roi.chend, TypeDesc::UINT8 ); // Load image file ImageBuf *imageBuf = new ImageBuf( minimapFile ); imageBuf->read( 0, 0, false, TypeDesc::UINT8 ); //FIXME attempt to generate minimap from tile files. if( !imageBuf->initialized() ) { // Create from height imageBuf->reset( minimapFile ); imageBuf->read( 0, 0, false, TypeDesc::UINT8 ); } if( !imageBuf->initialized() ) { // Create blank imageBuf->reset( "minimap", imageSpec); } imageSpec = imageBuf->specmod(); ImageBuf fixBuf; // Fix channels if( imageSpec.nchannels != roi.chend ) { int map[] = {2,1,0,3}; float fill[] = {0,0,0,255}; ImageBufAlgo::channels(fixBuf, *imageBuf, roi.chend, map, fill); imageBuf->copy(fixBuf); fixBuf.clear(); } // Fix dimensions if( imageSpec.width != roi.xend || imageSpec.height != roi.yend ) { printf( "\tWARNING: %s is (%i,%i), wanted (%i, %i), Resampling.\n", minimapFile.c_str(), imageSpec.width, imageSpec.height, roi.xend, roi.yend ); ImageBufAlgo::resample(fixBuf, *imageBuf, true, roi); imageBuf->copy(fixBuf); fixBuf.clear(); } pixels = (unsigned char *)imageBuf->localpixels(); // setup DXT1 Compression nvtt::InputOptions inputOptions; inputOptions.setTextureLayout( nvtt::TextureType_2D, 1024, 1024 ); inputOptions.setMipmapData( pixels, 1024, 1024 ); nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat( nvtt::Format_DXT1 ); if( slowcomp ) compressionOptions.setQuality( nvtt::Quality_Normal ); else compressionOptions.setQuality( nvtt::Quality_Fastest ); nvtt::OutputOptions outputOptions; outputOptions.setOutputHeader( false ); NVTTOutputHandler *outputHandler = new NVTTOutputHandler(MINIMAP_SIZE + 1); outputOptions.setOutputHandler( outputHandler ); nvtt::Compressor compressor; compressor.process( inputOptions, compressionOptions, outputOptions ); // Write data to smf smf.write( outputHandler->buffer, MINIMAP_SIZE ); delete outputHandler; smf.close(); delete imageBuf; return false; }
bool SMF::saveHeight() { if( verbose )cout << "INFO: saveHeight\n"; // Dimensions of displacement map. ImageBuf *imageBuf = NULL; ROI roi( 0, width * 64 + 1, // xbegin, xend 0, length * 64 + 1, // ybegin, yend 0, 1, // zbegin, zend 0, 1); // chbegin, chend ImageSpec imageSpec( roi.xend, roi.yend, roi.chend, TypeDesc::UINT16 ); if( is_smf(heightFile) ) { // Load from SMF SMF sourcesmf(heightFile); imageBuf = sourcesmf.getHeight(); } if( !imageBuf ) { // load image file imageBuf = new ImageBuf( heightFile ); imageBuf->read( 0, 0, false, TypeDesc::UINT16 ); if( !imageBuf->initialized() ) { delete imageBuf; imageBuf = NULL; } } if( !imageBuf ) { // Generate blank imageBuf = new ImageBuf( "height", imageSpec ); } imageSpec = imageBuf->specmod(); ImageBuf fixBuf; // Fix the number of channels if( imageSpec.nchannels != roi.chend ) { int map[] = {0}; ImageBufAlgo::channels(fixBuf, *imageBuf, roi.chend, map); imageBuf->copy(fixBuf); fixBuf.clear(); } // Fix the size if ( imageSpec.width != roi.xend || imageSpec.height != roi.yend ) { if( verbose ) printf( "\tWARNING: %s is (%i,%i), wanted (%i, %i), Resampling.\n", heightFile.c_str(), imageSpec.width, imageSpec.height, roi.xend, roi.yend ); ImageBufAlgo::resample(fixBuf, *imageBuf, true, roi); imageBuf->copy(fixBuf); fixBuf.clear(); } // Invert height if ( invert ) { ImageSpec fixSpec(roi.xend, roi.yend, roi.chend, TypeDesc::UINT16); fixBuf.reset( "fixBuf", fixSpec ); const float fill[] = {65535}; ImageBufAlgo::fill(fixBuf, fill); ImageBufAlgo::sub(*imageBuf, fixBuf, *imageBuf); fixBuf.clear(); } // FIXME filter to remove stepping artifacts from 8bit images, // if ( lowpass ) { // } unsigned short *pixels = (unsigned short *)imageBuf->localpixels(); // write height data to smf. char filename[256]; sprintf( filename, "%s.smf", outPrefix.c_str() ); fstream smf(filename, ios::binary | ios::in| ios::out); smf.seekp(heightPtr); smf.write( (char *)pixels, imageBuf->spec().image_bytes() ); smf.close(); delete imageBuf; if( is_smf( heightFile ) ) delete [] pixels; return false; }