[arrayfire] 280/408: FEAT Added image IO using memory functions and tests

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:12:13 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/sid
in repository arrayfire.

commit 817ccc31e05aaaa18c09933340a666ab4cfa18db
Author: Shehzan Mohammed <shehzan at arrayfire.com>
Date:   Tue Aug 18 16:00:46 2015 -0400

    FEAT Added image IO using memory functions and tests
    
    * Load and save image formats to memory
---
 docs/details/image.dox  |  25 ++++
 include/af/image.h      |  93 ++++++++++++--
 src/api/c/imageio.cpp   | 314 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/api/cpp/imageio.cpp |  19 +++
 test/imageio.cpp        |  64 ++++++++++
 5 files changed, 504 insertions(+), 11 deletions(-)

diff --git a/docs/details/image.dox b/docs/details/image.dox
index ed0efae..d3b32d3 100644
--- a/docs/details/image.dox
+++ b/docs/details/image.dox
@@ -427,6 +427,31 @@ Save an array to disk as an image
 Supported formats include JPG, PNG, PPM and other formats supported by freeimage
 
 
+\defgroup imagemem_func_load loadImageMem
+\ingroup imageio_mat
+
+Load an image from memory which is stored as a FreeImage stream (FIMEMORY).
+
+Supported formats include JPG, PNG, PPM and other formats supported by freeimage
+
+
+
+\defgroup imagemem_func_save saveImageMem
+\ingroup imageio_mat
+
+Save an array to memory as an image using FreeImage stream (FIMEMORY).
+
+Supported formats include JPG, PNG, PPM and other formats supported by freeimage
+
+
+\defgroup imagemem_func_delete deleteImageMem
+\ingroup imageio_mat
+
+Delete memory created by saveImageMem and af_save_image_memory function.
+This internally calls FreeImage_CloseMemory.
+
+Supported formats include JPG, PNG, PPM and other formats supported by freeimage
+
 
 \defgroup calc_func_grad grad
 \ingroup calc_mat
diff --git a/include/af/image.h b/include/af/image.h
index 4f7227c..2f8c85a 100644
--- a/include/af/image.h
+++ b/include/af/image.h
@@ -48,6 +48,47 @@ AFAPI array loadImage(const char* filename, const bool is_color=false);
 AFAPI void saveImage(const char* filename, const array& in);
 
 /**
+    C++ Interface for loading an image from memory
+
+    \param[in] ptr is the location of the image data in memory. This is the pointer
+    created by saveImage.
+    \return image loaded as \ref af::array()
+
+    \note The pointer used is a void* cast of the FreeImage type FIMEMORY which is
+    created using the FreeImage_OpenMemory API. If the user is opening a FreeImage
+    stream external to ArrayFire, that pointer can be passed to this function as well.
+
+    \ingroup imagemem_func_load
+*/
+AFAPI array loadImageMem(const void *ptr);
+
+/**
+    C++ Interface for saving an image to memory
+
+    \param[in] filename is a dummy string that contains the image type. This is
+    used to determine the filetype to be used. No file is created.
+    \param[in] in is the arrayfire array to be saved as an image
+
+    \return a void* pointer which is a type cast of the FreeImage type FIMEMORY* pointer.
+
+    \note Ensure that \ref deleteImageMem is called on this pointer. Otherwise there will
+    be memory leaks
+
+    \ingroup imagemem_func_save
+*/
+AFAPI void* saveImageMem(const char* filename, const array& in);
+
+/**
+    C++ Interface for deleting memory created by \ref saveImageMem or
+    \ref af_save_image_memory
+
+    \param[in] ptr is the pointer to the FreeImage stream created by saveImageMem.
+
+    \ingroup imagemem_func_delete
+*/
+AFAPI void deleteImageMem(void *ptr);
+
+/**
     C++ Interface for resizing an image to specified dimensions
 
     \param[in] in is input image
@@ -562,19 +603,55 @@ extern "C" {
     */
     AFAPI af_err af_load_image(af_array *out, const char* filename, const bool isColor);
 
-   /**
-      C Interface for saving an image
+    /**
+       C Interface for saving an image
 
-      \param[in] filename is name of file to be loaded
-      \param[in] in is the arrayfire array to be saved as an image
-      \return     \ref AF_SUCCESS if the color transformation is successful,
-      otherwise an appropriate error code is returned.
+       \param[in] filename is name of file to be loaded
+       \param[in] in is the arrayfire array to be saved as an image
+       \return     \ref AF_SUCCESS if the color transformation is successful,
+       otherwise an appropriate error code is returned.
 
-      \ingroup imageio_func_save
-   */
+       \ingroup imageio_func_save
+    */
     AFAPI af_err af_save_image(const char* filename, const af_array in);
 
     /**
+       C Interface for loading an image from memory
+
+       \param[out] out is an array that will contain the image
+       \param[in] ptr is the FIMEMORY pointer created by either saveImageMem function, the
+       af_save_image_memory function, or the FreeImage_OpenMemory API.
+       \return     \ref AF_SUCCESS if successful
+
+       \ingroup imagemem_func_load
+    */
+    AFAPI af_err af_load_image_memory(af_array *out, const void* ptr);
+
+    /**
+       C Interface for saving an image to memory using FreeImage
+
+       \param[out] ptr is the FIMEMORY pointer created by FreeImage.
+       \param[in] filename is a string that contains the type of image storage to be used.
+       No file is created. This is used to determine the type and encoding to use.
+       \param[in] in is the arrayfire array to be saved as an image
+       \return     \ref AF_SUCCESS if successful.
+
+       \ingroup imagemem_func_save
+    */
+    AFAPI af_err af_save_image_memory(void** ptr, const char* filename, const af_array in);
+
+    /**
+       C Interface for deleting an image from memory
+
+       \param[in] ptr is the FIMEMORY pointer created by either saveImageMem function, the
+       af_save_image_memory function, or the FreeImage_OpenMemory API.
+       \return     \ref AF_SUCCESS if successful
+
+       \ingroup imagemem_func_delete
+    */
+    AFAPI af_err af_delete_image_memory(void* ptr);
+
+    /**
        C Interface for resizing an image to specified dimensions
 
        \param[out] out will contain the resized image of specified by \p odim0 and \p odim1
diff --git a/src/api/c/imageio.cpp b/src/api/c/imageio.cpp
index 2f670aa..567ff07 100644
--- a/src/api/c/imageio.cpp
+++ b/src/api/c/imageio.cpp
@@ -167,8 +167,11 @@ static af_err readImage(af_array *rImage, const uchar* pSrcLine, const int nSrcP
     return err;
 }
 
-/// Load a gray-scale image from disk.
-AFAPI af_err af_load_image(af_array *out, const char* filename, const bool isColor)
+////////////////////////////////////////////////////////////////////////////////
+// File IO
+////////////////////////////////////////////////////////////////////////////////
+// Load image from disk.
+af_err af_load_image(af_array *out, const char* filename, const bool isColor)
 {
     try {
         ARG_ASSERT(1, filename != NULL);
@@ -435,10 +438,297 @@ af_err af_save_image(const char* filename, const af_array in_)
     return AF_SUCCESS;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Memory IO
+////////////////////////////////////////////////////////////////////////////////
+/// Load image from memory.
+af_err af_load_image_memory(af_array *out, const void* ptr)
+{
+    try {
+        ARG_ASSERT(1, ptr != NULL);
+
+        // for statically linked FI
+        FI_Init();
+
+        // set your own FreeImage error handler
+        FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+        FIMEMORY *stream = (FIMEMORY*)ptr;
+        FreeImage_SeekMemory(stream, 0L, SEEK_SET);
+
+        // try to guess the file format from the file extension
+        FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(stream, 0);
+        //if (fif == FIF_UNKNOWN) {
+        //    fif = FreeImage_GetFIFFromFilenameFromMemory(filename);
+        //}
+
+        if(fif == FIF_UNKNOWN) {
+            AF_ERROR("FreeImage Error: Unknown File or Filetype", AF_ERR_NOT_SUPPORTED);
+        }
+
+        // check that the plugin has reading capabilities ...
+        FIBITMAP* pBitmap = NULL;
+        if (FreeImage_FIFSupportsReading(fif)) {
+            pBitmap = FreeImage_LoadFromMemory(fif, stream, 0);
+        }
+
+        if(pBitmap == NULL) {
+            AF_ERROR("FreeImage Error: Error reading image or file does not exist", AF_ERR_RUNTIME);
+        }
+
+        // check image color type
+        uint color_type = FreeImage_GetColorType(pBitmap);
+        const uint fi_bpp = FreeImage_GetBPP(pBitmap);
+        //int fi_color = (int)((fi_bpp / 8.0) + 0.5);        //ceil
+        int fi_color;
+        if      (color_type == 1) fi_color = 1;
+        else if (color_type == 2) fi_color = 3;
+        else if (color_type == 4) fi_color = 4;
+        else                      fi_color = 3;
+        const int fi_bpc = fi_bpp / fi_color;
+        if(fi_bpc != 8 && fi_bpc != 16 && fi_bpc != 32) {
+            AF_ERROR("FreeImage Error: Bits per channel not supported", AF_ERR_NOT_SUPPORTED);
+        }
+
+        // sizes
+        uint fi_w = FreeImage_GetWidth(pBitmap);
+        uint fi_h = FreeImage_GetHeight(pBitmap);
+
+        // FI = row major | AF = column major
+        uint nSrcPitch = FreeImage_GetPitch(pBitmap);
+        const uchar* pSrcLine = FreeImage_GetBits(pBitmap) + nSrcPitch * (fi_h - 1);
+
+        // result image
+        af_array rImage;
+        if(fi_color == 4) {     //4 channel image
+            if(fi_bpc == 8)
+                AF_CHECK((readImage<uchar, 4, 4>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+            else if(fi_bpc == 16)
+                AF_CHECK((readImage<ushort,4, 4>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+            else if(fi_bpc == 32)
+                AF_CHECK((readImage<float, 4, 4>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+        } else if (fi_color == 1) { // 1 channel image
+            if(fi_bpc == 8)
+                AF_CHECK((readImage<uchar, 1>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+            else if(fi_bpc == 16)
+                AF_CHECK((readImage<ushort,1>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+            else if(fi_bpc == 32)
+                AF_CHECK((readImage<float, 1>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+        } else {             //3 channel image
+            if(fi_bpc == 8)
+                AF_CHECK((readImage<uchar, 3, 3>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+            else if(fi_bpc == 16)
+                AF_CHECK((readImage<ushort,3, 3>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+            else if(fi_bpc == 32)
+                AF_CHECK((readImage<float, 3, 3>)(&rImage, pSrcLine, nSrcPitch, fi_w, fi_h));
+        }
+
+        FreeImage_Unload(pBitmap);
+        std::swap(*out,rImage);
+    } CATCHALL;
+
+    return AF_SUCCESS;
+}
+
+// Save an image to disk.
+af_err af_save_image_memory(void **ptr, const char* filename, const af_array in_)
+{
+    try {
+
+        ARG_ASSERT(0, filename != NULL);
+
+        FI_Init();
+
+        // set your own FreeImage error handler
+        FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+        // try to guess the file format from the file extension
+        FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(filename);
+        if (fif == FIF_UNKNOWN) {
+            fif = FreeImage_GetFIFFromFilename(filename);
+        }
+
+        if(fif == FIF_UNKNOWN) {
+            AF_ERROR("FreeImage Error: Unknown Filetype", AF_ERR_NOT_SUPPORTED);
+        }
+
+        ArrayInfo info = getInfo(in_);
+        // check image color type
+        uint channels = info.dims()[2];
+        DIM_ASSERT(1, channels <= 4);
+        DIM_ASSERT(1, channels != 2);
+
+        int fi_bpp = channels * 8;
+
+        // sizes
+        uint fi_w = info.dims()[1];
+        uint fi_h = info.dims()[0];
+
+        // create the result image storage using FreeImage
+        FIBITMAP* pResultBitmap = FreeImage_Allocate(fi_w, fi_h, fi_bpp);
+        if(pResultBitmap == NULL) {
+            AF_ERROR("FreeImage Error: Error creating image or file", AF_ERR_RUNTIME);
+        }
+
+        // FI assumes [0-255]
+        // If array is in 0-1 range, multiply by 255
+        af_array in;
+        double max_real, max_imag;
+        bool free_in = false;
+        AF_CHECK(af_max_all(&max_real, &max_imag, in_));
+        if (max_real <= 1) {
+            af_array c255;
+            AF_CHECK(af_constant(&c255, 255.0, info.ndims(), info.dims().get(), f32));
+            AF_CHECK(af_mul(&in, in_, c255, false));
+            AF_CHECK(af_release_array(c255));
+            free_in = true;
+        } else {
+            in = in_;
+        }
+
+        // FI = row major | AF = column major
+        uint nDstPitch = FreeImage_GetPitch(pResultBitmap);
+        uchar* pDstLine = FreeImage_GetBits(pResultBitmap) + nDstPitch * (fi_h - 1);
+        af_array rr = 0, gg = 0, bb = 0, aa = 0;
+        AF_CHECK(channel_split(in, info.dims(), &rr, &gg, &bb, &aa)); // convert array to 3 channels if needed
+
+        uint step = channels; // force 3 channels saving
+        uint indx = 0;
+
+        af_array rrT = 0, ggT = 0, bbT = 0, aaT = 0;
+        if(channels == 4) {
+
+            AF_CHECK(af_transpose(&rrT, rr, false));
+            AF_CHECK(af_transpose(&ggT, gg, false));
+            AF_CHECK(af_transpose(&bbT, bb, false));
+            AF_CHECK(af_transpose(&aaT, aa, false));
+
+            ArrayInfo cinfo = getInfo(rrT);
+            float* pSrc0 = pinnedAlloc<float>(cinfo.elements());
+            float* pSrc1 = pinnedAlloc<float>(cinfo.elements());
+            float* pSrc2 = pinnedAlloc<float>(cinfo.elements());
+            float* pSrc3 = pinnedAlloc<float>(cinfo.elements());
+
+            AF_CHECK(af_get_data_ptr((void*)pSrc0, rrT));
+            AF_CHECK(af_get_data_ptr((void*)pSrc1, ggT));
+            AF_CHECK(af_get_data_ptr((void*)pSrc2, bbT));
+            AF_CHECK(af_get_data_ptr((void*)pSrc3, aaT));
+
+            // Copy the array into FreeImage buffer
+            for (uint y = 0; y < fi_h; ++y) {
+                for (uint x = 0; x < fi_w; ++x) {
+                    *(pDstLine + x * step + 2) = (uchar) pSrc0[indx]; // b
+                    *(pDstLine + x * step + 1) = (uchar) pSrc1[indx]; // g
+                    *(pDstLine + x * step + 0) = (uchar) pSrc2[indx]; // r
+                    *(pDstLine + x * step + 3) = (uchar) pSrc3[indx]; // a
+                    ++indx;
+                }
+                pDstLine -= nDstPitch;
+            }
+            pinnedFree(pSrc0);
+            pinnedFree(pSrc1);
+            pinnedFree(pSrc2);
+            pinnedFree(pSrc3);
+        } else if(channels == 3) {
+            AF_CHECK(af_transpose(&rrT, rr, false));
+            AF_CHECK(af_transpose(&ggT, gg, false));
+            AF_CHECK(af_transpose(&bbT, bb, false));
+
+            ArrayInfo cinfo = getInfo(rrT);
+            float* pSrc0 = pinnedAlloc<float>(cinfo.elements());
+            float* pSrc1 = pinnedAlloc<float>(cinfo.elements());
+            float* pSrc2 = pinnedAlloc<float>(cinfo.elements());
+
+            AF_CHECK(af_get_data_ptr((void*)pSrc0, rrT));
+            AF_CHECK(af_get_data_ptr((void*)pSrc1, ggT));
+            AF_CHECK(af_get_data_ptr((void*)pSrc2, bbT));
+
+            // Copy the array into FreeImage buffer
+            for (uint y = 0; y < fi_h; ++y) {
+                for (uint x = 0; x < fi_w; ++x) {
+                    *(pDstLine + x * step + 2) = (uchar) pSrc0[indx]; // b
+                    *(pDstLine + x * step + 1) = (uchar) pSrc1[indx]; // g
+                    *(pDstLine + x * step + 0) = (uchar) pSrc2[indx]; // r
+                    ++indx;
+                }
+                pDstLine -= nDstPitch;
+            }
+            pinnedFree(pSrc0);
+            pinnedFree(pSrc1);
+            pinnedFree(pSrc2);
+        } else {
+            AF_CHECK(af_transpose(&rrT, rr, false));
+            ArrayInfo cinfo = getInfo(rrT);
+            float* pSrc0 = pinnedAlloc<float>(cinfo.elements());
+            AF_CHECK(af_get_data_ptr((void*)pSrc0, rrT));
+
+            for (uint y = 0; y < fi_h; ++y) {
+                for (uint x = 0; x < fi_w; ++x) {
+                    *(pDstLine + x * step) = (uchar) pSrc0[indx];
+                    ++indx;
+                }
+                pDstLine -= nDstPitch;
+            }
+            pinnedFree(pSrc0);
+        }
+
+        FIMEMORY *stream = FreeImage_OpenMemory();
+
+        // now save the result image
+        if (!(FreeImage_SaveToMemory(fif, pResultBitmap, stream, 0) == TRUE)) {
+            AF_ERROR("FreeImage Error: Failed to save image", AF_ERR_RUNTIME);
+        }
+
+        *ptr = stream;
+
+        FreeImage_Unload(pResultBitmap);
+
+        if(free_in) AF_CHECK(af_release_array(in ));
+        if(rr != 0) AF_CHECK(af_release_array(rr ));
+        if(gg != 0) AF_CHECK(af_release_array(gg ));
+        if(bb != 0) AF_CHECK(af_release_array(bb ));
+        if(aa != 0) AF_CHECK(af_release_array(aa ));
+        if(rrT!= 0) AF_CHECK(af_release_array(rrT));
+        if(ggT!= 0) AF_CHECK(af_release_array(ggT));
+        if(bbT!= 0) AF_CHECK(af_release_array(bbT));
+        if(aaT!= 0) AF_CHECK(af_release_array(aaT));
+
+    } CATCHALL
+
+    return AF_SUCCESS;
+}
+
+af_err af_delete_image_memory(void *ptr)
+{
+    try {
+
+        ARG_ASSERT(0, ptr != NULL);
+
+        FI_Init();
+
+        // set your own FreeImage error handler
+        FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+        FIMEMORY *stream = (FIMEMORY*)ptr;
+        FreeImage_SeekMemory(stream, 0L, SEEK_SET);
+
+        // Ensure data is freeimage compatible
+        FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory((FIMEMORY*)ptr, 0);
+        if(fif == FIF_UNKNOWN) {
+            AF_ERROR("FreeImage Error: Unknown Filetype", AF_ERR_NOT_SUPPORTED);
+        }
+
+        FreeImage_CloseMemory((FIMEMORY *)ptr);
+
+    } CATCHALL
+
+    return AF_SUCCESS;
+}
+
 #else   // WITH_FREEIMAGE
 #include <af/image.h>
 #include <stdio.h>
-AFAPI af_err af_load_image(af_array *out, const char* filename, const bool isColor)
+af_err af_load_image(af_array *out, const char* filename, const bool isColor)
 {
     printf("Error: Image IO requires FreeImage. See https://github.com/arrayfire/arrayfire\n");
     return AF_ERR_NOT_CONFIGURED;
@@ -449,4 +739,22 @@ af_err af_save_image(const char* filename, const af_array in_)
     printf("Error: Image IO requires FreeImage. See https://github.com/arrayfire/arrayfire\n");
     return AF_ERR_NOT_CONFIGURED;
 }
+
+af_err af_load_image_memory(af_array *out, const void* ptr)
+{
+    printf("Error: Image IO requires FreeImage. See https://github.com/arrayfire/arrayfire\n");
+    return AF_ERR_NOT_CONFIGURED;
+}
+
+af_err af_save_image_memory(void **ptr, const char* filename, const af_array in_)
+{
+    printf("Error: Image IO requires FreeImage. See https://github.com/arrayfire/arrayfire\n");
+    return AF_ERR_NOT_CONFIGURED;
+}
+
+af_err af_delete_image_memory(void *ptr)
+{
+    printf("Error: Image IO requires FreeImage. See https://github.com/arrayfire/arrayfire\n");
+    return AF_ERR_NOT_CONFIGURED;
+}
 #endif  // WITH_FREEIMAGE
diff --git a/src/api/cpp/imageio.cpp b/src/api/cpp/imageio.cpp
index a0647a0..a84861f 100644
--- a/src/api/cpp/imageio.cpp
+++ b/src/api/cpp/imageio.cpp
@@ -22,6 +22,13 @@ array loadImage(const char* filename, const bool is_color)
     return array(out);
 }
 
+array loadImageMem(const void* ptr)
+{
+    af_array out = 0;
+    AF_THROW(af_load_image_memory(&out, ptr));
+    return array(out);
+}
+
 array loadimage(const char* filename, const bool is_color)
 {
     return loadImage(filename, is_color);
@@ -32,9 +39,21 @@ void saveImage(const char* filename, const array& in)
     AF_THROW(af_save_image(filename, in.get()));
 }
 
+void* saveImageMem(const char* filename, const array& in)
+{
+    void* ptr = NULL;
+    AF_THROW(af_save_image_memory(&ptr, filename, in.get()));
+    return ptr;
+}
+
 void saveimage(const char* filename, const array& in)
 {
     return saveImage(filename, in);
 }
 
+void deleteImageMem(void* ptr)
+{
+    AF_THROW(af_delete_image_memory(ptr));
+}
+
 }
diff --git a/test/imageio.cpp b/test/imageio.cpp
index 95f40a9..f5b6017 100644
--- a/test/imageio.cpp
+++ b/test/imageio.cpp
@@ -167,4 +167,68 @@ TEST(ImageIO, SaveBMPCPP) {
     ASSERT_FALSE(af::anyTrue<bool>(out - input));
 }
 
+TEST(ImageMem, SaveMemPNG)
+{
+    if (noDoubleTests<float>()) return;
+
+    af::array img = af::loadImage(string(TEST_DIR"/imageio/color_seq.png").c_str(), true);
+
+    void* savedMem = af::saveImageMem("save.png", img);
+
+    af::array loadMem = af::loadImageMem(savedMem);
+
+    ASSERT_FALSE(af::anyTrue<bool>(img - loadMem));
+
+    af::deleteImageMem(savedMem);
+}
+
+TEST(ImageMem, SaveMemJPG1)
+{
+    if (noDoubleTests<float>()) return;
+
+    af::array img = af::loadImage(string(TEST_DIR"/imageio/color_seq.png").c_str(), false);
+    af::saveImage("color_seq1.jpg", img);
+
+    void* savedMem = af::saveImageMem("color_seq1.jpg", img);
+
+    af::array loadMem = af::loadImageMem(savedMem);
+    af::array imgJPG = af::loadImage("color_seq1.jpg", false);
+
+    ASSERT_FALSE(af::anyTrue<bool>(imgJPG - loadMem));
+
+    af::deleteImageMem(savedMem);
+}
+
+TEST(ImageMem, SaveMemJPG3)
+{
+    if (noDoubleTests<float>()) return;
+
+    af::array img = af::loadImage(string(TEST_DIR"/imageio/color_seq.png").c_str(), true);
+    af::saveImage("color_seq3.jpg", img);
+
+    void* savedMem = af::saveImageMem("color_seq3.jpg", img);
+
+    af::array loadMem = af::loadImageMem(savedMem);
+    af::array imgJPG = af::loadImage("color_seq3.jpg", true);
+
+    ASSERT_FALSE(af::anyTrue<bool>(imgJPG - loadMem));
+
+    af::deleteImageMem(savedMem);
+}
+
+TEST(ImageMem, SaveMemBMP)
+{
+    if (noDoubleTests<float>()) return;
+
+    af::array img = af::loadImage(string(TEST_DIR"/imageio/color_rand.png").c_str(), true);
+
+    void* savedMem = af::saveImageMem("save.png", img);
+
+    af::array loadMem = af::loadImageMem(savedMem);
+
+    ASSERT_FALSE(af::anyTrue<bool>(img - loadMem));
+
+    af::deleteImageMem(savedMem);
+}
+
 #endif // WITH_FREEIMAGE

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git



More information about the debian-science-commits mailing list