Example #1
0
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;
}
Example #2
0
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();
}
Example #3
0
static bool
convert_file (const std::string &in_filename, const std::string &out_filename)
{
    if (noclobber && Filesystem::exists(out_filename)) {
        std::cerr << "iconvert ERROR: Output file already exists \""
                  << out_filename << "\"\n";
        return false;
    }

    if (verbose)
        std::cout << "Converting " << in_filename << " to " << out_filename << "\n";

    std::string tempname = out_filename;
    if (tempname == in_filename) {
        tempname = out_filename + ".tmp"
                    + Filesystem::extension (out_filename);
    }

    // Find an ImageIO plugin that can open the input file, and open it.
    ImageInput *in = ImageInput::open (in_filename.c_str());
    if (! in) {
        std::string err = geterror();
        std::cerr << "iconvert ERROR: " 
                  << (err.length() ? err : Strutil::format("Could not open \"%s\"", in_filename))
                  << "\n";
        delete in;
        return false;
    }
    ImageSpec inspec = in->spec();
    std::string metadatatime = inspec.get_string_attribute ("DateTime");

    // Find an ImageIO plugin that can open the output file, and open it
    ImageOutput *out = ImageOutput::create (tempname.c_str());
    if (! out) {
        std::cerr 
            << "iconvert ERROR: Could not find an ImageIO plugin to write \"" 
            << out_filename << "\" :" << geterror() << "\n";
        delete in;
        return false;
    }

    // In order to deal with formats that support subimages, but not
    // subimage appending, we gather them all first.
    std::vector<ImageSpec> subimagespecs;
    if (out->supports("multiimage") && !out->supports("appendsubimage")) {
        ImageCache *imagecache = ImageCache::create ();
        int nsubimages = 0;
        ustring ufilename (in_filename);
        imagecache->get_image_info (ufilename, 0, 0, ustring("subimages"),
                                    TypeDesc::TypeInt, &nsubimages);
        if (nsubimages > 1) {
            subimagespecs.resize (nsubimages);
            for (int i = 0;  i < nsubimages;  ++i) {
                ImageSpec inspec = *imagecache->imagespec (ufilename, i, 0,
                                                           true /*native*/);
                subimagespecs[i] = inspec;
                adjust_spec (in, out, inspec, subimagespecs[i]);
            }
        }
        ImageCache::destroy (imagecache);
    }

    bool ok = true;
    bool mip_to_subimage_warning = false;
    for (int subimage = 0;
           ok && in->seek_subimage(subimage,0,inspec);
           ++subimage) {

        if (subimage > 0 &&  !out->supports ("multiimage")) {
            std::cerr << "iconvert WARNING: " << out->format_name()
                      << " does not support multiple subimages.\n";
            std::cerr << "\tOnly the first subimage has been copied.\n";
            break;  // we're done
        }

        int miplevel = 0;
        do {
            // Copy the spec, with possible change in format
            ImageSpec outspec = inspec;
            bool nocopy = adjust_spec (in, out, inspec, outspec);
        
            if (miplevel > 0) {
                // Moving to next MIP level
                ImageOutput::OpenMode mode;
                if (out->supports ("mipmap"))
                    mode = ImageOutput::AppendMIPLevel;
                else if (out->supports ("multiimage") &&
                         out->supports ("appendsubimage")) {
                    mode = ImageOutput::AppendSubimage; // use if we must
                    if (! mip_to_subimage_warning
                        && strcmp(out->format_name(),"tiff")) {
                        std::cerr << "iconvert WARNING: " << out->format_name()
                                  << " does not support MIPmaps.\n";
                        std::cerr << "\tStoring the MIPmap levels in subimages.\n";
                    }
                    mip_to_subimage_warning = true;
                } else {
                    std::cerr << "iconvert WARNING: " << out->format_name()
                              << " does not support MIPmaps.\n";
                    std::cerr << "\tOnly the first level has been copied.\n";
                    break;  // on to the next subimage
                }
                ok = out->open (tempname.c_str(), outspec, mode);
            } else if (subimage > 0) {
                // Moving to next subimage
                ok = out->open (tempname.c_str(), outspec,
                                ImageOutput::AppendSubimage);
            } else {
                // First time opening
                if (subimagespecs.size())
                    ok = out->open (tempname.c_str(), int(subimagespecs.size()),
                                    &subimagespecs[0]);
                else
                    ok = out->open (tempname.c_str(), outspec, ImageOutput::Create);
            }
            if (! ok) {
                std::string err = out->geterror();
                std::cerr << "iconvert ERROR: " 
                          << (err.length() ? err : Strutil::format("Could not open \"%s\"", out_filename))
                          << "\n";
                ok = false;
                break;
            }

            if (! nocopy) {
                ok = out->copy_image (in);
                if (! ok)
                    std::cerr << "iconvert ERROR copying \"" << in_filename 
                              << "\" to \"" << out_filename << "\" :\n\t" 
                              << out->geterror() << "\n";
            } else {
                // Need to do it by hand for some reason.  Future expansion in which
                // only a subset of channels are copied, or some such.
                std::vector<char> pixels ((size_t)outspec.image_bytes(true));
                ok = in->read_image (outspec.format, &pixels[0]);
                if (! ok) {
                    std::cerr << "iconvert ERROR reading \"" << in_filename 
                              << "\" : " << in->geterror() << "\n";
                } else {
                    ok = out->write_image (outspec.format, &pixels[0]);
                    if (! ok)
                        std::cerr << "iconvert ERROR writing \"" << out_filename 
                                  << "\" : " << out->geterror() << "\n";
                }
            }
        
            ++miplevel;
        } while (ok && in->seek_subimage(subimage,miplevel,inspec));
    }

    out->close ();
    delete out;
    in->close ();
    delete in;

    // Figure out a time for the input file -- either one supplied by
    // the metadata, or the actual time stamp of the input file.
    std::time_t in_time;
    if (metadatatime.empty() ||
           ! DateTime_to_time_t (metadatatime.c_str(), in_time))
        in_time = Filesystem::last_write_time (in_filename);

    if (out_filename != tempname) {
        if (ok) {
            Filesystem::remove (out_filename);
            Filesystem::rename (tempname, out_filename);
        }
        else
            Filesystem::remove (tempname);
    }

    // If user requested, try to adjust the file's modification time to
    // the creation time indicated by the file's DateTime metadata.
    if (ok && adjust_time)
        Filesystem::last_write_time (out_filename, in_time);

    return ok;
}
Example #4
0
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;
	}
}
Example #5
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::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;
}