summaryrefslogtreecommitdiff
path: root/2005/i/robert/src/image/image.cc
diff options
context:
space:
mode:
Diffstat (limited to '2005/i/robert/src/image/image.cc')
-rw-r--r--2005/i/robert/src/image/image.cc146
1 files changed, 146 insertions, 0 deletions
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 <cstring>
+#include <new>
+
+/// 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<uint8_t *> (this);
+}
+