#include #include //for ifstream, ofstream #include //for ostream_iterator #include //for min, max, copy #include //for system #include //for UCHAR_MAX #include //for strcmp #include #include "picture.h" picture::picture(int gray) { pixel p(gray, gray, gray); for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col] = p; } } } picture::picture(int red, int green, int blue) { pixel p(red, green, blue); for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col] = p; } } } picture::picture(pixel p) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col] = p; } } } picture::picture(pixel p[nrows][ncols]) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col] = p[row][col]; } } } picture& picture::operator+=(const picture& another) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col].red += another.a[row][col].red; a[row][col].green += another.a[row][col].green; a[row][col].blue += another.a[row][col].blue; } } return *this; } picture& picture::operator-=(const picture& another) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col].red -= another.a[row][col].red; a[row][col].green -= another.a[row][col].green; a[row][col].blue -= another.a[row][col].blue; } } return *this; } picture& picture::operator*=(int factor) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col].red *= factor; a[row][col].green *= factor; a[row][col].blue *= factor; } } return *this; } picture& picture::operator/=(int divisor) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { a[row][col].red /= divisor; a[row][col].green /= divisor; a[row][col].blue /= divisor; } } return *this; } picture& picture::operator&=(color c) { for (size_t row = 0; row < nrows; ++row) { for (size_t col = 0; col < ncols; ++col) { pixel *const p = &a[row][col]; switch (c) { case color_red: p->green = p->blue = 0; break; case color_green: p->red = p->blue = 0; break; case color_blue: p->red = p->green = 0; break; } } } return *this; } picture::picture(const char *filename) { if (strlen(filename) >= 4 && strcmp(filename + strlen(filename) - 4, ".jpg") == 0) { char command[1024]; const char *const tempfile = tmpnam(0); sprintf(command, "/opt/sfw/netpbm/bin/jpegtopnm %s | " "/opt/sfw/netpbm/bin/pnmtoplainpnm > %s", filename, tempfile); const int ret = system(command); if (ret < 0) { cerr << "constructor: system returned a negative number.\n"; } ifstream ifstr(tempfile); if (!ifstr) { cerr << "couldn't open input file " << tempfile << "\n"; exit(EXIT_FAILURE); } string format; int width, height, max; ifstr >> format >> width >> height >> max; for (size_t row = 0; row < height; ++row) { for (size_t col = 0; col < width; ++col) { unsigned red, green, blue; ifstr >> red >> green >> blue; if (row < nrows && col < ncols) { a[row][col].red = red; a[row][col].green = green; a[row][col].blue = blue; } } } ifstr.close(); if (unlink(tempfile) != 0) { cerr << "unlink did not return 0\n"; } } } inline int clamp(int i) {return max(0, min(UCHAR_MAX, i));} ostream& operator<<(ostream& ost, const picture& p) { char tempfile1[L_tmpnam]; strcpy(tempfile1, tmpnam(0)); ofstream ofstr(tempfile1); if (!ofstr) { cerr << "couldn't open output file " << tempfile1 << "\n"; exit(EXIT_FAILURE); } ofstr << "P3\n" << picture::ncols << " " << picture::nrows << "\n" << UCHAR_MAX << "\n"; for (size_t row = 0; row < picture::nrows; ++row) { for (size_t col = 0; col < picture::ncols; ++col) { const pixel pix = p.a[row][col]; ofstr << clamp(pix.red) << "\t" << clamp(pix.green) << "\t" << clamp(pix.blue) << "\n"; } } ofstr.close(); char *tempfile2 = tmpnam(0); char command[1024]; sprintf(command, "/opt/sfw/netpbm/bin/ppmtojpeg < %s > %s", tempfile1, tempfile2); const int ret = system(command); if (ret < 0) { cerr << "system returned a negative number.\n"; } if (unlink(tempfile1) != 0) { cerr << "unlink did not return 0\n"; } ifstream ifstr(tempfile2); ifstr >> noskipws; copy( istream_iterator(ifstr), istream_iterator(), ostream_iterator(cout)); ofstr.close(); if (unlink(tempfile2) != 0) { cerr << "unlink did not return 0\n"; } return ost; }