[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