main.cpp 3.46 KB
#include <iostream>
#include <string>
#include <openslide/openslide.h>
#include <opencv2/opencv.hpp>
#include <stim/parser/arguments.h>

stim::arglist args;
int32_t level = 0;
int64_t x = 0;
int64_t y = 0;
int64_t sx, sy;
openslide_t* slide = NULL;

std::string infile;
std::string outfile;

void openSlide() {
	slide = openslide_open(infile.c_str());						//open the slide file
	if (slide == NULL) {											//if the slide wasn't opened
		throw std::runtime_error("ERROR: unable to open file");
	}
}
void closeSlide() {
	openslide_close(slide);											//close the slide file
}
//this function displays details about the specified image
void dispDetails() {
	std::cout << "OpenSlide version: " << openslide_get_version() << std::endl;
	openSlide();
	std::cout << "Details for slide file: " << infile << std::endl;
	int32_t levels = openslide_get_level_count(slide);
	int64_t w, h;
	std::cout << "level sizes (in pixels):" << std::endl;
	std::cout << "-------------------------------------" << std::endl;
	for (int32_t l = 0; l < levels; l++) {
		std::cout << "level " << l;
		openslide_get_level_dimensions(slide, l, &w, &h);
		std::cout << " [" << w << " x " << h << "]" << std::endl;
	}
	closeSlide();
}

void addArguments() {
	args.add("help", "prints this help");
	args.add("level", "specify the level to output", "", "integer value between 0 and max");
	args.add("region", "region to save", "", "x-pos y-pos x-size y-size");
}

void readArguments() {

	if (args.nargs() > 0) infile = args.arg(0);						//store the file name

	if (args.nargs() > 1) outfile = args.arg(1);					//store the output file name

	if (args["level"]) {
		level = args["level"].as_int();								//store the desired level to extract
	}
	else {															//if the desired level isn't set, default to the smallest resolution image
		openSlide();
		int32_t levels = openslide_get_level_count(slide);
		level = levels - 1;
		closeSlide();
	}
	if (args["region"]) {
		if (args["region"].nargs() == 4) {
			x = args["region"].as_int(0);
			y = args["region"].as_int(1);
			sx = args["region"].as_int(2);
			sy = args["region"].as_int(3);
		}
		else {
			throw std::runtime_error("ERROR: --region requires 4 parameters");
		}
	}
	else {
		openSlide();
		openslide_get_level_dimensions(slide, level, &sx, &sy);
		closeSlide();
	}
}

int main(int argc, char** argv) {
	addArguments();
	args.parse(argc, argv);
	readArguments();
	if (args.nargs() == 0 || args["help"]) {	//if the user requests help or doesn't do anything, show usage
		std::cout << "OpenSlide version: " << openslide_get_version() << std::endl;
		std::cout << "Usage----------------" << std::endl;
		std::cout << "save the full image at the lowest resolution:  slideconvert slidefile.ndpi output.bmp" << std::endl;
		std::cout << "save the level-3 (3x downsampling) image:      slideconvert slidefile.ndpi output.bmp --level 3" << std::endl;
		std::cout << "save a 1024x1024 region at full-resolution:    slideconvert slidefile.ndpi output.bmp --level 0 --region 10000 15000 1024 1024" << std::endl;
		std::cout << args.str();				//if no arguments are provided, show usage
		return 0;
	}
	else if (args.nargs() == 1) {				//if one argument is provided, display file information
		dispDetails();
		return 0;
	}
	else if (args.nargs() == 2) {				//if two arguments are provided, save the specified region
		openSlide();
		cv::Mat I(sy, sx, CV_8UC4);				//allocate an OpenCV image array
		openslide_read_region(slide, (uint32_t*)I.data, x, y, level, sx, sy);
		cv::imwrite(outfile, I);
		closeSlide();
	}
}