From 2f7a5c3050668a308d98593979ccd8df8c115bb4 Mon Sep 17 00:00:00 2001 From: schodet Date: Sun, 13 Mar 2005 20:09:29 +0000 Subject: Ajout de image. --- 2005/i/robert/src/image/Makefile.defs | 7 ++ 2005/i/robert/src/image/image.cc | 146 ++++++++++++++++++++++++++++++++ 2005/i/robert/src/image/image.hh | 114 +++++++++++++++++++++++++ 2005/i/robert/src/image/image.tcc | 121 ++++++++++++++++++++++++++ 2005/i/robert/src/image/image_reader.hh | 42 +++++++++ 2005/i/robert/src/image/image_writer.hh | 42 +++++++++ 2005/i/robert/src/image/raw_reader.hh | 44 ++++++++++ 2005/i/robert/src/image/test_image.cc | 73 ++++++++++++++++ 8 files changed, 589 insertions(+) create mode 100644 2005/i/robert/src/image/Makefile.defs create mode 100644 2005/i/robert/src/image/image.cc create mode 100644 2005/i/robert/src/image/image.hh create mode 100644 2005/i/robert/src/image/image.tcc create mode 100644 2005/i/robert/src/image/image_reader.hh create mode 100644 2005/i/robert/src/image/image_writer.hh create mode 100644 2005/i/robert/src/image/raw_reader.hh create mode 100644 2005/i/robert/src/image/test_image.cc diff --git a/2005/i/robert/src/image/Makefile.defs b/2005/i/robert/src/image/Makefile.defs new file mode 100644 index 0000000..1423798 --- /dev/null +++ b/2005/i/robert/src/image/Makefile.defs @@ -0,0 +1,7 @@ +PROGRAMS += test_image + +image_OBJECTS = image.o + +test_image_OBJECTS = test_image.o $(image_OBJECTS) + +test_image: $(test_image_OBJECTS) diff --git a/2005/i/robert/src/image/image.cc b/2005/i/robert/src/image/image.cc new file mode 100644 index 0000000..99968c9 --- /dev/null +++ b/2005/i/robert/src/image/image.cc @@ -0,0 +1,146 @@ +// image.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "image.hh" +#include "image_reader.hh" +#include "image_writer.hh" + +#include +#include + +/// Construit une image vide. +Image::Image (void) + // Évite les tests pour toutes les opérations en fabriquant un Rep vide. + : rep_ (Rep::create (0, 0, rgb)) +{ +} + +/// Construit une image aux pixels non initialisée. +Image::Image (int width, int length, Image::PixelFormat pixelFormat) + : rep_ (Rep::create (width, length, pixelFormat)) +{ +} + +/// Construit une image directement à partir d'un ImageReader. +Image::Image (ImageReader &reader) + : rep_ (0) +{ + read (reader); +} + +/// Opérateur d'affectation. +Image & +Image::operator= (const Image &rhs) +{ + rep_->release (); + rep_ = rhs.rep_->copyRef (); + return *this; +} + +/// Lit une image. +void +Image::read (ImageReader &reader) +{ + int width, height; + PixelFormat pixelFormat; + // Récupère les paramètres. + reader.getParam (width, height, pixelFormat); + // Réalloue de la mémoire si nécessaire. + if (!rep_ + || rep_->references_ != 0 + || width != rep_->width_ + || height != rep_->height_ + || pixelFormat != rep_->pixelFormat_) + { + if (rep_) + rep_->release (); + rep_ = Rep::create (width, height, pixelFormat); + } + // Charge l'image. + reader.read (rep_->getBuf (), getBufSize ()); +} + +/// Écrit une image. +void +Image::write (ImageWriter &writer) const +{ + writer.setParam (rep_->width_, rep_->height_, rep_->pixelFormat_); + writer.write (rep_->getBuf (), getBufSize ()); +} + +/// Crée un Rep, avec de la place pour l'image. +Image::Rep * +Image::Rep::create (int width, int height, Image::PixelFormat pixelFormat) +{ + unsigned bpp = Image::getBytePerPixel (pixelFormat); + unsigned bufSize = Image::getBufSize (width, height, pixelFormat); + void *p = new uint8_t[bufSize * sizeof (uint8_t) + sizeof (Rep)]; + Rep *rep = new (p) Rep; + rep->width_ = width; + rep->height_ = height; + rep->pixelFormat_ = pixelFormat; + rep->bpp_ = bpp; + rep->bufSize_ = bufSize; + rep->references_ = 0; + return rep; +} + +/// Copie un Rep, par référence (ne fait qu'incrémenter le nombre de +/// références). +Image::Rep * +Image::Rep::copyRef (void) +{ + references_++; + return this; +} + +/// Copie un Rep, vrai copie. +Image::Rep * +Image::Rep::copy (void) +{ + Rep *rep = Rep::create (width_, height_, pixelFormat_); + memcpy (rep->getBuf (), getBuf (), bufSize_); + // On peut décrémenter references_ car sa valeur a déjà été testée (sinon + // on n'aurait pas été appelé. + references_--; + return rep; +} + +/// Libère le Rep, detruit si necessaire. +void +Image::Rep::release (void) +{ + if (references_ == 0) + destroy (); + else + references_--; +} + +/// Détruit le Rep. +void +Image::Rep::destroy (void) +{ + delete[] reinterpret_cast (this); +} + diff --git a/2005/i/robert/src/image/image.hh b/2005/i/robert/src/image/image.hh new file mode 100644 index 0000000..2496ef7 --- /dev/null +++ b/2005/i/robert/src/image/image.hh @@ -0,0 +1,114 @@ +#ifndef image_hh +#define image_hh +// image.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#include + +class ImageReader; +class ImageWriter; + +/// Classe contenant une image. Le but est de faciliter l'échange des images +/// entre différentes classes, et de minimiser les copies. Il y a un comptage +/// de référence et un copy-on-write, ce qui veut dire que si l'on copie cet +/// objet, il n'y a pas de copie des pixels tant que l'on essaye pas de la +/// modifier. +/// +/// La classe n'est pas thread-safe à cause du comptage de référence +/// implémenté sans lock. +class Image +{ + public: + enum PixelFormat { rgb, bgr, yuv422, yuv, hsi }; + typedef uint32_t pixel_t; + public: + /// Construit une image vide. + Image (void); + /// Construit une image aux pixels non initialisée. + Image (int width, int length, PixelFormat pixelFormat); + /// Constructeur de copie, copy-on-write. + Image (const Image &image); + /// Construit une image directement à partir d'un ImageReader. + Image (ImageReader &reader); + /// Destructeur. + ~Image (void); + /// Opérateur d'affectation. + Image &operator= (const Image &rhs); + /// Récupère la taille de l'image. + void getSize (int &width, int &height) const; + /// Retourne le format des pixels. + PixelFormat getPixelFormat (void) const; + /// Retourne le nombre d'octets par pixels. + unsigned getBytePerPixel (void) const; + /// Retourne le nombre d'octets par pixels pour un format donnée. + static unsigned getBytePerPixel (PixelFormat pixelFormat); + /// Retourne la taille du tampon mémoire. + unsigned getBufSize (void) const; + /// Retourne la taille du tampon mémoire pour une image donnée. + static unsigned getBufSize (int width, int height, PixelFormat pixelFormat); + /// Récupère un pointeur vers l'image. + const uint8_t *getBuf (void) const; + /// Récupère un pointeur mutable vers l'image. Déclenche éventuellement + /// une copie. + uint8_t *getMutableBuf (void); + /// Lit une image. + void read (ImageReader &reader); + /// Écrit une image. + void write (ImageWriter &writer) const; + private: + struct Rep + { + int width_; + int height_; + PixelFormat pixelFormat_; + unsigned bpp_; + unsigned bufSize_; + int references_; + public: + /// Crée un Rep, avec de la place pour l'image. + static Rep *create (int width, int height, PixelFormat pixelFormat); + /// Copie un Rep, par référence (ne fait qu'incrémenter le nombre de + /// références). + Rep *copyRef (void); + /// Copie un Rep, vrai copie. + Rep *copy (void); + /// Libère le Rep, detruit si necessaire. + void release (void); + /// Détruit le Rep. + void destroy (void); + /// Récupère le buffer. + uint8_t *getBuf (void); + private: + /// Constructeur, interdit. + Rep (void); + /// Constructeur de copie, interdit. + Rep (const Rep &rep); + }; + mutable Rep *rep_; +}; + +#include "image.tcc" + +#endif // image_hh diff --git a/2005/i/robert/src/image/image.tcc b/2005/i/robert/src/image/image.tcc new file mode 100644 index 0000000..5baed09 --- /dev/null +++ b/2005/i/robert/src/image/image.tcc @@ -0,0 +1,121 @@ +// image.tcc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +/// Constructeur de copie, copy-on-write. +inline +Image::Image (const Image &image) + : rep_ (image.rep_->copyRef ()) +{ +} + +/// Destructeur. +inline +Image::~Image (void) +{ + rep_->release (); +} + +/// Récupère la taille de l'image. +inline +void +Image::getSize (int &width, int &height) const +{ + width = rep_->width_; + height = rep_->height_; +} + +/// Retourne le format des pixels. +inline +Image::PixelFormat +Image::getPixelFormat (void) const +{ + return rep_->pixelFormat_; +} + +/// Retourne le nombre d'octets par pixels. +inline +unsigned +Image::getBytePerPixel (void) const +{ + return rep_->bpp_; +} + +/// Retourne le nombre d'octets par pixels pour un format donnée. +inline +unsigned +Image::getBytePerPixel (Image::PixelFormat pixelFormat) +{ + return pixelFormat == Image::yuv422 ? 2 : 3; +} + +/// Retourne la taille du tampon mémoire. +inline +unsigned +Image::getBufSize (void) const +{ + return rep_->bufSize_; +} + +/// Retourne la taille du tampon mémoire pour une image donnée. +inline +unsigned +Image::getBufSize (int width, int height, Image::PixelFormat pixelFormat) +{ + return width * height * Image::getBytePerPixel (pixelFormat); +} + +/// Récupère un pointeur vers l'image. +inline +const uint8_t * +Image::getBuf (void) const +{ + return rep_->getBuf (); +} + +/// Récupère un pointeur mutable vers l'image. Déclenche éventuellement +/// une copie. +inline +uint8_t * +Image::getMutableBuf (void) +{ + if (rep_->references_ != 0) + rep_ = rep_->copy (); + return rep_->getBuf (); +} + +/// Récupère le buffer. +inline +uint8_t * +Image::Rep::getBuf (void) +{ + return reinterpret_cast (this + 1); +} + +/// Constructeur, interdit. +inline +Image::Rep::Rep (void) +{ +} + diff --git a/2005/i/robert/src/image/image_reader.hh b/2005/i/robert/src/image/image_reader.hh new file mode 100644 index 0000000..fd6d308 --- /dev/null +++ b/2005/i/robert/src/image/image_reader.hh @@ -0,0 +1,42 @@ +#ifndef image_reader_hh +#define image_reader_hh +// image_reader.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "image.hh" + +/// Classe de base d'un lecteur d'image. +class ImageReader +{ + public: + /// Destructeur. + virtual ~ImageReader (void) { } + /// Récupère les paramètres de l'image. + virtual void getParam (int &width, int &height, + Image::PixelFormat &pixelFormat) const = 0; + /// Lit une image, lance une exception en cas d'erreur. + virtual void read (uint8_t *buf, unsigned size) = 0; +}; + +#endif // image_reader_hh diff --git a/2005/i/robert/src/image/image_writer.hh b/2005/i/robert/src/image/image_writer.hh new file mode 100644 index 0000000..eef61b0 --- /dev/null +++ b/2005/i/robert/src/image/image_writer.hh @@ -0,0 +1,42 @@ +#ifndef image_writer_hh +#define image_writer_hh +// image_writer.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "image.hh" + +/// Classe de base d'un écrivain d'image. +class ImageWriter +{ + public: + /// Destructeur. + virtual ~ImageWriter (void) { } + /// Paramètre l'image. + virtual void setParam (int with, int height, + Image::PixelFormat &pixelFormat) = 0; + /// Écrit une image, lance une exception en cas d'erreur. + virtual void write (uint8_t *buf, unsigned size) = 0; +}; + +#endif // image_writer_hh diff --git a/2005/i/robert/src/image/raw_reader.hh b/2005/i/robert/src/image/raw_reader.hh new file mode 100644 index 0000000..8f401f2 --- /dev/null +++ b/2005/i/robert/src/image/raw_reader.hh @@ -0,0 +1,44 @@ +#ifndef raw_reader_hh +#define raw_reader_hh +// raw_reader.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "image_reader.hh" + +/// Classe de lecture d'images crues. +class RawReader : public ImageReader +{ + int width_, height_; + Image::PixelFormat pixelFormat_; + public: + /// Destructeur. + ~ImageReader (void) { } + /// Récupère les paramètres de l'image. + void getParam (int &width, int &height, + Image::PixelFormat &pixelFormat) const; + /// Lit une image, lance une exception en cas d'erreur. + void read (uint8_t *buf, unsigned size); +}; + +#endif // raw_reader_hh diff --git a/2005/i/robert/src/image/test_image.cc b/2005/i/robert/src/image/test_image.cc new file mode 100644 index 0000000..d8b388e --- /dev/null +++ b/2005/i/robert/src/image/test_image.cc @@ -0,0 +1,73 @@ +// test_image.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "image.hh" + +#include +#include +#include + +void +printImage (const char *msg, const Image &i) +{ + int w, h, bpp, s; + i.getSize (w, h); + bpp = i.getBytePerPixel (); + s = i.getBufSize (); + std::cout << msg << ' ' << w << ' ' << h << ' ' << bpp << ' ' << s << + std::endl; + const uint8_t *first = i.getBuf (); + const uint8_t *last = i.getBuf () + s;; + std::copy (first, last, std::ostream_iterator (std::cout)); + std::cout << std::endl; +} + +int +main (void) +{ + try + { + Image i1 (1, 2, Image::rgb); + uint8_t *p = i1.getMutableBuf (); + memcpy (p, "rgbRGB", 6); + printImage ("i1", i1); + Image i2 (i1); + printImage ("i2 (i1)", i2); + i2 = i1; + printImage ("i2 = i1", i2); + memcpy (p, "123456", 6); + printImage ("i1 (buggy modification)", i1); + printImage ("i2", i2); + p = i1.getMutableBuf (); + memcpy (p, "654321", 6); + printImage ("i1 (clean modification)", i1); + printImage ("i2", i2); + } + catch (const std::exception &e) + { + std::cerr << e.what () << std::endl; + return 1; + } + return 0; +} -- cgit v1.2.3