Beispiel #1
0
static void
test_getimagespec_gettexels (ustring filename)
{
    ImageSpec spec;
    if (! texsys->get_imagespec (filename, 0, spec)) {
        std::cerr << "Could not get spec for " << filename << "\n";
        std::string e = texsys->geterror ();
        if (! e.empty())
            std::cerr << "ERROR: " << e << "\n";
        return;
    }
    int w = spec.width/2, h = spec.height/2;
    ImageSpec postagespec (w, h, spec.nchannels, TypeDesc::FLOAT);
    ImageBuf buf ("postage.exr", postagespec);
    TextureOptions opt;
    opt.nchannels = spec.nchannels;
    if (missing[0] >= 0)
        opt.missingcolor.init ((float *)&missing, 0);
    std::vector<float> tmp (w*h*spec.nchannels);
    bool ok = texsys->get_texels (filename, opt, 0, w/2, w/2+w, h/2, h/2+h,
                                  0, 1, postagespec.format, &tmp[0]);
    if (! ok)
        std::cerr << texsys->geterror() << "\n";
    for (int y = 0;  y < h;  ++y)
        for (int x = 0;  x < w;  ++x) {
            imagesize_t offset = (y*w + x) * spec.nchannels;
            buf.setpixel (x, y, &tmp[offset]);
        }
    buf.save ();
}
Beispiel #2
0
bool
SMT::decompile()
{
	ImageBuf *bigBuf = getBig();

	char filename[256];
	sprintf(filename, "%s_tiles.png", outPrefix.c_str());
	if(verbose )cout << "INFO: Saving to " << filename << endl; 
	bigBuf->save(filename);
	return false;
}
Beispiel #3
0
bool
SMF::decompileMinimap()
{
	ImageBuf *imageBuf = getMinimap();
	if( !imageBuf ) return true;

	char filename[256];
	sprintf( filename, "%s_minimap.png", outPrefix.c_str() );

	imageBuf->save( filename );
	return false;
}
Beispiel #4
0
bool
SMF::decompileHeight()
{
	ImageBuf *imageBuf = getHeight();
	if( !imageBuf ) return true;

	char filename[256];
	sprintf( filename, "%s_height.tif", outPrefix.c_str() );

	imageBuf->save( filename );
	return false;
}
Beispiel #5
0
void
SMTool::imageToSMT( SMT *smt, ImageBuf *sourceBuf )
{
    using namespace std::chrono;

    if( verbose )
        cout << "INFO: Converting image to tiles and saving to smt" << endl;
    
    ImageSpec sourceSpec = sourceBuf->spec();
    unsigned int tileRes = smt->getTileSize();

    ImageBuf tileBuf;
    ImageSpec tileSpec( tileRes, tileRes, 4, TypeDesc::UINT8 );
    ROI roi( 0, 1, 0, 1, 0, 1, 0, 4 );

    ImageSpec mapSpec(
            sourceSpec.width / tileSpec.width,
            sourceSpec.height / tileSpec.height,
            1,
            TypeDesc::UINT );

    ImageBuf mapBuf( "tilemap", mapSpec );

    // Loop vars
    unsigned int currentTile;

    // Comparison vars
    bool match;
    unsigned int i;
    string hash;
    vector<string> hashTable;
    TileBufListEntry *listEntry;
    deque<TileBufListEntry *> tileList;

    if( verbose ){
        cout << "\tSource: " << sourceSpec.width << "x" << sourceSpec.height << endl;
        cout << "\ttileRes: " << tileSpec.width << "x" << tileSpec.height << endl;
        cout << "\ttilemap: " << mapSpec.width << "x" << mapSpec.height << endl;
        cout << "\tmaxTiles: " << mapSpec.image_pixels() << endl;
        cout << "  Processing tiles:\n";
    }

    for( ImageBuf::Iterator<unsigned int, unsigned int> it(mapBuf); ! it.done(); ++it ){
        currentTile = it.y() * mapSpec.width + it.x();

        // define the cropping region.
        roi.xbegin = it.x() * tileSpec.width;
        roi.xend = it.x() * tileSpec.width + tileSpec.width;
        roi.ybegin = it.y() * tileSpec.height;
        roi.yend = it.y() * tileSpec.height + tileSpec.height;

        // crop out tile.
        ImageBufAlgo::cut( tileBuf, *sourceBuf, roi );

#ifdef DEBUG_IMG
        tileBuf.save("SMTool::imageToSMT_tileBuf_" + to_string( currentTile + 1 ) + ".tif", "tif");
#endif //DEBUG_IMG

        // reset match variables
        match = false;
        i = smt->getNTiles();

        // Optimisation
        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 {
            //Comparison based on numerical differences of pixels
            listEntry = new TileBufListEntry;
            listEntry->image.copy( tileBuf );
            listEntry->tileNum = smt->getNTiles();

            ImageBufAlgo::CompareResults result;

            for( auto 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();
                }
            }
        }

        // write tile to file.
        if(! match ) {
            smt->append( &tileBuf );
        }

        tileBuf.clear();

        // Write index to tilemap
        it[0] = currentTile;

        // progress report
        cout << "\033[1A\033[2K\033[0G\t" << currentTile+1 << " of " << mapSpec.image_pixels() << ", %" << ((float)currentTile + 1) / mapSpec.image_pixels() * 100 << " complete." << endl;
    }
    hashTable.clear();
    if( verbose ) cout << endl;

    // Save tileindex
    mapBuf.save( "tilemap.exr", "exr" );
}
Beispiel #6
0
static void
test_texture3d (ustring filename)
{
    std::cerr << "Testing 3d texture " << filename << ", output = " 
              << output_filename << "\n";
    const int nchannels = 4;
    ImageSpec outspec (output_xres, output_yres, nchannels, TypeDesc::HALF);
    ImageBuf image (output_filename, outspec);
    ImageBufAlgo::zero (image);

    Imath::M33f scale;  scale.scale (Imath::V2f (0.5, 0.5));
    Imath::M33f rot;    rot.rotate (radians(30.0f));
    Imath::M33f trans;  trans.translate (Imath::V2f (0.35f, 0.15f));
    Imath::M33f xform = scale * rot * trans;
    xform.invert();

    TextureOptions opt;
    opt.sblur = blur;
    opt.tblur = blur;
    opt.rblur = blur;
    opt.swidth = width;
    opt.twidth = width;
    opt.rwidth = width;
    opt.nchannels = nchannels;
    float localfill = (fill >= 0 ? fill : 0.0f);
    opt.fill = localfill;
    if (missing[0] >= 0)
        opt.missingcolor.init ((float *)&missing, 0);

    opt.swrap = opt.twrap = opt.rwrap = TextureOptions::WrapPeriodic;
    int shadepoints = blocksize*blocksize;
    Imath::V3f *P = ALLOCA (Imath::V3f, shadepoints);
    Runflag *runflags = ALLOCA (Runflag, shadepoints);
    Imath::V3f *dPdx = ALLOCA (Imath::V3f, shadepoints);
    Imath::V3f *dPdy = ALLOCA (Imath::V3f, shadepoints);
    Imath::V3f *dPdz = ALLOCA (Imath::V3f, shadepoints);
    float *result = ALLOCA (float, shadepoints*nchannels);
    
    for (int iter = 0;  iter < iters;  ++iter) {
        // Iterate over blocks

        // Trick: switch to second texture, if given, for second iteration
        if (iter && filenames.size() > 1)
            filename = ustring (filenames[1]);

        for (int by = 0;  by < output_yres;  by+=blocksize) {
            for (int bx = 0;  bx < output_xres;  bx+=blocksize) {
                // Process pixels within a block.  First save the texture warp
                // (s,t) and derivatives into SIMD vectors.
                int idx = 0;
                for (int y = by; y < by+blocksize; ++y) {
                    for (int x = bx; x < bx+blocksize; ++x) {
                        if (x < output_xres && y < output_yres) {
                            if (nowarp) {
                                P[idx][0] = (float)x/output_xres * sscale;
                                P[idx][1] = (float)y/output_yres * tscale;
                                P[idx][2] = 0.5f * sscale;
                                P[idx] += offset;
                                dPdx[idx][0] = 1.0f/output_xres * sscale;
                                dPdx[idx][1] = 0;
                                dPdx[idx][2] = 0;
                                dPdy[idx][0] = 0;
                                dPdy[idx][1] = 1.0f/output_yres * tscale;
                                dPdy[idx][2] = 0;
                                dPdz[idx].setValue (0,0,0);
                            } else {
                                Imath::V3f coord = warp ((float)x/output_xres,
                                                         (float)y/output_yres,
                                                         0.5, xform);
                                coord.x *= sscale;
                                coord.y *= tscale;
                                coord += offset;
                                Imath::V3f coordx = warp ((float)(x+1)/output_xres,
                                                          (float)y/output_yres,
                                                          0.5, xform);
                                coordx.x *= sscale;
                                coordx.y *= tscale;
                                coordx += offset;
                                Imath::V3f coordy = warp ((float)x/output_xres,
                                                          (float)(y+1)/output_yres,
                                                          0.5, xform);
                                coordy.x *= sscale;
                                coordy.y *= tscale;
                                coordy += offset;
                                P[idx] = coord;
                                dPdx[idx] = coordx - coord;
                                dPdy[idx] = coordy - coord;
                                dPdz[idx].setValue (0,0,0);
                            }
                            runflags[idx] = RunFlagOn;
                        } else {
                            runflags[idx] = RunFlagOff;
                        }
                        ++idx;
                    }
                }
                // Call the texture system to do the filtering.
                bool ok = texsys->texture3d (filename, opt, runflags, 0, shadepoints,
                                             Varying(P), Varying(dPdx),
                                             Varying(dPdy), Varying(dPdz),
                                             result);
                if (! ok) {
                    std::string e = texsys->geterror ();
                    if (! e.empty())
                        std::cerr << "ERROR: " << e << "\n";
                }
                for (int i = 0;  i < shadepoints*nchannels;  ++i)
                    result[i] *= scalefactor;

                // Save filtered pixels back to the image.
                idx = 0;
                for (int y = by; y < by+blocksize; ++y) {
                    for (int x = bx; x < bx+blocksize; ++x) {
                        if (runflags[idx]) {
                            image.setpixel (x, y, result + idx*nchannels);
                        }
                        ++idx;
                    }
                }
            }
        }
    }
    
    if (! image.save ()) 
        std::cerr << "Error writing " << output_filename 
                  << " : " << image.geterror() << "\n";
}
Beispiel #7
0
static void
test_plain_texture ()
{
    std::cerr << "Testing 2d texture " << filenames[0] << ", output = " 
              << output_filename << "\n";
    const int nchannels = 4;
    ImageSpec outspec (output_xres, output_yres, nchannels, TypeDesc::HALF);
    ImageBuf image (output_filename, outspec);
    ImageBufAlgo::zero (image);

    Imath::M33f scale;  scale.scale (Imath::V2f (0.5, 0.5));
    Imath::M33f rot;    rot.rotate (radians(30.0f));
    Imath::M33f trans;  trans.translate (Imath::V2f (0.35f, 0.15f));
    Imath::M33f xform = scale * rot * trans;
    xform.invert();

    TextureOptions opt;
    opt.sblur = blur;
    opt.tblur = blur;
    opt.swidth = width;
    opt.twidth = width;
    opt.nchannels = nchannels;
    
    float localfill = (fill >= 0.0f) ? fill : 1.0f;
    opt.fill = localfill;
    if (missing[0] >= 0)
        opt.missingcolor.init ((float *)&missing, 0);
//    opt.interpmode = TextureOptions::InterpSmartBicubic;
//    opt.mipmode = TextureOptions::MipModeAniso;
    opt.swrap = opt.twrap = TextureOptions::WrapPeriodic;
//    opt.twrap = TextureOptions::WrapBlack;

#if 1
    TextureOpt opt1;
    opt1.sblur = blur;
    opt1.tblur = blur;
    opt1.swidth = width;
    opt1.twidth = width;
    opt1.nchannels = nchannels;
    opt1.fill = localfill;
    if (missing[0] >= 0)
        opt1.missingcolor = (float *)&missing;
    opt1.swrap = opt1.twrap = TextureOpt::WrapPeriodic;
#endif

    int shadepoints = blocksize*blocksize;
    float *s = ALLOCA (float, shadepoints);
    float *t = ALLOCA (float, shadepoints);
    Runflag *runflags = ALLOCA (Runflag, shadepoints);
    float *dsdx = ALLOCA (float, shadepoints);
    float *dtdx = ALLOCA (float, shadepoints);
    float *dsdy = ALLOCA (float, shadepoints);
    float *dtdy = ALLOCA (float, shadepoints);
    float *result = ALLOCA (float, shadepoints*nchannels);
    
    ustring filename = ustring (filenames[0]);
    TextureSystem::Perthread *perthread_info = texsys->get_perthread_info ();
    TextureSystem::TextureHandle *texture_handle = texsys->get_texture_handle (filename);

    for (int iter = 0;  iter < iters;  ++iter) {
        if (iters > 1 && filenames.size() > 1) {
            // Use a different filename for each iteration
            int texid = std::min (iter, (int)filenames.size()-1);
            filename = ustring (filenames[texid]);
            std::cerr << "iter " << iter << " file " << filename << "\n";
        }

        // Iterate over blocks
        for (int by = 0, b = 0;  by < output_yres;  by+=blocksize) {
            for (int bx = 0;  bx < output_xres;  bx+=blocksize, ++b) {
                // Trick: switch to other textures on later iterations, if any
                if (iters == 1 && filenames.size() > 1) {
                    // Use a different filename from block to block
                    filename = ustring (filenames[b % (int)filenames.size()]);
                }

                // Process pixels within a block.  First save the texture warp
                // (s,t) and derivatives into SIMD vectors.
                int idx = 0;
                for (int y = by; y < by+blocksize; ++y) {
                    for (int x = bx; x < bx+blocksize; ++x) {
                        if (x < output_xres && y < output_yres) {
                            if (nowarp) {
                                s[idx] = (float)x/output_xres * sscale + offset[0];
                                t[idx] = (float)y/output_yres * tscale + offset[1];
                                dsdx[idx] = 1.0f/output_xres * sscale;
                                dtdx[idx] = 0;
                                dsdy[idx] = 0;
                                dtdy[idx] = 1.0f/output_yres * tscale;
                            } else {
                                Imath::V3f coord = warp ((float)x/output_xres,
                                                         (float)y/output_yres,
                                                         xform);
                                coord.x *= sscale;
                                coord.y *= tscale;
                                coord += offset;
                                Imath::V3f coordx = warp ((float)(x+1)/output_xres,
                                                          (float)y/output_yres,
                                                          xform);
                                coordx.x *= sscale;
                                coordx.y *= tscale;
                                coordx += offset;
                                Imath::V3f coordy = warp ((float)x/output_xres,
                                                          (float)(y+1)/output_yres,
                                                          xform);
                                coordy.x *= sscale;
                                coordy.y *= tscale;
                                coordy += offset;
                                s[idx] = coord[0];
                                t[idx] = coord[1];
                                dsdx[idx] = coordx[0] - coord[0];
                                dtdx[idx] = coordx[1] - coord[1];
                                dsdy[idx] = coordy[0] - coord[0];
                                dtdy[idx] = coordy[1] - coord[1];
                            }
                            runflags[idx] = RunFlagOn;
                        } else {
                            runflags[idx] = RunFlagOff;
                        }
                        ++idx;
                    }
                }

                // Call the texture system to do the filtering.
                bool ok;
                if (blocksize == 1) {
                    if (use_handle)
                        ok = texsys->texture (texture_handle, perthread_info, opt1,
                                              s[0], t[0], dsdx[0], dtdx[0],
                                              dsdy[0], dtdy[0], result);
                    else
                        ok = texsys->texture (filename, opt1,
                                              s[0], t[0], dsdx[0], dtdx[0],
                                              dsdy[0], dtdy[0], result);
                } else {
                    ok = texsys->texture (filename, opt, runflags, 0,
                                          shadepoints, Varying(s), Varying(t),
                                          Varying(dsdx), Varying(dtdx),
                                          Varying(dsdy), Varying(dtdy), result);
                }
                if (! ok) {
                    std::string e = texsys->geterror ();
                    if (! e.empty())
                        std::cerr << "ERROR: " << e << "\n";
                }
                for (int i = 0;  i < shadepoints*nchannels;  ++i)
                    result[i] *= scalefactor;

                // Save filtered pixels back to the image.
                idx = 0;
                for (int y = by; y < by+blocksize; ++y) {
                    for (int x = bx; x < bx+blocksize; ++x) {
                        if (runflags[idx]) {
                            image.setpixel (x, y, result + idx*nchannels);
                        }
                        ++idx;
                    }
                }
            }
        }
    }
    
    if (! image.save ()) 
        std::cerr << "Error writing " << output_filename 
                  << " : " << image.geterror() << "\n";
}
Beispiel #8
0
void
SMT::pasteDecals(ImageBuf *bigBuf)
{
	printf("WARNING: decal pasting is not yet implemented\n");
	return;
	// load definitions file
	vector<type> list;

	// Parse the file
	printf( "INFO: Reading %s\n", decalFile.c_str() );
	ifstream decalList( decalFile.c_str() );

	string line;
	string cell;
	vector<string> tokens;
	while ( getline( decalList, line ) ) {
		stringstream lineStream( line );
		tokens.clear();
		while( getline( lineStream, cell, ',' ) ) tokens.push_back( cell );

		if(tokens.size() <2 ) continue;

		// use parsed line
		coord xy;
		type *decal;
		// search for existing decal filename
		bool found = false;
		for(unsigned int i = 0; i < list.size(); ++i ) {
			if( !list[i].imageName.compare( tokens[0].c_str() ) ) {
				decal = &list[i];
				found = true;
				break;
			}
		}
		if( !found ) {
			decal = new type;
			decal->imageName = tokens[0].c_str();
		}
		xy.x = atoi( tokens[1].c_str() );
		xy.y = atoi( tokens[2].c_str() );
		decal->coordinates.push_back(xy);
		if( !found ) list.push_back(*decal);
	}

	// loop through list of decals.
	for(unsigned int i = 0; i < list.size(); ++i ) {
		if( verbose )printf("     %i %s ", (int)list[i].coordinates.size(),
			list[i].imageName.c_str() );

		ImageBuf decalBuf( list[i].imageName );
		decalBuf.read( 0, 0, false, TypeDesc::FLOAT );
		if( !decalBuf.initialized() ) {
			printf("ERROR: could not load %s\n", list[i].imageName.c_str() );
			continue;
		}
		ImageSpec decalSpec = decalBuf.spec();

		printf("(%i,%i)%i\n", decalSpec.width, decalSpec.height,
			decalSpec.nchannels );

		// loop through list of coordinates
		for(unsigned int j = 0; j < list[i].coordinates.size(); ++j ) {
			coord xy = list[i].coordinates[j];

			ROI roi( xy.x, xy.x + decalSpec.width,
					xy.y, xy.y + decalSpec.height,
					0,1,
					0,5);
			ImageBuf pasteBuf;
			ImageBufAlgo::crop(pasteBuf, *bigBuf, roi);

			ImageBuf compBuf;
			if( !ImageBufAlgo::over( compBuf, decalBuf, pasteBuf) ) {
				cout << "ERROR with composite: ";
				cout << compBuf.geterror() << endl;
				continue;
			}
			char filename[256];
			sprintf(filename, "test%i.png", j);
			compBuf.save(filename);
		}
	}
	return;
}
Beispiel #9
0
int
main (int argc, char *argv[])
{
    getargs (argc, argv);

    std::cout << "Comparing \"" << filenames[0] 
             << "\" and \"" << filenames[1] << "\"\n";

    // Create a private ImageCache so we can customize its cache size
    // and instruct it store everything internally as floats.
    ImageCache *imagecache = ImageCache::create (true);
    imagecache->attribute ("forcefloat", 1);
    if (sizeof(void *) == 4)  // 32 bit or 64?
        imagecache->attribute ("max_memory_MB", 512.0);
    else
        imagecache->attribute ("max_memory_MB", 2048.0);
    imagecache->attribute ("autotile", 256);
#ifdef DEBUG
    imagecache->attribute ("statistics:level", 2);
#endif

    ImageBuf img0, img1;
    if (! read_input (filenames[0], img0, imagecache) ||
        ! read_input (filenames[1], img1, imagecache))
        return ErrFile;
//    ImageSpec spec0 = img0.spec();  // stash it

    int ret = ErrOK;
    for (int subimage = 0;  subimage < img0.nsubimages();  ++subimage) {
        if (subimage > 0 && !compareall)
            break;
        if (subimage >= img1.nsubimages())
            break;

        if (compareall) {
            std::cout << "Subimage " << subimage << ": ";
            std::cout << img0.spec().width << " x " << img0.spec().height;
            if (img0.spec().depth > 1)
                std::cout << " x " << img0.spec().depth;
            std::cout << ", " << img0.spec().nchannels << " channel\n";
        }

        if (! read_input (filenames[0], img0, imagecache, subimage) ||
            ! read_input (filenames[1], img1, imagecache, subimage))
            return ErrFile;

        if (img0.nmiplevels() != img1.nmiplevels()) {
            std::cout << "Files do not match in their number of MIPmap levels\n";
        }

        for (int m = 0;  m < img0.nmiplevels();  ++m) {
            if (m > 0 && !compareall)
                break;
            if (m > 0 && img0.nmiplevels() != img1.nmiplevels()) {
                std::cout << "Files do not match in their number of MIPmap levels\n";
                ret = ErrDifferentSize;
                break;
            }

            if (! read_input (filenames[0], img0, imagecache, subimage, m) ||
                ! read_input (filenames[1], img1, imagecache, subimage, m))
                return ErrFile;

            if (compareall && img0.nmiplevels() > 1) {
                std::cout << " MIP level " << m << ": ";
                std::cout << img0.spec().width << " x " << img0.spec().height;
                if (img0.spec().depth > 1)
                    std::cout << " x " << img0.spec().depth;
                std::cout << ", " << img0.spec().nchannels << " channel\n";
            }

            // Compare the dimensions of the images.  Fail if they
            // aren't the same resolution and number of channels.  No
            // problem, though, if they aren't the same data type.
            if (! same_size (img0, img1)) {
                std::cout << "Images do not match in size: ";
                std::cout << "(" << img0.spec().width << "x" << img0.spec().height;
                if (img0.spec().depth > 1)
                    std::cout << "x" << img0.spec().depth;
                std::cout << "x" << img0.spec().nchannels << ")";
                std::cout << " versus ";
                std::cout << "(" << img1.spec().width << "x" << img1.spec().height;
                if (img1.spec().depth > 1)
                    std::cout << "x" << img1.spec().depth;
                std::cout << "x" << img1.spec().nchannels << ")\n";
                ret = ErrDifferentSize;
                break;
            }

            int npels = img0.spec().width * img0.spec().height * img0.spec().depth;
            ASSERT (img0.spec().format == TypeDesc::FLOAT);

            // Compare the two images.
            //
            ImageBufAlgo::CompareResults cr;
            ImageBufAlgo::compare (img0, img1, failthresh, warnthresh, cr);

            int yee_failures = 0;
            if (perceptual)
                yee_failures = ImageBufAlgo::compare_Yee (img0, img1);

            // Print the report
            //
            std::cout << "  Mean error = ";
            safe_double_print (cr.meanerror);
            std::cout << "  RMS error = ";
            safe_double_print (cr.rms_error);
            std::cout << "  Peak SNR = ";
            safe_double_print (cr.PSNR);
            std::cout << "  Max error  = " << cr.maxerror;
            if (cr.maxerror != 0) {
                std::cout << " @ (" << cr.maxx << ", " << cr.maxy;
                if (img0.spec().depth > 1)
                    std::cout << ", " << cr.maxz;
                std::cout << ", " << img0.spec().channelnames[cr.maxc] << ')';
            }
            std::cout << "\n";
// when Visual Studio is used float values in scientific foramt are 
// printed with three digit exponent. We change this behaviour to fit
// Linux way
#ifdef _MSC_VER
            _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
            int precis = std::cout.precision();
            std::cout << "  " << cr.nwarn << " pixels (" 
                      << std::setprecision(3) << (100.0*cr.nwarn / npels) 
                      << std::setprecision(precis) << "%) over " << warnthresh << "\n";
            std::cout << "  " << cr.nfail << " pixels (" 
                      << std::setprecision(3) << (100.0*cr.nfail / npels) 
                      << std::setprecision(precis) << "%) over " << failthresh << "\n";
            if (perceptual)
                std::cout << "  " << yee_failures << " pixels ("
                          << std::setprecision(3) << (100.0*yee_failures / npels) 
                          << std::setprecision(precis)
                          << "%) failed the perceptual test\n";

            if (cr.nfail > (failpercent/100.0 * npels) || cr.maxerror > hardfail ||
                yee_failures > (failpercent/100.0 * npels)) {
                ret = ErrFail;
            } else if (cr.nwarn > (warnpercent/100.0 * npels) || cr.maxerror > hardwarn) {
                if (ret != ErrFail)
                    ret = ErrWarn;
            }

            // If the user requested that a difference image be output,
            // do that.  N.B. we only do this for the first subimage
            // right now, because ImageBuf doesn't really know how to
            // write subimages.
            if (diffimage.size() && (cr.maxerror != 0 || !outdiffonly)) {
                ImageBuf diff (diffimage, img0.spec());
                ImageBuf::ConstIterator<float,float> pix0 (img0);
                ImageBuf::ConstIterator<float,float> pix1 (img1);
                ImageBuf::Iterator<float,float> pixdiff (diff);
                // Subtract the second image from the first.  At which
                // time we no longer need the second image, so free it.
                if (diffabs) {
                    for (  ;  pix0.valid();  ++pix0) {
                        pix1.pos (pix0.x(), pix0.y());  // ensure alignment
                        pixdiff.pos (pix0.x(), pix0.y());
                        for (int c = 0;  c < img0.nchannels();  ++c)
                            pixdiff[c] = diffscale * fabsf (pix0[c] - pix1[c]);
                    }
                } else {
                    for (  ;  pix0.valid();  ++pix0) {
                        pix1.pos (pix0.x(), pix0.y());  // ensure alignment
                        pixdiff.pos (pix0.x(), pix0.y());
                        for (int c = 0;  c < img0.spec().nchannels;  ++c)
                            pixdiff[c] = diffscale * (pix0[c] - pix1[c]);
                    }
                }

                diff.save (diffimage);

                // Clear diff image name so we only save the first
                // non-matching subimage.
                diffimage = "";
            }
        }
    }

    if (compareall && img0.nsubimages() != img1.nsubimages()) {
        std::cout << "Images had differing numbers of subimages ("
                  << img0.nsubimages() << " vs " << img1.nsubimages() << ")\n";
        ret = ErrFail;
    }
    if (!compareall && (img0.nsubimages() > 1 || img1.nsubimages() > 1)) {
        std::cout << "Only compared the first subimage (of "
                  << img0.nsubimages() << " and " << img1.nsubimages() 
                  << ", respectively)\n";
    }

    if (ret == ErrOK)
        std::cout << "PASS\n";
    else if (ret == ErrWarn)
        std::cout << "WARNING\n";
    else
        std::cout << "FAILURE\n";

    ImageCache::destroy (imagecache);
    return ret;
}
Beispiel #10
0
int main (int argc, char *argv[])
{
    // Arguments
    if(argc != 3)
    {
        std::cerr << "mkthumbnail usage : mkthumbnail <input> <output>" << std::endl;
        return EXIT_FAILURE;
    }
    
    std::string inputname=argv[1];
    std::string outputname=argv[2];
	std::string colortransfer_to = "sRGB";
	std::string colortransfer_from = "sRGB";
    
    // Colorspace selection
    if(extensionIs(inputname, "exr") )
    {
       colortransfer_from="Linear"; 
    } 
    else if(extensionIs(inputname, "dpx"))
    {
       colortransfer_from="KodakLog"; 
    }
    else
    {
        colortransfer_from="sRGB"; 
    }

    bool ok = true;
    
    ImageBuf in;
    if (! read_input (inputname, in)) 
    {
        std::cerr << "mkthumbnail: read error: " << in.geterror() << "\n";
        return EXIT_FAILURE;
    }
    
    ColorTransfer *from_func = ColorTransfer::create (colortransfer_from + "_to_linear");
    if (from_func == NULL) {
        std::cerr << "mkthumbnail: --colorspace needs a 'colorspace' of "
            << "Linear, Gamma, sRGB, AdobeRGB, Rec709 or KodakLog\n";
        return EXIT_FAILURE;
    }

    ColorTransfer *to_func = ColorTransfer::create (std::string("linear_to_") + colortransfer_to);
    if (to_func == NULL) {
        std::cerr << "mkthumbnail: --transfer needs a 'colorspace' of "
            << "Linear, Gamma, sRGB, AdobeRGB, Rec709 or KodakLog\n";
        return EXIT_FAILURE;
    }
    std::cout << "Converting [" << colortransfer_from << "] " << inputname 
        << " to [" << colortransfer_to << "] " << outputname << "\n";
    
    //
    ImageBuf linear;
    ImageBuf outtmp;
    ImageBufAlgo::colortransfer (linear, in, from_func);
    ImageBufAlgo::colortransfer (outtmp, linear, to_func);
    std::cout << "finished color transfer\n";
    
  
    // Pixel aspect ratio
	const ImageIOParameter *aspect = in.spec().find_attribute ("pixelaspectratio", TypeDesc::FLOAT);
	float pixel_ratio = aspect ? *(float *)aspect->data() : 1.0f;
    float ratio = ((float)in.spec().height+(float)in.spec().y)/((float)in.spec().width+(float)in.spec().x);
	pixel_ratio = pixel_ratio != 0.f ? pixel_ratio : 1.f;
	const int resize_w = 480; // resize target width
    int resize_y = (int)((float)resize_w*ratio/pixel_ratio);
    int resize_x = resize_w;
    
    ImageSpec outspec = outtmp.spec();
	outspec.x = 0;
	outspec.y = 0;
	outspec.full_x = 0;
	outspec.full_y = 0;
    outspec.width = resize_x;
    outspec.height = resize_y;
    outspec.full_width = resize_x;
    outspec.full_height = resize_y;
    ImageBuf out (outputname, outspec);
    float pixel[3] = { .1f, .1f, .1f };
    ImageBufAlgo::fill (out, pixel);
    if(!ImageBufAlgo::resize (out, outtmp, out.xbegin(), out.xend(),
                          out.ybegin(), out.yend()))
    {
        std::cerr << "mkthumbnail: unable to resize image, " << out.geterror() << std::endl;
        return EXIT_FAILURE;
    }

    if(out.spec().nchannels>3) 
    {
        std::cout << "Changing number of channels to 3 "<< "\n";
        ImageBuf newout("temp", out.spec());
        setNbChannels (newout, out, 3);
        out = newout;
    }
    
    if(!out.save (outputname)) 
    {
        std::cerr << "mkthumbnail: unable to save output image, " << out.geterror() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
Beispiel #11
0
static void
test_plain_texture ()
{
    std::cerr << "Testing 2d texture " << filenames[0] << ", output = " 
              << output_filename << "\n";
    const int nchannels = 4;
    ImageSpec outspec (output_xres, output_yres, nchannels, TypeDesc::HALF);
    if (! dataformatname.empty()) {
        if (dataformatname == "uint8")
            outspec.set_format (TypeDesc::UINT8);
        else if (dataformatname == "int8")
            outspec.set_format (TypeDesc::INT8);
        else if (dataformatname == "uint10") {
            outspec.attribute ("oiio:BitsPerSample", 10);
            outspec.set_format (TypeDesc::UINT16);
        }
        else if (dataformatname == "uint12") {
            outspec.attribute ("oiio:BitsPerSample", 12);
            outspec.set_format (TypeDesc::UINT16);
        }
        else if (dataformatname == "uint16")
            outspec.set_format (TypeDesc::UINT16);
        else if (dataformatname == "int16")
            outspec.set_format (TypeDesc::INT16);
        else if (dataformatname == "half")
            outspec.set_format (TypeDesc::HALF);
        else if (dataformatname == "float")
            outspec.set_format (TypeDesc::FLOAT);
        else if (dataformatname == "double")
            outspec.set_format (TypeDesc::DOUBLE);
        outspec.channelformats.clear ();
    }
    ImageBuf image (output_filename, outspec);
    ImageBufAlgo::zero (image);

    Imath::M33f scale;  scale.scale (Imath::V2f (0.5, 0.5));
    Imath::M33f rot;    rot.rotate (radians(30.0f));
    Imath::M33f trans;  trans.translate (Imath::V2f (0.35f, 0.15f));
    Imath::M33f xform = scale * rot * trans;
    xform.invert();

    TextureOptions opt;
    opt.sblur = blur;
    opt.tblur = blur;
    opt.swidth = width;
    opt.twidth = width;
    opt.nchannels = nchannels;
    
    float localfill = (fill >= 0.0f) ? fill : 1.0f;
    opt.fill = localfill;
    if (missing[0] >= 0)
        opt.missingcolor.init ((float *)&missing, 0);
//    opt.interpmode = TextureOptions::InterpSmartBicubic;
//    opt.mipmode = TextureOptions::MipModeAniso;
    TextureOptions::parse_wrapmodes (wrapmodes.c_str(), opt.swrap, opt.twrap);

    TextureOpt opt1;
    opt1.sblur = blur;
    opt1.tblur = blur;
    opt1.swidth = width;
    opt1.twidth = width;
    opt1.nchannels = nchannels;
    opt1.fill = localfill;
    if (missing[0] >= 0)
        opt1.missingcolor = (float *)&missing;
    TextureOpt::parse_wrapmodes (wrapmodes.c_str(), opt1.swrap, opt1.twrap);

    int shadepoints = blocksize*blocksize;
    float *s = ALLOCA (float, shadepoints);
    float *t = ALLOCA (float, shadepoints);
    Runflag *runflags = ALLOCA (Runflag, shadepoints);
    float *dsdx = ALLOCA (float, shadepoints);
    float *dtdx = ALLOCA (float, shadepoints);
    float *dsdy = ALLOCA (float, shadepoints);
    float *dtdy = ALLOCA (float, shadepoints);
    float *result = ALLOCA (float, shadepoints*nchannels);
    
    ustring filename = ustring (filenames[0]);
    TextureSystem::Perthread *perthread_info = texsys->get_perthread_info ();
    TextureSystem::TextureHandle *texture_handle = texsys->get_texture_handle (filename);

    for (int iter = 0;  iter < iters;  ++iter) {
        if (iters > 1 && filenames.size() > 1) {
            // Use a different filename for each iteration
            int texid = std::min (iter, (int)filenames.size()-1);
            filename = ustring (filenames[texid]);
            std::cerr << "iter " << iter << " file " << filename << "\n";
        }

        // Iterate over blocks
        for (int by = 0, b = 0;  by < output_yres;  by+=blocksize) {
            for (int bx = 0;  bx < output_xres;  bx+=blocksize, ++b) {
                // Trick: switch to other textures on later iterations, if any
                if (iters == 1 && filenames.size() > 1) {
                    // Use a different filename from block to block
                    filename = ustring (filenames[b % (int)filenames.size()]);
                }

                // Process pixels within a block.  First save the texture warp
                // (s,t) and derivatives into SIMD vectors.
                int idx = 0;
                for (int y = by; y < by+blocksize; ++y) {
                    for (int x = bx; x < bx+blocksize; ++x) {
                        if (x < output_xres && y < output_yres) {
                            if (nowarp) {
                                s[idx] = (float)x/output_xres * sscale + offset[0];
                                t[idx] = (float)y/output_yres * tscale + offset[1];
                                dsdx[idx] = 1.0f/output_xres * sscale;
                                dtdx[idx] = 0;
                                dsdy[idx] = 0;
                                dtdy[idx] = 1.0f/output_yres * tscale;
                            } else if (tube) {
                                float xt = float(x)/output_xres - 0.5f;
                                float dxt_dx = 1.0f/output_xres;
                                float yt = float(y)/output_yres - 0.5f;
                                float dyt_dy = 1.0f/output_yres;
                                float theta = atan2f (yt, xt);
                                // See OSL's Dual2 for partial derivs of
                                // atan2, hypot, and 1/x
                                float denom = 1.0f / (xt*xt + yt*yt);
                                float dtheta_dx = yt*dxt_dx * denom;
                                float dtheta_dy = -xt*dyt_dy * denom;
                                s[idx] = 4.0f * theta / (2.0f * M_PI);
                                dsdx[idx] = 4.0f * dtheta_dx / (2.0f * M_PI);
                                dsdy[idx] = 4.0f * dtheta_dy / (2.0f * M_PI);
                                float h = hypot(xt,yt);
                                float dh_dx = xt*dxt_dx / h;
                                float dh_dy = yt*dyt_dy / h;
                                h *= M_SQRT2;
                                dh_dx *= M_SQRT2; dh_dy *= M_SQRT2;
                                float hinv = 1.0f / h;
                                t[idx] = hinv;
                                dtdx[idx] = hinv * (-hinv * dh_dx);
                                dtdy[idx] = hinv * (-hinv * dh_dy);
                            } else {
                                Imath::V3f coord = warp ((float)x/output_xres,
                                                         (float)y/output_yres,
                                                         xform);
                                coord.x *= sscale;
                                coord.y *= tscale;
                                coord += offset;
                                Imath::V3f coordx = warp ((float)(x+1)/output_xres,
                                                          (float)y/output_yres,
                                                          xform);
                                coordx.x *= sscale;
                                coordx.y *= tscale;
                                coordx += offset;
                                Imath::V3f coordy = warp ((float)x/output_xres,
                                                          (float)(y+1)/output_yres,
                                                          xform);
                                coordy.x *= sscale;
                                coordy.y *= tscale;
                                coordy += offset;
                                s[idx] = coord[0];
                                t[idx] = coord[1];
                                dsdx[idx] = coordx[0] - coord[0];
                                dtdx[idx] = coordx[1] - coord[1];
                                dsdy[idx] = coordy[0] - coord[0];
                                dtdy[idx] = coordy[1] - coord[1];
                            }
                            runflags[idx] = RunFlagOn;
                        } else {
                            runflags[idx] = RunFlagOff;
                        }
                        ++idx;
                    }
                }

                // Call the texture system to do the filtering.
                bool ok;
                if (blocksize == 1) {
                    if (use_handle)
                        ok = texsys->texture (texture_handle, perthread_info, opt1,
                                              s[0], t[0], dsdx[0], dtdx[0],
                                              dsdy[0], dtdy[0], result);
                    else
                        ok = texsys->texture (filename, opt1,
                                              s[0], t[0], dsdx[0], dtdx[0],
                                              dsdy[0], dtdy[0], result);
                } else {
                    ok = texsys->texture (filename, opt, runflags, 0,
                                          shadepoints, Varying(s), Varying(t),
                                          Varying(dsdx), Varying(dtdx),
                                          Varying(dsdy), Varying(dtdy), result);
                }
                if (! ok) {
                    std::string e = texsys->geterror ();
                    if (! e.empty())
                        std::cerr << "ERROR: " << e << "\n";
                }
                for (int i = 0;  i < shadepoints*nchannels;  ++i)
                    result[i] *= scalefactor;

                // Save filtered pixels back to the image.
                idx = 0;
                for (int y = by; y < by+blocksize; ++y) {
                    for (int x = bx; x < bx+blocksize; ++x) {
                        if (runflags[idx]) {
                            image.setpixel (x, y, result + idx*nchannels);
                        }
                        ++idx;
                    }
                }
            }
        }

        if (resetstats) {
            std::cout << texsys->getstats(2) << "\n";
            texsys->reset_stats ();
        }
    }
    
    if (! image.save ()) 
        std::cerr << "Error writing " << output_filename 
                  << " : " << image.geterror() << "\n";
}
Beispiel #12
0
int
OiioTool::do_action_diff (ImageRec &ir0, ImageRec &ir1,
                          Oiiotool &ot)
{
    std::cout << "Computing diff of \"" << ir0.name() << "\" vs \""
              << ir1.name() << "\"\n";
    ir0.read ();
    ir1.read ();

    int ret = DiffErrOK;
    for (int subimage = 0;  subimage < ir0.subimages();  ++subimage) {
        if (subimage > 0 && !ot.allsubimages)
            break;
        if (subimage >= ir1.subimages())
            break;

        if (ot.allsubimages) {
            std::cout << "Subimage " << subimage << ": ";
            const ImageSpec &spec (*ir0.spec(subimage));
            std::cout << spec.width << " x " << spec.height;
            if (spec.depth > 1)
                std::cout << " x " << spec.depth;
            std::cout << ", " << spec.nchannels << " channel\n";
        }

        if (ir0.miplevels(subimage) != ir1.miplevels(subimage)) {
            std::cout << "Files do not match in their number of MIPmap levels\n";
        }

        for (int m = 0;  m < ir0.miplevels(subimage);  ++m) {
            if (m > 0 && !ot.allsubimages)
                break;
            if (m > 0 && ir0.miplevels(subimage) != ir1.miplevels(subimage)) {
                std::cout << "Files do not match in their number of MIPmap levels\n";
                ret = DiffErrDifferentSize;
                break;
            }

            ImageBuf &img0 (ir0(subimage,m));
            ImageBuf &img1 (ir1(subimage,m));

            if (ot.allsubimages && ir0.miplevels(subimage) > 1) {
                std::cout << " MIP level " << m << ": ";
                std::cout << img0.spec().width << " x " << img0.spec().height;
                if (img0.spec().depth > 1)
                    std::cout << " x " << img0.spec().depth;
                std::cout << ", " << img0.spec().nchannels << " channel\n";
            }

            // Compare the dimensions of the images.  Fail if they
            // aren't the same resolution and number of channels.  No
            // problem, though, if they aren't the same data type.
            if (! same_size (img0, img1)) {
                std::cout << "Images do not match in size: ";
                std::cout << "(" << img0.spec().width << "x" << img0.spec().height;
                if (img0.spec().depth > 1)
                    std::cout << "x" << img0.spec().depth;
                std::cout << "x" << img0.spec().nchannels << ")";
                std::cout << " versus ";
                std::cout << "(" << img1.spec().width << "x" << img1.spec().height;
                if (img1.spec().depth > 1)
                    std::cout << "x" << img1.spec().depth;
                std::cout << "x" << img1.spec().nchannels << ")\n";
                ret = DiffErrDifferentSize;
                break;
            }

            int npels = img0.spec().width * img0.spec().height * img0.spec().depth;
            ASSERT (img0.spec().format == TypeDesc::FLOAT);

            // Compare the two images.
            //
            ImageBufAlgo::CompareResults cr;
            ImageBufAlgo::compare (img0, img1, ot.diff_failthresh, ot.diff_warnthresh, cr);

            int yee_failures = 0;
#if 0
            if (perceptual)
                yee_failures = ImageBufAlgo::compare_Yee (img0, img1);
#endif

            // Print the report
            //
            std::cout << "  Mean error = ";
            safe_double_print (cr.meanerror);
            std::cout << "  RMS error = ";
            safe_double_print (cr.rms_error);
            std::cout << "  Peak SNR = ";
            safe_double_print (cr.PSNR);
            std::cout << "  Max error  = " << cr.maxerror;
            if (cr.maxerror != 0) {
                std::cout << " @ (" << cr.maxx << ", " << cr.maxy;
                if (img0.spec().depth > 1)
                    std::cout << ", " << cr.maxz;
                std::cout << ", " << img0.spec().channelnames[cr.maxc] << ')';
            }
            std::cout << "\n";
// when Visual Studio is used float values in scientific foramt are 
// printed with three digit exponent. We change this behaviour to fit
// Linux way
#ifdef _MSC_VER
            _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
            int precis = std::cout.precision();
            std::cout << "  " << cr.nwarn << " pixels (" 
                      << std::setprecision(3) << (100.0*cr.nwarn / npels) 
                      << std::setprecision(precis) << "%) over " << ot.diff_warnthresh << "\n";
            std::cout << "  " << cr.nfail << " pixels (" 
                      << std::setprecision(3) << (100.0*cr.nfail / npels) 
                      << std::setprecision(precis) << "%) over " << ot.diff_failthresh << "\n";
#if 0
            if (perceptual)
                std::cout << "  " << yee_failures << " pixels ("
                          << std::setprecision(3) << (100.0*yee_failures / npels) 
                          << std::setprecision(precis)
                          << "%) failed the perceptual test\n";
#endif
            if (cr.nfail > (ot.diff_failpercent/100.0 * npels) || cr.maxerror > ot.diff_hardfail ||
                yee_failures > (ot.diff_failpercent/100.0 * npels)) {
                ret = DiffErrFail;
            } else if (cr.nwarn > (ot.diff_warnpercent/100.0 * npels) || cr.maxerror > ot.diff_hardwarn) {
                if (ret != DiffErrFail)
                    ret = DiffErrWarn;
            }

#if 0
            // If the user requested that a difference image be output,
            // do that.  N.B. we only do this for the first subimage
            // right now, because ImageBuf doesn't really know how to
            // write subimages.
            if (diffimage.size() && (cr.maxerror != 0 || !outdiffonly)) {
                ImageBuf diff (diffimage, img0.spec());
                ImageBuf::ConstIterator<float,float> pix0 (img0);
                ImageBuf::ConstIterator<float,float> pix1 (img1);
                ImageBuf::Iterator<float,float> pixdiff (diff);
                // Subtract the second image from the first.  At which
                // time we no longer need the second image, so free it.
                if (diffabs) {
                    for (  ;  pix0.valid();  ++pix0) {
                        pix1.pos (pix0.x(), pix0.y());  // ensure alignment
                        pixdiff.pos (pix0.x(), pix0.y());
                        for (int c = 0;  c < img0.nchannels();  ++c)
                            pixdiff[c] = diffscale * fabsf (pix0[c] - pix1[c]);
                    }
                } else {
                    for (  ;  pix0.valid();  ++pix0) {
                        pix1.pos (pix0.x(), pix0.y());  // ensure alignment
                        pixdiff.pos (pix0.x(), pix0.y());
                        for (int c = 0;  c < img0.spec().nchannels;  ++c)
                            pixdiff[c] = diffscale * (pix0[c] - pix1[c]);
                    }
                }

                diff.save (diffimage);

                // Clear diff image name so we only save the first
                // non-matching subimage.
                diffimage = "";
            }
#endif
        }
    }

    if (ot.allsubimages && ir0.subimages() != ir1.subimages()) {
        std::cout << "Images had differing numbers of subimages ("
                  << ir0.subimages() << " vs " << ir1.subimages() << ")\n";
        ret = DiffErrFail;
    }
    if (!ot.allsubimages && (ir0.subimages() > 1 || ir1.subimages() > 1)) {
        std::cout << "Only compared the first subimage (of "
                  << ir0.subimages() << " and " << ir1.subimages() 
                  << ", respectively)\n";
    }

    if (ret == DiffErrOK)
        std::cout << "PASS\n";
    else if (ret == DiffErrWarn)
        std::cout << "WARNING\n";
    else {
        std::cout << "FAILURE\n";
    }
    return ret;
}