add -copyreduced

This commit is contained in:
David Rose 2005-06-01 04:40:22 +00:00
parent 59537b18d2
commit 4030ea3a8e
10 changed files with 402 additions and 156 deletions

View File

@ -96,7 +96,6 @@ generate_images(const Filename &archive_dir, PNMTextMaker *text_maker) {
PNMImage index_image;
Filename reduced_dir(archive_dir, "reduced/" + _dir->get_basename());
Filename thumbnail_dir(archive_dir, "thumbs");
Filename output_filename(thumbnail_dir, _name);
output_filename.set_extension("jpg");
@ -160,130 +159,17 @@ generate_images(const Filename &archive_dir, PNMTextMaker *text_maker) {
for (pi = _photos.begin(); pi != _photos.end(); ++pi) {
const PhotoInfo &pinfo = (*pi);
Photo *photo = _dir->get_photo(pinfo._photo_index);
Filename photo_filename(_dir->get_dir(), photo->get_basename());
Filename reduced_filename(reduced_dir, photo->get_basename());
photo_filename.standardize();
reduced_filename.standardize();
PNMImage reduced_image;
if (!dummy_mode && photo_filename != reduced_filename &&
(force_regenerate ||
reduced_filename.compare_timestamps(photo_filename) < 0)) {
// If the reduced filename does not exist or is older than the
// source filename, we must read the complete source filename to
// generate the reduced image.
PNMImage photo_image;
PNMReader *reader = photo_image.make_reader(photo_filename);
if (reader == (PNMReader *)NULL) {
nout << "Unable to read " << photo_filename << ".\n";
return false;
}
photo_image.copy_header_from(*reader);
photo->_full_x_size = photo_image.get_x_size();
photo->_full_y_size = photo_image.get_y_size();
// Generate a reduced image for the photo.
compute_reduction(photo_image, reduced_image,
reduced_width, reduced_height);
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
// Only bother making a reduced version if it would actually be
// smaller than the original.
if (photo->_reduced_x_size < photo->_full_x_size ||
photo->_reduced_y_size < photo->_full_y_size) {
nout << "Reading " << photo_filename << "\n";
if (!photo_image.read(reader)) {
nout << "Unable to read.\n";
return false;
}
reader = NULL;
reduced_image.quick_filter_from(photo_image);
reduced_filename.make_dir();
nout << "Writing " << reduced_filename << "\n";
if (!reduced_image.write(reduced_filename)) {
nout << "Unable to write.\n";
delete reader;
return false;
}
photo->_has_reduced = true;
} else {
// We're not making a reduced version. But maybe we still
// need to read the original so we can make a thumbnail.
reduced_filename = photo_filename;
reduced_image.copy_header_from(photo_image);
if (!dummy_mode && generate_index_image) {
nout << "Reading " << photo_filename << "\n";
if (!reduced_image.read(reader)) {
nout << "Unable to read image.\n";
return false;
}
reader = NULL;
}
}
if (reader != (PNMReader *)NULL) {
delete reader;
}
} else {
// If the reduced image already exists and is newer than the
// source image, use it.
// We still read the image header to determine its size.
PNMImageHeader photo_image;
if (!photo_image.read_header(photo_filename)) {
nout << "Unable to read " << photo_filename << "\n";
return false;
}
photo->_full_x_size = photo_image.get_x_size();
photo->_full_y_size = photo_image.get_y_size();
photo->_has_reduced = true;
if (dummy_mode) {
// In dummy mode, we may or may not actually have a reduced
// image. In either case, ignore the file and compute its
// appropriate size from the source image.
compute_reduction(photo_image, reduced_image, reduced_width, reduced_height);
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
} else if (generate_index_image) {
// Now read the reduced image from disk, so we can put it on
// the index image.
nout << "Reading " << reduced_filename << "\n";
if (!reduced_image.read(reduced_filename)) {
nout << "Unable to read.\n";
return false;
}
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
} else {
// If we're not generating an index image, we don't even need
// the reduced image--just scan its header to get its size.
if (!reduced_image.read_header(reduced_filename)) {
nout << "Unable to read " << reduced_filename << "\n";
return false;
}
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
}
if (!make_reduced_image(photo, reduced_image, generate_index_image, false)) {
return false;
}
if (generate_index_image) {
// Generate a thumbnail image for the photo.
PNMImage thumbnail_image;
compute_reduction(reduced_image, thumbnail_image,
thumb_interior_width, thumb_interior_height);
if (dummy_mode) {
draw_box(thumbnail_image);
} else {
@ -292,7 +178,7 @@ generate_images(const Filename &archive_dir, PNMTextMaker *text_maker) {
// Center the thumbnail image within its box.
int x_center = (thumb_width - thumbnail_image.get_x_size()) / 2;
int y_center = (thumb_height - thumbnail_image.get_y_size()) / 2;
if (draw_frames) {
draw_frame(index_image,
pinfo._x_place, pinfo._y_place,
@ -300,16 +186,16 @@ generate_images(const Filename &archive_dir, PNMTextMaker *text_maker) {
pinfo._x_place + x_center, pinfo._y_place + y_center,
thumbnail_image.get_x_size(), thumbnail_image.get_y_size());
}
thumbnail_image.set_color_type(index_image.get_color_type());
index_image.copy_sub_image(thumbnail_image,
pinfo._x_place + x_center,
pinfo._y_place + y_center);
if (text_maker != (PNMTextMaker *)NULL) {
int label_x = pinfo._x_place + thumb_width / 2;
int label_y = pinfo._y_place + thumb_height + thumb_caption_height;
int width =
text_maker->generate_into(photo->get_frame_number(), index_image,
label_x, label_y);
@ -340,6 +226,159 @@ generate_images(const Filename &archive_dir, PNMTextMaker *text_maker) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: IndexImage::make_reduced_image
// Access: Public
// Description: Copies the full-sized image to the reduced image
// folder, if necessary.
////////////////////////////////////////////////////////////////////
bool IndexImage::
make_reduced_image(Photo *photo, PNMImage &reduced_image,
bool generate_index_image, bool force_reduced) {
Filename reduced_dir(archive_dir, "reduced/" + _dir->get_basename());
Filename photo_filename(_dir->get_dir(), photo->get_basename());
Filename reduced_filename(reduced_dir, photo->get_basename());
photo_filename.standardize();
reduced_filename.standardize();
if (!dummy_mode && photo_filename != reduced_filename &&
(force_regenerate ||
reduced_filename.compare_timestamps(photo_filename) < 0)) {
// If the reduced filename does not exist or is older than the
// source filename, we must read the complete source filename to
// generate the reduced image.
PNMImage photo_image;
PNMReader *reader = photo_image.make_reader(photo_filename);
if (reader == (PNMReader *)NULL) {
nout << "Unable to read " << photo_filename << ".\n";
return false;
}
photo_image.copy_header_from(*reader);
photo->_full_x_size = photo_image.get_x_size();
photo->_full_y_size = photo_image.get_y_size();
// Generate a reduced image for the photo.
compute_reduction(photo_image, reduced_image,
reduced_width, reduced_height);
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
// Only bother making a reduced version if it would actually be
// smaller than the original.
if (photo->_reduced_x_size < photo->_full_x_size ||
photo->_reduced_y_size < photo->_full_y_size) {
nout << "Reading " << photo_filename << "\n";
if (!photo_image.read(reader)) {
nout << "Unable to read.\n";
return false;
}
reader = NULL;
reduced_image.quick_filter_from(photo_image);
reduced_filename.make_dir();
nout << "Writing " << reduced_filename << "\n";
if (!reduced_image.write(reduced_filename)) {
nout << "Unable to write.\n";
delete reader;
return false;
}
photo->_has_reduced = true;
} else if (force_reduced) {
// Even though the reduced image would not be smaller, copy it
// anyway when force_reduced is true.
nout << "Reading " << photo_filename << "\n";
if (!reduced_image.read(reader)) {
nout << "Unable to read.\n";
return false;
}
reader = NULL;
reduced_filename.make_dir();
nout << "Writing " << reduced_filename << "\n";
if (!reduced_image.write(reduced_filename)) {
nout << "Unable to write.\n";
delete reader;
return false;
}
photo->_has_reduced = true;
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
} else {
// We're not making a reduced version. But maybe we still
// need to read the original so we can make a thumbnail.
reduced_filename = photo_filename;
reduced_image.copy_header_from(photo_image);
if (!dummy_mode && generate_index_image) {
nout << "Reading " << photo_filename << "\n";
if (!reduced_image.read(reader)) {
nout << "Unable to read image.\n";
return false;
}
reader = NULL;
}
}
if (reader != (PNMReader *)NULL) {
delete reader;
}
} else {
// If the reduced image already exists and is newer than the
// source image, use it.
// We still read the image header to determine its size.
PNMImageHeader photo_image;
if (!photo_image.read_header(photo_filename)) {
nout << "Unable to read " << photo_filename << "\n";
return false;
}
photo->_full_x_size = photo_image.get_x_size();
photo->_full_y_size = photo_image.get_y_size();
photo->_has_reduced = true;
if (dummy_mode) {
// In dummy mode, we may or may not actually have a reduced
// image. In either case, ignore the file and compute its
// appropriate size from the source image.
compute_reduction(photo_image, reduced_image, reduced_width, reduced_height);
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
} else if (generate_index_image) {
// Now read the reduced image from disk, so we can put it on
// the index image.
nout << "Reading " << reduced_filename << "\n";
if (!reduced_image.read(reduced_filename)) {
nout << "Unable to read.\n";
return false;
}
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
} else {
// If we're not generating an index image, we don't even need
// the reduced image--just scan its header to get its size.
if (!reduced_image.read_header(reduced_filename)) {
nout << "Unable to read " << reduced_filename << "\n";
return false;
}
photo->_reduced_x_size = reduced_image.get_x_size();
photo->_reduced_y_size = reduced_image.get_y_size();
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: IndexImage::generate_html
// Access: Public
@ -397,6 +436,44 @@ generate_html(ostream &root_html, const Filename &archive_dir,
return true;
}
////////////////////////////////////////////////////////////////////
// Function: IndexImage::copy_reduced
// Access: Public
// Description: Copies key files from the full directory into the
// reduced directory.
////////////////////////////////////////////////////////////////////
bool IndexImage::
copy_reduced(const Filename &archive_dir) {
Photos::const_iterator pi;
for (pi = _photos.begin(); pi != _photos.end(); ++pi) {
const PhotoInfo &pinfo = (*pi);
int photo_index = pinfo._photo_index;
Photo *photo = _dir->get_photo(pinfo._photo_index);
// Make sure we have a "reduced" image.
PNMImage reduced_image;
if (!make_reduced_image(photo, reduced_image, false, true)) {
return false;
}
if (photo->_has_movie) {
// Also copy the movie file to the reduced directory, even
// though it's not reduced in any way--but there's no way
// (presently) to reduce a movie file.
Filename movie_filename(_dir->get_dir(), photo->get_movie());
if (movie_filename.exists()) {
movie_filename.set_binary();
Filename reduced_dir(archive_dir, "reduced/" + _dir->get_basename());
if (!copy_file(movie_filename, reduced_dir)) {
return false;
}
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: IndexImage::output
// Access: Public
@ -528,11 +605,10 @@ generate_reduced_html(ostream &html, Photo *photo, int photo_index, int pi,
generate_nav_buttons(html, prev_photo_filename, next_photo_filename,
up_href);
Filename cm_filename(_dir->get_dir(), photo->get_basename());
cm_filename.set_extension("cm");
if (cm_filename.exists()) {
if (photo->_has_cm) {
// If a comment file for the photo exists, insert its contents
// here, right above the photo.
Filename cm_filename(_dir->get_dir(), photo->get_cm());
if (!RollDirectory::insert_html_comment(html, cm_filename)) {
return false;
}

View File

@ -43,9 +43,14 @@ public:
bool add_photo(int index);
bool generate_images(const Filename &archive_dir, PNMTextMaker *text_maker);
bool make_reduced_image(Photo *photo, PNMImage &reduced_image,
bool generate_index_image, bool force_reduced);
bool generate_html(ostream &root_html, const Filename &archive_dir,
const Filename &roll_dir_root);
bool copy_reduced(const Filename &archive_dir);
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;

View File

@ -228,3 +228,44 @@ escape_html(const string &input) {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: copy_file
// Description: Copies a file into the named directory, if it does
// not already exist there. Returns true if
// successful, false otherwise.
////////////////////////////////////////////////////////////////////
bool
copy_file(const Filename &source_file, const Filename &dest_dir) {
Filename dest_file = source_file;
dest_file.set_dirname(dest_dir);
if (dest_file.exists()) {
return true;
}
if (!source_file.exists()) {
return false;
}
ifstream in;
if (!source_file.open_read(in)) {
cerr << "Unable to read " << source_file << "\n";
return false;
}
ofstream out;
if (!dest_file.open_write(out)) {
cerr << "Unable to write " << dest_file << "\n";
return false;
}
cerr << "Copying " << source_file << " to " << dest_file << "\n";
int c = in.get();
while (in && !in.eof()) {
out.put(c);
c = in.get();
}
return in.eof();
}

View File

@ -145,6 +145,7 @@ Filename compose_href(const Filename &rel_dir, const Filename &user_prefix,
const Filename &basename = Filename());
string escape_html(const string &input);
bool copy_file(const Filename &source_file, const Filename &dest_dir);
#endif

View File

@ -252,6 +252,14 @@ Indexify() {
"there are one or more movie files found in the directory.",
&Indexify::dispatch_filename, NULL, &movie_icon);
add_option
("copyreduced", "", 0,
"Instead of generating index files, copy key files (such as "
"*.cm, *.ds) from the full image directory into the reduced "
"image directory, so that the full image directory may be removed "
"for generating a reduced-size archive.",
&Indexify::dispatch_none, &_copy_reduced);
_photo_extension = "jpg";
_movie_extension = "mov";
_text_maker = (PNMTextMaker *)NULL;
@ -549,7 +557,23 @@ run() {
exit(1);
}
if (_copy_reduced) {
do_copy_reduced();
} else {
do_generate_images();
}
}
////////////////////////////////////////////////////////////////////
// Function: Indexify::do_generate_images
// Access: Public
// Description: The main work function. Generates all of the reduced
// images and the html code.
////////////////////////////////////////////////////////////////////
void Indexify::
do_generate_images() {
// First, generate all the images.
RollDirs::iterator di;
for (di = _roll_dirs.begin(); di != _roll_dirs.end(); ++di) {
RollDirectory *roll_dir = (*di);
if (!roll_dir->generate_images(archive_dir, _text_maker)) {
@ -657,6 +681,25 @@ run() {
<< "</html>\n";
}
////////////////////////////////////////////////////////////////////
// Function: Indexify::do_copy_reduced
// Access: Public
// Description: The main work function in -copyreduced mode. Simply
// copies key files from the full directory to the
// reduced directory.
////////////////////////////////////////////////////////////////////
void Indexify::
do_copy_reduced() {
RollDirs::iterator di;
for (di = _roll_dirs.begin(); di != _roll_dirs.end(); ++di) {
RollDirectory *roll_dir = (*di);
if (!roll_dir->copy_reduced(archive_dir)) {
nout << "Failure.\n";
exit(1);
}
}
}
int main(int argc, char *argv[]) {
Indexify prog;

View File

@ -48,6 +48,8 @@ protected:
public:
void run();
void do_generate_images();
void do_copy_reduced();
string _front_title;
Filename _roll_dir_root;
@ -56,6 +58,7 @@ public:
Filename _font_filename;
bool _generate_icons;
double _font_aa_factor;
bool _copy_reduced;
typedef pvector<RollDirectory *> RollDirs;
RollDirs _roll_dirs;

View File

@ -27,10 +27,9 @@
// Description:
////////////////////////////////////////////////////////////////////
Photo::
Photo(RollDirectory *dir, const Filename &basename, const Filename &movie) :
Photo(RollDirectory *dir, const Filename &basename, const string &movie_extension) :
_dir(dir),
_basename(basename),
_movie(movie)
_basename(basename)
{
_name = _basename.get_basename_wo_extension();
_frame_number = _name;
@ -52,7 +51,22 @@ Photo(RollDirectory *dir, const Filename &basename, const Filename &movie) :
_reduced_x_size = 0;
_reduced_y_size = 0;
_has_reduced = false;
_has_movie = !_movie.empty();
_has_movie = false;
Filename movie_filename(_dir->get_dir(), _basename);
movie_filename.set_extension(movie_extension);
if (movie_filename.exists()) {
_movie = movie_filename.get_basename();
_has_movie = true;
}
_has_cm = false;
Filename cm_filename(_dir->get_dir(), _basename);
cm_filename.set_extension("cm");
if (cm_filename.exists()) {
_cm = cm_filename.get_basename();
_has_cm = true;
}
}
////////////////////////////////////////////////////////////////////
@ -77,6 +91,17 @@ get_movie() const {
return _movie;
}
////////////////////////////////////////////////////////////////////
// Function: Photo::get_cm
// Access: Public
// Description: Returns the filename of the comment file associated
// with the photo, if any.
////////////////////////////////////////////////////////////////////
const Filename &Photo::
get_cm() const {
return _cm;
}
////////////////////////////////////////////////////////////////////
// Function: Photo::get_name
// Access: Public

View File

@ -32,10 +32,11 @@ class RollDirectory;
class Photo {
public:
Photo(RollDirectory *dir, const Filename &basename,
const Filename &movie = Filename());
const string &movie_extension);
const Filename &get_basename() const;
const Filename &get_movie() const;
const Filename &get_cm() const;
const string &get_name() const;
const string &get_frame_number() const;
@ -48,11 +49,13 @@ public:
int _reduced_y_size;
bool _has_reduced;
bool _has_movie;
bool _has_cm;
private:
RollDirectory *_dir;
Filename _basename;
Filename _movie;
Filename _cm;
string _name;
string _frame_number;
};

View File

@ -36,14 +36,18 @@ RollDirectory::
RollDirectory(const Filename &dir) :
_dir(dir)
{
_prev = (RollDirectory *)NULL;
_next = (RollDirectory *)NULL;
_basename = _dir.get_basename();
if (format_rose) {
_name = format_basename(_basename);
} else {
_name = _basename;
}
_prev = (RollDirectory *)NULL;
_next = (RollDirectory *)NULL;
_got_ds_file = false;
_got_ls_file = false;
}
////////////////////////////////////////////////////////////////////
@ -123,19 +127,20 @@ scan(const string &photo_extension, const string &movie_extension) {
// Check for a .ds file, which contains a one-line description of
// the contents of the directory.
Filename ds_filename(_basename);
ds_filename.set_extension("ds");
if (cm_search.is_empty() || !ds_filename.resolve_filename(cm_search)) {
_ds_filename = Filename(_basename);
_ds_filename.set_extension("ds");
if (cm_search.is_empty() || !_ds_filename.resolve_filename(cm_search)) {
// If the ds file isn't found along the search path specified
// via -cmdir on the command line, then look for it in the
// appropriate source directory.
ds_filename = Filename(_dir, ds_filename);
_ds_filename = Filename(_dir, _ds_filename);
}
if (ds_filename.exists()) {
ds_filename.set_text();
if (_ds_filename.exists()) {
_got_ds_file = true;
_ds_filename.set_text();
ifstream ds;
if (!ds_filename.open_read(ds)) {
nout << "Could not read " << ds_filename << "\n";
if (!_ds_filename.open_read(ds)) {
nout << "Could not read " << _ds_filename << "\n";
} else {
// Get the words out one at a time and put just one space
// between them.
@ -160,14 +165,15 @@ scan(const string &photo_extension, const string &movie_extension) {
// Check for an .ls file in the roll directory, which may give an
// explicit ordering, or if empty, it specifies reverse ordering.
Filename ls_filename(_dir, _basename);
ls_filename.set_extension("ls");
if (ls_filename.exists()) {
add_contributing_filename(ls_filename);
ls_filename.set_text();
_ls_filename = Filename(_dir, _basename);
_ls_filename.set_extension("ls");
if (_ls_filename.exists()) {
_got_ls_file = true;
add_contributing_filename(_ls_filename);
_ls_filename.set_text();
ifstream ls;
if (!ls_filename.open_read(ls)) {
nout << "Could not read " << ls_filename << "\n";
if (!_ls_filename.open_read(ls)) {
nout << "Could not read " << _ls_filename << "\n";
} else {
bool any_words = false;
string word;
@ -511,8 +517,13 @@ generate_html(const Filename &archive_dir, const Filename &roll_dir_root) {
generate_nav_buttons(index_html, prev_roll_filename, next_roll_filename,
up_href);
if (!omit_complete) {
index_html
<< "<a href=\"complete.htm#" << _basename
<< "\">(complete archive)</a>\n";
}
index_html
<< "<a href=\"complete.htm#" << _basename << "\">(complete archive)</a>\n"
<< "</body>\n"
<< "</html>\n";
@ -552,6 +563,44 @@ get_index_html() const {
return _index_html;
}
////////////////////////////////////////////////////////////////////
// Function: RollDirectory::copy_reduced
// Access: Public
// Description: Copies key files from the full directory into the
// reduced directory.
////////////////////////////////////////////////////////////////////
bool RollDirectory::
copy_reduced(const Filename &archive_dir) {
if (is_empty()) {
return true;
}
nassertr(!_index_images.empty(), false);
Filename reduced_dir(archive_dir, "reduced/" + _dir.get_basename());
if (_got_ds_file) {
if (!copy_file(_ds_filename, reduced_dir)) {
return false;
}
}
if (_got_ls_file) {
if (!copy_file(_ls_filename, reduced_dir)) {
return false;
}
}
IndexImages::iterator ii;
for (ii = _index_images.begin(); ii != _index_images.end(); ++ii) {
IndexImage *index_image = (*ii);
if (!index_image->copy_reduced(archive_dir)) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: RollDirectory::output
// Access: Public
@ -639,14 +688,7 @@ insert_html_comment(ostream &html, Filename cm_filename) {
////////////////////////////////////////////////////////////////////
void RollDirectory::
add_photo(const Filename &basename, const string &movie_extension) {
Photo *photo = NULL;
Filename movie_filename(_dir, basename);
movie_filename.set_extension(movie_extension);
if (movie_filename.exists()) {
photo = new Photo(this, basename, movie_filename.get_basename());
} else {
photo = new Photo(this, basename);
}
Photo *photo = new Photo(this, basename, movie_extension);
_photos.push_back(photo);
}

View File

@ -62,6 +62,8 @@ public:
const string &get_comment_html() const;
const string &get_index_html() const;
bool copy_reduced(const Filename &archive_dir);
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
@ -89,6 +91,11 @@ private:
string _desc;
typedef pvector<Photo *> Photos;
Photos _photos;
bool _got_ds_file;
Filename _ds_filename;
bool _got_ls_file;
Filename _ls_filename;
Filename _newest_contributing_filename;