void SaveTexture(	const std::string& _filename,
							float* _data,
							int _w,
							int _h,
							bool _verbose)
		{
			int xRes 	  = _w;
			int yRes 	  = _h;
			int xOffset   = 0;
			int yOffset   = 0;
			int nChannels = 4;

			Imf::Header header(xRes, yRes);
			Imath::Box2i dataWindow(Imath::V2i(xOffset, yOffset), Imath::V2i(xOffset + xRes - 1, yOffset + yRes - 1));
			header.dataWindow() = dataWindow;

			header.channels().insert("R", Imf::Channel (Imf::HALF));
			header.channels().insert("G", Imf::Channel (Imf::HALF));
			header.channels().insert("B", Imf::Channel (Imf::HALF));
			header.channels().insert("A", Imf::Channel (Imf::HALF));

			::half *hchannels   = new ::half[nChannels * xRes * yRes];
			for (int y = 0; y < yRes; ++y)
			for (int x = 0; x < xRes; ++x)
			for (int c = 0; c < nChannels; ++c)
			{
				int iSrc = c + x*nChannels + (yRes-1-y)*xRes*nChannels; 
				int iDst = c + x*nChannels + y*xRes*nChannels;
				hchannels[iDst] = _data[iSrc];
			}

			Imf::FrameBuffer fb;
			fb.insert("R", Imf::Slice(Imf::HALF, (char *)hchannels,						nChannels*sizeof(::half), nChannels*xRes*sizeof(::half)));
			fb.insert("G", Imf::Slice(Imf::HALF, (char *)hchannels+1*sizeof(::half),	nChannels*sizeof(::half), nChannels*xRes*sizeof(::half)));
			fb.insert("B", Imf::Slice(Imf::HALF, (char *)hchannels+2*sizeof(::half),	nChannels*sizeof(::half), nChannels*xRes*sizeof(::half)));
			fb.insert("A", Imf::Slice(Imf::HALF, (char *)hchannels+3*sizeof(::half),	nChannels*sizeof(::half), nChannels*xRes*sizeof(::half)));

			Imf::OutputFile file(_filename.c_str(), header);
			file.setFrameBuffer(fb);
			try 
			{
				file.writePixels(yRes);
			}
			catch (const std::exception &e) 
			{
				Error("Unable to write image file \"%s\": %s", _filename.c_str(), e.what());
				assert(false);
			}

			delete[] hchannels;
		}
Exemple #2
0
//---------------------------------------------------------------------------
void File_Exr::Data_Parse()
{
    
    if (CC4(Buffer+Buffer_Offset)==0x762F3101) //"v/1"+1 //Header
        Header();
    else if (name=="comments" && type=="string")
        comments();
    else if (name=="compression" && type=="compression" && Element_Size==1)
        compression();
    else if (name=="dataWindow" && type=="box2i" && Element_Size==16)
        dataWindow();
    else if (name=="displayWindow" && type=="box2i" && Element_Size==16)
        displayWindow();
    else if (name=="pixelAspectRatio" && type=="float" && Element_Size==4)
        pixelAspectRatio();
    else
        Skip_XX(Element_Size,                                   "value");
}
Exemple #3
0
//---------------------------------------------------------------------------
void File_Exr::Data_Parse()
{
         if (name_End==0)
        ImageData();
    else if (name=="channels" && type=="chlist")
        channels();
    else if (name=="comments" && type=="string")
        comments();
    else if (name=="compression" && type=="compression" && Element_Size==1)
        compression();
    else if (name=="dataWindow" && type=="box2i" && Element_Size==16)
        dataWindow();
    else if (name=="displayWindow" && type=="box2i" && Element_Size==16)
        displayWindow();
    else if (name=="pixelAspectRatio" && type=="float" && Element_Size==4)
        pixelAspectRatio();
    else
        Skip_XX(Element_Size,                                   "value");
}
Exemple #4
0
void
DPXCodec::decompress(const DataChunk &data)
{
	MemoryFile file(data);
	
	DPXCodec_InStream istream(file);
	
	dpx::Reader dpx;
	
	dpx.SetInStream(&istream);
	
	const bool header_read = dpx.ReadHeader();
	
	if(header_read)
	{
		const int dpx_width = dpx.header.Width();
		const int dpx_height = dpx.header.Height();
		const int dpx_channels = dpx.header.ImageElementComponentCount(0);
		
		assert(dpx_width == _descriptor.getStoredWidth());
		assert(dpx_height == _descriptor.getStoredHeight());
		assert(dpx_channels == (_channels == DPX_RGBA ? 4 : 3));
		
		
		const Box2i dataW = dataWindow();
		
		if(dpx_width != (dataW.max.x - dataW.min.x + 1))
			throw MoxMxf::InputExc("Stored data is wrong width");

		if(dpx_height != (dataW.max.y - dataW.min.y + 1))
			throw MoxMxf::InputExc("Stored data is wrong height");
		
		
		const size_t pixsize = (_depth == DPX_8 ? sizeof(unsigned char) : sizeof(unsigned short));
		const size_t rowbytes = dpx_width * pixsize * dpx_channels;
		const size_t buffer_size = rowbytes * dpx_height;
		
		DataChunkPtr frame_data = new DataChunk(buffer_size);
		
		char *origin = (char *)frame_data->Data;
		
		FrameBufferPtr frame_buffer = new FrameBuffer(dataW);
		
		const PixelType pixel_type = (_depth == DPX_8 ? MoxFiles::UINT8 : MoxFiles::UINT16);
		const size_t bytes_per_subpixel = PixelSize(pixel_type);
		const size_t bytes_per_pixel = bytes_per_subpixel * dpx_channels;
	
		frame_buffer->insert("R", Slice(pixel_type, origin + (bytes_per_subpixel * 0), bytes_per_pixel, rowbytes));
		frame_buffer->insert("G", Slice(pixel_type, origin + (bytes_per_subpixel * 1), bytes_per_pixel, rowbytes));
		frame_buffer->insert("B", Slice(pixel_type, origin + (bytes_per_subpixel * 2), bytes_per_pixel, rowbytes));
		
		if(_channels == DPX_RGBA)
			frame_buffer->insert("A", Slice(pixel_type, origin + (bytes_per_subpixel * 3), bytes_per_pixel, rowbytes));
			
		frame_buffer->attachData(frame_data);
		
		
		dpx::Block block(0, 0, dpx_width - 1, dpx_height - 1);
		
		const dpx::Descriptor dpx_desc = dpx.header.ImageDescriptor(0);
		const dpx::DataSize dpx_size = (_depth == DPX_8 ? dpx::kByte : dpx::kWord);
		
		const bool image_read = dpx.ReadBlock((void *)origin, dpx_size, block, dpx_desc);
		
		if(image_read)
		{
			storeFrame(frame_buffer);
		}
		else
			assert(false);
	}
	else
		assert(false);
}
Exemple #5
0
void
DPXCodec::compress(const FrameBuffer &frame)
{
	const PixelType pixel_type = (_depth == DPX_8 ? MoxFiles::UINT8 : MoxFiles::UINT16);
	const size_t bytes_per_subpixel = PixelSize(pixel_type);
	const int num_channels = (_channels == DPX_RGBA ? 4 : 3);
	
	const Box2i dataW = dataWindow();
	
	const int width = (dataW.max.x - dataW.min.x + 1);
	const int height = (dataW.max.y - dataW.min.y + 1);
	
	const size_t bytes_per_pixel = bytes_per_subpixel * num_channels;
	const size_t rowbytes = bytes_per_pixel * width;
	const size_t buffer_size = rowbytes * height;
	
	
	DataChunk data(buffer_size);
	
	FrameBuffer frame_buffer(dataW);
		
	char *origin = (char *)data.Data;
	
	frame_buffer.insert("R", Slice(pixel_type, origin + (bytes_per_subpixel * 0), bytes_per_pixel, rowbytes));
	frame_buffer.insert("G", Slice(pixel_type, origin + (bytes_per_subpixel * 1), bytes_per_pixel, rowbytes));
	frame_buffer.insert("B", Slice(pixel_type, origin + (bytes_per_subpixel * 2), bytes_per_pixel, rowbytes));
	
	if(_channels == DPX_RGBA)
		frame_buffer.insert("A", Slice(pixel_type, origin + (bytes_per_subpixel * 3), bytes_per_pixel, rowbytes));
	
	
	frame_buffer.copyFromFrame(frame);
	
	
	MemoryFile file(buffer_size);
	
	DPXCodec_OutStream ostream(file);
	
	dpx::Writer dpx;
	
	dpx.SetOutStream(&ostream);
	
	dpx.SetFileInfo("MOX",	// fileName
					NULL,			// creation time (set by libdpx)
					"DPXcodec, part of MOX", // creator
					NULL,			// project
					NULL,			// copyright
					~0,				// encryption key (0xffffffff means no encryption)
					false);			// don't swap byte order
	
	dpx.SetImageInfo(width, height);
	
	dpx.header.SetAspectRatio(0, _pixelAspectRatio.Numerator);
	dpx.header.SetAspectRatio(1, _pixelAspectRatio.Denominator);
	
	dpx.header.SetFrameRate((dpx::R32)_frameRate.Numerator / (dpx::R32)_frameRate.Denominator);
	
	//dpx.header.SetInterlace(info->field_label->type == FIEL_Type_FRAME_RENDERED ? 0 : 1);
	
	const unsigned int bit_depth = (_depth == DPX_8 ? 8 :
									_depth == DPX_10 ? 10 :
									_depth == DPX_12 ? 12 :
									_depth == DPX_16 ? 16 :
									10);
	
	const dpx::Descriptor dpx_desc = (_channels == DPX_RGBA ? dpx::kRGBA : dpx::kRGB);
	const dpx::Packing packing = ((bit_depth == 8 || bit_depth == 16) ? dpx::kPacked : dpx::kFilledMethodA);
	
	const dpx::Characteristic transfer = dpx::kLogarithmic;
	const dpx::Characteristic colorimetric = dpx::kLogarithmic;
	
	dpx.SetElement(0, dpx_desc, bit_depth, transfer, colorimetric, packing);
	
	
	const bool wrote_header = dpx.WriteHeader();
	
	if(!wrote_header)
		throw MoxMxf::ArgExc("Error writing header");
	

	const dpx::DataSize size = (pixel_type == MoxFiles::UINT16 ? dpx::kWord : dpx::kByte);
	
	const bool wrote_element = dpx.WriteElement(0, data.Data, size);
	
	if(!wrote_element)
		throw MoxMxf::ArgExc("Error writing image");
	
	
	const bool wrote_finish = dpx.Finish();
	
	if(!wrote_finish)
		throw MoxMxf::ArgExc("Error writing finish");
	
	
	storeData( file.getDataChunk() );
}
Exemple #6
0
void
JPEGLSCodec::decompress(const DataChunk &data)
{
	ByteStreamInfo inStream = FromByteArray(data.Data, data.Size);
	
	
	struct JlsParameters info;
	
	JLS_ERROR err = JpegLsReadHeaderStream(inStream, &info);
	
	if(err == OK)
	{
		const int width = info.width;
		const int height = info.height;
		
		assert(info.components == (_channels == JPEGLS_RGBA ? 4 : 3));
		assert(info.colorTransform == COLORXFORM_NONE);
		
		const PixelType pixType = (_depth == JPEGLS_8 ? UINT8 :
									_depth == JPEGLS_10 ? UINT10 :
									_depth == JPEGLS_12 ? UINT12 :
									_depth == JPEGLS_16 ? UINT16 :
									UINT8);
		
		const size_t pixSize = PixelSize(pixType);
		const unsigned int bitDepth = PixelBits(pixType);
		
		assert(info.bitspersample == bitDepth);
									
		const size_t pixelSize = (info.components * PixelSize(pixType));
		const size_t rowBytes = (width * pixelSize);
		const size_t bufSize = (height * rowBytes);
		
		DataChunkPtr frameData = new DataChunk(bufSize);
		
		char *buf = (char *)frameData->Data;
		
		const Box2i dataW = dataWindow();
		
		assert(width == (dataW.max.x - dataW.min.x + 1));
		assert(height == (dataW.max.y - dataW.min.y + 1));
		assert(dataW.min.x == 0);
		assert(dataW.min.y == 0);
			
		FrameBufferPtr frameBuffer = new FrameBuffer(dataW);
		
		frameBuffer->insert("R", Slice(pixType, &buf[0 * pixSize], pixelSize, rowBytes));
		frameBuffer->insert("G", Slice(pixType, &buf[1 * pixSize], pixelSize, rowBytes));
		frameBuffer->insert("B", Slice(pixType, &buf[2 * pixSize], pixelSize, rowBytes));
		
		if(info.components >= 4)
			frameBuffer->insert("A", Slice(pixType, &buf[3 * pixSize], pixelSize, rowBytes));
		
		frameBuffer->attachData(frameData);
		
		
		ByteStreamInfo outStream = FromByteArray(frameData->Data, frameData->Size);
		
		
		err = JpegLsDecodeStream(outStream, inStream, &info);
		
		if(err == OK)
		{
			storeFrame(frameBuffer);
		}
	}
	
	if(err != OK)
		throw MoxMxf::ArgExc("JPEG-LS decompression error");
}
Exemple #7
0
void
JPEGLSCodec::compress(const FrameBuffer &frame)
{
	const Box2i dataW = dataWindow();
	
	const int width = (dataW.max.x - dataW.min.x + 1);
	const int height = (dataW.max.y - dataW.min.y + 1);

	const PixelType pixType = (_depth == JPEGLS_8 ? UINT8 :
								_depth == JPEGLS_10 ? UINT10 :
								_depth == JPEGLS_12 ? UINT12 :
								_depth == JPEGLS_16 ? UINT16 :
								UINT8);
	
	const size_t pixSize = PixelSize(pixType);
	const unsigned int bitDepth = PixelBits(pixType);
	const int numChannels = (_channels == JPEGLS_RGBA ? 4 : 3);
	
	const size_t tempPixelSize = (numChannels * pixSize);
	const size_t tempRowbytes = (tempPixelSize * width);
	const size_t tempBufSize = (tempRowbytes * height);
	
	DataChunk dataChunk(tempBufSize);
	
	char *tempBuffer = (char *)dataChunk.Data;
	
	assert(dataW.min.x == 0 && dataW.min.y == 0);
	
	FrameBuffer tempFrameBuffer(dataW);
	
	tempFrameBuffer.insert("R", Slice(pixType, &tempBuffer[0 * pixSize], tempPixelSize, tempRowbytes));
	tempFrameBuffer.insert("G", Slice(pixType, &tempBuffer[1 * pixSize], tempPixelSize, tempRowbytes));
	tempFrameBuffer.insert("B", Slice(pixType, &tempBuffer[2 * pixSize], tempPixelSize, tempRowbytes));
	
	if(_channels == JPEGLS_RGBA)
		tempFrameBuffer.insert("A", Slice(pixType, &tempBuffer[3 * pixSize], tempPixelSize, tempRowbytes));
	
	tempFrameBuffer.copyFromFrame(frame);
	
	
	JlsParameters params = JlsParameters();
	
	params.width = width;
	params.height = height;
	params.bitspersample = bitDepth;
	//params.bytesperline = (tempRowbytes / 3);
	params.components = numChannels;
	params.allowedlossyerror = 0; // always lossless
	params.ilv = ILV_SAMPLE;
	params.colorTransform = COLORXFORM_NONE;
	//params.outputBgr = 0;
	
	/*
	params.custom.MAXVAL = 255;
	params.custom.T1 = 0;
	params.custom.T2 = 0;
	params.custom.T3 = 0;
	params.custom.RESET = 1;
	
	
	params.jfif.Ver = 123;
	params.jfif.units = 0;
	params.jfif.XDensity = 72;
	params.jfif.YDensity = 72;
	params.jfif.Xthumb = 0;
	params.jfif.Ythumb = 0;
	params.jfif.pdataThumbnail = NULL;
	*/
	
	
	ByteStreamInfo inStream = FromByteArray(dataChunk.Data, dataChunk.Size);
	
	DataChunkPtr outDataChunk = new DataChunk(tempBufSize);
	
	
	size_t bytesWritten = 0;
	
	JLS_ERROR err = OK;
	
	do
	{
		ByteStreamInfo outStream = FromByteArray(outDataChunk->Data, outDataChunk->Size);
		
		err = JpegLsEncodeStream(outStream, &bytesWritten, inStream, &params);
		
		if(err == CompressedBufferTooSmall)
		{
			outDataChunk->Resize(2 * outDataChunk->Size, false);
		}
	
	}while(err == CompressedBufferTooSmall);
	
	assert(err != TooMuchCompressedData);
	
	
	if(err == OK)
	{
		assert(bytesWritten > 0);
	
		outDataChunk->Resize(bytesWritten);
		
		storeData(outDataChunk);
	}
	else
		throw MoxMxf::ArgExc("JPEG-LS compression error");
}
Exemple #8
0
bool DeepImageReader::loadFileFromPath( const std::string &filePath, std::string &errorMsg )
{
	try
	{
		// Perform an early-out if we have already loaded the desired file.
		if( m_currentPath == filePath && m_reader && m_currentPath != "" )
		{
			return true;
		}

		IECore::ReaderPtr object( IECore::Reader::create( filePath ) );
		m_reader = IECore::runTimeCast<IECore::DeepImageReader>( object );
		
		if( m_reader )
		{
			m_currentPath = filePath;
			std::vector< std::string > channelNames;

			m_reader->channelNames( channelNames );

			m_channels = DD::Image::ChannelSet( DD::Image::Mask_DeepFront | DD::Image::Mask_DeepBack );
			m_channelMap.clear();
			for( std::vector< std::string >::const_iterator it( channelNames.begin() ); it != channelNames.end(); ++it )
			{
				int idx( it - channelNames.begin() ); 
				if( *it == "A" )
				{
					m_channels += DD::Image::Chan_Alpha;
					m_channelMap[DD::Image::Chan_Alpha] = idx; 
				}
				else if( *it == "R" )
				{
					m_channels += DD::Image::Chan_Red;
					m_channelMap[DD::Image::Chan_Red] = idx; 
				}
				else if( *it == "G" )
				{
					m_channels += DD::Image::Chan_Green;
					m_channelMap[DD::Image::Chan_Green] = idx; 
				}
				else if( *it == "B" )
				{
					m_channels += DD::Image::Chan_Blue;
					m_channelMap[DD::Image::Chan_Blue] = idx; 
				}
			}
			
			Imath::Box2i dataWindow( m_reader->dataWindow() ); 
			m_dataWindow = DD::Image::Box( dataWindow.min[0], dataWindow.min[1], dataWindow.max[0]+1, dataWindow.max[1]+1 );
			errorMsg = "";
			return true;
		}
		else
		{
			errorMsg = "Object is not an IECore::DeepImageReader.";
		}
	}
	catch( const IECore::Exception &e )
	{
		errorMsg = ( boost::format( "DeepImageReader : %s" ) % e.what() ).str();
	}
	return false;
}
Exemple #9
0
void
JPEGCodec::decompress(const DataChunk &data)
{
	struct jpeg_error_mgr jerr;
	
	jerr.error_exit = my_error_exit;
	jerr.emit_message = my_emit_message;
	jerr.output_message = my_output_message;
	jerr.format_message = my_format_message;
	jerr.reset_error_mgr = my_reset_error_mgr;
	
	jerr.trace_level = 0;
	jerr.num_warnings = 0;
	jerr.msg_code = 0;
	
	jerr.jpeg_message_table = jpeg_std_message_table;
	jerr.last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
	
	jerr.addon_message_table = NULL;
	jerr.first_addon_message = 0;
	jerr.last_jpeg_message = 0;
	
	
	my_source_mgr mgr;
	
	mgr.infile = new MemoryFile(data);
	mgr.buffer = (JOCTET *)malloc(4096 * sizeof(JOCTET));
	mgr.bufferSize = 4096;
	mgr.pub.bytes_in_buffer = 0;
	mgr.pub.next_input_byte = NULL;
	
	if(mgr.buffer == NULL)
		throw MoxMxf::NullExc("out of memory");
	
	mgr.pub.init_source = my_init_source;
	mgr.pub.fill_input_buffer = my_fill_input_buffer;
	mgr.pub.skip_input_data = my_skip_input_data;
	mgr.pub.resync_to_restart = jpeg_resync_to_restart;
	mgr.pub.term_source = my_term_source;
	
	
	struct jpeg_decompress_struct cinfo;
	
	cinfo.err = &jerr;
	
	jpeg_create_decompress(&cinfo);
	
	
	cinfo.src = (jpeg_source_mgr *)&mgr;
	
	
	bool success = true;
	
	try
	{
		const int status = jpeg_read_header(&cinfo, TRUE);
		
		if(status == JPEG_HEADER_OK)
		{
			jpeg_start_decompress(&cinfo);
			
			const JDIMENSION width = cinfo.image_width;
			const JDIMENSION height = cinfo.image_height;
			
			assert(cinfo.num_components == 3);
			assert(cinfo.out_color_space == JCS_RGB);
			
			
			const size_t pixelSize = (3 * PixelSize(UINT8));
			const size_t rowBytes = (width * pixelSize);
			const size_t bufSize = (height * rowBytes);
			
			DataChunkPtr frameData = new DataChunk(bufSize);
			
			char *buf = (char *)frameData->Data;
			
			const Box2i dataW = dataWindow();
			
			assert(width == (dataW.max.x - dataW.min.x + 1));
			assert(height == (dataW.max.y - dataW.min.y + 1));
			assert(dataW.min.x == 0);
			assert(dataW.min.y == 0);
				
			FrameBufferPtr frameBuffer = new FrameBuffer(dataW);
			
			frameBuffer->insert("R", Slice(UINT8, &buf[0], pixelSize, rowBytes));
			frameBuffer->insert("G", Slice(UINT8, &buf[1], pixelSize, rowBytes));
			frameBuffer->insert("B", Slice(UINT8, &buf[2], pixelSize, rowBytes));
			
			frameBuffer->attachData(frameData);
			
			
			JSAMPARRAY scanlines = (JSAMPARRAY)malloc(height * sizeof(JSAMPROW));
			
			if(scanlines == NULL)
				throw MoxMxf::NullExc("out of memory");
			
			for(int y=0; y < height; y++)
			{
				scanlines[y] = (JSAMPROW)(buf + (y * rowBytes));
			}
			
			
			JDIMENSION linesRead = 0;
			
			while(linesRead < height)
			{
				linesRead += jpeg_read_scanlines(&cinfo, &scanlines[linesRead], height - linesRead);
			}
			
			
			free(scanlines);
			
			jpeg_finish_decompress(&cinfo);
			
			
			storeFrame(frameBuffer);
		}
		else
			throw MoxMxf::ArgExc("Error reading header");
	}
	catch(...)
	{
		success = false;
	}
	
	
	jpeg_destroy_decompress(&cinfo);
	
	
	free(mgr.buffer);
	
	delete mgr.infile;
	
	
	if(!success)
		throw MoxMxf::ArgExc("JPEG decompression error");
}
Exemple #10
0
void
JPEGCodec::compress(const FrameBuffer &frame)
{
	struct jpeg_error_mgr jerr;
	
	jerr.error_exit = my_error_exit;
	jerr.emit_message = my_emit_message;
	jerr.output_message = my_output_message;
	jerr.format_message = my_format_message;
	jerr.reset_error_mgr = my_reset_error_mgr;
	
	jerr.trace_level = 0;
	jerr.num_warnings = 0;
	jerr.msg_code = 0;
	
	jerr.jpeg_message_table = jpeg_std_message_table;
	jerr.last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
	
	jerr.addon_message_table = NULL;
	jerr.first_addon_message = 0;
	jerr.last_jpeg_message = 0;
	
	
	
	struct jpeg_compress_struct cinfo;
	
	cinfo.err = &jerr;
	
	jpeg_create_compress(&cinfo);
	
	
	my_destination_mgr mgr;
	
	mgr.outfile = new MemoryFile;
	mgr.buffer = NULL;
	mgr.bufferSize = 0;
	
	mgr.pub.init_destination = my_init_destination;
	mgr.pub.empty_output_buffer = my_empty_output_buffer;
	mgr.pub.term_destination = my_term_destination;
	
	
	cinfo.dest = (jpeg_destination_mgr *)&mgr;
	
	
	const Box2i dataW = dataWindow();
	
	const int width = (dataW.max.x - dataW.min.x + 1);
	const int height = (dataW.max.y - dataW.min.y + 1);
	
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	
	jpeg_set_defaults(&cinfo);
	
	
	jpeg_set_quality(&cinfo, _quality, TRUE);
	
	
	bool success = true;
	
	try
	{
		jpeg_start_compress(&cinfo, TRUE);
		
		
		const size_t tempPixelSize = (3 * PixelSize(UINT8));
		const size_t tempRowbytes = (tempPixelSize * width);
		const size_t tempBufSize = (tempRowbytes * height);
		
		DataChunk dataChunk(tempBufSize);
		
		char *tempBuffer = (char *)dataChunk.Data;
		
		FrameBuffer tempFrameBuffer(dataW);
		
		tempFrameBuffer.insert("R", Slice(UINT8, &tempBuffer[0], tempPixelSize, tempRowbytes));
		tempFrameBuffer.insert("G", Slice(UINT8, &tempBuffer[1], tempPixelSize, tempRowbytes));
		tempFrameBuffer.insert("B", Slice(UINT8, &tempBuffer[2], tempPixelSize, tempRowbytes));
		
		tempFrameBuffer.copyFromFrame(frame);
		
		
		JSAMPARRAY scanlines = (JSAMPARRAY)malloc(height * sizeof(JSAMPROW));
		
		if(scanlines == NULL)
			throw MoxMxf::NullExc("out of memory");
		
		for(int y=0; y < height; y++)
		{
			scanlines[y] = (JSAMPROW)(tempBuffer + (y * tempRowbytes));
		}
		
		
		const JDIMENSION linesWrote = jpeg_write_scanlines(&cinfo, scanlines, height);
		
		assert(linesWrote == height);
		
		
		jpeg_finish_compress(&cinfo);
		
		
		assert(jerr.msg_code == 0);
		
		storeData( mgr.outfile->getDataChunk() );
		
		
		free(scanlines);
	}
	catch(...)
	{
		success = false;
	}
	
	
	jpeg_destroy_compress(&cinfo);
	
	
	if(mgr.buffer != NULL)
		free(mgr.buffer);
	
	delete mgr.outfile;
	
	
	if(!success)
		throw MoxMxf::ArgExc("JPEG compression error");
}