// 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 = operator new[] (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) { this->~Rep (); operator delete[] (this); }