pixops_medialib_composite (guchar          *dest_buf,
                           int              dest_width,
                           int              dest_height,
                           int              dest_rowstride,
                           int              dest_channels,
                           int              dest_has_alpha,
                           const guchar    *src_buf,
                           int              src_width,
                           int              src_height,
                           int              src_rowstride,
                           int              src_channels,
                           int              src_has_alpha,
                           int              dest_x,
                           int              dest_y,
                           int              dest_region_width,
                           int              dest_region_height,
                           double           offset_x,
                           double           offset_y,
                           double           scale_x,
                           double           scale_y,
                           PixopsInterpType interp_type,
                           int              overall_alpha)
{
  mlib_blend blend;
  g_return_if_fail (!(dest_channels == 3 && dest_has_alpha));
  g_return_if_fail (!(src_channels == 3 && src_has_alpha));

  if (scale_x == 0 || scale_y == 0)
    return;

  if (!medialib_initialized)
    _pixops_use_medialib ();

  if (!use_medialib)
    {
      /* Use non-mediaLib version */
      _pixops_composite_real (dest_buf + (gsize)dest_y * dest_rowstride + (gsize)dest_x *
			      dest_channels, dest_x - offset_x, dest_y -
			      offset_y, dest_x + dest_region_width - offset_x,
			      dest_y + dest_region_height - offset_y,
			      dest_rowstride, dest_channels, dest_has_alpha,
			      src_buf, src_width, src_height, src_rowstride,
			      src_channels, src_has_alpha, scale_x, scale_y,
			      interp_type, overall_alpha);
    }
  else
    {
      mlInterp ml_interp;
      mlib_image img_src, img_dest;
      double ml_offset_x, ml_offset_y;

      if (!src_has_alpha && overall_alpha == 255 &&
	  dest_channels <= src_channels) 
        {
          pixops_medialib_scale (dest_buf, dest_region_width,
				 dest_region_height, dest_rowstride,
				 dest_channels, dest_has_alpha, src_buf,
				 src_width, src_height, src_rowstride,
				 src_channels, src_has_alpha, dest_x, dest_y,
				 dest_region_width, dest_region_height,
				 offset_x, offset_y, scale_x, scale_y,
				 interp_type);
          return;
        }

      mlib_ImageSetStruct (&img_src, MLIB_BYTE, src_channels,
			   src_width, src_height, src_rowstride, src_buf);

      if (dest_x == 0 && dest_y == 0 &&
          dest_width  == dest_region_width &&
          dest_height == dest_region_height)
        {
          mlib_ImageSetStruct (&img_dest, MLIB_BYTE, dest_channels,
			       dest_width, dest_height, dest_rowstride,
			       dest_buf);
        }
      else
        {
	  mlib_u8 *data = dest_buf + (gsize)dest_y * dest_rowstride +
				     (gsize)dest_x * dest_channels;

          mlib_ImageSetStruct (&img_dest, MLIB_BYTE, dest_channels,
			       dest_region_width, dest_region_height,
			       dest_rowstride, data);
        }

      ml_offset_x = floor (offset_x) - dest_x;
      ml_offset_y = floor (offset_y) - dest_y;

      if (interp_type == PIXOPS_INTERP_NEAREST)
        {
          blend = src_has_alpha ? MLIB_BLEND_GTK_SRC_OVER2 : MLIB_BLEND_GTK_SRC;

          mlib_ImageZoomTranslateBlend (&img_dest,
                                        &img_src,
                                        scale_x,
                                        scale_y,
                                        ml_offset_x,
                                        ml_offset_y,
                                        MLIB_NEAREST,
                                        MLIB_EDGE_SRC_EXTEND_INDEF,
                                        blend,
                                        overall_alpha,
                                        1);
        }
      else
        {
          blend = src_has_alpha ? MLIB_BLEND_GTK_SRC_OVER : MLIB_BLEND_GTK_SRC;

          if (interp_type == PIXOPS_INTERP_BILINEAR &&
	      scale_x > 1.0 && scale_y > 1.0)
            {
              mlib_ImageZoomTranslateBlend (&img_dest,
                                            &img_src,
                                            scale_x,
                                            scale_y,
                                            ml_offset_x,
                                            ml_offset_y,
                                            MLIB_BILINEAR,
                                            MLIB_EDGE_SRC_EXTEND_INDEF,
                                            blend,
                                            overall_alpha,
                                            1);
            }
          else
            {
              medialib_get_interpolation (&ml_interp, interp_type, scale_x,
					  scale_y, overall_alpha/255.0);

              if (ml_interp.interp_table != NULL)
                {
                  mlib_ImageZoomTranslateTableBlend (&img_dest,
                                                     &img_src,
                                                     scale_x,
                                                     scale_y,
                                                     ml_offset_x + ml_interp.tx,
                                                     ml_offset_y + ml_interp.ty,
                                                     ml_interp.interp_table,
                                                     MLIB_EDGE_SRC_EXTEND_INDEF,
                                                     blend,
                                                     1);
                  mlib_ImageInterpTableDelete (ml_interp.interp_table);
                }
              else
                {
                  /* Should not happen - Use non-mediaLib version */
                  _pixops_composite_real (dest_buf + (gsize)dest_y * dest_rowstride +
                                          (gsize)dest_x * dest_channels,
                                          dest_x - offset_x, dest_y - offset_y,
                                          dest_x + dest_region_width - offset_x,
                                          dest_y + dest_region_height - offset_y,
                                          dest_rowstride, dest_channels,
                                          dest_has_alpha, src_buf, src_width,
                                          src_height, src_rowstride,
                                          src_channels, src_has_alpha, scale_x,
                                          scale_y, interp_type, overall_alpha);
                }
            }
        }
    }
}