예제 #1
0
bool
DPXInput::open (const std::string &name, ImageSpec &newspec)
{
    // open the image
    m_stream = new InStream();
    if (! m_stream->Open(name.c_str())) {
        error ("Could not open file \"%s\"", name.c_str());
        return false;
    }
    
    m_dpx.SetInStream(m_stream);
    if (! m_dpx.ReadHeader()) {
        error ("Could not read header");
        return false;
    }

    bool ok = seek_subimage (0, 0, newspec);
    newspec = spec ();
    return ok;
}
예제 #2
0
OIIO_PLUGIN_EXPORTS_END



bool
DPXInput::valid_file (const std::string &filename) const
{
    InStream *stream = new InStream();
    if (! stream)
        return false;
    bool ok = false;
    if (stream->Open(filename.c_str())) {
        dpx::Reader dpx;
        dpx.SetInStream(stream);
        ok = dpx.ReadHeader();
        stream->Close();
    }
    delete stream;
    return ok;
}
예제 #3
0
파일: dpx2tiff.cpp 프로젝트: MOXfiles/dpx
int main(int argc, char **argv)
{
	int offset = 1;
	bool write8bit = false;
	//bool write8bit = true;
	
	if (argc == 4 && strcmp(argv[1], "-8") == 0)
	{
		write8bit = true;
		offset++;
	}
	else if (argc != 3)
	{
		Usage();
		return 1;
	}

	// open the image
	InStream img;
	if (!img.Open(argv[offset]))
	{
		cout << "Unable to open file " << argv[1] << endl;
		return 1;
	}
	
	dpx::Reader dpx;
	dpx.SetInStream(&img);
	if (!dpx.ReadHeader())
	{
		cout << "Unable to read header" << endl;
		return 2;
	}
	
	TIFF *out;
	out = TIFFOpen(argv[offset+1], "w");
	if (out == NULL)
	{
		cout << "Unable to open output file" << endl;
		return 3;
	}

	// data size, override if user specifies
	dpx::DataSize size = dpx.header.ComponentDataSize(0);
	int nob = dpx.header.ComponentByteCount(0);
	if (write8bit)
	{
		size = dpx::kByte;
		nob = 1;
	}

	cout << "Image Width " << dpx.header.Width() << " Height " << 
			dpx.header.Height() << " component byte count " << 
			dpx.header.ComponentByteCount(0) << endl;
	
	// conversion
	int format = PHOTOMETRIC_RGB;
	int elementCount = 3;
	if (dpx.header.ImageElementComponentCount(0) == 1) {
		format = PHOTOMETRIC_MINISBLACK;
		elementCount = 1;
	}

	TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) dpx.header.Width());
	TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) dpx.header.Height());
	TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (uint32) nob * 8);
	TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, elementCount);
	TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
	TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
	TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, format);
	TIFFSetField(out, TIFFTAG_MINSAMPLEVALUE, 0);
	int max = 0xff;
	if (nob == 2)
		max = 0xffff;
	else
		max = 0xffffffff;
	TIFFSetField(out, TIFFTAG_MAXSAMPLEVALUE, max);
	
	tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
	if (buf == NULL) 
	{
		cout << "memory allocation error" << endl;
		return 4;
	}

	Block block(0, 0, dpx.header.Width()-1, 0);
	int y;
	for (y = 0; y < dpx.header.Height(); y++)
	{
		block.y1 = y;
		block.y2 = y;
			
		if (dpx.ReadBlock(buf, size, block, dpx.header.ImageDescriptor(0)) == false)
		{
			cout << "unable to read line " << y << " with component data size " << size << endl;
			return 5;
		}

		if (TIFFWriteScanline(out, buf, y, 0) < 0)
		{
			cout << "unable to write tiff scanline " << y << endl;
			return 6;
		}
	}


	_TIFFfree(buf);
	
	img.Close();
	TIFFClose(out);
	
	return 0;
}
예제 #4
0
OIIO_PLUGIN_EXPORTS_END



bool
CineonInput::open (const std::string &name, ImageSpec &newspec)
{
    // open the image
    m_stream = new InStream();
    if (! m_stream->Open(name.c_str())) {
        error ("Could not open file \"%s\"", name.c_str());
        return false;
    }
    
    m_cin.SetInStream(m_stream);
    if (! m_cin.ReadHeader()) {
        error ("Could not read header");
        return false;
    }

    // create imagespec
    TypeDesc typedesc;
    int maxbits = 0;
    for (int i = 0; i < m_cin.header.NumberOfElements (); i++) {
        if (maxbits < m_cin.header.BitDepth (i))
            maxbits = m_cin.header.BitDepth (i);
    }
    switch ((maxbits + 7) / 8) {
        case 1:
            typedesc = TypeDesc::UINT8;
            break;
        case 2:
            typedesc = TypeDesc::UINT16;
            break;
        case 3:
        case 4:
            typedesc = TypeDesc::UINT32;
            break;
        default:
            error ("Unsupported bit depth %d", maxbits);
            return false;
    }
    m_spec = ImageSpec (m_cin.header.Width(), m_cin.header.Height(),
        m_cin.header.NumberOfElements (), typedesc);
    // fill channel names
    m_spec.channelnames.clear ();
    int gscount = 0, rcount = 0, gcount = 0, bcount = 0;
    char buf[3];
    for (int i = 0; i < m_cin.header.NumberOfElements (); i++) {
        switch (m_cin.header.ImageDescriptor (i)) {
            case cineon::kGrayscale:
                if (++gscount > 1) {
                    std::string ch = Strutil::format ("I%d", gscount);
                    m_spec.channelnames.push_back (ch);
                } else
                    m_spec.channelnames.emplace_back("I");
                break;
            case cineon::kPrintingDensityRed:
            case cineon::kRec709Red:
                if (++gscount > 1) {
                    std::string ch = Strutil::format ("R%d", rcount);
                    m_spec.channelnames.push_back (ch);
                } else
                    m_spec.channelnames.emplace_back("R");
                break;
            case cineon::kPrintingDensityGreen:
            case cineon::kRec709Green:
                if (++gcount > 1) {
                    std::string ch = Strutil::format ("G%d", gcount);
                    m_spec.channelnames.push_back (ch);
                } else
                    m_spec.channelnames.emplace_back("G");
                break;
            case cineon::kPrintingDensityBlue:
            case cineon::kRec709Blue:
                if (++bcount > 1) {
                    std::string ch = Strutil::format ("B%d", bcount);
                    m_spec.channelnames.push_back (ch);
                } else
                    m_spec.channelnames.emplace_back("B");
                break;
            default:
                std::string ch = Strutil::format ("channel%d", (int)m_spec.channelnames.size());
                m_spec.channelnames.push_back (ch);
                break;
        }
    }
    // bits per sample
    m_spec.attribute ("oiio:BitsPerSample", maxbits);
    // image orientation - see appendix B.2 of the OIIO documentation
    int orientation;
    switch (m_cin.header.ImageOrientation ()) {
        case cineon::kLeftToRightTopToBottom:
            orientation = 1;
            break;
        case cineon::kRightToLeftTopToBottom:
            orientation = 2;
            break;
        case cineon::kLeftToRightBottomToTop:
            orientation = 4;
            break;
        case cineon::kRightToLeftBottomToTop:
            orientation = 3;
            break;
        case cineon::kTopToBottomLeftToRight:
            orientation = 5;
            break;
        case cineon::kTopToBottomRightToLeft:
            orientation = 6;
            break;
        case cineon::kBottomToTopLeftToRight:
            orientation = 8;
            break;
        case cineon::kBottomToTopRightToLeft:
            orientation = 7;
            break;
        default:
            orientation = 0;
            break;
    }
    m_spec.attribute ("Orientation", orientation);

#if 1
    // This is not very smart, but it seems that as a practical matter,
    // all Cineon files are log. So ignore the gamma field and just set
    // the color space to KodakLog.
    m_spec.attribute ("oiio:ColorSpace", "KodakLog");
#else
    // image linearity
    // FIXME: making this more robust would require the per-channel transfer
    // function functionality which isn't yet in OIIO
    switch (m_cin.header.ImageDescriptor (0)) {
        case cineon::kRec709Red:
        case cineon::kRec709Green:
        case cineon::kRec709Blue:
            m_spec.attribute ("oiio:ColorSpace", "Rec709");
        default:
            // either grayscale or printing density
            if (!isinf (m_cin.header.Gamma ()) && m_cin.header.Gamma () != 0.0f)
                // actual gamma value is read later on
                m_spec.attribute ("oiio:ColorSpace",
                                  Strutil::format("GammaCorrected%.2g", g));
            break;
    }

    // gamma exponent
    if (!isinf (m_cin.header.Gamma ()) && m_cin.header.Gamma () != 0.0f)
        m_spec.attribute ("oiio:Gamma", (float) m_cin.header.Gamma ());
#endif

    // general metadata
    // some non-compliant writers will dump a field filled with 0xFF rather
    // than a NULL string termination on the first character, so take that
    // into account, too
    if (m_cin.header.creationDate[0] && m_cin.header.creationTime[0]) {
        // libcineon's date/time format is pretty close to OIIO's (libcineon
        // uses %Y:%m:%d:%H:%M:%S%Z)
        m_spec.attribute ("DateTime", Strutil::format ("%s %s",
            m_cin.header.creationDate, m_cin.header.creationTime));
        // FIXME: do something about the time zone
    }

    // cineon-specific metadata
    char *strings[8];
    int ints[8];
    float floats[8];
    
    // image descriptor
    for (int i = 0; i < m_cin.header.NumberOfElements (); i++)
        strings[i] = get_descriptor_string (m_cin.header.ImageDescriptor (i));
    m_spec.attribute ("cineon:ImageDescriptor", TypeDesc (TypeDesc::STRING,
        m_cin.header.NumberOfElements ()), &strings);

    // save some typing by using macros
    // "internal" macros
// per-file attribs
#define CINEON_SET_ATTRIB_S(x, n, s)    m_spec.attribute (s,                \
                                            m_cin.header.x (n))
#define CINEON_SET_ATTRIB(x, n)         CINEON_SET_ATTRIB_S(x, n,           \
                                            "cineon:" #x)
#define CINEON_SET_ATTRIB_BYTE(x)       if (m_cin.header.x () != 0xFF)      \
                                            CINEON_SET_ATTRIB(x, )
#define CINEON_SET_ATTRIB_INT(x)        if (static_cast<unsigned int>       \
                                            (m_cin.header.x ())             \
                                            != 0xFFFFFFFF)                  \
                                            CINEON_SET_ATTRIB(x, )
#define CINEON_SET_ATTRIB_FLOAT(x)      if (! isinf(m_cin.header.x ()))     \
                                            CINEON_SET_ATTRIB(x, )
#define CINEON_SET_ATTRIB_COORDS(x)     m_cin.header.x (floats);            \
                                        if (!isinf (floats[0])              \
                                            && !isinf (floats[1])           \
                                            && !(floats[0] == 0. && floats[1] == 0.)) \
                                            m_spec.attribute ("cineon:" #x, \
                                                TypeDesc (TypeDesc::FLOAT, 2), \
                                                &floats[0])
#define CINEON_SET_ATTRIB_STR(X, x)     if (m_cin.header.x[0]               \
                                        && m_cin.header.x[0] != char(-1))   \
                                            m_spec.attribute ("cineon:" #X, \
                                                m_cin.header.x)

// per-element attribs
#define CINEON_SET_ATTRIB_N(x, a, t, c) for (int i = 0; i < m_cin.header.   \
                                            NumberOfElements (); i++) {     \
                                            c(x)                            \
                                            a[i] = m_cin.header.x (i);      \
                                        }                                   \
                                        m_spec.attribute ("cineon:" #x,     \
                                            TypeDesc (TypeDesc::t,          \
                                            m_cin.header.NumberOfElements()),\
                                            &a)
#define CINEON_CHECK_ATTRIB_FLOAT(x)    if (!isinf (m_cin.header.x (i)))
#define CINEON_SET_ATTRIB_FLOAT_N(x)    CINEON_SET_ATTRIB_N(x, floats,      \
                                            FLOAT, CINEON_CHECK_ATTRIB_FLOAT)
#define CINEON_CHECK_ATTRIB_INT(x)      if (m_cin.header.x (i) != 0xFFFFFFFF)
#define CINEON_SET_ATTRIB_INT_N(x)      CINEON_SET_ATTRIB_N(x, ints,        \
                                            UINT32, CINEON_CHECK_ATTRIB_INT)
#define CINEON_CHECK_ATTRIB_BYTE(x)     if (m_cin.header.x (i) != 0xFF)
#define CINEON_SET_ATTRIB_BYTE_N(x)     CINEON_SET_ATTRIB_N(x, ints,        \
                                            UINT32, CINEON_CHECK_ATTRIB_BYTE)

    CINEON_SET_ATTRIB_STR(Version, version);

    // per-element data
    CINEON_SET_ATTRIB_BYTE_N(Metric);
    CINEON_SET_ATTRIB_BYTE_N(BitDepth);
    CINEON_SET_ATTRIB_INT_N(PixelsPerLine);
    CINEON_SET_ATTRIB_INT_N(LinesPerElement);
    CINEON_SET_ATTRIB_FLOAT_N(LowData);
    CINEON_SET_ATTRIB_FLOAT_N(LowQuantity);
    CINEON_SET_ATTRIB_FLOAT_N(HighData);
    CINEON_SET_ATTRIB_FLOAT_N(HighQuantity);

    CINEON_SET_ATTRIB_COORDS(WhitePoint);
    CINEON_SET_ATTRIB_COORDS(RedPrimary);
    CINEON_SET_ATTRIB_COORDS(GreenPrimary);
    CINEON_SET_ATTRIB_COORDS(BluePrimary);
    CINEON_SET_ATTRIB_STR(LabelText, labelText);

    CINEON_SET_ATTRIB_INT(XOffset);
    CINEON_SET_ATTRIB_INT(YOffset);
    CINEON_SET_ATTRIB_STR(SourceImageFileName, sourceImageFileName);
    CINEON_SET_ATTRIB_STR(InputDevice, inputDevice);
    CINEON_SET_ATTRIB_STR(InputDeviceModelNumber, inputDeviceModelNumber);
    CINEON_SET_ATTRIB_STR(InputDeviceSerialNumber, inputDeviceSerialNumber);
    CINEON_SET_ATTRIB_FLOAT(XDevicePitch);
    CINEON_SET_ATTRIB_FLOAT(YDevicePitch);
    
    CINEON_SET_ATTRIB_INT(FramePosition);
    CINEON_SET_ATTRIB_FLOAT(FrameRate);
    CINEON_SET_ATTRIB_STR(Format, format);
    CINEON_SET_ATTRIB_STR(FrameId, frameId);
    CINEON_SET_ATTRIB_STR(SlateInfo, slateInfo);
    
#undef CINEON_SET_ATTRIB_BYTE_N
#undef CINEON_CHECK_ATTRIB_BYTE
#undef CINEON_SET_ATTRIB_INT_N
#undef CINEON_CHECK_ATTRIB_INT
#undef CINEON_SET_ATTRIB_FLOAT_N
#undef CINEON_CHECK_ATTRIB_FLOAT
#undef CINEON_SET_ATTRIB_N
#undef CINEON_SET_ATTRIB_STR
#undef CINEON_SET_ATTRIB_COORDS
#undef CINEON_SET_ATTRIB_FLOAT
#undef CINEON_SET_ATTRIB_INT
#undef CINEON_SET_ATTRIB
#undef CINEON_SET_ATTRIB_S

    std::string tmpstr;
    switch (m_cin.header.ImagePacking () & ~cineon::kPackAsManyAsPossible) {
        case cineon::kPacked:
            tmpstr = "Packed";
            break;
        case cineon::kByteLeft:
            tmpstr = "8-bit boundary, left justified";
            break;
        case cineon::kByteRight:
            tmpstr = "8-bit boundary, right justified";
            break;
        case cineon::kWordLeft:
            tmpstr = "16-bit boundary, left justified";
            break;
        case cineon::kWordRight:
            tmpstr = "16-bit boundary, right justified";
            break;
        case cineon::kLongWordLeft:
            tmpstr = "32-bit boundary, left justified";
            break;
        case cineon::kLongWordRight:
            tmpstr = "32-bit boundary, right justified";
            break;
    }
    if (m_cin.header.ImagePacking () & cineon::kPackAsManyAsPossible)
        tmpstr += ", as many fields as possible per cell";
    else
        tmpstr += ", at most one pixel per cell";
    
    if (!tmpstr.empty ())
        m_spec.attribute ("cineon:Packing", tmpstr);

    if (m_cin.header.sourceDate[0] && m_cin.header.sourceTime[0]) {
        // libcineon's date/time format is pretty close to OIIO's (libcineon
        // uses %Y:%m:%d:%H:%M:%S%Z)
        m_spec.attribute ("DateTime", Strutil::format ("%s %s",
            m_cin.header.sourceDate, m_cin.header.sourceTime));
        // FIXME: do something about the time zone
    }
    m_cin.header.FilmEdgeCode(buf);
    if (buf[0])
        m_spec.attribute ("cineon:FilmEdgeCode", buf);

    // read in user data
    if (m_cin.header.UserSize () != 0
        && m_cin.header.UserSize () != 0xFFFFFFFF) {
        m_userBuf.resize (m_cin.header.UserSize ());
        m_cin.ReadUserData (&m_userBuf[0]);
    }
    if (!m_userBuf.empty ())
        m_spec.attribute ("cineon:UserData", TypeDesc (TypeDesc::UCHAR,
            m_cin.header.UserSize ()), &m_userBuf[0]);

    newspec = spec ();
    return true;
}