Exemple #1
1
judge_result testcase_impl::run(env &env, compiler::result &cr)
{
	judge_result result = {0};
	shared_ptr<temp_dir> dir = _prepare_dir(env.pool(), cr);
	env.grant_access(dir->path());

	path_a executable_path;
	if (cr.compiler->target_executable_path().empty()) {
		executable_path = dir->path();
		executable_path.push(cr.compiler->target_filename().c_str());
	} else {
		executable_path = cr.compiler->target_executable_path();
	}

	shared_ptr<testcase_impl::context> context(new testcase_impl::context(*this));
	judge::bunny bunny(env, false, executable_path.c_str(), cr.compiler->target_command_line(), dir->path(),
		context->stdin_pipe.read_handle(), context->stdout_pipe.write_handle(), context->stderr_pipe.write_handle(), limit_);
	context->stdin_pipe.close_read();
	context->stdout_pipe.close_write();
	context->stderr_pipe.close_write();

	// stdin thread
	env.pool().thread_pool().queue([context]()->void {
		try {
			istream in(&context->stdin_buf);
			os_filebuf out_buf(context->stdin_pipe.write_handle(), false);
			ostream out(&out_buf);
			const size_t buffer_size = 4096;
			util::stream_copy<buffer_size>(in, out);
		} catch (...) {
		}
		context->stdin_pipe.close_write();
		context->stdin_event.set();
	});

	// stderr thread
	env.pool().thread_pool().queue([context]()->void {
		try {
			os_filebuf in_buf(context->stderr_pipe.read_handle(), false);
			istream in(&in_buf);
			const size_t buffer_size = 4096;
			util::stream_copy_n<buffer_size>(in, context->stderr_stream, context->stderr_output_limit);
		} catch (...) {
		}
		context->stderr_pipe.close_read();
		context->stderr_event.set();
	});

	bunny.start();

	// judge
	{
		istream model_in(&context->stdout_buf);
		os_filebuf user_buf(context->stdout_pipe.read_handle(), false);
		istream user_in(&user_buf);
		pair<bool, string> compare_result = compare_stream(model_in, user_in);
		if (compare_result.first) {
			result.flag = max(result.flag, JUDGE_ACCEPTED);
		} else {
			result.flag = max(result.flag, JUDGE_WRONG_ANSWER);
		}
		judge_output_ = move(compare_result.second);

		// read all user output
		const size_t buffer_size = 4096;
		util::stream_copy<buffer_size>(user_in, onullstream());
	}

	bunny::result bunny_result = bunny.wait();
	DWORD wait_result = winstl::wait_for_multiple_objects(context->stdin_event, context->stderr_event, true, INFINITE);
	if (wait_result == WAIT_FAILED) {
		throw win32_exception(::GetLastError());
	}

	result.flag = max(result.flag, bunny_result.flag);
	result.time_usage_ms = bunny_result.time_usage_ms;
	result.memory_usage_kb = bunny_result.memory_usage_kb;
	result.runtime_error = bunny_result.runtime_error;
	result.judge_output = judge_output_.c_str();
	user_output_ = context->stderr_stream.str();
	result.user_output = user_output_.c_str();
	return result;
}
const std::basic_string<CharType> in(
    const std::basic_string<Byte>& external_str,
    const std::codecvt<CharType, Byte, mbstate_t>& codecvt)
{
  typedef std::basic_string<CharType> wstring;
  typedef std::basic_string<Byte>     string;
  typedef std::codecvt<CharType, Byte, mbstate_t> codecvt_type;

  typename string::size_type external_str_size = external_str.length();
  const Byte* first_external = external_str.data();
  const Byte* last_external  = first_external + external_str_size;
  const Byte* next_external  = last_external;

  wstring internal_str;

  // Zero initialized
  typename codecvt_type::state_type state;
  std::memset(&state, 0, sizeof(state));

  typename wstring::size_type out_buf_size =
      static_cast<typename wstring::size_type>(
          codecvt.length(state, first_external, last_external,
              internal_str.max_size()));

#if defined(MA_USE_CXX11_STDLIB_MEMORY)
  detail::unique_ptr<CharType[]> out_buf(new CharType[out_buf_size]);
#else
  detail::scoped_array<CharType> out_buf(new CharType[out_buf_size]);
#endif

  CharType* first_internal = out_buf.get();
  CharType* last_internal  = first_internal + out_buf_size;
  CharType* next_internal  = first_internal;

  typename codecvt_type::result r = codecvt.in(state,
      first_external, last_external, next_external,
      first_internal, last_internal, next_internal);

  if (codecvt_type::ok == r)
  {
    internal_str.assign(first_internal, last_internal);
  }
  else if (codecvt_type::noconv == r)
  {
    internal_str.assign(reinterpret_cast<const CharType*>(first_external),
        reinterpret_cast<const CharType*>(last_external));
  }
  else
  {
    boost::throw_exception(bad_conversion());
  }

  return internal_str;
}
Exemple #3
0
const std::basic_string<Byte> out(
    const std::basic_string<CharType>& internal_str,
    const std::codecvt<CharType, Byte, mbstate_t>& codecvt)
{
  typedef std::basic_string<CharType> wstring;
  typedef std::basic_string<Byte>     string;
  typedef std::codecvt<CharType, Byte, mbstate_t> codecvt_type;

  string external_str;

  typename wstring::size_type internal_str_size = internal_str.length();
  typename wstring::size_type out_buf_size =
      static_cast<typename wstring::size_type>(codecvt.max_length()) *
          internal_str_size;

#if defined(MA_USE_CXX11_STDLIB_MEMORY)
  std::unique_ptr<Byte[]> out_buf(new Byte[out_buf_size]);
#else
  boost::scoped_array<Byte> out_buf(new Byte[out_buf_size]);
#endif

  const CharType* first_internal = internal_str.data();
  const CharType* last_internal  = first_internal + internal_str_size;
  const CharType* next_internal  = first_internal;

  Byte* first_external = out_buf.get();
  Byte* last_external  = first_external + out_buf_size;
  Byte* next_external  = first_external;

  typename codecvt_type::state_type state(0);

  typename codecvt_type::result r = codecvt.out(state,
      first_internal, last_internal, next_internal,
      first_external, last_external, next_external);

  if (codecvt_type::ok == r)
  {
    external_str.assign(first_external, next_external);
  }
  else if (codecvt_type::noconv == r)
  {
    external_str.assign(reinterpret_cast<const Byte*>(first_internal),
        reinterpret_cast<const Byte*>(last_internal));
  }
  else
  {
    boost::throw_exception(bad_conversion());
  }

  return external_str;
}
Exemple #4
0
void
out_char(int c)
{
    if (c == EOF) {
        out_buf();        /* flag that we're all done */
        return;
    }

    if (outcnt <= 0)
        out_buf();        /* buffer is full, write it first */

    *outptr++ = c;        /* just store in buffer */
    outcnt--;
}
/*!
 * \param partial_lcp		Vector containing LCP values for all indexes \f$i\f$ with
 *                      	index_done[i] == 0. Let x=partail_lcp[rank(index_done, i, 0)];
 *                      	LCP[i]=x if x!=0 and index_done[i] == 0
 * \param lcp_file			Path to the LCP array on disk.
 * \param index_done		Entry index_done[i] indicates if LCP[i] is already calculated.
 * \param max_lcp_value 	Maximum known LCP value
 * \param lcp_value_offset	Largest LCP value in lcp_file
 */
void insert_lcp_values(int_vector<>& partial_lcp, bit_vector& index_done, std::string lcp_file, uint64_t max_lcp_value, uint64_t lcp_value_offset)
{
    std::string tmp_lcp_file  = lcp_file+"_TMP";
    const uint64_t buffer_size = 1000000; // has to be a multiple of 64
    typedef int_vector<>::size_type size_type;
    int_vector_buffer<> lcp_buffer(lcp_file, std::ios::in, buffer_size); // open lcp_file
    uint64_t n = lcp_buffer.size();

    // open tmp_lcp_file
    uint8_t int_width = bits::hi(max_lcp_value-1)+1;
    int_vector_buffer<> out_buf(tmp_lcp_file, std::ios::out, buffer_size, int_width);		// Output buffer
    // Write values into buffer
    for (size_type i=0, calc_idx=0; i < n; ++i) {
        if (index_done[i]) {   // If value was already calculated
            out_buf[i] = lcp_buffer[i]; // Copy value
        } else {
            if (partial_lcp[calc_idx]) {   // If value was calculated now
                // Insert value
                out_buf[i] = partial_lcp[calc_idx]+lcp_value_offset;
                index_done[i] = true;
            }
            ++calc_idx;
        }
    }
    // Close file and replace old file with new one
    out_buf.close();
    sdsl::rename(tmp_lcp_file, lcp_file);
}
Exemple #6
0
int main()
{
    try {
        cl::Context context;
        std::vector<cl::Device> devices;
        std::tie(context, devices) = init_open_cl();
        cl::CommandQueue queue(context, devices[0]);
        cl::Program program = load_program("program.cl", context, devices);
        cl_fn reduce_fn(program, "do_reduce");
        cl_fn sweep_fn(program, "do_sweep");

        std::ifstream in(INPUT_FILE);
        size_t n, npow2;
        in >> n;
        npow2 = pow(2.0, ceil(log2(n)));
        std::vector<float> in_array(npow2);
        for (size_t i = 0; i < n; ++i)
            in >> in_array[i];

        cl::Buffer out_buf(context, std::begin(in_array), std::end(in_array), false);
        std::vector<cl::Event> events;

        for (size_t offset = 1; npow2 / (offset * 2) >= WORKGROUP_SIZE; offset *= 2)
            exec_fn(reduce_fn, out_buf, npow2, offset, npow2 / offset, events, queue);

        if (npow2 < 512)
            exec_fn(reduce_fn, out_buf, npow2, 1, WORKGROUP_SIZE, events, queue);

        exec_fn(sweep_fn, out_buf, npow2, npow2 / 2, WORKGROUP_SIZE, events, queue);

        for (size_t offset = npow2 / 1024; offset > 0; offset /= 2)
            exec_fn(sweep_fn, out_buf, npow2, offset, npow2 / offset, events, queue);

        std::vector<float> out_array(n);
        queue.enqueueReadBuffer(out_buf, CL_TRUE, 0, sizeof(float) * n, &out_array[0]);

        std::ofstream out(OUTPUT_FILE);
        out << std::fixed << std::setprecision(3);
        for (size_t i = 0; i < n; i++)
            out << out_array[i] << " ";
        out << std::endl;
    }
    catch (cl::Error &e) {
        std::cerr << "ERROR: " << e.what() << " (" << e.err() << ")" << std::endl;
    }
    catch (std::runtime_error &e) {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}
Exemple #7
0
const std::basic_string<CharType> in(
    const std::basic_string<Byte>& external_str, 
    const std::codecvt<CharType, Byte, mbstate_t>& codecvt)
{
  typedef std::basic_string<CharType> wstring;
  typedef std::basic_string<Byte> string;
  typedef std::codecvt<CharType, Byte, mbstate_t> codecvt_type;

  typename string::size_type external_str_size = external_str.length();
  const Byte* first_external = external_str.data();
  const Byte* last_external  = first_external + external_str_size;
  const Byte* next_external  = last_external;

  wstring internal_str;

  typename codecvt_type::state_type state(0);
  typename wstring::size_type out_buf_size = codecvt.length(state,
      first_external, last_external, internal_str.max_size());
  
  boost::scoped_array<CharType> out_buf(new CharType[out_buf_size]);

  CharType* first_internal = out_buf.get();
  CharType* last_internal  = first_internal + out_buf_size;
  CharType* next_internal  = first_internal;

  typename codecvt_type::result r = codecvt.in(state,
      first_external, last_external, next_external,
      first_internal, last_internal, next_internal);

  if (codecvt_type::ok != r)
  {
    boost::throw_exception(bad_conversion());
  }
  else if (codecvt_type::noconv == r)
  {
    internal_str.assign(reinterpret_cast<const CharType*>(first_external),
        reinterpret_cast<const CharType*>(last_external));
  }
  else 
  {
    internal_str.assign(first_internal, last_internal);
  }

  return internal_str;
}
Exemple #8
0
static int	add_buffer(t_main *c, char *buf, int len)
{
  int		i;
  int		start;
  int		end;

  i = 0;
  while (i != len)
    if (!in_buf(c, buf[i++]))
      break;
  start = c->start;
  end = c->end;
  while (start != end)
    {
      if (c->buf[start] == '\n')
	return (out_buf(c, 0, start));
      start = (start + 1) % BUF_SIZE;
    }
  c->start = start;
  return (0);
}
bool JpegEncoder::write( const Mat& img, const vector<int>& params )
{
    m_last_error.clear();

    struct fileWrapper
    {
        FILE* f;

        fileWrapper() : f(0) {}
        ~fileWrapper() { if(f) fclose(f); }
    };
    bool result = false;
    fileWrapper fw;
    int width = img.cols, height = img.rows;

    vector<uchar> out_buf(1 << 12);
    AutoBuffer<uchar> _buffer;
    uchar* buffer;

    struct jpeg_compress_struct cinfo;
    JpegErrorMgr jerr;
    JpegDestination dest;

    jpeg_create_compress(&cinfo);
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = error_exit;

    if( !m_buf )
    {
        fw.f = fopen( m_filename.c_str(), "wb" );
        if( !fw.f )
            goto _exit_;
        jpeg_stdio_dest( &cinfo, fw.f );
    }
    else
    {
        dest.dst = m_buf;
        dest.buf = &out_buf;

        jpeg_buffer_dest( &cinfo, &dest );

        dest.pub.next_output_byte = &out_buf[0];
        dest.pub.free_in_buffer = out_buf.size();
    }

    if( setjmp( jerr.setjmp_buffer ) == 0 )
    {
        cinfo.image_width = width;
        cinfo.image_height = height;

        int _channels = img.channels();
        int channels = _channels > 1 ? 3 : 1;
        cinfo.input_components = channels;
        cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;

        int quality = 95;

        for( size_t i = 0; i < params.size(); i += 2 )
        {
            if( params[i] == CV_IMWRITE_JPEG_QUALITY )
            {
                quality = params[i+1];
                quality = MIN(MAX(quality, 0), 100);
            }
        }

        jpeg_set_defaults( &cinfo );
        jpeg_set_quality( &cinfo, quality,
                          TRUE /* limit to baseline-JPEG values */ );
        jpeg_start_compress( &cinfo, TRUE );

        if( channels > 1 )
            _buffer.allocate(width*channels);
        buffer = _buffer;

        for( int y = 0; y < height; y++ )
        {
            uchar *data = img.data + img.step*y, *ptr = data;

            if( _channels == 3 )
            {
                icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) );
                ptr = buffer;
            }
            else if( _channels == 4 )
            {
                icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 );
                ptr = buffer;
            }

            jpeg_write_scanlines( &cinfo, &ptr, 1 );
        }

        jpeg_finish_compress( &cinfo );
        result = true;
    }

_exit_:

    if(!result)
    {
        char jmsg_buf[JMSG_LENGTH_MAX];
        jerr.pub.format_message((j_common_ptr)&cinfo, jmsg_buf);
        m_last_error = jmsg_buf;
    }

    jpeg_destroy_compress( &cinfo );

    return result;
}
Exemple #10
0
bool CompressFileToBlob(const std::string& infile_path, const std::string& outfile_path,
                        u32 sub_type, int block_size, CompressCB callback, void* arg)
{
  bool scrubbing = false;

  File::IOFile infile(infile_path, "rb");
  if (IsGCZBlob(infile))
  {
    PanicAlertT("\"%s\" is already compressed! Cannot compress it further.", infile_path.c_str());
    return false;
  }

  if (!infile)
  {
    PanicAlertT("Failed to open the input file \"%s\".", infile_path.c_str());
    return false;
  }

  File::IOFile outfile(outfile_path, "wb");
  if (!outfile)
  {
    PanicAlertT("Failed to open the output file \"%s\".\n"
                "Check that you have permissions to write the target folder and that the media can "
                "be written.",
                outfile_path.c_str());
    return false;
  }

  DiscScrubber disc_scrubber;
  if (sub_type == 1)
  {
    if (!disc_scrubber.SetupScrub(infile_path, block_size))
    {
      PanicAlertT("\"%s\" failed to be scrubbed. Probably the image is corrupt.",
                  infile_path.c_str());
      return false;
    }

    scrubbing = true;
  }

  z_stream z = {};
  if (deflateInit(&z, 9) != Z_OK)
    return false;

  callback(GetStringT("Files opened, ready to compress."), 0, arg);

  CompressedBlobHeader header;
  header.magic_cookie = GCZ_MAGIC;
  header.sub_type = sub_type;
  header.block_size = block_size;
  header.data_size = infile.GetSize();

  // round upwards!
  header.num_blocks = (u32)((header.data_size + (block_size - 1)) / block_size);

  std::vector<u64> offsets(header.num_blocks);
  std::vector<u32> hashes(header.num_blocks);
  std::vector<u8> out_buf(block_size);
  std::vector<u8> in_buf(block_size);

  // seek past the header (we will write it at the end)
  outfile.Seek(sizeof(CompressedBlobHeader), SEEK_CUR);
  // seek past the offset and hash tables (we will write them at the end)
  outfile.Seek((sizeof(u64) + sizeof(u32)) * header.num_blocks, SEEK_CUR);
  // seek to the start of the input file to make sure we get everything
  infile.Seek(0, SEEK_SET);

  // Now we are ready to write compressed data!
  u64 position = 0;
  int num_compressed = 0;
  int num_stored = 0;
  int progress_monitor = std::max<int>(1, header.num_blocks / 1000);
  bool success = true;

  for (u32 i = 0; i < header.num_blocks; i++)
  {
    if (i % progress_monitor == 0)
    {
      const u64 inpos = infile.Tell();
      int ratio = 0;
      if (inpos != 0)
        ratio = (int)(100 * position / inpos);

      std::string temp =
          StringFromFormat(GetStringT("%i of %i blocks. Compression ratio %i%%").c_str(), i,
                           header.num_blocks, ratio);
      bool was_cancelled = !callback(temp, (float)i / (float)header.num_blocks, arg);
      if (was_cancelled)
      {
        success = false;
        break;
      }
    }

    offsets[i] = position;

    size_t read_bytes;
    if (scrubbing)
      read_bytes = disc_scrubber.GetNextBlock(infile, in_buf.data());
    else
      infile.ReadArray(in_buf.data(), header.block_size, &read_bytes);
    if (read_bytes < header.block_size)
      std::fill(in_buf.begin() + read_bytes, in_buf.begin() + header.block_size, 0);

    int retval = deflateReset(&z);
    z.next_in = in_buf.data();
    z.avail_in = header.block_size;
    z.next_out = out_buf.data();
    z.avail_out = block_size;

    if (retval != Z_OK)
    {
      ERROR_LOG(DISCIO, "Deflate failed");
      success = false;
      break;
    }

    int status = deflate(&z, Z_FINISH);
    int comp_size = block_size - z.avail_out;

    u8* write_buf;
    int write_size;
    if ((status != Z_STREAM_END) || (z.avail_out < 10))
    {
      // PanicAlert("%i %i Store %i", i*block_size, position, comp_size);
      // let's store uncompressed
      write_buf = in_buf.data();
      offsets[i] |= 0x8000000000000000ULL;
      write_size = block_size;
      num_stored++;
    }
    else
    {
      // let's store compressed
      // PanicAlert("Comp %i to %i", block_size, comp_size);
      write_buf = out_buf.data();
      write_size = comp_size;
      num_compressed++;
    }

    if (!outfile.WriteBytes(write_buf, write_size))
    {
      PanicAlertT("Failed to write the output file \"%s\".\n"
                  "Check that you have enough space available on the target drive.",
                  outfile_path.c_str());
      success = false;
      break;
    }

    position += write_size;

    hashes[i] = HashAdler32(write_buf, write_size);
  }

  header.compressed_data_size = position;

  if (!success)
  {
    // Remove the incomplete output file.
    outfile.Close();
    File::Delete(outfile_path);
  }
  else
  {
    // Okay, go back and fill in headers
    outfile.Seek(0, SEEK_SET);
    outfile.WriteArray(&header, 1);
    outfile.WriteArray(offsets.data(), header.num_blocks);
    outfile.WriteArray(hashes.data(), header.num_blocks);
  }

  // Cleanup
  deflateEnd(&z);

  if (success)
  {
    callback(GetStringT("Done compressing disc image."), 1.0f, arg);
  }
  return success;
}
Exemple #11
0
bool JpegEncoder::write( const Mat& img, const std::vector<int>& params )
{
    m_last_error.clear();

    struct fileWrapper
    {
        FILE* f;

        fileWrapper() : f(0) {}
        ~fileWrapper() { if(f) fclose(f); }
    };
    volatile bool result = false;
    fileWrapper fw;
    int width = img.cols, height = img.rows;

    std::vector<uchar> out_buf(1 << 12);
    AutoBuffer<uchar> _buffer;
    uchar* buffer;

    struct jpeg_compress_struct cinfo;
    JpegErrorMgr jerr;
    JpegDestination dest;

    jpeg_create_compress(&cinfo);
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = error_exit;

    if( !m_buf )
    {
        fw.f = fopen( m_filename.c_str(), "wb" );
        if( !fw.f )
            goto _exit_;
        jpeg_stdio_dest( &cinfo, fw.f );
    }
    else
    {
        dest.dst = m_buf;
        dest.buf = &out_buf;

        jpeg_buffer_dest( &cinfo, &dest );

        dest.pub.next_output_byte = &out_buf[0];
        dest.pub.free_in_buffer = out_buf.size();
    }

    if( setjmp( jerr.setjmp_buffer ) == 0 )
    {
        cinfo.image_width = width;
        cinfo.image_height = height;

        int _channels = img.channels();
        int channels = _channels > 1 ? 3 : 1;
        cinfo.input_components = channels;
        cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;

        int quality = 95;
        int progressive = 0;
        int optimize = 0;
        int rst_interval = 0;
        int luma_quality = -1;
        int chroma_quality = -1;

        for( size_t i = 0; i < params.size(); i += 2 )
        {
            if( params[i] == CV_IMWRITE_JPEG_QUALITY )
            {
                quality = params[i+1];
                quality = MIN(MAX(quality, 0), 100);
            }

            if( params[i] == CV_IMWRITE_JPEG_PROGRESSIVE )
            {
                progressive = params[i+1];
            }

            if( params[i] == CV_IMWRITE_JPEG_OPTIMIZE )
            {
                optimize = params[i+1];
            }

            if( params[i] == CV_IMWRITE_JPEG_LUMA_QUALITY )
            {
                if (params[i+1] >= 0)
                {
                    luma_quality = MIN(MAX(params[i+1], 0), 100);

                    quality = luma_quality;

                    if (chroma_quality < 0)
                    {
                        chroma_quality = luma_quality;
                    }
                }
            }

            if( params[i] == CV_IMWRITE_JPEG_CHROMA_QUALITY )
            {
                if (params[i+1] >= 0)
                {
                    chroma_quality = MIN(MAX(params[i+1], 0), 100);
                }
            }

            if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL )
            {
                rst_interval = params[i+1];
                rst_interval = MIN(MAX(rst_interval, 0), 65535L);
            }
        }

        jpeg_set_defaults( &cinfo );
        cinfo.restart_interval = rst_interval;

        jpeg_set_quality( &cinfo, quality,
                          TRUE /* limit to baseline-JPEG values */ );
        if( progressive )
            jpeg_simple_progression( &cinfo );
        if( optimize )
            cinfo.optimize_coding = TRUE;

#if JPEG_LIB_VERSION >= 70
        if (luma_quality >= 0 && chroma_quality >= 0)
        {
            cinfo.q_scale_factor[0] = jpeg_quality_scaling(luma_quality);
            cinfo.q_scale_factor[1] = jpeg_quality_scaling(chroma_quality);
            if ( luma_quality != chroma_quality )
            {
                /* disable subsampling - ref. Libjpeg.txt */
                cinfo.comp_info[0].v_samp_factor = 1;
                cinfo.comp_info[0].h_samp_factor = 1;
                cinfo.comp_info[1].v_samp_factor = 1;
                cinfo.comp_info[1].h_samp_factor = 1;
            }
            jpeg_default_qtables( &cinfo, TRUE );
        }
#endif // #if JPEG_LIB_VERSION >= 70

        jpeg_start_compress( &cinfo, TRUE );

        if( channels > 1 )
            _buffer.allocate(width*channels);
        buffer = _buffer;

        for( int y = 0; y < height; y++ )
        {
            uchar *data = img.data + img.step*y, *ptr = data;

            if( _channels == 3 )
            {
                icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) );
                ptr = buffer;
            }
            else if( _channels == 4 )
            {
                icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 );
                ptr = buffer;
            }

            jpeg_write_scanlines( &cinfo, &ptr, 1 );
        }

        jpeg_finish_compress( &cinfo );
        result = true;
    }

_exit_:

    if(!result)
    {
        char jmsg_buf[JMSG_LENGTH_MAX];
        jerr.pub.format_message((j_common_ptr)&cinfo, jmsg_buf);
        m_last_error = jmsg_buf;
    }

    jpeg_destroy_compress( &cinfo );

    return result;
}