/*******************************************************************
 * File:     ifc
 * Purpose:  ImageFileConvert interfaces
 * Author:   Justin Fletcher
 * Date:     07 Jun 2003
 ******************************************************************/

#include <stdlib.h>
#include "swis.h"
#include "ImageFileConvertSWIs.h"

static _kernel_oserror err_NoMem={0,"Not enough memory to create image"};

/*************************************************** Gerph *********
 Function:     ifc_convert
 Description:  Convert a buffer from one format to another
 Parameters:   srcbuf-> the source buffer (word aligned)
               srclen = length of the source buffer
               srctype = the filetype of the source data
               desttype = the filetype of the destination data
               background = background colour to compose against, or
                            -1 for the natural background
               destbufp-> where to store the destination buffer pointer
                          will be allocated with malloc/realloc and must
                          therefore be freed with free.
               destlenp-> where to store the destination buffer length
 Returns:      pointer to error, or NULL if conversion successful
 ******************************************************************/
_kernel_oserror *ifc_convert(const char *srcbuf, size_t srclen,
                             unsigned long srctype, unsigned long desttype,
                             unsigned long background,
                             char **destbufp, size_t *destlenp)
{
  _kernel_oserror *err;
  char *out;
  size_t outlength;

  /* Find out how much space it'll take */
  err = _swix(ImageFileConvert_Convert,_INR(0,6)|_OUT(5),
                       0,(srctype<<16) | (desttype),
                       srcbuf,srclen, NULL,0,
                       background, &outlength);
  if (err)
    return err;

  if (outlength==-1)
  {
    /* Don't know how much memory it'll need */
    outlength = srclen;
    out = NULL;

    while (1)
    {
      _kernel_oserror *err;
      char *newout = realloc(out,outlength);
      if (newout==NULL)
      {
        free(out);
        return &err_NoMem;
      }
      out=newout;

      /* Do conversion */
      err = _swix(ImageFileConvert_Convert,_INR(0,6)|_OUT(5),
                    0, (srctype<<16) | (desttype),
                    srcbuf,srclen, out,outlength,
                    background, &outlength);
      if (err==NULL)
        break;
      if (err && err->errnum == 0x81ACCA)
      {
        /* Output buffer too small - we'll double the output buffer size.
           This method should allow large, well compressed, images to be
           created more quickly but may use more memory that strictly
           necessary.
         */
        outlength=outlength*2;
      }
      else if (err)
      {
        free(out);
        return err;
      }
    }
  }
  else
  {
    out = malloc(outlength);
    if (out==NULL)
    {
      return &err_NoMem;
    }

    /* Do conversion */
    err = _swix(ImageFileConvert_Convert,_INR(0,6)|_OUT(5),
                  0, (srctype<<16) | (desttype),
                  srcbuf,srclen, out,outlength,
                  background, &outlength);
    if (err)
    {
      free(out);
      return err;
    }
  }

  /* Success! */

  *destbufp = out;
  *destlenp = outlength;

  return NULL;
}
