FgImg4UC
fgLoadImg4UC(const FgString & fname)
{
    FgImg4UC        ret;
    if (!fgFileReadable(fname))
        fgThrow("Unable to read file",fname);
    fgEnsureMagick();
    FgScopePtr<ExceptionInfo>   exception(AcquireExceptionInfo(),DestroyExceptionInfo);
    FgScopePtr<ImageInfo>       image_info(CloneImageInfo(0),DestroyImageInfo);
    (void) strcpy(image_info->filename,fname.as_utf8_string().c_str());
    // TODO: Do we need to convert into a specific colourspace?
    Image *imgPtr = ReadImage(image_info.get(),exception.get());
    if (imgPtr == 0)
        // exception.description is NULL
        fgThrow("Unable to read image file",fname + ": " + exception->reason);
    FgScopeGuard                sg0(boost::bind(DestroyImage,imgPtr));
    FgScopePtr<CacheView>       view(AcquireCacheView(imgPtr),DestroyCacheView);
    ret.resize(uint(imgPtr->columns),uint(imgPtr->rows));
    for(uint row= 0; row < imgPtr->rows; ++row) {
        for(uint column = 0; column < imgPtr->columns; ++column) {
            PixelPacket pixel;
            FGASSERT(MagickTrue == 
                    GetOneCacheViewAuthenticPixel(view.get(),column,row,&pixel,exception.get()));
            ret.elem(column,row)[0] = uchar(pixel.red);
            ret.elem(column,row)[1] = uchar(pixel.green);
            ret.elem(column,row)[2] = uchar(pixel.blue);
            ret.elem(column,row)[3] =  255 - uchar(pixel.opacity);
        }
    }
    return ret;
}
void
fgLoadImgAnyFormat(
    const FgString &    fname,
    FgImgF &            img)
{
    if (!fgFileReadable(fname))
        fgThrow("Unable to read file",fname);

    fgEnsureMagick();

    FgScopePtr<ExceptionInfo>   exception(AcquireExceptionInfo(),DestroyExceptionInfo);
    FgScopePtr<ImageInfo>       image_info(CloneImageInfo(0),DestroyImageInfo);

    (void) strcpy(image_info->filename,fname.as_utf8_string().c_str());

    // TODO: Do we need to convert into a specific colourspace?
    Image *imgPtr = ReadImage(image_info.get(),exception.get());
    if (imgPtr == 0)
        // exception.description is NULL
        fgThrow("Unable to read image file",fname + ": " + exception->reason);
    FgScopeGuard                sg0(boost::bind(DestroyImage,imgPtr));

    FgScopePtr<CacheView>       view(AcquireCacheView(imgPtr),DestroyCacheView);

    img.resize(uint(imgPtr->columns),uint(imgPtr->rows));

    for(uint row = 0; row < imgPtr->rows; ++row) {
        for(uint column = 0; column < imgPtr->columns; ++column) {
            PixelPacket pixel;
            FGASSERT(MagickTrue == 
                    GetOneCacheViewAuthenticPixel(view.get(),column,row,&pixel,exception.get()));
            img.elem(column,row) = pixel.red;   // All channels same value if single-channel read
        }
    }
}
void
fgRemoveFile(const FgString & fname)
{
    string      utf8 = fname.as_utf8_string();
    if (remove(utf8.c_str()) != 0)
        fgThrow("Unable to remove file",fname);
}
void
fgSaveImgAnyFormat(
    const FgString &    fname,
    const FgImgRgbaUb & img)
{
    FGASSERT(fname.length() > 0);

    fgEnsureMagick();
    FgScopePtr<ImageInfo>       image_info(CloneImageInfo(0),DestroyImageInfo);
    FgScopePtr<ExceptionInfo>   exception(AcquireExceptionInfo(),DestroyExceptionInfo);
    FgScopePtr<Image>           image(ConstituteImage(img.width(),img.height(),"RGBA",
                                                   CharPixel,
                                                   img.dataPtr(),
                                                   exception.get()),
                                   DestroyImage);
    (void) strcpy(image_info->filename,fname.as_utf8_string().c_str());
    FGASSERT(
        MagickTrue == 
            WriteImages(image_info.get(),image.get(),fname.as_utf8_string().c_str(),exception.get()));
}
bool
fgSetCurrentDir(
    const FgString &    dir,
    bool                throwOnFail)
{
    string      sdir = dir.as_utf8_string();
    bool ret = (chdir(sdir.c_str()) == 0);
    if ((!ret) && throwOnFail)
        fgThrow("Unable to set current directory to",dir);
    return ret;
}
bool
fgRemoveDirectory(
    const FgString &    dir,
    bool                throwOnFail)
{
    string      sdir = dir.as_utf8_string();
    int         ret =  rmdir(sdir.c_str());
    if (ret == 0)
        return true;
    if (throwOnFail)
        fgThrow("Unable to remove directory",dir);
    return false;
}
bool
fgCreateDirectory(const FgString & dir)
{
    string      sdir = dir.as_utf8_string();
    return (mkdir(sdir.c_str(),0777) == 0);
}
 Dir(const FgString & dirName)
 {handle = opendir(dirName.as_utf8_string().c_str()); }