    // Copyright (C) 2006  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #ifndef DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_H__
    #define DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_H__

    #include "array2d_kernel.h"
    #include "../pixel.h"

    namespace dlib
    {

    // ----------------------------------------------------------------------------------------

        /*
            This file contains overloads of the serialize functions for array2d object
            for the case where they contain simple 8bit POD pixel types.  In these
            cases we can perform a much faster serialization by writing data in chunks
            instead of one pixel at a time (this avoids a lot of function call overhead
            inside the iostreams).
        */

    // ----------------------------------------------------------------------------------------

        template <
            typename mem_manager
            >
        void serialize (
            const array2d<rgb_pixel,mem_manager>& item,
            std::ostream& out
        )
        {
            try
            {
                // The reason the serialization is a little funny is because we are trying to
                // maintain backwards compatibility with an older serialization format used by
                // dlib while also encoding things in a way that lets the array2d and matrix
                // objects have compatible serialization formats.
                serialize(-item.nr(),out);
                serialize(-item.nc(),out);

                COMPILE_TIME_ASSERT(sizeof(rgb_pixel) == 3);

                if (item.size() != 0)
                    out.write((char*)&item[0][0], sizeof(rgb_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                throw serialization_error(e.info + "\n   while serializing object of type array2d");
            }
        }

        template <
            typename mem_manager
            >
        void deserialize (
            array2d<rgb_pixel,mem_manager>& item,
            std::istream& in
        )
        {
            try
            {
                COMPILE_TIME_ASSERT(sizeof(rgb_pixel) == 3);

                long nr, nc;
                deserialize(nr,in);
                deserialize(nc,in);

                // this is the newer serialization format
                if (nr < 0 || nc < 0)
                {
                    nr *= -1;
                    nc *= -1;
                }
                else
                {
                    std::swap(nr,nc);
                }

                item.set_size(nr,nc);

                if (item.size() != 0)
                    in.read((char*)&item[0][0], sizeof(rgb_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                item.clear();
                throw serialization_error(e.info + "\n   while deserializing object of type array2d");
            }
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename mem_manager
            >
        void serialize (
            const array2d<bgr_pixel,mem_manager>& item,
            std::ostream& out
        )
        {
            try
            {
                // The reason the serialization is a little funny is because we are trying to
                // maintain backwards compatibility with an older serialization format used by
                // dlib while also encoding things in a way that lets the array2d and matrix
                // objects have compatible serialization formats.
                serialize(-item.nr(),out);
                serialize(-item.nc(),out);

                COMPILE_TIME_ASSERT(sizeof(bgr_pixel) == 3);

                if (item.size() != 0)
                    out.write((char*)&item[0][0], sizeof(bgr_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                throw serialization_error(e.info + "\n   while serializing object of type array2d");
            }
        }

        template <
            typename mem_manager
            >
        void deserialize (
            array2d<bgr_pixel,mem_manager>& item,
            std::istream& in
        )
        {
            try
            {
                COMPILE_TIME_ASSERT(sizeof(bgr_pixel) == 3);

                long nr, nc;
                deserialize(nr,in);
                deserialize(nc,in);

                // this is the newer serialization format
                if (nr < 0 || nc < 0)
                {
                    nr *= -1;
                    nc *= -1;
                }
                else
                {
                    std::swap(nr,nc);
                }

                item.set_size(nr,nc);

                if (item.size() != 0)
                    in.read((char*)&item[0][0], sizeof(bgr_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                item.clear();
                throw serialization_error(e.info + "\n   while deserializing object of type array2d");
            }
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename mem_manager
            >
        void serialize (
            const array2d<hsi_pixel,mem_manager>& item,
            std::ostream& out
        )
        {
            try
            {
                // The reason the serialization is a little funny is because we are trying to
                // maintain backwards compatibility with an older serialization format used by
                // dlib while also encoding things in a way that lets the array2d and matrix
                // objects have compatible serialization formats.
                serialize(-item.nr(),out);
                serialize(-item.nc(),out);

                COMPILE_TIME_ASSERT(sizeof(hsi_pixel) == 3);

                if (item.size() != 0)
                    out.write((char*)&item[0][0], sizeof(hsi_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                throw serialization_error(e.info + "\n   while serializing object of type array2d");
            }
        }

        template <
            typename mem_manager
            >
        void deserialize (
            array2d<hsi_pixel,mem_manager>& item,
            std::istream& in
        )
        {
            try
            {
                COMPILE_TIME_ASSERT(sizeof(hsi_pixel) == 3);

                long nr, nc;
                deserialize(nr,in);
                deserialize(nc,in);

                // this is the newer serialization format
                if (nr < 0 || nc < 0)
                {
                    nr *= -1;
                    nc *= -1;
                }
                else
                {
                    std::swap(nr,nc);
                }

                item.set_size(nr,nc);

                if (item.size() != 0)
                    in.read((char*)&item[0][0], sizeof(hsi_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                item.clear();
                throw serialization_error(e.info + "\n   while deserializing object of type array2d");
            }
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename mem_manager
            >
        void serialize (
            const array2d<rgb_alpha_pixel,mem_manager>& item,
            std::ostream& out
        )
        {
            try
            {
                // The reason the serialization is a little funny is because we are trying to
                // maintain backwards compatibility with an older serialization format used by
                // dlib while also encoding things in a way that lets the array2d and matrix
                // objects have compatible serialization formats.
                serialize(-item.nr(),out);
                serialize(-item.nc(),out);

                COMPILE_TIME_ASSERT(sizeof(rgb_alpha_pixel) == 4);

                if (item.size() != 0)
                    out.write((char*)&item[0][0], sizeof(rgb_alpha_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                throw serialization_error(e.info + "\n   while serializing object of type array2d");
            }
        }

        template <
            typename mem_manager
            >
        void deserialize (
            array2d<rgb_alpha_pixel,mem_manager>& item,
            std::istream& in
        )
        {
            try
            {
                COMPILE_TIME_ASSERT(sizeof(rgb_alpha_pixel) == 4);

                long nr, nc;
                deserialize(nr,in);
                deserialize(nc,in);

                // this is the newer serialization format
                if (nr < 0 || nc < 0)
                {
                    nr *= -1;
                    nc *= -1;
                }
                else
                {
                    std::swap(nr,nc);
                }

                item.set_size(nr,nc);

                if (item.size() != 0)
                    in.read((char*)&item[0][0], sizeof(rgb_alpha_pixel)*item.size());
            }
            catch (serialization_error e)
            {
                item.clear();
                throw serialization_error(e.info + "\n   while deserializing object of type array2d");
            }
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename mem_manager
            >
        void serialize (
            const array2d<unsigned char,mem_manager>& item,
            std::ostream& out
        )
        {
            try
            {
                // The reason the serialization is a little funny is because we are trying to
                // maintain backwards compatibility with an older serialization format used by
                // dlib while also encoding things in a way that lets the array2d and matrix
                // objects have compatible serialization formats.
                serialize(-item.nr(),out);
                serialize(-item.nc(),out);

                if (item.size() != 0)
                    out.write((char*)&item[0][0], sizeof(unsigned char)*item.size());
            }
            catch (serialization_error e)
            {
                throw serialization_error(e.info + "\n   while serializing object of type array2d");
            }
        }

        template <
            typename mem_manager
            >
        void deserialize (
            array2d<unsigned char,mem_manager>& item,
            std::istream& in
        )
        {
            try
            {
                long nr, nc;
                deserialize(nr,in);
                deserialize(nc,in);
                // this is the newer serialization format
                if (nr < 0 || nc < 0)
                {
                    nr *= -1;
                    nc *= -1;
                }
                else
                {
                    std::swap(nr,nc);
                }

                item.set_size(nr,nc);

                if (item.size() != 0)
                    in.read((char*)&item[0][0], sizeof(unsigned char)*item.size());
            }
            catch (serialization_error e)
            {
                item.clear();
                throw serialization_error(e.info + "\n   while deserializing object of type array2d");
            }
        }

    // ----------------------------------------------------------------------------------------

    }

    #endif // DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_H__