ImageInput * ImageInput::open (const std::string &filename, const ImageSpec *config) { if (config == NULL) { // Without config, this is really just a call to create-with-open. return ImageInput::create (filename, true, std::string()); } // With config, create without open, then try to open with config. ImageInput *in = ImageInput::create (filename, false, std::string()); if (! in) return NULL; // create() failed ImageSpec newspec; if (in->open (filename, newspec, *config)) return in; // creted fine, opened fine, return it // The open failed. Transfer the error from 'in' to the global OIIO // error, delete the ImageInput we allocated, and return NULL. std::string err = in->geterror(); if (err.size()) pvt::error ("%s", err.c_str()); delete in; return NULL; }
static bool is_float_image(const string& filename) { ImageInput *in = ImageInput::create(filename); bool is_float = false; 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; for(size_t channel = 0; channel < spec.channelformats.size(); channel++) { if(spec.channelformats[channel].basesize() > 1) is_float = true; } in->close(); } delete in; } return is_float; }
void lux::readOIIOImage( const char* fname, Image& img ) { int xres, yres, channels; ImageInput *in = ImageInput::create (fname); if (! in) {return;} ImageSpec spec; in->open (fname, spec); xres = spec.width; yres = spec.height; channels = spec.nchannels; float* pixels = new float[xres*yres*channels]; in->read_image (TypeDesc::FLOAT, pixels); img.reset( xres, yres, channels ); long index = 0; for( int j=0;j<yres;j++) { for( int i=0;i<xres;i++ ) { for( int c=0;c<channels;c++ ) { img.value(i,img.Height() - j - 1,c) = pixels[index++]; } } } in->close (); delete in; delete[] pixels; }
void RawInput::read_tiff_metadata (const std::string &filename) { // Many of these raw formats look just like TIFF files, and we can use // that to extract a bunch of extra Exif metadata and thumbnail. ImageInput *in = ImageInput::create ("tiff"); if (! in) { (void) OIIO::geterror(); // eat the error return; } ImageSpec newspec; bool ok = in->open (filename, newspec); if (ok) { // Transfer "Exif:" metadata to the raw spec. for (ParamValueList::const_iterator p = newspec.extra_attribs.begin(); p != newspec.extra_attribs.end(); ++p) { if (Strutil::istarts_with (p->name().c_str(), "Exif:")) { m_spec.attribute (p->name().c_str(), p->type(), p->data()); } } } in->close (); delete in; }
static bool is_float_image(const string& filename) { ImageInput *in = ImageInput::create(filename); bool is_float = false; if(in) { ImageSpec spec; if(in->open(filename, spec)) { /* check the main format, and channel formats; if any are non-integer, we'll need a float texture slot */ if(spec.format == TypeDesc::HALF || spec.format == TypeDesc::FLOAT || spec.format == TypeDesc::DOUBLE) { is_float = true; } for(size_t channel = 0; channel < spec.channelformats.size(); channel++) { if(spec.channelformats[channel] == TypeDesc::HALF || spec.channelformats[channel] == TypeDesc::FLOAT || spec.channelformats[channel] == TypeDesc::DOUBLE) { is_float = true; } } in->close(); } delete in; } return is_float; }
void readOIIOImage( const char* fname, float* img ) { int xres, yres, channels; ImageInput *in = ImageInput::create (fname); if (! in) {return;} ImageSpec spec; in->open (fname, spec); xres = spec.width; yres = spec.height; channels = spec.nchannels; float* pixels = new float[xres*yres*channels]; in->read_image (TypeDesc::FLOAT, pixels); long index = 0; for( int j=0;j<yres;j++) { for( int i=0;i<xres;i++ ) { for( int c=0;c<channels;c++ ) { img[ (i + xres*(yres - j - 1))*channels + c ] = pixels[index++]; } } } in->close (); delete in; }
void lux::readOIIOImage( const char* fname, Image& img, map<string,string>& labels ) { int xres, yres, channels; ImageInput *in = ImageInput::create (fname); if (! in) {return;} ImageSpec spec; in->open (fname, spec); xres = spec.width; yres = spec.height; channels = spec.nchannels; float* pixels = new float[xres*yres*channels]; in->read_image (TypeDesc::FLOAT, pixels); img.reset( xres, yres, channels ); long index = 0; for( int j=0;j<yres;j++) { for( int i=0;i<xres;i++ ) { for( int c=0;c<channels;c++ ) { img.value(i,img.Height() - j - 1,c) = pixels[index++]; } } } for( size_t i=0;i<spec.extra_attribs.size();i++) { const ParamValue& p = spec.extra_attribs[i]; string name = p.name().c_str(); string value = spec.metadata_val ( p, true); labels[name] = value; } in->close (); delete in; delete[] pixels; }
ImageInput * ImageInput::create (const std::string &filename, bool do_open, const std::string &plugin_searchpath) { if (filename.empty()) { // Can't even guess if no filename given pvt::error ("ImageInput::create() called with no filename"); return NULL; } // Extract the file extension from the filename (without the leading dot) std::string format = Filesystem::extension (filename, false); if (format.empty()) { // If the file had no extension, maybe it was itself the format name format = filename; } ImageInput::Creator create_function = NULL; { // scope the lock: recursive_lock_guard lock (imageio_mutex); // Ensure thread safety // See if it's already in the table. If not, scan all plugins we can // find to populate the table. Strutil::to_lower (format); InputPluginMap::const_iterator found = input_formats.find (format); if (found == input_formats.end()) { catalog_all_plugins (plugin_searchpath.size() ? plugin_searchpath : pvt::plugin_searchpath.string()); found = input_formats.find (format); } if (found != input_formats.end()) create_function = found->second; } // Remember which prototypes we've already tried, so we don't double dip. std::vector<ImageInput::Creator> formats_tried; std::string specific_error; if (create_function) { if (filename != format) { // If given a full filename, double-check that our guess // based on the extension actually works. You never know // when somebody will have an incorrectly-named file, let's // deal with it robustly. formats_tried.push_back (create_function); ImageInput *in = (ImageInput *)create_function(); if (! do_open && in && in->valid_file(filename)) { // Special case: we don't need to return the file // already opened, and this ImageInput says that the // file is the right type. return in; } ImageSpec tmpspec; bool ok = in && in->open (filename, tmpspec); if (ok) { // It worked if (! do_open) in->close (); return in; } else { // Oops, it failed. Apparently, this file can't be // opened with this II. Clear create_function to force // the code below to check every plugin we know. create_function = NULL; if (in) specific_error = in->geterror(); } delete in; } } if (! create_function) { // If a plugin can't be found that was explicitly designated for // this extension, then just try every one we find and see if // any will open the file. Pass it a configuration request that // includes a "nowait" option so that it returns immediately if // it's a plugin that might wait for an event, like a socket that // doesn't yet exist). ImageSpec config; config.attribute ("nowait", (int)1); recursive_lock_guard lock (imageio_mutex); // Ensure thread safety for (InputPluginMap::const_iterator plugin = input_formats.begin(); plugin != input_formats.end(); ++plugin) { // If we already tried this create function, don't do it again if (std::find (formats_tried.begin(), formats_tried.end(), plugin->second) != formats_tried.end()) continue; formats_tried.push_back (plugin->second); // remember ImageSpec tmpspec; ImageInput *in = NULL; try { in = plugin->second(); } catch (...) { // Safety in case the ctr throws an exception } if (! in) continue; if (! do_open && ! in->valid_file(filename)) { // Since we didn't need to open it, we just checked whether // it was a valid file, and it's not. Try the next one. delete in; continue; } // We either need to open it, or we already know it appears // to be a file of the right type. bool ok = in->open(filename, tmpspec, config); if (ok) { if (! do_open) in->close (); return in; } delete in; } } if (create_function == NULL) { recursive_lock_guard lock (imageio_mutex); // Ensure thread safety if (input_formats.empty()) { // This error is so fundamental, we echo it to stderr in // case the app is too dumb to do so. const char *msg = "ImageInput::create() could not find any ImageInput plugins!\n" " Perhaps you need to set OIIO_LIBRARY_PATH.\n"; fprintf (stderr, "%s", msg); pvt::error ("%s", msg); } else if (! specific_error.empty()) { // Pass along any specific error message we got from our // best guess of the format. pvt::error ("%s", specific_error); } else if (Filesystem::exists (filename)) pvt::error ("OpenImageIO could not find a format reader for \"%s\". " "Is it a file format that OpenImageIO doesn't know about?\n", filename.c_str()); else pvt::error ("Image \"%s\" does not exist. Also, it is not the name of an image format that OpenImageIO recognizes.\n", filename.c_str()); return NULL; } return (ImageInput *) create_function(); }
bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_img) { if(img->filename == "") return false; /* load image from file through OIIO */ ImageInput *in = ImageInput::create(img->filename); if(!in) return false; ImageSpec spec; if(!in->open(img->filename, spec)) { delete in; return false; } /* we only handle certain number of components */ int width = spec.width; int height = spec.height; int components = spec.nchannels; if(!(components == 1 || components == 3 || components == 4)) { in->close(); delete in; return false; } printf("loading float image: '%s' %dx%d\n", img->filename.c_str(), width, height); /* read RGBA pixels */ float *pixels = (float*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(float); in->read_image(TypeDesc::FLOAT, (uchar*)pixels + (height-1)*scanlinesize, AutoStride, -scanlinesize, AutoStride); in->close(); delete in; if(components == 3) { for(int i = width*height-1; i >= 0; 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) { for(int i = width*height-1; i >= 0; 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]; } } return true; }
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; }
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; } }
struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE]) { ImageInput *in = NULL; struct ImBuf *ibuf = NULL; int width, height, components; bool is_float, is_alpha; TypeDesc typedesc; int basesize; char file_colorspace[IM_MAX_SPACE]; /* load image from file through OIIO */ if (imb_is_a_photoshop(filename) == 0) return (NULL); colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); in = ImageInput::create(filename); if (!in) { std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl << OpenImageIO::geterror() << std::endl; return NULL; } ImageSpec spec, config; config.attribute("oiio:UnassociatedAlpha", (int) 1); if (!in->open(filename, spec, config)) { std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl << in->geterror() << std::endl; delete in; return NULL; } string ics = spec.get_string_attribute("oiio:ColorSpace"); BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE); /* only use colorspaces exis */ if (colormanage_colorspace_get_named(file_colorspace)) strcpy(colorspace, file_colorspace); else std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace << "\") not supported in existent OCIO configuration file. Fallback " << "to system default colorspace (\"" << colorspace << "\")." << std::endl; width = spec.width; height = spec.height; components = spec.nchannels; is_alpha = spec.alpha_channel != -1; basesize = spec.format.basesize(); is_float = basesize > 1; /* we only handle certain number of components */ if (!(components >= 1 && components <= 4)) { if (in) { in->close(); delete in; } return NULL; } if (is_float) ibuf = imb_oiio_load_image_float(in, width, height, components, flags, is_alpha); else ibuf = imb_oiio_load_image(in, width, height, components, flags, is_alpha); if (in) { in->close(); delete in; } if (!ibuf) return NULL; /* ImBuf always needs 4 channels */ ibuf->ftype = IMB_FTYPE_PSD; ibuf->channels = 4; ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize; try { return ibuf; } catch (const std::exception &exc) { std::cerr << exc.what() << std::endl; if (ibuf) IMB_freeImBuf(ibuf); return NULL; } }
bool OiioTool::print_info (const std::string &filename, const print_info_options &opt, long long &totalsize, std::string &error) { error.clear(); ImageInput *input = ImageInput::create (filename.c_str(), "" /* searchpath */); if (! input) { error = geterror(); if (error.empty()) error = Strutil::format ("Could not open \"%s\"", filename.c_str()); return false; } ImageSpec spec; if (! input->open (filename.c_str(), spec)) { error = input->geterror(); if (error.empty()) error = Strutil::format ("Could not open \"%s\"", filename.c_str()); delete input; return false; } boost::regex field_re; if (! opt.metamatch.empty()) field_re.assign (opt.metamatch, boost::regex::extended | boost::regex_constants::icase); bool printed = 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 { printf ("%s", spec.format.c_str()); } 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"); printed = true; } 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); } input->close (); delete input; return true; }
bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) { if(img->filename == "") return false; fprintf(stderr, "image input disabled\n"); #if 0 /* load image from file through OIIO */ ImageInput *in = ImageInput::create(img->filename); if(!in) return false; ImageSpec spec; if(!in->open(img->filename, spec)) { delete in; return false; } /* we only handle certain number of components */ int width = spec.width; int height = spec.height; int components = spec.nchannels; if(!(components == 1 || components == 3 || components == 4)) { in->close(); delete in; return false; } /* read RGBA pixels */ uchar *pixels = (uchar*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(uchar); in->read_image(TypeDesc::UINT8, (uchar*)pixels + (height-1)*scanlinesize, AutoStride, -scanlinesize, AutoStride); in->close(); delete in; if(components == 3) { for(int i = width*height-1; i >= 0; i--) { pixels[i*4+3] = 255; 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) { for(int i = width*height-1; i >= 0; i--) { pixels[i*4+3] = 255; pixels[i*4+2] = pixels[i]; pixels[i*4+1] = pixels[i]; pixels[i*4+0] = pixels[i]; } } return true; #endif return false; }