Пример #1
0
bool
OiioTool::print_info (const std::string &filename,
                      const print_info_options &opt,
                      long long &totalsize,
                      std::string &error)
{
    error.clear();
    ImageInput *input = ImageInput::open (filename.c_str());
    if (! input) {
        error = geterror();
        if (error.empty())
            error = Strutil::format ("Could not open \"%s\"", filename.c_str());
        return false;
    }
    ImageSpec spec = input->spec();

    boost::regex field_re;
    boost::regex field_exclude_re;
    if (! opt.metamatch.empty()) {
        try {
            field_re.assign (opt.metamatch,
                             boost::regex::extended | boost::regex_constants::icase);
        } catch (const std::exception &e) {
            error = Strutil::format ("Regex error '%s' on metamatch regex \"%s\"",
                                     e.what(), opt.metamatch);
            return false;
        }
    }
    if (! opt.nometamatch.empty()) {
        try {
            field_exclude_re.assign (opt.nometamatch,
                                     boost::regex::extended | boost::regex_constants::icase);
        } catch (const std::exception &e) {
            error = Strutil::format ("Regex error '%s' on metamatch regex \"%s\"",
                                     e.what(), opt.nometamatch);
            return false;
        }
    }

    int padlen = std::max (0, (int)opt.namefieldlength - (int)filename.length());
    std::string padding (padlen, ' ');

    // checking how many subimages and mipmap levels are stored in the file
    int num_of_subimages = 1;
    bool any_mipmapping = false;
    std::vector<int> num_of_miplevels;
    {
        int nmip = 1;
        while (input->seek_subimage (input->current_subimage(), nmip, spec)) {
            ++nmip;
            any_mipmapping = true;
        }
        num_of_miplevels.push_back (nmip);
    }
    while (input->seek_subimage (num_of_subimages, 0, spec)) {
        // maybe we should do this more gently?
        ++num_of_subimages;
        int nmip = 1;
        while (input->seek_subimage (input->current_subimage(), nmip, spec)) {
            ++nmip;
            any_mipmapping = true;
        }
        num_of_miplevels.push_back (nmip);
    }
    input->seek_subimage (0, 0, spec);  // re-seek to the first

    if (opt.metamatch.empty() ||
            boost::regex_search ("resolution, width, height, depth, channels", field_re)) {
        printf ("%s%s : %4d x %4d", filename.c_str(), padding.c_str(),
                spec.width, spec.height);
        if (spec.depth > 1)
            printf (" x %4d", spec.depth);
        printf (", %d channel, ", spec.nchannels);
        if (spec.channelformats.size()) {
            for (size_t c = 0;  c < spec.channelformats.size();  ++c)
                printf ("%s%s", c ? "/" : "",
                        spec.channelformats[c].c_str());
        } else {
            int bits = spec.get_int_attribute ("oiio:BitsPerSample", 0);
            printf ("%s", extended_format_name(spec.format, bits));
        }
        if (spec.depth > 1)
            printf (" volume");
        printf (" %s", input->format_name());
        if (opt.sum) {
            imagesize_t imagebytes = spec.image_bytes (true);
            totalsize += imagebytes;
            printf (" (%.2f MB)", (float)imagebytes / (1024.0*1024.0));
        }
        // we print info about how many subimages are stored in file
        // only when we have more then one subimage
        if ( ! opt.verbose && num_of_subimages != 1)
            printf (" (%d subimages%s)", num_of_subimages,
                    any_mipmapping ? " +mipmap)" : "");
        if (! opt.verbose && num_of_subimages == 1 && any_mipmapping)
            printf (" (+mipmap)");
        printf ("\n");
    }

    if (opt.verbose && num_of_subimages != 1) {
        // info about num of subimages and their resolutions
        printf ("    %d subimages: ", num_of_subimages);
        for (int i = 0; i < num_of_subimages; ++i) {
            input->seek_subimage (i, 0, spec);
            if (spec.depth > 1)
                printf ("%dx%dx%d ", spec.width, spec.height, spec.depth);
            else
                printf ("%dx%d ", spec.width, spec.height);
        }
        printf ("\n");
    }

    // if the '-a' flag is not set we print info
    // about first subimage only
    if ( ! opt.subimages)
        num_of_subimages = 1;
    for (int i = 0; i < num_of_subimages; ++i) {
        print_info_subimage (i, num_of_subimages, spec, input,
                             filename, opt, field_re, field_exclude_re);
    }

    input->close ();
    delete input;
    return true;
}
Пример #2
0
bool ImageManager::get_image_metadata(const string& filename,
                                      void *builtin_data,
                                      ImageMetaData& metadata)
{
	memset(&metadata, 0, sizeof(metadata));

	if(builtin_data) {
		if(builtin_image_info_cb) {
			builtin_image_info_cb(filename, builtin_data, metadata);
		}
		else {
			return false;
		}

		if(metadata.is_float) {
			metadata.is_linear = true;
			metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
		}
		else {
			metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
		}

		return true;
	}

	/* Perform preliminary checks, with meaningful logging. */
	if(!path_exists(filename)) {
		VLOG(1) << "File '" << filename << "' does not exist.";
		return false;
	}
	if(path_is_directory(filename)) {
		VLOG(1) << "File '" << filename << "' is a directory, can't use as image.";
		return false;
	}

	ImageInput *in = ImageInput::create(filename);

	if(!in) {
		return false;
	}

	ImageSpec spec;
	if(!in->open(filename, spec)) {
		delete in;
		return false;
	}

	metadata.width = spec.width;
	metadata.height = spec.height;
	metadata.depth = spec.depth;

	/* check the main format, and channel formats;
	 * if any take up more than one byte, we'll need a float texture slot */
	if(spec.format.basesize() > 1) {
		metadata.is_float = true;
		metadata.is_linear = true;
	}

	for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
		if(spec.channelformats[channel].basesize() > 1) {
			metadata.is_float = true;
			metadata.is_linear = true;
		}
	}

	/* check if it's half float */
	if(spec.format == TypeDesc::HALF)
		metadata.is_half = true;

	/* basic color space detection, not great but better than nothing
	 * before we do OpenColorIO integration */
	if(metadata.is_float) {
		string colorspace = spec.get_string_attribute("oiio:ColorSpace");

		metadata.is_linear = !(colorspace == "sRGB" ||
							   colorspace == "GammaCorrected" ||
							   (colorspace == "" &&
								   (strcmp(in->format_name(), "png") == 0 ||
									strcmp(in->format_name(), "tiff") == 0 ||
									strcmp(in->format_name(), "dpx") == 0 ||
									strcmp(in->format_name(), "jpeg2000") == 0)));
	}
	else {
		metadata.is_linear = false;
	}

	/* set type and channels */
	metadata.channels = spec.nchannels;

	if(metadata.is_half) {
		metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
	}
	else if(metadata.is_float) {
		metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
	}
	else {
		metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
	}

	in->close();
	delete in;

	return true;
}
Пример #3
0
bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
{
	ImageInput *in = NULL;
	int width, height, depth, components;

	if(!file_load_image_generic(img, &in, width, height, depth, components))
		return false;

	/* read RGBA pixels */
	float *pixels = (float*)tex_img.resize(width, height, depth);
	if(pixels == NULL) {
		return false;
	}
	bool cmyk = false;

	if(in) {
		float *readpixels = pixels;
		vector<float> tmppixels;

		if(components > 4) {
			tmppixels.resize(((size_t)width)*height*components);
			readpixels = &tmppixels[0];
		}

		if(depth <= 1) {
			size_t scanlinesize = ((size_t)width)*components*sizeof(float);
			in->read_image(TypeDesc::FLOAT,
			               (uchar*)readpixels + (height-1)*scanlinesize,
			               AutoStride,
			               -scanlinesize,
			               AutoStride);
		}
		else {
			in->read_image(TypeDesc::FLOAT, (uchar*)readpixels);
		}

		if(components > 4) {
			size_t dimensions = ((size_t)width)*height;
			for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
				pixels[i*4+3] = tmppixels[i*components+3];
				pixels[i*4+2] = tmppixels[i*components+2];
				pixels[i*4+1] = tmppixels[i*components+1];
				pixels[i*4+0] = tmppixels[i*components+0];
			}

			tmppixels.clear();
		}

		cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;

		in->close();
		delete in;
	}
	else {
		builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
	}

	/* Check if we actually have a float4 slot, in case components == 1, but device
	 * doesn't support single channel textures. */
	if(type == IMAGE_DATA_TYPE_FLOAT4) {
		size_t num_pixels = ((size_t)width) * height * depth;
		if(cmyk) {
			/* CMYK */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = 255;
				pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
				pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
				pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
			}
		}
		else if(components == 2) {
			/* grayscale + alpha */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = pixels[i*2+1];
				pixels[i*4+2] = pixels[i*2+0];
				pixels[i*4+1] = pixels[i*2+0];
				pixels[i*4+0] = pixels[i*2+0];
			}
		}
		else if(components == 3) {
			/* RGB */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = 1.0f;
				pixels[i*4+2] = pixels[i*3+2];
				pixels[i*4+1] = pixels[i*3+1];
				pixels[i*4+0] = pixels[i*3+0];
			}
		}
		else if(components == 1) {
			/* grayscale */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = 1.0f;
				pixels[i*4+2] = pixels[i];
				pixels[i*4+1] = pixels[i];
				pixels[i*4+0] = pixels[i];
			}
		}

		if(img->use_alpha == false) {
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = 1.0f;
			}
		}
	}

	return true;
}
Пример #4
0
bool ImageManager::file_load_image(Image *img,
                                   ImageDataType type,
                                   int texture_limit,
                                   device_vector<DeviceType>& tex_img)
{
	const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1;
	ImageInput *in = NULL;
	int width, height, depth, components;
	if(!file_load_image_generic(img, &in, width, height, depth, components)) {
		return false;
	}
	/* Read RGBA pixels. */
	vector<StorageType> pixels_storage;
	StorageType *pixels;
	const size_t max_size = max(max(width, height), depth);
	if(max_size == 0) {
		/* Don't bother with invalid images. */
		return false;
	}
	if(texture_limit > 0 && max_size > texture_limit) {
		pixels_storage.resize(((size_t)width)*height*depth*4);
		pixels = &pixels_storage[0];
	}
	else {
		thread_scoped_lock device_lock(device_mutex);
		pixels = (StorageType*)tex_img.alloc(width, height, depth);
	}
	if(pixels == NULL) {
		/* Could be that we've run out of memory. */
		return false;
	}
	bool cmyk = false;
	const size_t num_pixels = ((size_t)width) * height * depth;
	if(in) {
		StorageType *readpixels = pixels;
		vector<StorageType> tmppixels;
		if(components > 4) {
			tmppixels.resize(((size_t)width)*height*components);
			readpixels = &tmppixels[0];
		}
		if(depth <= 1) {
			size_t scanlinesize = ((size_t)width)*components*sizeof(StorageType);
			in->read_image(FileFormat,
			               (uchar*)readpixels + (height-1)*scanlinesize,
			               AutoStride,
			               -scanlinesize,
			               AutoStride);
		}
		else {
			in->read_image(FileFormat, (uchar*)readpixels);
		}
		if(components > 4) {
			size_t dimensions = ((size_t)width)*height;
			for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
				pixels[i*4+3] = tmppixels[i*components+3];
				pixels[i*4+2] = tmppixels[i*components+2];
				pixels[i*4+1] = tmppixels[i*components+1];
				pixels[i*4+0] = tmppixels[i*components+0];
			}
			tmppixels.clear();
		}
		cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
		in->close();
		delete in;
	}
	else {
		if(FileFormat == TypeDesc::FLOAT) {
			builtin_image_float_pixels_cb(img->filename,
			                              img->builtin_data,
			                              (float*)&pixels[0],
			                              num_pixels * components,
			                              img->builtin_free_cache);
		}
		else if(FileFormat == TypeDesc::UINT8) {
			builtin_image_pixels_cb(img->filename,
			                        img->builtin_data,
			                        (uchar*)&pixels[0],
			                        num_pixels * components,
			                        img->builtin_free_cache);
		}
		else {
			/* TODO(dingto): Support half for ImBuf. */
		}
	}
	/* Check if we actually have a float4 slot, in case components == 1,
	 * but device doesn't support single channel textures.
	 */
	bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 ||
	                type == IMAGE_DATA_TYPE_HALF4 ||
	                type == IMAGE_DATA_TYPE_BYTE4);
	if(is_rgba) {
		if(cmyk) {
			/* CMYK */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255;
				pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255;
				pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255;
				pixels[i*4+3] = alpha_one;
			}
		}
		else if(components == 2) {
			/* grayscale + alpha */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = pixels[i*2+1];
				pixels[i*4+2] = pixels[i*2+0];
				pixels[i*4+1] = pixels[i*2+0];
				pixels[i*4+0] = pixels[i*2+0];
			}
		}
		else if(components == 3) {
			/* RGB */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = alpha_one;
				pixels[i*4+2] = pixels[i*3+2];
				pixels[i*4+1] = pixels[i*3+1];
				pixels[i*4+0] = pixels[i*3+0];
			}
		}
		else if(components == 1) {
			/* grayscale */
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = alpha_one;
				pixels[i*4+2] = pixels[i];
				pixels[i*4+1] = pixels[i];
				pixels[i*4+0] = pixels[i];
			}
		}
		if(img->use_alpha == false) {
			for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
				pixels[i*4+3] = alpha_one;
			}
		}
	}
	/* Make sure we don't have buggy values. */
	if(FileFormat == TypeDesc::FLOAT) {
		/* For RGBA buffers we put all channels to 0 if either of them is not
		 * finite. This way we avoid possible artifacts caused by fully changed
		 * hue.
		 */
		if(is_rgba) {
			for(size_t i = 0; i < num_pixels; i += 4) {
				StorageType *pixel = &pixels[i*4];
				if(!isfinite(pixel[0]) ||
				   !isfinite(pixel[1]) ||
				   !isfinite(pixel[2]) ||
				   !isfinite(pixel[3]))
				{
					pixel[0] = 0;
					pixel[1] = 0;
					pixel[2] = 0;
					pixel[3] = 0;
				}
			}
		}
		else {
			for(size_t i = 0; i < num_pixels; ++i) {
				StorageType *pixel = &pixels[i];
				if(!isfinite(pixel[0])) {
					pixel[0] = 0;
				}
			}
		}
	}
	/* Scale image down if needed. */
	if(pixels_storage.size() > 0) {
		float scale_factor = 1.0f;
		while(max_size * scale_factor > texture_limit) {
			scale_factor *= 0.5f;
		}
		VLOG(1) << "Scaling image " << img->filename
		        << " by a factor of " << scale_factor << ".";
		vector<StorageType> scaled_pixels;
		size_t scaled_width, scaled_height, scaled_depth;
		util_image_resize_pixels(pixels_storage,
		                         width, height, depth,
		                         is_rgba ? 4 : 1,
		                         scale_factor,
		                         &scaled_pixels,
		                         &scaled_width, &scaled_height, &scaled_depth);

		StorageType *texture_pixels;

		{
			thread_scoped_lock device_lock(device_mutex);
			texture_pixels = (StorageType*)tex_img.alloc(scaled_width,
			                                             scaled_height,
			                                             scaled_depth);
		}

		memcpy(texture_pixels,
		       &scaled_pixels[0],
		       scaled_pixels.size() * sizeof(StorageType));
	}
	return true;
}
Пример #5
0
ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filename,
                                                             void *builtin_data,
                                                             bool& is_linear)
{
	bool is_float = false, is_half = false;
	is_linear = false;
	int channels = 4;

	if(builtin_data) {
		if(builtin_image_info_cb) {
			int width, height, depth;
			builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels);
		}

		if(is_float) {
			is_linear = true;
			return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
		}
		else {
			return (channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
		}
	}

	ImageInput *in = ImageInput::create(filename);

	if(in) {
		ImageSpec spec;

		if(in->open(filename, spec)) {
			/* check the main format, and channel formats;
			 * if any take up more than one byte, we'll need a float texture slot */
			if(spec.format.basesize() > 1) {
				is_float = true;
				is_linear = true;
			}

			for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
				if(spec.channelformats[channel].basesize() > 1) {
					is_float = true;
					is_linear = true;
				}
			}

			/* check if it's half float */
			if(spec.format == TypeDesc::HALF)
				is_half = true;

			channels = spec.nchannels;

			/* basic color space detection, not great but better than nothing
			 * before we do OpenColorIO integration */
			if(is_float) {
				string colorspace = spec.get_string_attribute("oiio:ColorSpace");

				is_linear = !(colorspace == "sRGB" ||
				              colorspace == "GammaCorrected" ||
				              (colorspace == "" &&
				                  (strcmp(in->format_name(), "png") == 0 ||
				                   strcmp(in->format_name(), "tiff") == 0 ||
				                   strcmp(in->format_name(), "dpx") == 0 ||
				                   strcmp(in->format_name(), "jpeg2000") == 0)));
			}
			else {
				is_linear = false;
			}

			in->close();
		}

		delete in;
	}

	if(is_half) {
		return (channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
	}
	else if(is_float) {
		return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
	}
	else {
		return (channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
	}
}