You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
3.0 KiB
102 lines
3.0 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//===========================================================================// |
|
|
|
#include "tier0/platform.h" |
|
#include "bitmap/float_bm.h" |
|
#include "mathlib/mathlib.h" |
|
#include "tier2/tier2.h" |
|
#include "bitmap/tgaloader.h" |
|
|
|
#define NEIGHBORHOOD_SIZE 5 |
|
|
|
void SynthesizeTexture(FloatBitMap_t & output, FloatBitMap_t const & input) |
|
{ |
|
// init output with histogram-equalized random pixels |
|
output.InitializeWithRandomPixelsFromAnotherFloatBM(input); |
|
|
|
// build image pyramids |
|
FloatImagePyramid_t input_pyramid(input,PYRAMID_MODE_GAUSSIAN); |
|
FloatImagePyramid_t output_pyramid(output,PYRAMID_MODE_GAUSSIAN); |
|
|
|
// now, synthesize texture from lowest res to highest |
|
for(int level=min(input_pyramid.m_nLevels,output_pyramid.m_nLevels)-2;level>=0;level--) |
|
{ |
|
FloatBitMap_t & output=*(output_pyramid.Level(level)); |
|
FloatBitMap_t & output0=*(output_pyramid.Level(level+1)); |
|
FloatBitMap_t & input=*(input_pyramid.Level(level)); |
|
FloatBitMap_t & input0=*(input_pyramid.Level(level+1)); |
|
if ( |
|
(input.Width < NEIGHBORHOOD_SIZE*3) || |
|
(input.Height < NEIGHBORHOOD_SIZE*3) |
|
) |
|
{ |
|
printf("skip level %d\n",level); |
|
continue; |
|
} |
|
// now, synthesize each pixel |
|
for(int yloop=0;yloop<output.Height;yloop++) |
|
{ |
|
int yo=((yloop+NEIGHBORHOOD_SIZE) % output.Height); |
|
printf("level %d line %d\n",level,yo); |
|
for(int xo=0;xo<output.Width;xo++) |
|
{ |
|
int best_pixel_x=-1, best_pixel_y=-1; |
|
float best_error=1.0e22; |
|
// traverse all neighborhoods of src |
|
for(int nblk_y=NEIGHBORHOOD_SIZE;nblk_y<input.Height;nblk_y++) |
|
for(int nblk_x=NEIGHBORHOOD_SIZE;nblk_x<input.Width-NEIGHBORHOOD_SIZE;nblk_x++) |
|
{ |
|
float our_error=0; |
|
// now, compare this block to the neighborhood around our output pixel |
|
for(int oy=-NEIGHBORHOOD_SIZE;oy<=0;oy++) |
|
{ |
|
int xlimit=NEIGHBORHOOD_SIZE/2; |
|
if (oy==0) |
|
xlimit=-1; // on last line, don't step past our output pixel |
|
for(int ox=-NEIGHBORHOOD_SIZE/2;ox<=xlimit;ox++) |
|
for(int c=0;c<3;c++) |
|
{ |
|
float pix_diff= |
|
output.PixelWrapped(xo+ox,yo+oy,c)- |
|
input.Pixel(nblk_x+ox,nblk_y+oy,c); |
|
our_error+=pix_diff*pix_diff; |
|
float pix_diff0= |
|
output0.PixelWrapped(xo+ox,yo+oy,c)- |
|
input0.PixelClamped(nblk_x+ox,nblk_y+oy,c); |
|
our_error+=pix_diff0*pix_diff0; |
|
} |
|
} |
|
if (our_error < best_error) |
|
{ |
|
best_pixel_x=nblk_x; |
|
best_pixel_y=nblk_y; |
|
best_error=our_error; |
|
} |
|
} |
|
for(int c=0;c<3;c++) |
|
output.Pixel(xo,yo,c)=input.Pixel(best_pixel_x,best_pixel_y,c); |
|
} |
|
} |
|
} |
|
output_pyramid.WriteTGAs("synth_out"); |
|
} |
|
|
|
|
|
|
|
void main(int argc,char **argv) |
|
{ |
|
InitCommandLineProgram( argc, argv ); |
|
FloatBitMap_t src_texture(argv[1]); |
|
|
|
int out_width = atoi( argv[2] ); |
|
int out_height = atoi( argv[3] ); |
|
|
|
|
|
FloatBitMap_t output_map(out_width,out_height); |
|
|
|
SynthesizeTexture(output_map,src_texture); |
|
|
|
}
|
|
|