// Copyright 2019 Gene Callahan
This is the implementation of our image class. It is designed to teach class hierarchy and buffer allocation.
#include <string>
#include <iostream>
using namespace std;
#include "./image.h"
"Ordinary" constructor initializing each field:
Image::Image(int width, int height, const string& flnm)
: width(width), height(height) {
image_buf = new unsigned char[image_sz()];
}
This is the Image copy constructor. We have to handle properly copying the image_buf to the target object. We use copy_fields() so we can share copy code with the assignment operator.
Image::Image(const Image& img2) {
cout << "In image copy constructor\n";
copy_fields(img2);
}
Image destructor must free the image buf so that the memory can be used for other purposes.
Image::~Image() {
if (image_buf != nullptr) delete image_buf;
}
The Image assignment operator has to delete the image buf is not null, then do the copy like the copy constructor.
Image& Image::operator=(const Image& img2) {
if (image_buf != nullptr) delete image_buf;
copy_fields(img2);
return *this;
}
This is the base class display() operator, to illustrate polymorphism.
void Image::display(const string& s) const {
cout << s << endl;
}
int Image::image_sz() { return width * height; }
We extract the copy into its own method so that it can be shared by the copy constructor and assignment.
void Image::copy_fields(const Image& img2) {
width = img2.width;
height = img2.height;
image_buf = new unsigned char[image_sz()];
for (int i = 0; i < image_sz(); i++)
image_buf[i] = img2.image_buf[i];
}
Correct way to call base class copy constructor: Gif::Gif(const Gif& img2) : Image(img2) { }
Incorrect way to call it: Gif::Gif(const Gif& img2) { Image(img2); }
Specialized over-riding display method for Gif. In it we call the parent display method with Image::display().
void Gif::display(const string& s) const {
Image::display("Gif");
}
Gif has its own compress() with an int parameter. It will hide the base class compress() unless we explicitly prevent it from doing so.
void Gif::compress(int i) {
cout << "compressing at level: " << i << endl;
}
AnimGif::AnimGif(int width, int height, const string& flnm)
: Gif(width, height, flnm) {
image_buf2 = new unsigned char[image_sz()];
}
AnimGif::AnimGif(const AnimGif& img2) : Gif(img2) {
cout << "In AnimGif copy constructor\n";
image_buf2 = new unsigned char[image_sz()];
for (int i = 0; i < image_sz(); i++)
image_buf2[i] = img2.image_buf2[i];
}
AnimGif& AnimGif::operator=(const AnimGif& img2) {
Gif::operator=(img2);
if (image_buf2 != nullptr) delete image_buf2;
for (int i = 0; i < image_sz(); i++)
image_buf2[i] = img2.image_buf2[i];
return *this;
}
AnimGif::~AnimGif() {
if (image_buf2 != nullptr) delete image_buf2;
}
Specialized over-riding display method for AnimGif. In it we call the parent display method with Image::display(). void AnimGif::display(const string& s) const { Image::display("AnimGif"); }
Specialized over-riding display method for Jpeg. In it we call the parent display method with Image::display().
void Jpeg::display(const string& s) const {
Image::display("Jpeg");
}
Specialized over-riding display method for Png. In it we call the parent display method with Image::display().
void Png::display(const string& s) const {
Image::display("Png");
}