Image *Read(IStream *file, const Image::ReadOptions& options) { unsigned int width; unsigned int height; Image *image = NULL; // OpenEXR files store linear color values by default, so never convert unless the user overrides // (e.g. to handle a non-compliant file). GammaCurvePtr gamma; if (options.gammacorrect) { if (options.gammaOverride) gamma = TranscodingGammaCurve::Get(options.workingGamma, options.defaultGamma); else gamma = TranscodingGammaCurve::Get(options.workingGamma, NeutralGammaCurve::Get()); } // OpenEXR officially uses premultiplied alpha, so that's the preferred mode to use for the image container unless the user overrides // (e.g. to handle a non-compliant file). bool premul = true; if (options.premultiplyOverride) premul = options.premultiply; // TODO: code this to observe the request for alpha in the input file type. POV_EXR_IStream is(*file); try { RgbaInputFile rif(is); Array2D<Rgba> pixels; Box2i dw = rif.dataWindow(); Image::ImageDataType imagetype = options.itype; width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; pixels.resizeErase(height, width); rif.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); rif.readPixels(dw.min.y, dw.max.y); if(imagetype == Image::Undefined) imagetype = Image::RGBFT_Float; image = Image::Create(width, height, imagetype); image->SetPremultiplied(premul); // set desired storage mode regarding alpha premultiplication for(int row = 0; row < height; row++) { for(int col = 0; col < width; col++) { struct Rgba &rgba = pixels [row][col]; SetEncodedRGBAValue(image, col, row, gamma, (float)rgba.r, (float)rgba.g, (float)rgba.b, (float)rgba.a, premul); } } } catch(const std::exception& e) { throw POV_EXCEPTION(kFileDataErr, e.what()); } return image; }
void readTiled1 (const char fileName[], Array2D<GZ> &pixels, int &width, int &height) { TiledInputFile in (fileName); Box2i dw = in.header().dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; int dx = dw.min.x; int dy = dw.min.y; pixels.resizeErase (height, width); FrameBuffer frameBuffer; frameBuffer.insert ("G", // name Slice (HALF, // type (char *) &pixels[-dy][-dx].g, // base sizeof (pixels[0][0]) * 1, // xStride sizeof (pixels[0][0]) * width)); // yStride frameBuffer.insert ("Z", // name Slice (FLOAT, // type (char *) &pixels[-dy][-dx].z, // base sizeof (pixels[0][0]) * 1, // xStride sizeof (pixels[0][0]) * width)); // yStride in.setFrameBuffer (frameBuffer); in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1); }
void readRgba (const char fileName[], Array2D<Rgba> &pixels, int &width, int &height) { // // Read an RGBA image using class RgbaInputFile: // // - open the file // - allocate memory for the pixels // - describe the memory layout of the pixels // - read the pixels from the file // RgbaInputFile file (fileName); Box2i dw = file.dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; pixels.resizeErase (height, width); file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); file.readPixels (dw.min.y, dw.max.y); }
static void readRgba1(const std::string& filename, Array2D<Rgba>& pixels, int& width, int& height) { RgbaInputFile file{filename.c_str()}; Box2i dw = file.dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; pixels.resizeErase(height, width); file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); file.readPixels(dw.min.y, dw.max.y); }
void Exr::readRgba(const string inf, Array2D<Rgba> &pix, int &w, int &h) { RgbaInputFile file (inf.c_str()); Box2i dw = file.dataWindow(); w = dw.max.x - dw.min.x + 1; h = dw.max.y - dw.min.y + 1; pix.resizeErase (h, w); file.setFrameBuffer (&pix[0][0] - dw.min.x - dw.min.y * w, 1, w); file.readPixels (dw.min.y, dw.max.y); }
void readRgba1 (const char fileName[], Array2D<Rgba> &pixels, int &width, int &height) // from openexr-1.7.0/doc/ReadingAndWritingImageFiles.pdf page 6 { RgbaInputFile file (fileName); Box2i dw = file.dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; pixels.resizeErase (height, width); file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); file.readPixels (dw.min.y, dw.max.y); }
void readTiledRgba1 (const char fileName[], Array2D<Rgba> &pixels, int &width, int &height) { TiledRgbaInputFile in (fileName); Box2i dw = in.dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; int dx = dw.min.x; int dy = dw.min.y; pixels.resizeErase (height, width); in.setFrameBuffer (&pixels[-dy][-dx], 1, width); in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1); }
void readGZ2 (const char fileName[], Array2D<GZ> &pixels, int &width, int &height) { // // Read an image using class InputFile. Try to read one channel, // G, of type HALF, and one channel, Z, of type FLOAT. In memory, // the G and Z channels will be interleaved in a single buffer. // // - open the file // - allocate memory for the pixels // - describe the layout of the GZ pixel buffer // - read the pixels from the file // InputFile file (fileName); Box2i dw = file.header().dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; int dx = dw.min.x; int dy = dw.min.y; pixels.resizeErase (height, width); FrameBuffer frameBuffer; frameBuffer.insert ("G", // name Slice (IMF::HALF, // type (char *) &pixels[-dy][-dx].g, // base sizeof (pixels[0][0]) * 1, // xStride sizeof (pixels[0][0]) * width)); // yStride frameBuffer.insert ("Z", // name Slice (IMF::FLOAT, // type (char *) &pixels[-dy][-dx].z, // base sizeof (pixels[0][0]) * 1, // xStride sizeof (pixels[0][0]) * width)); // yStride file.setFrameBuffer (frameBuffer); file.readPixels (dw.min.y, dw.max.y); }
KDE_EXPORT void kimgio_exr_read( TQImageIO *io ) { try { int width, height; // This won't work if io is not TQFile ! RgbaInputFile file (TQFile::encodeName(io->fileName())); Imath::Box2i dw = file.dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; Array2D<Rgba> pixels; pixels.resizeErase (height, width); file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); file.readPixels (dw.min.y, dw.max.y); TQImage image(width, height, 32, 0, TQImage::BigEndian); if( image.isNull()) return; // somehow copy pixels into image for ( int y=0; y < height; y++ ) { for ( int x=0; x < width; x++ ) { // copy pixels(x,y) into image(x,y) image.setPixel( x, y, RgbaToQrgba( pixels[y][x] ) ); } } io->setImage( image ); io->setStatus( 0 ); } catch (const std::exception &exc) { kdDebug(399) << exc.what() << endl; return; } }
void AVPCL::decompress(string avpclf, string outf) { Array2D<RGBA> pixels; int w, h; char block[AVPCL::BLOCKSIZE]; extract(avpclf, w, h, AVPCL::mode_rgb); FILE *avpclfile = fopen(avpclf.c_str(), "rb"); if (avpclfile == NULL) throw "Unable to open .avpcl file for read"; pixels.resizeErase(h, w); // convert to tiles and decompress each tile for (int y=0; y<h; y+=Tile::TILE_H) { int ysize = MIN(Tile::TILE_H, h-y); for (int x=0; x<w; x+=Tile::TILE_W) { int xsize = MIN(Tile::TILE_W, w-x); Tile t(xsize, ysize); if (fread(block, sizeof(char), AVPCL::BLOCKSIZE, avpclfile) != AVPCL::BLOCKSIZE) throw "File error on read"; stats(block); // collect statistics AVPCL::decompress(block, t); t.extract(pixels, x, y); } } if (fclose(avpclfile)) throw "Close failed on .avpcl file"; Targa::write(outf, pixels, w, h); printstats(); // print statistics }
unsigned char *exr_load(std::istream& fin, int *width_ret, int *height_ret, int *numComponents_ret, unsigned int *dataType_ret) { unsigned char *buffer=NULL; // returned to sender & as read from the disk bool inputError = false; Array2D<Rgba> pixels; int width,height,numComponents; try { C_IStream inStream(&fin); RgbaInputFile rgbafile(inStream); Box2i dw = rgbafile.dataWindow(); /*RgbaChannels channels =*/ rgbafile.channels(); (*width_ret) = width = dw.max.x - dw.min.x + 1; (*height_ret)=height = dw.max.y - dw.min.y + 1; (*dataType_ret) = GL_HALF_FLOAT_ARB; pixels.resizeErase (height, width); rgbafile.setFrameBuffer((&pixels)[0][0] - dw.min.x - dw.min.y * width, 1, width); rgbafile.readPixels(dw.min.y, dw.max.y); } catch( char * str ) { inputError = true; } //If error during stream read return a empty pointer if (inputError) { return buffer; } //If there is no information in alpha channel do not store the alpha channel numComponents = 3; for (long i = height-1; i >= 0; i--) { for (long j = 0 ; j < width; j++) { if (pixels[i][j].a != half(1.0f) ) { numComponents = 4; break; } } } (*numComponents_ret) = numComponents; if (!( numComponents == 3 || numComponents == 4)) { return NULL; } //Copy and allocate data to a unsigned char array that OSG can use for texturing unsigned dataSize = (sizeof(half) * height * width * numComponents); //buffer = new unsigned char[dataSize]; buffer = (unsigned char*)malloc(dataSize); half* pOut = (half*) buffer; for (long i = height-1; i >= 0; i--) { for (long j = 0 ; j < width; j++) { (*pOut) = pixels[i][j].r; pOut++; (*pOut) = pixels[i][j].g; pOut++; (*pOut) = pixels[i][j].b; pOut++; if (numComponents >= 4) { (*pOut) = pixels[i][j].a; pOut++; } } } return buffer; }
void readGZ1 (const char fileName[], Array2D<half> &rPixels, Array2D<half> &gPixels, Array2D<float> &zPixels, int &width, int &height) { // // Read an image using class InputFile. Try to read two // channels, R and G, of type HALF, and one channel, Z, // of type FLOAT. Store the R, G, and Z pixels in three // separate memory buffers. // If a channel is missing in the file, the buffer for that // channel will be filled with an appropriate default value. // // - open the file // - allocate memory for the pixels // - describe the layout of the R, G, and Z pixel buffers // - read the pixels from the file // InputFile file (fileName); Box2i dw = file.header().dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; rPixels.resizeErase (height, width); gPixels.resizeErase (height, width); zPixels.resizeErase (height, width); FrameBuffer frameBuffer; frameBuffer.insert ("R", // name Slice (IMF::HALF, // type (char *) (&rPixels[0][0] - // base dw.min.x - dw.min.y * width), sizeof (rPixels[0][0]) * 1, // xStride sizeof (rPixels[0][0]) * width, // yStride 1, 1, // x/y sampling 0.0)); // fillValue frameBuffer.insert ("G", // name Slice (IMF::HALF, // type (char *) (&gPixels[0][0] - // base dw.min.x - dw.min.y * width), sizeof (gPixels[0][0]) * 1, // xStride sizeof (gPixels[0][0]) * width, // yStride 1, 1, // x/y sampling 0.0)); // fillValue frameBuffer.insert ("Z", // name Slice (IMF::FLOAT, // type (char *) (&zPixels[0][0] - // base dw.min.x - dw.min.y * width), sizeof (zPixels[0][0]) * 1, // xStride sizeof (zPixels[0][0]) * width, // yStride 1, 1, // x/y sampling FLT_MAX)); // fillValue file.setFrameBuffer (frameBuffer); file.readPixels (dw.min.y, dw.max.y); }
int main(int argc, char **argv) { short x,y,c,i; char outfile[300], infile[300]; short num_chars; int first, last, frame, first_out; float s, t, tmp; float red, grn, blu; short argnm=0; if (argc <= 4) { printf(" usage: %s infiles, outfiles, first_frame, last_frame, first_frame_out\n", argv[0]); exit(1); } first = atoi(argv[3]); last = atoi(argv[4]); if(argc > 5) { first_out = atoi(argv[5]); } else { first_out=first; } printf(" processing frames %d to %d to frames %d to %d\n", first, last, first_out, last + first_out - first); /*******************************************************************************************************************************************************/ /* frame loop: */ for (frame=first; frame <= last; frame++) { sprintf(infile, argv[1], frame); num_chars = strlen(infile); /* length of infile string */ if ((!strcmp(&infile[num_chars-1], "r"))||(!strcmp(&infile[num_chars-1], "R"))) { /* EXR file ending in ".exr" */ printf(" processing input file %s\n", infile); } else { /* not exr */ printf(" unknown filetype for reading, since extension doesn't end in r, only exr reading supported, infile = %s, aborting\n", outfile); exit(1); } /* exr or not */ sprintf(outfile, argv[2], frame + first_out - first); num_chars = strlen(outfile); /* length of outfile string */ if ((!strcmp(&outfile[num_chars-1], "x")) ||(!strcmp(&outfile[num_chars-1], "X")) || /* DPX floating point file ending in ".dpx" */ (!strcmp(&outfile[num_chars-3], "x32"))||(!strcmp(&outfile[num_chars-3], "X32"))) { /* DPX32 */ printf(" processing output file %s\n", outfile); } else { /* not exr */ printf(" unknown filetype for writing, since extension doesn't end in x or x32, only dpx float writing supported, outfile = %s, aborting\n", outfile); exit(1); } /* exr or not */ RgbaInputFile file (infile, 1 ); Box2i dw = file.dataWindow(); h_reso = dw.max.x - dw.min.x + 1; v_reso = dw.max.y - dw.min.y + 1; half_float_pixels.resizeErase (v_reso, h_reso); file.setFrameBuffer (&half_float_pixels[0][0] - dw.min.x - dw.min.y * h_reso, 1, h_reso); file.readPixels (dw.min.y, dw.max.y); if (pixels == NULL) { pixels = (float *) malloc(h_reso * v_reso * 12); /* 4-bytes/float * 3-colors */ } for(y=0; y< v_reso; y++) { for(x=0; x< h_reso; x++) { pixels[(0*v_reso + y) * h_reso + x] = half_float_pixels[y][x].r; pixels[(1*v_reso + y) * h_reso + x] = half_float_pixels[y][x].g; pixels[(2*v_reso + y) * h_reso + x] = half_float_pixels[y][x].b; } /* x */ } /* y */ dpx_write_float(outfile, pixels, h_reso, v_reso); printf(" finished writing %s at x_reso = %d y_reso = %d\n", outfile, h_reso, v_reso); } /* frame loop */ } /* main */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { char *exrFileName; double *mxData; int width = 0; int height = 0; int nSlices = 0; if (nrhs != 1 || !mxIsChar(prhs[0])) { mexErrMsgTxt("Usage: ReadMultichannelEXR('exrFile')\n"); } // read the exr file with OpenEXR general interface exrFileName = mxArrayToString(prhs[0]); InputFile file (exrFileName); // query general file properties Box2i dw = file.header().dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; const ChannelList &channels = file.header().channels(); for (ChannelList::ConstIterator iter = channels.begin(); iter != channels.end(); ++iter) { nSlices++; } mexPrintf("Read \"%s\": width=%d height=%d nSlices=%d\n", exrFileName, width, height, nSlices); mxFree(exrFileName); // return a struct with info about image slices mwSize nDims = 2; mwSize infoDims[] = {1, 0}; infoDims[1] = nSlices; const char* fieldNames[] = {"name", "pixelType", "xSampling", "ySampling", "isLinear"}; int nFields = sizeof(fieldNames)/sizeof(fieldNames[0]); plhs[0] = mxCreateStructArray(nDims, infoDims, nFields, fieldNames); // return a double array with size [height width nSlices] nDims = 3; mwSize dataDims[] = {0, 0, 0}; dataDims[0] = height; dataDims[1] = width; dataDims[2] = nSlices; plhs[1] = mxCreateNumericArray(nDims, dataDims, mxDOUBLE_CLASS, mxREAL); if (NULL == plhs[1]) { mexPrintf("Could not allocate image array of size [%d %d %d]\n", dataDims[0], dataDims[1], dataDims[2]); return; } double* data = mxGetPr(plhs[1]); // fill in info struct and data array int channelIndex = 0; for (ChannelList::ConstIterator iter = channels.begin(); iter != channels.end(); ++iter) { const Channel &channel = iter.channel(); // fill in info struct for this channel mxSetField(plhs[0], channelIndex, "name", mxCreateString(iter.name())); mxSetField(plhs[0], channelIndex, "xSampling", mxCreateDoubleScalar((double)channel.xSampling)); mxSetField(plhs[0], channelIndex, "ySampling", mxCreateDoubleScalar((double)channel.ySampling)); mxSetField(plhs[0], channelIndex, "isLinear", mxCreateLogicalScalar((mxLogical)channel.pLinear)); // fill in a slice of the data matrix for this channel // memory allocation depends on slice pixel type mxArray* typeName = NULL; FrameBuffer frameBuffer; switch (channel.type) { case UINT:{ typeName = mxCreateString("UINT"); // copy slice data from file to a frame buffer Array2D<MATLAB_UINT32> slicePixels; slicePixels.resizeErase(height, width); frameBuffer.insert(iter.name(), Slice(HALF, (char *)(&slicePixels[0][0] - dw.min.x - dw.min.y * width), sizeof(slicePixels[0][0]) * 1, sizeof(slicePixels[0][0]) * width, channel.xSampling, channel.ySampling, 0.0)); file.setFrameBuffer (frameBuffer); file.readPixels (dw.min.y, dw.max.y); // copy slice data from frame buffer to data array for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { data[M3I(height, width, i, j, channelIndex)] = slicePixels[i][j]; } } break; } case HALF:{ typeName = mxCreateString("HALF"); // copy slice data from file to a frame buffer Array2D<half> slicePixels; slicePixels.resizeErase(height, width); frameBuffer.insert(iter.name(), Slice(HALF, (char *)(&slicePixels[0][0] - dw.min.x - dw.min.y * width), sizeof(slicePixels[0][0]) * 1, sizeof(slicePixels[0][0]) * width, channel.xSampling, channel.ySampling, 0.0)); file.setFrameBuffer (frameBuffer); file.readPixels (dw.min.y, dw.max.y); // copy slice data from frame buffer to data array for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { data[M3I(height, width, i, j, channelIndex)] = slicePixels[i][j]; } } break; } case FLOAT:{ typeName = mxCreateString("FLOAT"); // copy slice data from file to a frame buffer Array2D<half> slicePixels; slicePixels.resizeErase(height, width); frameBuffer.insert(iter.name(), Slice(HALF, (char *)(&slicePixels[0][0] - dw.min.x - dw.min.y * width), sizeof(slicePixels[0][0]) * 1, sizeof(slicePixels[0][0]) * width, channel.xSampling, channel.ySampling, 0.0)); file.setFrameBuffer (frameBuffer); file.readPixels (dw.min.y, dw.max.y); // copy slice data from frame buffer to data array for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { data[M3I(height, width, i, j, channelIndex)] = slicePixels[i][j]; } } break; } default:{ typeName = mxCreateString("UNKNOWN"); break; } } mxSetField(plhs[0], channelIndex, "pixelType", typeName); channelIndex++; //mexPrintf(" channel \"%s\": type=%d xSampling=%d ySampling=%d, isLinear=%d\n", // iter.name(), channel.type, // channel.xSampling, channel.ySampling, channel.pLinear); } }