diff --git a/src/PqxxExtension.hpp b/src/PqxxExtension.hpp
index bf2caebf4a7b5dae6503a15bb7b2eedefcb83a6d..37b07168942725817664d18ea31fe5b97f6ca28a 100644
--- a/src/PqxxExtension.hpp
+++ b/src/PqxxExtension.hpp
@@ -172,24 +172,54 @@ public:
         // currently. Copy the str into a std::string so we can work with it more easily.
         std::string in(str + 1, str + (strlen(str) - 1));
 
-        // count commas and add one to deduce elements in the string,
+        // count opening brackets and add one to deduce elements in the string,
         // note we reduce string size to remove the brace at each end
-        auto items = std::count(in.begin(), in.end(), ',');
-        value.clear();
+        auto dim_y = std::count(in.begin(), in.end(), '{');
 
-        // preallocate all the items in the vector, we can then
-        // simply set each in turn
-        value.resize(items + 1);
+        if(dim_y == 0)
+        {
+            // Regular array
+            auto items = std::count(in.begin(), in.end(), ',');
+            value.dim_y = dim_y;
+            value.dim_x = items + 1;
 
-        auto element = 0;
-        std::string::size_type comma = 0;
+            // preallocate all the items in the vector, we can then
+            // simply set each in turn
+            value.resize(value.dim_x);
 
-        // loop and copy out each value from between the separators
-        while ((comma = in.find_first_not_of(',', comma)) != std::string::npos)
+            auto element = 0;
+            std::string::size_type comma = 0;
+
+            // loop and copy out each value from between the separators
+            while ((comma = in.find_first_not_of(',', comma)) != std::string::npos)
+            {
+                auto next_comma = in.find_first_of(',', comma);
+                string_traits<T>::from_string(in.substr(comma, next_comma - comma).c_str(), value[element++]);
+                comma = next_comma;
+            }
+        }
+        else
         {
-            auto next_comma = in.find_first_of(',', comma);
-            string_traits<T>::from_string(in.substr(comma, next_comma - comma).c_str(), value[element++]);
-            comma = next_comma;
+            // 2D array, or image
+            auto items = std::count(in.begin(), in.end(), ',');
+            value.dim_y = dim_y;
+            value.dim_x = (items + 1) / dim_y;
+
+            // Look for enclosing brackets to extract rows 
+            std::string::size_type bracket = 0;
+            std::string::size_type close_bracket = 0;
+
+            // loop and copy out each value from between the separators
+            while ((bracket = in.find_first_of('{', close_bracket)) != std::string::npos)
+            {
+                close_bracket = in.find_first_of('}', bracket);
+
+                // We clear the value so we need to extract in another vector
+                hdbpp_internal::TangoValue<T> row;
+                string_traits<hdbpp_internal::TangoValue<T>>::from_string(in.substr(bracket, close_bracket - bracket + 1).c_str(), row);
+
+                value.insert(value.end(), row.begin(), row.end());
+            }
         }
     }
 
@@ -212,19 +242,16 @@ public:
 
         std::stringstream result;
         result << "{";
-        for(std::size_t i = 0; i != value.dim_y; ++i)
+        
+	result << "{" << separated_list(",", value.begin(), std::next(value.begin(), value.dim_x)) << "}";
+        for(std::size_t i = 1; i != value.dim_y; ++i)
         {
-            if (i > 0)
-            {
-                result << ",";
-            }
-
-            result << "{" << separated_list(",", std::next(value.begin(), i * value.dim_x), std::next(value.begin(), (i+1) * value.dim_x)) << "}";
+            result << ", {" << separated_list(",", std::next(value.begin(), i * value.dim_x), std::next(value.begin(), (i+1) * value.dim_x)) << "}";
         }
         result << "}";
         return result.str();
     }
-    
+
 };
 
 // This specialisation is for string types. Unlike other types the string type requires
@@ -256,29 +283,30 @@ public:
 
         value.clear();
 
+        value.dim_x = 0;
+        value.dim_y = 0;
+
         std::pair<array_parser::juncture, std::string> output;
 
         // use pqxx array parser features to get each element from the array
         array_parser parser(str);
         output = parser.get_next();
 
-        if (output.first == array_parser::juncture::row_start)
+        while (output.first != array_parser::juncture::done)
         {
             output = parser.get_next();
-
-            // loop and extract each string in turn
-            while (output.first == array_parser::juncture::string_value)
+            if (output.first == array_parser::juncture::string_value)
             {
                 value.push_back(output.second);
-                output = parser.get_next();
-
-                if (output.first == array_parser::juncture::row_end)
-                    break;
-
-                if (output.first == array_parser::juncture::done)
-                    break;
+                continue;
+            }
+            if(output.first == array_parser::juncture::row_start)
+            {
+                ++(value.dim_y);
+                continue;
             }
         }
+        value.dim_x = value.dim_y == 0 ? value.size() : (value.size() / value.dim_y);
     }
 
     // NOLINTNEXTLINE (readability-identifier-naming)
@@ -323,22 +351,56 @@ public:
         // testing only. Copy the str into a std::string so we can work
         // with it more easily.
         std::string in(str + 1, str + (strlen(str) - 1));
-        std::string::size_type comma = 0;
+        
+        // count opening brackets and add one to deduce elements in the string,
+        // note we reduce string size to remove the brace at each end
+        auto dim_y = std::count(in.begin(), in.end(), '{');
 
-        // loop and copy out each value from between the separators
-        while ((comma = in.find_first_not_of(',', comma)) != std::string::npos)
+        if(dim_y == 0)
         {
-            auto next_comma = in.find_first_of(',', comma);
+            // Regular array
+            auto items = std::count(in.begin(), in.end(), ',');
+            value.dim_y = dim_y;
+            value.dim_x = items + 1;
 
-            // we can not pass an element of the vector, since vector<bool> is not
-            // in fact a container, but some kind of bit field. In this case, we
-            // have to create a local variable to read the value into, then push this
-            // back onto the vector
-            bool field;
-            string_traits<bool>::from_string(in.substr(comma, next_comma - comma).c_str(), field);
-            value.push_back(field);
+            std::string::size_type comma = 0;
 
-            comma = next_comma;
+            // loop and copy out each value from between the separators
+            while ((comma = in.find_first_not_of(',', comma)) != std::string::npos)
+            {
+                auto next_comma = in.find_first_of(',', comma);
+                // we can not pass an element of the vector, since vector<bool> is not
+                // in fact a container, but some kind of bit field. In this case, we
+                // have to create a local variable to read the value into, then push this
+                // back onto the vector
+                bool field;
+                string_traits<bool>::from_string(in.substr(comma, next_comma - comma).c_str(), field);
+                value.push_back(field);
+                comma = next_comma;
+            }
+        }
+        else
+        {
+            // 2D array, or image
+            auto items = std::count(in.begin(), in.end(), ',');
+            value.dim_y = dim_y;
+            value.dim_x = (items + 1) / dim_y;
+
+            // Look for enclosing brackets to extract rows 
+            std::string::size_type bracket = 0;
+            std::string::size_type close_bracket = 0;
+
+            // loop and copy out each value from between the separators
+            while ((bracket = in.find_first_of('{', close_bracket)) != std::string::npos)
+            {
+                close_bracket = in.find_first_of('}', bracket);
+
+                // We clear the value so we need to extract in another vector
+                hdbpp_internal::TangoValue<bool> row;
+                string_traits<hdbpp_internal::TangoValue<bool>>::from_string(in.substr(bracket, close_bracket - bracket + 1).c_str(), row);
+
+                value.insert(value.end(), row.begin(), row.end());
+            }
         }
     }
 
@@ -348,8 +410,27 @@ public:
         if (value.empty())
             return {};
 
-        // simply use the pqxx utilities for this, rather than reinvent the wheel
-        return "{" + separated_list(",", value.begin(), value.end()) + "}";
+        if(value.dim_y < 2)
+        {
+            // simply use the pqxx utilities for this, rather than reinvent the wheel
+            return "{" + separated_list(",", value.begin(), value.end()) + "}";
+        }
+
+        // In case of image, unwrap the vector. 
+
+        assert(value.dim_x != 0);
+        assert(value.dim_y * value.dim_x != value.size());
+
+        std::stringstream result;
+        result << "{";
+        
+	result << "{" << separated_list(",", value.begin(), std::next(value.begin(), value.dim_x)) << "}";
+        for(std::size_t i = 1; i != value.dim_y; ++i)
+        {
+            result << ", {" << separated_list(",", std::next(value.begin(), i * value.dim_x), std::next(value.begin(), (i+1) * value.dim_x)) << "}";
+        }
+        result << "}";
+        return result.str();
     }
 };
 
diff --git a/test/DbConnectionTests.cpp b/test/DbConnectionTests.cpp
index 85315bb74f9a23cb0569e7f65bc5a15e374a55d2..f37d8a5b869343964bf30c8a7e7c9eaac353b705 100644
--- a/test/DbConnectionTests.cpp
+++ b/test/DbConnectionTests.cpp
@@ -325,6 +325,12 @@ void DbConnectionTestsFixture::checkStoreTestEventData(
         REQUIRE(data_row.at(schema::DatColValueR).size() > 0);
         REQUIRE(compareVector(data_row.at(schema::DatColValueR).as<TangoValue<T>>(), get<0>(data)) == true);
     }
+    
+    if (traits.isImage() && traits.hasReadData())
+    {
+        REQUIRE(data_row.at(schema::DatColValueR).size() > 0);
+        REQUIRE(compareVector(data_row.at(schema::DatColValueR).as<TangoValue<T>>(), get<0>(data)) == true);
+    }
 
     if (traits.isScalar() && traits.hasWriteData())
     {
@@ -337,6 +343,12 @@ void DbConnectionTestsFixture::checkStoreTestEventData(
         REQUIRE(data_row.at(schema::DatColValueW).size() > 0);
         REQUIRE(compareVector(data_row.at(schema::DatColValueW).as<TangoValue<T>>(), get<1>(data)) == true);
     }
+    
+    if (traits.isImage() && traits.hasWriteData())
+    {
+        REQUIRE(data_row.at(schema::DatColValueW).size() > 0);
+        REQUIRE(compareVector(data_row.at(schema::DatColValueW).as<TangoValue<T>>(), get<1>(data)) == true);
+    }
 }
 }; // namespace pqxx_conn_test