Exemple #1
0
bool
PNGOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
                          stride_t xstride)
{
    y -= m_spec.y;
    m_spec.auto_stride(xstride, format, spec().nchannels);
    const void* origdata = data;
    data = to_native_scanline(format, data, xstride, m_scratch, m_dither, y, z);
    if (data == origdata) {
        m_scratch.assign((unsigned char*)data,
                         (unsigned char*)data + m_spec.scanline_bytes());
        data = &m_scratch[0];
    }

    // PNG specifically dictates unassociated (un-"premultiplied") alpha
    if (m_convert_alpha) {
        if (m_spec.format == TypeDesc::UINT16)
            deassociateAlpha((unsigned short*)data, m_spec.width,
                             m_spec.nchannels, m_spec.alpha_channel, m_gamma);
        else
            deassociateAlpha((unsigned char*)data, m_spec.width,
                             m_spec.nchannels, m_spec.alpha_channel, m_gamma);
    }

    // PNG is always big endian
    if (littleendian() && m_spec.format == TypeDesc::UINT16)
        swap_endian((unsigned short*)data, m_spec.width * m_spec.nchannels);

    if (!PNG_pvt::write_row(m_png, (png_byte*)data)) {
        error("PNG library error");
        return false;
    }

    return true;
}
Exemple #2
0
bool
SgiInput::read_header()
{
    if (!fread(&m_sgi_header.magic, sizeof(m_sgi_header.magic), 1) ||
        !fread(&m_sgi_header.storage, sizeof(m_sgi_header.storage), 1) ||
        !fread(&m_sgi_header.bpc, sizeof(m_sgi_header.bpc), 1) ||
        !fread(&m_sgi_header.dimension, sizeof(m_sgi_header.dimension), 1) ||
        !fread(&m_sgi_header.xsize, sizeof(m_sgi_header.xsize), 1) ||
        !fread(&m_sgi_header.ysize, sizeof(m_sgi_header.ysize), 1) ||
        !fread(&m_sgi_header.zsize, sizeof(m_sgi_header.zsize), 1) ||
        !fread(&m_sgi_header.pixmin, sizeof(m_sgi_header.pixmin), 1) ||
        !fread(&m_sgi_header.pixmax, sizeof(m_sgi_header.pixmax), 1) ||
        !fread(&m_sgi_header.dummy, sizeof(m_sgi_header.dummy), 1) ||
        !fread(&m_sgi_header.imagename, sizeof(m_sgi_header.imagename), 1))
        return false;

    m_sgi_header.imagename[79] = '\0';
    if (! fread(&m_sgi_header.colormap, sizeof(m_sgi_header.colormap), 1))
        return false;

    //don't read dummy bytes
    fseek (m_fd, 404, SEEK_CUR);

    if (littleendian()) {
        swap_endian(&m_sgi_header.magic);
        swap_endian(&m_sgi_header.dimension);
        swap_endian(&m_sgi_header.xsize);
        swap_endian(&m_sgi_header.ysize);
        swap_endian(&m_sgi_header.zsize);
        swap_endian(&m_sgi_header.pixmin);
        swap_endian(&m_sgi_header.pixmax);
        swap_endian(&m_sgi_header.colormap);
    }
    return true;
}
Exemple #3
0
bool
SgiOutput::create_and_write_header()
{
    sgi_pvt::SgiHeader sgi_header;
    sgi_header.magic   = sgi_pvt::SGI_MAGIC;
    sgi_header.storage = sgi_pvt::VERBATIM;
    sgi_header.bpc     = m_spec.format.size();

    if (m_spec.height == 1 && m_spec.nchannels == 1)
        sgi_header.dimension = sgi_pvt::ONE_SCANLINE_ONE_CHANNEL;
    else if (m_spec.nchannels == 1)
        sgi_header.dimension = sgi_pvt::MULTI_SCANLINE_ONE_CHANNEL;
    else
        sgi_header.dimension = sgi_pvt::MULTI_SCANLINE_MULTI_CHANNEL;

    sgi_header.xsize  = m_spec.width;
    sgi_header.ysize  = m_spec.height;
    sgi_header.zsize  = m_spec.nchannels;
    sgi_header.pixmin = 0;
    sgi_header.pixmax = (sgi_header.bpc == 1) ? 255 : 65535;
    sgi_header.dummy  = 0;

    ParamValue* ip = m_spec.find_attribute("ImageDescription",
                                           TypeDesc::STRING);
    if (ip && ip->data()) {
        const char** img_descr = (const char**)ip->data();
        strncpy(sgi_header.imagename, *img_descr, 80);
        sgi_header.imagename[79] = 0;
    }

    sgi_header.colormap = sgi_pvt::NORMAL;

    if (littleendian()) {
        swap_endian(&sgi_header.magic);
        swap_endian(&sgi_header.dimension);
        swap_endian(&sgi_header.xsize);
        swap_endian(&sgi_header.ysize);
        swap_endian(&sgi_header.zsize);
        swap_endian(&sgi_header.pixmin);
        swap_endian(&sgi_header.pixmax);
        swap_endian(&sgi_header.colormap);
    }

    char dummy[404] = { 0 };
    if (!fwrite(&sgi_header.magic) || !fwrite(&sgi_header.storage)
        || !fwrite(&sgi_header.bpc) || !fwrite(&sgi_header.dimension)
        || !fwrite(&sgi_header.xsize) || !fwrite(&sgi_header.ysize)
        || !fwrite(&sgi_header.zsize) || !fwrite(&sgi_header.pixmin)
        || !fwrite(&sgi_header.pixmax) || !fwrite(&sgi_header.dummy)
        || !fwrite(sgi_header.imagename, 1, 80) || !fwrite(&sgi_header.colormap)
        || !fwrite(dummy, 404, 1)) {
        error("Error writing to \"%s\"", m_filename);
        return false;
    }
    return true;
}
Exemple #4
0
bool
PicFileHeader::read_header (FILE* fd)
{
    int byte_count = 0;
    byte_count += fread (this, 1, sizeof (PicFileHeader), fd);
    
    // Check if we're running on a little endian processor
    if (littleendian ())
        swap_endian();
        
    return (byte_count == sizeof (PicFileHeader));
}
Exemple #5
0
bool
SgiInput::read_native_scanline (int y, int z, void *data)
{
    if (y < 0 || y > m_spec.height)
        return false;

    y = m_spec.height - y - 1;

    int bpc = m_sgi_header.bpc;
    std::vector<std::vector<unsigned char> > channeldata (m_spec.nchannels);
    if (m_sgi_header.storage == sgi_pvt::RLE) {
        // reading and uncompressing first channel (red in RGBA images)
        for (int c = 0;  c < m_spec.nchannels;  ++c) {
            int off = y + c*m_spec.height;  // offset for this scanline/channel
            int scanline_offset = start_tab[off];
            int scanline_length = length_tab[off];
            channeldata[c].resize (m_spec.width * bpc);
            uncompress_rle_channel (scanline_offset, scanline_length,
                                    &(channeldata[c][0]));
        }
    } else {
        // non-RLE case -- just read directly into our channel data
        for (int c = 0;  c < m_spec.nchannels;  ++c) {
            int off = y + c*m_spec.height;  // offset for this scanline/channel
            int scanline_offset = sgi_pvt::SGI_HEADER_LEN + off * m_spec.width * bpc;
            fseek (m_fd, scanline_offset, SEEK_SET);
            channeldata[c].resize (m_spec.width * bpc);
            if (! fread (&(channeldata[c][0]), 1, m_spec.width * bpc))
                return false;
        }
    }

    if (m_spec.nchannels == 1) {
        // If just one channel, no interleaving is necessary, just memcpy
        memcpy (data, &(channeldata[0][0]), channeldata[0].size());
    } else {
        unsigned char *cdata = (unsigned char *)data;
        for (int x = 0; x < m_spec.width; ++x) {
            for (int c = 0;  c < m_spec.nchannels;  ++c) {
                *cdata++ = channeldata[c][x*bpc];
                if (bpc == 2)
                    *cdata++ = channeldata[c][x*bpc+1];
            }
        }
    }

    // Swap endianness if needed
    if (bpc == 2 && littleendian())
        swap_endian ((unsigned short *)data, m_spec.width*m_spec.nchannels);

    return true;
}
Exemple #6
0
bool
SgiInput::read_offset_tables ()
{
    int tables_size = m_sgi_header.ysize * m_sgi_header.zsize;
    start_tab.resize(tables_size);
    length_tab.resize(tables_size);
    if (!fread (&start_tab[0], sizeof(uint32_t), tables_size) ||
        !fread (&length_tab[0], sizeof(uint32_t), tables_size))
        return false;

    if (littleendian ()) {
        swap_endian (&length_tab[0], length_tab.size ());
        swap_endian (&start_tab[0], start_tab.size());
    }
    return true;
}
Exemple #7
0
bool
TIFFInput::valid_file (const std::string &filename) const
{
    FILE *file = Filesystem::fopen (filename, "r");
    if (! file)
        return false;  // needs to be able to open
    unsigned short magic[2] = { 0, 0 };
    fread (magic, sizeof(unsigned short), 2, file);
    fclose (file);
    if (magic[0] != TIFF_LITTLEENDIAN && magic[0] != TIFF_BIGENDIAN)
        return false;  // not the right byte order
    if ((magic[0] == TIFF_LITTLEENDIAN) != littleendian())
        swap_endian (&magic[1], 1);
    return (magic[1] == 42 /* Classic TIFF */ ||
            magic[1] == 43 /* Big TIFF */);
}
Exemple #8
0
bool
FitsInput::read_native_scanline (int y, int z, void *data)
{
    // we return true just to support 0x0 images
    if (!m_naxes)
        return true;

    std::vector<unsigned char> data_tmp (m_spec.scanline_bytes ());
    long scanline_off = (m_spec.height - y) * m_spec.scanline_bytes ();
    fseek (m_fd, scanline_off, SEEK_CUR);
    size_t n = fread (&data_tmp[0], 1, m_spec.scanline_bytes(), m_fd);
    if (n != m_spec.scanline_bytes()) {
        if (feof (m_fd))
            error ("Hit end of file unexpectedly");
        else
            error ("read error");
        return false;   // Read failed
    }

    // in FITS image data is stored in big-endian so we have to switch to
    // little-endian on little-endian machines
    if (littleendian ()) {
        if (m_spec.format == TypeDesc::USHORT)
            swap_endian ((unsigned short*)&data_tmp[0],
                         data_tmp.size () / sizeof (unsigned short));
        else if (m_spec.format == TypeDesc::UINT)
            swap_endian ((unsigned int*)&data_tmp[0],
                         data_tmp.size () / sizeof (unsigned int));
        else if (m_spec.format == TypeDesc::FLOAT)
            swap_endian ((float*)&data_tmp[0],
                         data_tmp.size () / sizeof (float));
        else if (m_spec.format == TypeDesc::DOUBLE)
            swap_endian ((double*)&data_tmp[0],
                         data_tmp.size () / sizeof (double));
    }

    memcpy (data, &data_tmp[0], data_tmp.size ());

    // after reading scanline we set file pointer to the start of image data
    fsetpos (m_fd, &m_filepos);
    return true;
};
Exemple #9
0
bool
SgiOutput::write_scanline (int y, int z, TypeDesc format, const void *data,
                           stride_t xstride)
{
    y = m_spec.height - y - 1;
    data = to_native_scanline (format, data, xstride, m_scratch,
                               m_dither, y, z);

    // In SGI format all channels are saved to file separately: firsty all
    // channel 1 scanlines are saved, then all channel2 scanlines are saved
    // and so on.
    //
    // Note that since SGI images are pretty archaic and most probably
    // people won't be too picky about full flexibility writing them, we
    // content ourselves with only writing uncompressed data, and don't
    // attempt to write with RLE encoding.

    int bpc = m_spec.format.size();  // bytes per channel
    std::vector<unsigned char> channeldata (m_spec.width * bpc);

    for (int c = 0;  c < m_spec.nchannels;  ++c) {
        unsigned char *cdata = (unsigned char *)data + c*bpc;
        for (int x = 0;  x < m_spec.width;  ++x) {
            channeldata[x*bpc] = cdata[0];
            if (bpc == 2)
                channeldata[x*bpc+1] = cdata[1];
            cdata += m_spec.nchannels * bpc;  // advance to next pixel
        }
        if (bpc == 2 && littleendian())
            swap_endian ((unsigned short *)&channeldata[0], m_spec.width);
        long scanline_offset = sgi_pvt::SGI_HEADER_LEN + (c * m_spec.height + y)
                                  * m_spec.width * bpc;
        fseek (m_fd, scanline_offset, SEEK_SET);
        if (!fwrite (&channeldata[0], 1, m_spec.width * bpc)) {
            return false;
        }
    }

    return true;    
}
Exemple #10
0
static void
convert_pack_bits (T *data, int nvals)
{
    const int BITS_FROM = sizeof(T)*8;
    T *in = data;
    T *out = in - 1;    // because we'll increment first time through

    int bitstofill = 0;
    // Invariant: the next value to convert is *in. We're going to write
    // the result of the conversion starting at *out, which still has
    // bitstofill bits left before moving on to the next slot.
    for (int i = 0; i < nvals; ++i) {
        // Grab the next value and convert it
        T val = bit_range_convert<BITS_FROM,BITS_TO> (*in++);
        // If we have no more bits to fill in the slot, move on to the
        // next slot.
        if (bitstofill == 0) {
            ++out; *out = 0;        // move to next slot and clear its bits
            bitstofill = BITS_FROM; // all bits are for the taking
        }
        if (bitstofill >= BITS_TO) {
            // we can fit the whole val in this slot
            *out |= val << (bitstofill - BITS_TO);
            bitstofill -= BITS_TO;
            // printf ("\t\t%d bits left\n", bitstofill);
        } else {
            // not enough bits -- will need to split across slots
            int bitsinnext = BITS_TO - bitstofill;
            *out |= val >> bitsinnext;
            val &= (1 << bitsinnext) - 1;  // mask out bits we saved
            ++out; *out = 0;        // move to next slot and clear its bits
            *out |= val << (BITS_FROM - bitsinnext);
            bitstofill = BITS_FROM - bitsinnext;
        }
    }
    // Because we filled in a big-endian way, swap bytes if we need to
    if (littleendian())
        swap_endian (data, nvals);
}
Exemple #11
0
int savebmp(char *filename, unsigned char *buf, int w, int h,
	enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
{
	int fd=-1, byteswritten, dstpitch, retcode=0;
	int flags=O_RDWR|O_CREAT|O_TRUNC;
	unsigned char *tempbuf=NULL;  char *temp;
	bmphdr bh;  int mode;

	#ifdef _WIN32
	flags|=O_BINARY;  mode=_S_IREAD|_S_IWRITE;
	#else
	mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
	#endif
	if(!filename || !buf || w<1 || h<1 || f<0 || f>BMPPIXELFORMATS-1 || srcpitch<0)
		_throw("bad argument to savebmp()");

	if(srcpitch==0) srcpitch=w*ps[f];

	if((temp=strrchr(filename, '.'))!=NULL)
	{
		if(!stricmp(temp, ".ppm"))
			return saveppm(filename, buf, w, h, f, srcpitch, srcbottomup);
	}

	_unix(fd=open(filename, flags, mode));
	dstpitch=((w*3)+3)&(~3);

	bh.bfType=0x4d42;
	bh.bfSize=BMPHDRSIZE+dstpitch*h;
	bh.bfReserved1=0;  bh.bfReserved2=0;
	bh.bfOffBits=BMPHDRSIZE;
	bh.biSize=40;
	bh.biWidth=w;  bh.biHeight=h;
	bh.biPlanes=0;  bh.biBitCount=24;
	bh.biCompression=BI_RGB;  bh.biSizeImage=0;
	bh.biXPelsPerMeter=0;  bh.biYPelsPerMeter=0;
	bh.biClrUsed=0;  bh.biClrImportant=0;

	if(!littleendian())
	{
		bh.bfType=byteswap16(bh.bfType);
		bh.bfSize=byteswap(bh.bfSize);
		bh.bfOffBits=byteswap(bh.bfOffBits);
		bh.biSize=byteswap(bh.biSize);
		bh.biWidth=byteswap(bh.biWidth);
		bh.biHeight=byteswap(bh.biHeight);
		bh.biPlanes=byteswap16(bh.biPlanes);
		bh.biBitCount=byteswap16(bh.biBitCount);
		bh.biCompression=byteswap(bh.biCompression);
		bh.biSizeImage=byteswap(bh.biSizeImage);
		bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
		bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
		bh.biClrUsed=byteswap(bh.biClrUsed);
		bh.biClrImportant=byteswap(bh.biClrImportant);
	}

	writeme(fd, &bh.bfType, sizeof(unsigned short));
	writeme(fd, &bh.bfSize, sizeof(unsigned int));
	writeme(fd, &bh.bfReserved1, sizeof(unsigned short));
	writeme(fd, &bh.bfReserved2, sizeof(unsigned short));
	writeme(fd, &bh.bfOffBits, sizeof(unsigned int));
	writeme(fd, &bh.biSize, sizeof(unsigned int));
	writeme(fd, &bh.biWidth, sizeof(int));
	writeme(fd, &bh.biHeight, sizeof(int));
	writeme(fd, &bh.biPlanes, sizeof(unsigned short));
	writeme(fd, &bh.biBitCount, sizeof(unsigned short));
	writeme(fd, &bh.biCompression, sizeof(unsigned int));
	writeme(fd, &bh.biSizeImage, sizeof(unsigned int));
	writeme(fd, &bh.biXPelsPerMeter, sizeof(int));
	writeme(fd, &bh.biYPelsPerMeter, sizeof(int));
	writeme(fd, &bh.biClrUsed, sizeof(unsigned int));
	writeme(fd, &bh.biClrImportant, sizeof(unsigned int));

	if((tempbuf=(unsigned char *)malloc(dstpitch*h))==NULL)
		_throw("Memory allocation error");

	pixelconvert(buf, f, srcpitch, tempbuf, BMP_BGR, dstpitch, w, h, 
		!srcbottomup);

	if((byteswritten=write(fd, tempbuf, dstpitch*h))!=dstpitch*h)
		_throw(strerror(errno));

	finally:
	if(tempbuf) free(tempbuf);
	if(fd!=-1) close(fd);
	return retcode;
}
Exemple #12
0
int loadbmp(char *filename, unsigned char **buf, int *w, int *h, 
	enum BMPPIXELFORMAT f, int align, int dstbottomup)
{
	int fd=-1, bytesread, srcpitch, srcbottomup=1, srcps, dstpitch,
		retcode=0;
	unsigned char *tempbuf=NULL;
	bmphdr bh;  int flags=O_RDONLY;

	dstbottomup=dstbottomup? 1:0;
	#ifdef _WIN32
	flags|=O_BINARY;
	#endif
	if(!filename || !buf || !w || !h || f<0 || f>BMPPIXELFORMATS-1 || align<1)
		_throw("invalid argument to loadbmp()");
	if((align&(align-1))!=0)
		_throw("Alignment must be a power of 2");
	_unix(fd=open(filename, flags));

	readme(fd, &bh.bfType, sizeof(unsigned short));
	if(!littleendian())	bh.bfType=byteswap16(bh.bfType);

	if(bh.bfType==0x3650)
	{
		_catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 0));
		goto finally;
	}
	if(bh.bfType==0x3350)
	{
		_catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 1));
		goto finally;
	}

	readme(fd, &bh.bfSize, sizeof(unsigned int));
	readme(fd, &bh.bfReserved1, sizeof(unsigned short));
	readme(fd, &bh.bfReserved2, sizeof(unsigned short));
	readme(fd, &bh.bfOffBits, sizeof(unsigned int));
	readme(fd, &bh.biSize, sizeof(unsigned int));
	readme(fd, &bh.biWidth, sizeof(int));
	readme(fd, &bh.biHeight, sizeof(int));
	readme(fd, &bh.biPlanes, sizeof(unsigned short));
	readme(fd, &bh.biBitCount, sizeof(unsigned short));
	readme(fd, &bh.biCompression, sizeof(unsigned int));
	readme(fd, &bh.biSizeImage, sizeof(unsigned int));
	readme(fd, &bh.biXPelsPerMeter, sizeof(int));
	readme(fd, &bh.biYPelsPerMeter, sizeof(int));
	readme(fd, &bh.biClrUsed, sizeof(unsigned int));
	readme(fd, &bh.biClrImportant, sizeof(unsigned int));

	if(!littleendian())
	{
		bh.bfSize=byteswap(bh.bfSize);
		bh.bfOffBits=byteswap(bh.bfOffBits);
		bh.biSize=byteswap(bh.biSize);
		bh.biWidth=byteswap(bh.biWidth);
		bh.biHeight=byteswap(bh.biHeight);
		bh.biPlanes=byteswap16(bh.biPlanes);
		bh.biBitCount=byteswap16(bh.biBitCount);
		bh.biCompression=byteswap(bh.biCompression);
		bh.biSizeImage=byteswap(bh.biSizeImage);
		bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
		bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
		bh.biClrUsed=byteswap(bh.biClrUsed);
		bh.biClrImportant=byteswap(bh.biClrImportant);
	}

	if(bh.bfType!=0x4d42 || bh.bfOffBits<BMPHDRSIZE
	|| bh.biWidth<1 || bh.biHeight==0)
		_throw("Corrupt bitmap header");
	if((bh.biBitCount!=24 && bh.biBitCount!=32) || bh.biCompression!=BI_RGB)
		_throw("Only uncompessed RGB bitmaps are supported");

	*w=bh.biWidth;  *h=bh.biHeight;  srcps=bh.biBitCount/8;
	if(*h<0) {*h=-(*h);  srcbottomup=0;}
	srcpitch=(((*w)*srcps)+3)&(~3);
	dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));

	if(srcpitch*(*h)+bh.bfOffBits!=bh.bfSize) _throw("Corrupt bitmap header");
	if((tempbuf=(unsigned char *)malloc(srcpitch*(*h)))==NULL
	|| (*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
		_throw("Memory allocation error");
	if(lseek(fd, (long)bh.bfOffBits, SEEK_SET)!=(long)bh.bfOffBits)
		_throw(strerror(errno));
	_unix(bytesread=read(fd, tempbuf, srcpitch*(*h)));
	if(bytesread!=srcpitch*(*h)) _throw("Read error");

	pixelconvert(tempbuf, BMP_BGR, srcpitch, *buf, f, dstpitch, *w, *h, 
		srcbottomup!=dstbottomup);

	finally:
	if(tempbuf) free(tempbuf);
	if(fd!=-1) close(fd);
	return retcode;
}
Exemple #13
0
int main(int argc,char * argv[])
    {
    int b1,b2,b3 = 0;
    FILE * fi = stdin;
    if(argc > 1)
        {
        fi = fopen(argv[1],"rb");
        }
    if(argc > 2)
        {
        type = argv[2];
        char * valid[] =
            {"LE"
            ,"BE"
            ,"UCS-2"
            ,"UCS-2-LE"
            ,"UCS-2-BE"
            ,"BIN"
            ,"UTF-16"
            ,"UTF-16-LE"
            ,"UTF-16-BE"
            ,"ASCII"
            ,"ISO"
            ,"UTF-8"
            ,"UTF-8-BOM"
            };
        int i;
        for(i = sizeof(valid)/sizeof(valid[0]);--i >= 0;)
            if(!strcmp(type,valid[i]))
                break;
        if(i < 0)
            {
            printf("second argument must be one of:\n");
            for(i = 0;i < sizeof(valid)/sizeof(valid[0]);++i)
                printf("%s\n",valid[i]);
            return 1;
            }
        }
    if(!fi)
        {
        printf("Cannot open input %s\n",argv[1]);
        return 1;
        }
    makeDuples();
    b1 = fgetc(fi);
    b2 = fgetc(fi);

    if(b1 == 0xff && b2 == 0xfe)
        {
        if(type[0])
            {
            le = true;
            if(!strcmp(type,"LE"))
                result = 1;
            }
        else
            {
            printf("Byte order: little endian\n");
            }
        littleendian(fi);
        }
    else if(b1 == 0xfe && b2 == 0xff)
        {
        bigendian(fi,true);
        }
    else if(b1 == 0 || b2 == 0) // No BOM, but still looks like UTF-16
        { // assume big endian
        surrogate((b1 << 8) + b2);
        bigendian(fi,false);
        }
    else
        {
        FILE * ftempInput = tmpfile();
        b3 = fgetc(fi);
        if(b3 == 0)// No BOM, but still looks like UTF-16
            { // assume big endian
            surrogate((b1 << 8) + b2);
            surrogate((b3 << 8) + fgetc(fi));
            bigendian(fi,false);
            }
        else
            {
            if(b1 == 0xEF && b2 == 0xBB && b3 == 0xBF) // BOM found, probably UTF8
                {
                ;// remove BOM
                }
            else
                {
                fputc(b1,ftempInput);
                fputc(b2,ftempInput);
                fputc(b3,ftempInput);
                b1 = b2 = b3 = 0;
                }

            int k;
            bool zeroFound = false;
            while((k = fgetc(fi)) != EOF)
                {
                if(k == 0)
                    zeroFound = true;
                fputc(k,ftempInput);
                }
            rewind(ftempInput);
            if(zeroFound)
                {
                if(b1 && b2 && b3)
                    {
                    surrogate((b1 << 8) + b2);
                    surrogate((b3 << 8) + fgetc(ftempInput));
                    }
                bigendian(ftempInput,false);
                }
            else
                {
                bool bom = false;
                if(b1 && b2 && b3)
                    {
                    if(type[0])
                        {
                        bom = true;
                        }
                    else
                        printf("BOM found, but not UTF-16. (UTF-8 file created in Windows?)\n");
                    }
                if(UTF8(ftempInput))
                    {
                    utf8 = true;
                    if(ascii)
                        {
                        if(type[0])
                            {
                            if(  !bom && (!strcmp(type,"ASCII") || !strcmp(type,"ISO"))
                              || !strcmp(type,"UTF-8") || bom && !strcmp(type,"UTF-8-BOM")
                              )
                                result = 1;
                            }
                        else
                            {
                            printf("encoding: ASCII (subset of UTF-8 and all ISO-8859 encodings)\n");
                            }
                        }
                    else
                        {
                        if(type[0])
                            {
                            if(!strcmp(type,"UTF-8") || bom && !strcmp(type,"UTF-8-BOM"))
                                result = 1;
                            }
                        else
                            {
                            printf("encoding: UTF-8\n");
                            }
                        }
                    }
                else
                    {
                    int c = 0;
                    while((k = fgetc(ftempInput)) != EOF)
                        getbyte(k);
                    if(type[0])
                        {
                        if(!bom && (!strcmp(type,"ASCII") || !strcmp(type,"ISO")))
                            result = 1;
                        }
                    else
                        {
                        printf("encoding: 8-bits\n");
                        }
                    }
                }
            }
        }
    if(fi != stdin)
        fclose(fi);
    if(!type[0])
        fprintf(stderr,"%s",report());
    if(!utf8 && ascii)
        if(!type[0])
            printf("File could have been encoded in ASCII!\n");
    deleteDuples();
    if(type[0])
        {
        printf("[%d]\t%s\n",result,argv[1]);
        }
    return 0;
    }
Exemple #14
0
bool
DPXOutput::open (const std::string &name, const ImageSpec &userspec,
                 OpenMode mode)
{
    close ();  // Close any already-opened file

    if (mode != Create) {
        error ("%s does not support subimages or MIP levels", format_name());
        return false;
    }

    m_spec = userspec;  // Stash the spec

    // open the image
    m_stream = new OutStream();
    if (! m_stream->Open(name.c_str ())) {
        error ("Could not open file \"%s\"", name.c_str ());
        return false;
    }

    // Check for things this format doesn't support
    if (m_spec.width < 1 || m_spec.height < 1) {
        error ("Image resolution must be at least 1x1, you asked for %d x %d",
                       m_spec.width, m_spec.height);
                       return false;
    }

    if (m_spec.depth < 1)
        m_spec.depth = 1;
    else if (m_spec.depth > 1) {
        error ("DPX does not support volume images (depth > 1)");
        return false;
    }

    if (m_spec.format == TypeDesc::UINT8
        || m_spec.format == TypeDesc::INT8)
        m_datasize = dpx::kByte;
    else if (m_spec.format == TypeDesc::UINT16
        || m_spec.format == TypeDesc::INT16)
        m_datasize = dpx::kWord;
    else if (m_spec.format == TypeDesc::FLOAT
        || m_spec.format == TypeDesc::HALF) {
        m_spec.format = TypeDesc::FLOAT;
        m_datasize = dpx::kFloat;
    } else if (m_spec.format == TypeDesc::DOUBLE)
        m_datasize = dpx::kDouble;
    else {
        // use 16-bit unsigned integers as a failsafe
        m_spec.format = TypeDesc::UINT16;
        m_datasize = dpx::kWord;
    }

    // check if the client is giving us raw data to write
    m_wantRaw = m_spec.get_int_attribute ("dpx:RawData", 0) != 0;
    
    // check if the client wants endianness reverse to native
    // assume big endian per Jeremy's request, unless little endian is
    // explicitly specified
    std::string tmpstr = m_spec.get_string_attribute ("oiio:Endian", littleendian() ? "little" : "big");
    m_wantSwap = (littleendian() != Strutil::iequals (tmpstr, "little"));

    m_dpx.SetOutStream (m_stream);

    // start out the file
    m_dpx.Start ();

    // some metadata
    std::string project = m_spec.get_string_attribute ("DocumentName", "");
    std::string copyright = m_spec.get_string_attribute ("Copyright", "");
    tmpstr = m_spec.get_string_attribute ("DateTime", "");
    if (tmpstr.size () >= 19) {
        // libdpx's date/time format is pretty close to OIIO's (libdpx uses
        // %Y:%m:%d:%H:%M:%S%Z)
        // NOTE: the following code relies on the DateTime attribute being properly
        // formatted!
        // assume UTC for simplicity's sake, fix it if someone complains
        tmpstr[10] = ':';
        tmpstr.replace (19, -1, "Z");
    }
    m_dpx.SetFileInfo (name.c_str (),                       // filename
        tmpstr.c_str (),                                    // cr. date
        OIIO_INTRO_STRING,                                  // creator
        project.empty () ? NULL : project.c_str (),         // project
        copyright.empty () ? NULL : copyright.c_str (),     // copyright
        m_spec.get_int_attribute ("dpx:EncryptKey", ~0),    // encryption key
        m_wantSwap);

    // image info
    m_dpx.SetImageInfo (m_spec.width, m_spec.height);

    // determine descriptor
    m_desc = get_descriptor_from_string
        (m_spec.get_string_attribute ("dpx:ImageDescriptor", ""));

    // transfer function
    dpx::Characteristic transfer;
    
    std::string colorspace = m_spec.get_string_attribute ("oiio:ColorSpace", "");
    if (Strutil::iequals (colorspace, "Linear"))  transfer = dpx::kLinear;
    else if (Strutil::iequals (colorspace, "GammaCorrected")) transfer = dpx::kUserDefined;
    else if (Strutil::iequals (colorspace, "Rec709")) transfer = dpx::kITUR709;
    else if (Strutil::iequals (colorspace, "KodakLog")) transfer = dpx::kLogarithmic;
    else {
        std::string dpxtransfer = m_spec.get_string_attribute ("dpx:Transfer", "");
        transfer = get_characteristic_from_string (dpxtransfer);
    }
    
    // colorimetric
    m_cmetr = get_characteristic_from_string
        (m_spec.get_string_attribute ("dpx:Colorimetric", "User defined"));

    // select packing method
    dpx::Packing packing;
    tmpstr = m_spec.get_string_attribute ("dpx:Packing", "Filled, method A");
    if (Strutil::iequals (tmpstr, "Packed"))
        packing = dpx::kPacked;
    else if (Strutil::iequals (tmpstr, "Filled, method B"))
        packing = dpx::kFilledMethodB;
    else
        packing = dpx::kFilledMethodA;

    // calculate target bit depth
    int bitDepth = m_spec.format.size () * 8;
    if (m_spec.format == TypeDesc::UINT16) {
        bitDepth = m_spec.get_int_attribute ("oiio:BitsPerSample", 16);
        if (bitDepth != 10 && bitDepth != 12 && bitDepth != 16) {
            error ("Unsupported bit depth %d", bitDepth);
            return false;
        }
    }
    m_dpx.header.SetBitDepth (0, bitDepth);

    // Bug workaround: libDPX doesn't appear to correctly support
    // "filled method A" for 12 bit data.  Does anybody care what
    // packing/filling we use?  Punt and just use "packed".
    if (bitDepth == 12)
        packing = dpx::kPacked;
    
    // see if we'll need to convert or not
    if (m_desc == dpx::kRGB || m_desc == dpx::kRGBA) {
        // shortcut for RGB(A) that gets the job done
        m_bytes = m_spec.scanline_bytes ();
        m_wantRaw = true;
    } else {
        m_bytes = dpx::QueryNativeBufferSize (m_desc, m_datasize, m_spec.width, 1);
        if (m_bytes == 0 && !m_wantRaw) {
            error ("Unable to deliver native format data from source data");
            return false;
        } else if (m_bytes < 0) {
            // no need to allocate another buffer
            if (!m_wantRaw)
                m_bytes = m_spec.scanline_bytes ();
            else
                m_bytes = -m_bytes;
        }
    }

    if (m_bytes < 0)
        m_bytes = -m_bytes;

    m_dpx.SetElement (0, m_desc, bitDepth, transfer, m_cmetr,
        packing, dpx::kNone, (m_spec.format == TypeDesc::INT8
            || m_spec.format == TypeDesc::INT16) ? 1 : 0,
        m_spec.get_int_attribute ("dpx:LowData", 0xFFFFFFFF),
        m_spec.get_float_attribute ("dpx:LowQuantity", std::numeric_limits<float>::quiet_NaN()),
        m_spec.get_int_attribute ("dpx:HighData", 0xFFFFFFFF),
        m_spec.get_float_attribute ("dpx:HighQuantity", std::numeric_limits<float>::quiet_NaN()),
        m_spec.get_int_attribute ("dpx:EndOfLinePadding", 0),
        m_spec.get_int_attribute ("dpx:EndOfImagePadding", 0));

    m_dpx.header.SetXScannedSize (m_spec.get_float_attribute
        ("dpx:XScannedSize", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetYScannedSize (m_spec.get_float_attribute
        ("dpx:YScannedSize", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetFramePosition (m_spec.get_int_attribute
        ("dpx:FramePosition", 0xFFFFFFFF));
    m_dpx.header.SetSequenceLength (m_spec.get_int_attribute
        ("dpx:SequenceLength", 0xFFFFFFFF));
    m_dpx.header.SetHeldCount (m_spec.get_int_attribute
        ("dpx:HeldCount", 0xFFFFFFFF));
    m_dpx.header.SetFrameRate (m_spec.get_float_attribute
        ("dpx:FrameRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetShutterAngle (m_spec.get_float_attribute
        ("dpx:ShutterAngle", std::numeric_limits<float>::quiet_NaN()));
    // FIXME: should we write the input version through or always default to 2.0?
    /*tmpstr = m_spec.get_string_attribute ("dpx:Version", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetVersion (tmpstr.c_str ());*/
    tmpstr = m_spec.get_string_attribute ("dpx:Format", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetFormat (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:FrameId", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetFrameId (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:SlateInfo", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetSlateInfo (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:SourceImageFileName", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetSourceImageFileName (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:InputDevice", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetInputDevice (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:InputDeviceSerialNumber", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetInputDeviceSerialNumber (tmpstr.c_str ());
    m_dpx.header.SetInterlace (m_spec.get_int_attribute ("dpx:Interlace", 0xFF));
    m_dpx.header.SetFieldNumber (m_spec.get_int_attribute ("dpx:FieldNumber", 0xFF));
    m_dpx.header.SetHorizontalSampleRate (m_spec.get_float_attribute
        ("dpx:HorizontalSampleRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetVerticalSampleRate (m_spec.get_float_attribute
        ("dpx:VerticalSampleRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetTemporalFrameRate (m_spec.get_float_attribute
        ("dpx:TemporalFrameRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetTimeOffset (m_spec.get_float_attribute
        ("dpx:TimeOffset", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetBlackLevel (m_spec.get_float_attribute
        ("dpx:BlackLevel", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetBlackGain (m_spec.get_float_attribute
        ("dpx:BlackGain", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetBreakPoint (m_spec.get_float_attribute
        ("dpx:BreakPoint", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetWhiteLevel (m_spec.get_float_attribute
        ("dpx:WhiteLevel", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetIntegrationTimes (m_spec.get_float_attribute
        ("dpx:IntegrationTimes", std::numeric_limits<float>::quiet_NaN()));
    float aspect = m_spec.get_float_attribute ("PixelAspectRatio", 1.0f);
    int aspect_num, aspect_den;
    float_to_rational (aspect, aspect_num, aspect_den);
    m_dpx.header.SetAspectRatio (0, aspect_num);
    m_dpx.header.SetAspectRatio (1, aspect_den);

    tmpstr = m_spec.get_string_attribute ("dpx:TimeCode", "");
    int tmpint = m_spec.get_int_attribute ("dpx:TimeCode", ~0);
    if (tmpstr.size () > 0)
        m_dpx.header.SetTimeCode (tmpstr.c_str ());
    else if (tmpint != ~0)
        m_dpx.header.timeCode = tmpint;
    m_dpx.header.userBits = m_spec.get_int_attribute ("dpx:UserBits", ~0);
    tmpstr = m_spec.get_string_attribute ("dpx:SourceDateTime", "");
    if (tmpstr.size () >= 19) {
        // libdpx's date/time format is pretty close to OIIO's (libdpx uses
        // %Y:%m:%d:%H:%M:%S%Z)
        // NOTE: the following code relies on the DateTime attribute being properly
        // formatted!
        // assume UTC for simplicity's sake, fix it if someone complains
        tmpstr[10] = ':';
        tmpstr.replace (19, -1, "Z");
        m_dpx.header.SetSourceTimeDate (tmpstr.c_str ());
    }
    
    // commit!
    if (!m_dpx.WriteHeader ()) {
        error ("Failed to write DPX header");
        return false;
    }

    // user data
    ImageIOParameter *user = m_spec.find_attribute ("dpx:UserData");
    if (user && user->datasize () > 0) {
        if (user->datasize () > 1024 * 1024) {
            error ("User data block size exceeds 1 MB");
            return false;
        }
        // FIXME: write the missing libdpx code
        /*m_dpx.SetUserData (user->datasize ());
        if (!m_dpx.WriteUserData ((void *)user->data ())) {
            error ("Failed to write user data");
            return false;
        }*/
    }

    // reserve space for the image data buffer
    m_buf.reserve (m_bytes * m_spec.height);

    return true;
}
Exemple #15
0
int main(int argc,char * argv[])
    {
    int b1,b2,b3 = 0;
    FILE * fi = stdin;
    FILE * fo = stdout;
    if(argc > 1)
        {
        fi = fopen(argv[1],"rb");
        if(argc > 2)
            fo = fopen(argv[2],"wb");
        }
    if(!fi || !fo)
        return 1;
    makeDuples();
    b1 = fgetc(fi);
    b2 = fgetc(fi);
    if(b1 == 0xff && b2 == 0xfe)
        littleendian(fi,fo);
    else if(b1 == 0xfe && b2 == 0xff)
        bigendian(fi,fo);
    else if(b1 == 0 || b2 == 0) // No BOM, but still looks like UTF-16
        { // assume big endian
        surrogate((b1 << 8) + b2,fo);
        bigendian(fi,fo);
        }
    else
        {
        FILE * ftempInput = tmpfile();
        b3 = fgetc(fi);
        if(b3 == 0)// No BOM, but still looks like UTF-16
            { // assume big endian
            surrogate((b1 << 8) + b2,fo);
            surrogate((b3 << 8) + fgetc(fi),fo);
            bigendian(fi,fo);
            }
        else
            {
            if(b1 == 0xEF && b2 == 0xBB && b3 == 0xBF) // BOM found, probably UTF8
                ; // remove BOM
            else
                {
                fputc(b1,ftempInput);
                fputc(b2,ftempInput);
                fputc(b3,ftempInput);
                b1 = b2 = b3 = 0;
                }

            int k;
            bool zeroFound = false;
            while((k = fgetc(fi)) != EOF)
                {
                if(k == 0)
                    zeroFound = true;
                fputc(k,ftempInput);
                }
            rewind(ftempInput);
            if(zeroFound)
                {
                if(b1 && b2 && b3)
                    {
                    surrogate((b1 << 8) + b2,fo);
                    surrogate((b3 << 8) + fgetc(ftempInput),fo);
                    }
                bigendian(ftempInput,fo);
                }
            else if(!UTF8(ftempInput,fo))
                {
                rewind(ftempInput);
                if(b1 && b2 && b3) // "BOM" found, but not in UTF8 file!
                    { // write "BOM"
                    fputc(b1,fo);
                    fputc(b2,fo);
                    fputc(b3,fo);
                    }
                copy(ftempInput,fo);
                }
            }
        }
    if(fi != stdin)
        fclose(fi);
    if(fo != stdout)
        fclose(fo);
    fprintf(stderr,"%s",report());
    deleteDuples();
    return 0;
    }
Exemple #16
0
bool
DPXOutput::open (const std::string &name, const ImageSpec &userspec,
                 OpenMode mode)
{
    if (mode == Create) {
        m_subimage = 0;
        if (m_subimage_specs.size() < 1) {
            m_subimage_specs.resize (1);
            m_subimage_specs[0] = userspec;
            m_subimages_to_write = 1;
        }
    } else if (mode == AppendSubimage) {
        if (m_write_pending)
            write_buffer ();
        ++m_subimage;
        if (m_subimage >= m_subimages_to_write) {
            error ("Exceeded the pre-declared number of subimages (%d)",
                   m_subimages_to_write);
            return false;
        }
        return prep_subimage (m_subimage, true);
        // Nothing else to do, the header taken care of when we opened with
        // Create.
    } else if (mode == AppendMIPLevel) {
        error ("DPX does not support MIP-maps");
        return false;
    }

    // From here out, all the heavy lifting is done for Create
    ASSERT (mode == Create);

    if (is_opened())
        close ();  // Close any already-opened file
    m_stream = new OutStream();
    if (! m_stream->Open(name.c_str ())) {
        error ("Could not open file \"%s\"", name.c_str ());
        return false;
    }
    m_dpx.SetOutStream (m_stream);
    m_dpx.Start ();
    m_subimage = 0;

    ImageSpec &m_spec (m_subimage_specs[m_subimage]); // alias the spec

    // Check for things this format doesn't support
    if (m_spec.width < 1 || m_spec.height < 1) {
        error ("Image resolution must be at least 1x1, you asked for %d x %d",
               m_spec.width, m_spec.height);
        return false;
    }

    if (m_spec.depth < 1)
        m_spec.depth = 1;
    else if (m_spec.depth > 1) {
        error ("DPX does not support volume images (depth > 1)");
        return false;
    }

    // some metadata
    std::string software = m_spec.get_string_attribute ("Software", "");
    std::string project = m_spec.get_string_attribute ("DocumentName", "");
    std::string copyright = m_spec.get_string_attribute ("Copyright", "");
    std::string datestr = m_spec.get_string_attribute ("DateTime", "");
    if (datestr.size () >= 19) {
        // libdpx's date/time format is pretty close to OIIO's (libdpx uses
        // %Y:%m:%d:%H:%M:%S%Z)
        // NOTE: the following code relies on the DateTime attribute being properly
        // formatted!
        // assume UTC for simplicity's sake, fix it if someone complains
        datestr[10] = ':';
        datestr.replace (19, -1, "Z");
    }

    // check if the client wants endianness reverse to native
    // assume big endian per Jeremy's request, unless little endian is
    // explicitly specified
    std::string endian = m_spec.get_string_attribute ("oiio:Endian", littleendian() ? "little" : "big");
    m_wantSwap = (littleendian() != Strutil::iequals (endian, "little"));

    m_dpx.SetFileInfo (name.c_str (),                               // filename
        datestr.c_str (),                                           // cr. date
        software.empty () ? OIIO_INTRO_STRING : software.c_str (),  // creator
        project.empty () ? NULL : project.c_str (),                 // project
        copyright.empty () ? NULL : copyright.c_str (),             // copyright
        m_spec.get_int_attribute ("dpx:EncryptKey", ~0),            // encryption key
        m_wantSwap);

    // image info
    m_dpx.SetImageInfo (m_spec.width, m_spec.height);

    for (int s = 0;  s < m_subimages_to_write;  ++s) {
        prep_subimage (s, false);
        m_dpx.header.SetBitDepth (s, m_bitdepth);
        ImageSpec &spec (m_subimage_specs[s]);
        bool datasign = (spec.format == TypeDesc::INT8 ||
                         spec.format == TypeDesc::INT16);
        m_dpx.SetElement (s, m_desc, m_bitdepth, m_transfer, m_cmetr,
                          m_packing, dpx::kNone, datasign,
                          spec.get_int_attribute ("dpx:LowData", 0xFFFFFFFF),
                          spec.get_float_attribute ("dpx:LowQuantity", std::numeric_limits<float>::quiet_NaN()),
                          spec.get_int_attribute ("dpx:HighData", 0xFFFFFFFF),
                          spec.get_float_attribute ("dpx:HighQuantity", std::numeric_limits<float>::quiet_NaN()),
                          spec.get_int_attribute ("dpx:EndOfLinePadding", 0),
                          spec.get_int_attribute ("dpx:EndOfImagePadding", 0));
        std::string desc = spec.get_string_attribute ("ImageDescription", "");
        m_dpx.header.SetDescription (s, desc.c_str());
    }

    m_dpx.header.SetXScannedSize (m_spec.get_float_attribute
        ("dpx:XScannedSize", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetYScannedSize (m_spec.get_float_attribute
        ("dpx:YScannedSize", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetFramePosition (m_spec.get_int_attribute
        ("dpx:FramePosition", 0xFFFFFFFF));
    m_dpx.header.SetSequenceLength (m_spec.get_int_attribute
        ("dpx:SequenceLength", 0xFFFFFFFF));
    m_dpx.header.SetHeldCount (m_spec.get_int_attribute
        ("dpx:HeldCount", 0xFFFFFFFF));
    m_dpx.header.SetFrameRate (m_spec.get_float_attribute
        ("dpx:FrameRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetShutterAngle (m_spec.get_float_attribute
        ("dpx:ShutterAngle", std::numeric_limits<float>::quiet_NaN()));
    // FIXME: should we write the input version through or always default to 2.0?
    /*tmpstr = m_spec.get_string_attribute ("dpx:Version", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetVersion (tmpstr.c_str ());*/
    std::string tmpstr;
    tmpstr = m_spec.get_string_attribute ("dpx:FrameId", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetFrameId (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:SlateInfo", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetSlateInfo (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:SourceImageFileName", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetSourceImageFileName (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:InputDevice", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetInputDevice (tmpstr.c_str ());
    tmpstr = m_spec.get_string_attribute ("dpx:InputDeviceSerialNumber", "");
    if (tmpstr.size () > 0)
        m_dpx.header.SetInputDeviceSerialNumber (tmpstr.c_str ());
    m_dpx.header.SetInterlace (m_spec.get_int_attribute ("dpx:Interlace", 0xFF));
    m_dpx.header.SetFieldNumber (m_spec.get_int_attribute ("dpx:FieldNumber", 0xFF));
    m_dpx.header.SetHorizontalSampleRate (m_spec.get_float_attribute
        ("dpx:HorizontalSampleRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetVerticalSampleRate (m_spec.get_float_attribute
        ("dpx:VerticalSampleRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetTemporalFrameRate (m_spec.get_float_attribute
        ("dpx:TemporalFrameRate", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetTimeOffset (m_spec.get_float_attribute
        ("dpx:TimeOffset", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetBlackLevel (m_spec.get_float_attribute
        ("dpx:BlackLevel", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetBlackGain (m_spec.get_float_attribute
        ("dpx:BlackGain", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetBreakPoint (m_spec.get_float_attribute
        ("dpx:BreakPoint", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetWhiteLevel (m_spec.get_float_attribute
        ("dpx:WhiteLevel", std::numeric_limits<float>::quiet_NaN()));
    m_dpx.header.SetIntegrationTimes (m_spec.get_float_attribute
        ("dpx:IntegrationTimes", std::numeric_limits<float>::quiet_NaN()));
    float aspect = m_spec.get_float_attribute ("PixelAspectRatio", 1.0f);
    int aspect_num, aspect_den;
    float_to_rational (aspect, aspect_num, aspect_den);
    m_dpx.header.SetAspectRatio (0, aspect_num);
    m_dpx.header.SetAspectRatio (1, aspect_den);
    m_dpx.header.SetXOffset ((unsigned int)std::max (0, m_spec.x));
    m_dpx.header.SetYOffset ((unsigned int)std::max (0, m_spec.y));
    m_dpx.header.SetXOriginalSize ((unsigned int)m_spec.full_width);
    m_dpx.header.SetYOriginalSize ((unsigned int)m_spec.full_height);

    static int DpxOrientations[] = { 0,
        dpx::kLeftToRightTopToBottom, dpx::kRightToLeftTopToBottom,
        dpx::kLeftToRightBottomToTop, dpx::kRightToLeftBottomToTop,
        dpx::kTopToBottomLeftToRight, dpx::kTopToBottomRightToLeft,
        dpx::kBottomToTopLeftToRight, dpx::kBottomToTopRightToLeft };
    int orient = m_spec.get_int_attribute ("Orientation", 0);
    orient = DpxOrientations[clamp (orient, 0, 8)];
    m_dpx.header.SetImageOrientation ((dpx::Orientation)orient);

    ImageIOParameter *tc = m_spec.find_attribute("smpte:TimeCode", TypeDesc::TypeTimeCode, false);
    if (tc) {
        unsigned int *timecode = (unsigned int*) tc->data();
        m_dpx.header.timeCode = timecode[0];
        m_dpx.header.userBits = timecode[1];
    }
    else {
        std::string timecode = m_spec.get_string_attribute ("dpx:TimeCode", "");
        int tmpint = m_spec.get_int_attribute ("dpx:TimeCode", ~0);
        if (timecode.size () > 0)
            m_dpx.header.SetTimeCode (timecode.c_str ());
        else if (tmpint != ~0)
        m_dpx.header.timeCode = tmpint;
        m_dpx.header.userBits = m_spec.get_int_attribute ("dpx:UserBits", ~0);
    }

    ImageIOParameter *kc = m_spec.find_attribute("smpte:KeyCode", TypeDesc::TypeKeyCode, false);
    if (kc) {
        int *array = (int*) kc->data();
        set_keycode_values(array);

        // See if there is an overloaded dpx:Format
        std::string format = m_spec.get_string_attribute ("dpx:Format", "");
        if (format.size () > 0)
            m_dpx.header.SetFormat (format.c_str ());
    }

    std::string srcdate = m_spec.get_string_attribute ("dpx:SourceDateTime", "");
    if (srcdate.size () >= 19) {
        // libdpx's date/time format is pretty close to OIIO's (libdpx uses
        // %Y:%m:%d:%H:%M:%S%Z)
        // NOTE: the following code relies on the DateTime attribute being properly
        // formatted!
        // assume UTC for simplicity's sake, fix it if someone complains
        srcdate[10] = ':';
        srcdate.replace (19, -1, "Z");
        m_dpx.header.SetSourceTimeDate (srcdate.c_str ());
    }

    // set the user data size
    ImageIOParameter *user = m_spec.find_attribute ("dpx:UserData");
    if (user && user->datasize () > 0 && user->datasize () <= 1024 * 1024) {
        m_dpx.SetUserData (user->datasize ());
    }

    // commit!
    if (!m_dpx.WriteHeader ()) {
        error ("Failed to write DPX header");
        return false;
    }

    // write the user data
    if (user && user->datasize () > 0 && user->datasize() <= 1024 * 1024) {
        if (!m_dpx.WriteUserData ((void *)user->data ())) {
            error ("Failed to write user data");
            return false;
        }
    }

    m_dither = (m_spec.format == TypeDesc::UINT8) ?
                    m_spec.get_int_attribute ("oiio:dither", 0) : 0;

    // If user asked for tiles -- which this format doesn't support, emulate
    // it by buffering the whole image.
    if (m_spec.tile_width && m_spec.tile_height)
        m_tilebuffer.resize (m_spec.image_bytes());

    return prep_subimage (m_subimage, true);
}
Exemple #17
0
void RRPlugin::sendvgl(rrdisplayclient *rrdpy, GLint drawbuf, bool spoillast,
                       int compress, int qual, int subsamp, bool block)
{

#if 0
   while(block && !rrdpy->frameready())
   {
      fprintf(stderr, "pause "); fflush(stderr);
      usleep(100000);
   }
#else
    (void)block;
#endif

    osgViewer::GraphicsWindow *win = coVRConfig::instance()->windows[0].window;
    int x, y, w, h;
    win->getWindowRectangle(x, y, w, h);

    if (spoillast && fconfig.spoil && !rrdpy->frameready())
        return;
    rrframe *b;
    int flags = RRBMP_BOTTOMUP, format = GL_RGB;
#ifdef GL_BGR_EXT
    if (littleendian() && compress != RRCOMP_RGB)
    {
        format = GL_BGR_EXT;
        flags |= RRBMP_BGR;
    }
#endif
    if (m_cudaReadBack && m_cudapinnedmemory)
        flags |= RRBMP_CUDAALLOC;
    errifnot(b = rrdpy->getbitmap(w, h, 3, flags,
                                  false /*stereo*/, fconfig.spoil));

    GLint buf = drawbuf;

    //b->_h.winid=_win;
    b->_h.dpynum = 0;
    b->_h.winid = 0;
    b->_h.framew = b->_h.width;
    b->_h.frameh = b->_h.height;
    b->_h.x = 0;
    b->_h.y = 0;
    b->_h.qual = qual;
    b->_h.subsamp = subsamp;
    b->_h.compress = (unsigned char)compress;

    double start = 0.;
    if (benchmark)
        start = cover->currentTime();
    double bpp = 4.;
#ifdef HAVE_CUDA
    if (m_cudaReadBack)
    {
        int hs = tjMCUWidth[jpegsub(subsamp)] / 8;
        int vs = tjMCUHeight[jpegsub(subsamp)] / 8;
        if (fconfig.compress == RRCOMP_YUV2JPEG)
        {
            m_cudaReadBack->readpixelsyuv(0, 0, b->_h.framew, b->_pitch, b->_h.frameh, format,
                                          b->_pixelsize, b->_bits, buf, hs, vs);
            bpp = 1. + 2. / hs / vs;
        }
        else
            m_cudaReadBack->readpixels(0, 0, b->_h.framew, b->_pitch, b->_h.frameh, format,
                                       b->_pixelsize, b->_bits, buf);
    }
    else
#endif
        readpixels(0, 0, b->_h.framew, b->_pitch, b->_h.frameh, format,
                   b->_pixelsize, b->_bits, buf);
    double dur = 0.;
    if (benchmark)
        dur = cover->currentTime() - start;
    double pix = b->_h.framew * b->_h.frameh;
    double bytes = pix * bpp;
    if (benchmark)
        fprintf(stderr, "%fs: %f mpix/s, %f gb/s (cuda=%d, yuv=%d)\n",
                dur,
                pix / dur / 1e6, bytes / dur / (1024 * 1024 * 1024),
                m_cudaReadBack != NULL, fconfig.compress == RRCOMP_YUV2JPEG);
    //b->_h.winid=_win;
    b->_h.dpynum = 0;
    b->_h.winid = 0;
    b->_h.framew = b->_h.width;
    b->_h.frameh = b->_h.height;
    b->_h.x = 0;
    b->_h.y = 0;
    b->_h.qual = qual;
    b->_h.subsamp = subsamp;
    b->_h.compress = (unsigned char)compress;

    if (m_sendThread)
    {
        m_sendThread->send(rrdpy, b);
    }
    else
        rrdpy->sendframe(b);
}
Exemple #18
0
static void
exif_parser_cb (ImageSpec* spec, int tag, int tifftype, int len,
                unsigned int byteorder, LibRaw_abstract_datastream* ifp)
{
    // Oy, the data offsets are all going to be relative to the start of the
    // stream, not relative to our current position and data block. So we
    // need to remember that offset and pass its negative as the
    // offset_adjustment to the handler.
    size_t streampos = ifp->tell();
    // std::cerr << "Stream position " << streampos << "\n";

    TypeDesc type = tiff_datatype_to_typedesc (TIFFDataType(tifftype), size_t(len));
    const TagInfo* taginfo = tag_lookup ("Exif", tag);
    if (! taginfo) {
        // Strutil::fprintf (std::cerr, "NO TAGINFO FOR CALLBACK tag=%d (0x%x): tifftype=%d,len=%d (%s), byteorder=0x%x\n",
        //                   tag, tag, tifftype, len, type, byteorder);
        return;
    }
    if (type.size() >= (1<<20))
        return;   // sanity check -- too much memory
    size_t size = tiff_data_size(TIFFDataType(tifftype)) * len;
    std::vector<unsigned char> buf (size);
    ifp->read (buf.data(), size, 1);

    // debug scaffolding
    // Strutil::fprintf (std::cerr, "CALLBACK tag=%s: tifftype=%d,len=%d (%s), byteorder=0x%x\n",
    //                   taginfo->name, tifftype, len, type, byteorder);
    // for (int i = 0; i < std::min(16UL,size); ++i) {
    //     if (buf[i] >= ' ' && buf[i] < 128)
    //         std::cerr << char(buf[i]);
    //     Strutil::fprintf (std::cerr, "(%d) ", int(buf[i]));
    // }
    // std::cerr << "\n";

    bool swab = (littleendian() != (byteorder == 0x4949));
    if (swab) {
        if (type.basetype == TypeDesc::UINT16)
            swap_endian ((uint16_t *)buf.data(), len);
        if (type.basetype == TypeDesc::UINT32)
            swap_endian ((uint32_t *)buf.data(), len);
    }

    if (taginfo->handler) {
        TIFFDirEntry dir;
        dir.tdir_tag = uint16_t(tag);
        dir.tdir_type = uint16_t(tifftype);
        dir.tdir_count = uint32_t(len);
        dir.tdir_offset = 0;
        taginfo->handler (*taginfo, dir, buf, *spec, swab, -int(streampos));
        // std::cerr << "HANDLED " << taginfo->name << "\n";
        return;
    }
    if (taginfo->tifftype == TIFF_NOTYPE)
        return;   // skip
    if (tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) {
        spec->attribute (taginfo->name, type, buf.data());
        return;
    }
    if (type.basetype == TypeDesc::UINT16) {
        spec->attribute (taginfo->name, type, buf.data());
        return;
    }
    if (type.basetype == TypeDesc::UINT32) {
        spec->attribute (taginfo->name, type, buf.data());
        return;
    }
    if (type == TypeString) {
        spec->attribute (taginfo->name, string_view((char*)buf.data(), size));
        return;
    }
    // Strutil::fprintf (std::cerr, "RAW metadata NOT HANDLED: tag=%s: tifftype=%d,len=%d (%s), byteorder=0x%x\n",
    //                   taginfo->name, tifftype, len, type, byteorder);
}