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; }
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 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 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 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 void time_read_image () { ImageInput *in = ImageInput::open (input_filename.c_str()); ASSERT (in); in->read_image (TypeDesc::TypeFloat, &buffer[0]); in->close (); delete in; }
static void time_read_64_scanlines_at_a_time () { ImageInput *in = ImageInput::open (input_filename.c_str()); ASSERT (in); const ImageSpec &spec (in->spec()); size_t pixelsize = spec.nchannels * sizeof(float); imagesize_t scanlinesize = spec.width * pixelsize; for (int y = 0; y < spec.height; y += 64) { in->read_scanlines (y+spec.y, std::min(y+spec.y+64, spec.y+spec.height), 0, TypeDesc::TypeFloat, &buffer[scanlinesize*y]); } in->close (); delete in; }
/** * @brief Read in images * @details Read foregournd and background images into program. * * @param image Image name to read in. */ void readImage(char *image) { // Open image input ImageInput *in = ImageInput::open(image); // Error handeling if (!in) { printf("Error reading image: %s\n", geterror().c_str()); exit(EXIT_FAILURE); } // Get input spec const ImageSpec &spec = in->spec(); // Get image details originalWidth = spec.width; originalHeight = spec.height; channels = spec.nchannels; // Init the global copy of the pixels // Read in the pixels and close the file oiioPixels.resize(originalWidth*originalHeight*channels*sizeof(float)); in->read_image(TypeDesc::FLOAT, &oiioPixels[0]); in->close(); delete in; // Initalize 2d array pixels = new rgba_pixel*[originalHeight]; pixels[0] = new rgba_pixel[originalWidth*originalHeight]; for (int i=1; i<originalHeight; i++) { pixels[i] = pixels[i-1] + originalWidth; } // Transfer into custom data structure for (int row = 0; row < originalHeight; row++) for (int col = 0; col < originalWidth; col++){ pixels[row][col].r = oiioPixels[(row*originalWidth+col)*channels + 0]; pixels[row][col].g = oiioPixels[(row*originalWidth+col)*channels + 1]; pixels[row][col].b = oiioPixels[(row*originalWidth+col)*channels + 2]; if(channels == 4) pixels[row][col].a = oiioPixels[(row*originalWidth+col)*channels + 3]; else pixels[row][col].a = 1.0; } }
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; }
//TODO go over this function to see if it can be refactored void TileCache::addSource( const std::string fileName ) { OIIO_NAMESPACE_USING; ImageInput *image = nullptr; if( (image = ImageInput::open( fileName )) ){ image->close(); delete image; _nTiles++; map.push_back( nTiles ); fileNames.push_back( fileName ); return; } SMT *smt = nullptr; if( (smt = SMT::open( fileName )) ){ if(! smt->nTiles ) return; _nTiles += smt->nTiles; map.push_back( nTiles ); fileNames.push_back( fileName ); delete smt; return; } SMF *smf = nullptr; if( (smf = SMF::open( fileName )) ){ // get the fileNames here auto smtList = smf->getSMTList(); for( auto i : smtList ) addSource( i.second ); delete smf; return; } LOG(ERROR) << "unrecognised format: " << fileName; }
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; }
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; }
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; }
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; }
bool ImageManager::file_load_half_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 */ half *pixels = (half*)tex_img.resize(width, height, depth); if(pixels == NULL) { return false; } if(in) { half *readpixels = pixels; vector<half> 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(half); in->read_image(TypeDesc::HALF, (uchar*)readpixels + (height-1)*scanlinesize, AutoStride, -scanlinesize, AutoStride); } else { in->read_image(TypeDesc::HALF, (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(); } in->close(); delete in; } #if 0 /* TODO(dingto): Support half for ImBuf. */ else { builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels); } #endif /* Check if we actually have a half4 slot, in case components == 1, but device * doesn't support single channel textures. */ if(type == IMAGE_DATA_TYPE_HALF4) { size_t num_pixels = ((size_t)width) * height * depth; 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; }
static void LoadTexture(std::string const& filename, Scene::Texture& texture, std::vector<std::unique_ptr<char[]> >& data) { OIIO_NAMESPACE_USING ImageInput* input = ImageInput::open(filename); if (!input) { throw std::runtime_error("Can't load " + filename + " image"); } ImageSpec const& spec = input->spec(); texture.w = spec.width; texture.h = spec.height; texture.d = spec.depth; texture.fmt = GetTextureForemat(spec); // Save old size for reading offset texture.dataoffset = (int)data.size(); if (texture.fmt == Scene::RGBA8) { texture.size = spec.width * spec.height * spec.depth * 4; // Resize storage std::unique_ptr<char[]> texturedata(new char[spec.width * spec.height * spec.depth * 4]); // Read data to storage input->read_image(TypeDesc::UINT8, texturedata.get(), sizeof(char) * 4); // Close handle input->close(); // Add to texture pool data.push_back(std::move(texturedata)); } else if (texture.fmt == Scene::RGBA16) { texture.size = spec.width * spec.height * spec.depth * sizeof(float) * 2; // Resize storage std::unique_ptr<char[]> texturedata(new char[spec.width * spec.height * spec.depth * sizeof(float) * 2]); // Read data to storage input->read_image(TypeDesc::HALF, texturedata.get(), sizeof(float) * 2); // Close handle input->close(); // Add to texture pool data.push_back(std::move(texturedata)); } else { texture.size = spec.width * spec.height * spec.depth * sizeof(float3); // Resize storage std::unique_ptr<char[]> texturedata(new char[spec.width * spec.height * spec.depth * sizeof(float3)]); // Read data to storage input->read_image(TypeDesc::FLOAT, texturedata.get(), sizeof(float3)); // Close handle input->close(); // Add to texture pool data.push_back(std::move(texturedata)); } // Cleanup delete input; }
bool OiioTool::print_info (Oiiotool &ot, const std::string &filename, const print_info_options &opt, long long &totalsize, std::string &error) { using Strutil::format; error.clear(); ImageSpec *config = ot.input_config_set ? &ot.input_config : NULL; ImageInput *input = ImageInput::open (filename.c_str(), config); if (! input) { error = geterror(); if (error.empty()) error = Strutil::format ("Could not open \"%s\"", filename); return false; } ImageSpec spec = input->spec(); ImageSpec::SerialFormat serformat = ImageSpec::SerialText; if (Strutil::iequals (opt.infoformat, "xml")) serformat = ImageSpec::SerialXML; ImageSpec::SerialVerbose verbose = opt.verbose ? ImageSpec::SerialDetailedHuman : ImageSpec::SerialBrief; 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; } } // checking how many subimages and mipmap levels are stored in the file std::vector<int> num_of_miplevels; int num_of_subimages; for (num_of_subimages = 0; input->seek_subimage (num_of_subimages, 0, spec); ++num_of_subimages) { int nmip = 1; while (input->seek_subimage (num_of_subimages, nmip, spec)) ++nmip; num_of_miplevels.push_back (nmip); } for (int current_subimage = 0; current_subimage < num_of_subimages; ++current_subimage) { if ( ! input->seek_subimage (current_subimage, 0, spec) ) break; print_info_subimage (ot, current_subimage, num_of_subimages, num_of_miplevels[current_subimage], spec, input, filename, opt, field_re, field_exclude_re, serformat, verbose); // if the '-a' flag is not set we print info // about first subimage only if ( ! opt.subimages) break; } input->close (); delete input; return true; }
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; }
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 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; }
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; } }
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, 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; }