Use PNG for thumbs so that we get alpha blending in wxwidgets.
authorCarl Hetherington <cth@carlh.net>
Thu, 11 Oct 2012 00:18:24 +0000 (01:18 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 11 Oct 2012 00:18:24 +0000 (01:18 +0100)
src/lib/film.cc
src/lib/film_state.cc
src/lib/imagemagick_encoder.cc [new file with mode: 0644]
src/lib/imagemagick_encoder.h [new file with mode: 0644]
src/lib/subtitle.cc [new file with mode: 0644]
src/lib/subtitle.h [new file with mode: 0644]
src/lib/thumbs_job.cc
src/lib/tiff_encoder.cc [deleted file]
src/lib/tiff_encoder.h [deleted file]
src/lib/wscript
src/wx/film_viewer.cc

index 1e23c4d6b932646c086bc1215b6a75c722a12ac6..08ef938d1219918db8ae0ba25e861e187c8ae25d 100644 (file)
@@ -30,7 +30,7 @@
 #include <boost/lexical_cast.hpp>
 #include "film.h"
 #include "format.h"
-#include "tiff_encoder.h"
+#include "imagemagick_encoder.h"
 #include "job.h"
 #include "filter.h"
 #include "transcoder.h"
@@ -397,7 +397,7 @@ Film::update_thumbs_post_gui ()
                string const l = i->leaf ();
 #endif
                
-               size_t const d = l.find (".tiff");
+               size_t const d = l.find (".png");
                if (d != string::npos) {
                        _state.thumbs.push_back (atoi (l.substr (0, d).c_str()));
                }
@@ -707,7 +707,7 @@ Film::thumb_subtitles (int n) const
                } else if (k == "x") {
                        sub_x = v;
                } else if (k == "y") {
-                       subs.push_back (make_pair (Position (sub_x, v), String::compose ("%1.sub.%2.tiff", _state.thumb_base(n), sub_number)));
+                       subs.push_back (make_pair (Position (sub_x, v), String::compose ("%1.sub.%2.png", _state.thumb_base(n), sub_number)));
                }
        }
 
index 2847ea51323593740d0a66db1823caee78e9c985..610362dcd595d2f13becda25cf9853860f759c4b 100644 (file)
@@ -191,7 +191,7 @@ FilmState::thumb_file (int n) const
 string
 FilmState::thumb_file_for_frame (int n) const
 {
-       return thumb_base_for_frame(n) + ".tiff";
+       return thumb_base_for_frame(n) + ".png";
 }
 
 string
diff --git a/src/lib/imagemagick_encoder.cc b/src/lib/imagemagick_encoder.cc
new file mode 100644 (file)
index 0000000..b7b79ed
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/imagemagick_encoder.cc
+ *  @brief An encoder that writes image files using ImageMagick (and does nothing with audio).
+ */
+
+#include <stdexcept>
+#include <vector>
+#include <sstream>
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <boost/filesystem.hpp>
+#include <Magick++/Image.h>
+#include "imagemagick_encoder.h"
+#include "film.h"
+#include "film_state.h"
+#include "options.h"
+#include "exceptions.h"
+#include "image.h"
+#include "subtitle.h"
+
+using namespace std;
+using namespace boost;
+
+/** @param s FilmState of the film that we are encoding.
+ *  @param o Options.
+ *  @param l Log.
+ */
+ImageMagickEncoder::ImageMagickEncoder (shared_ptr<const FilmState> s, shared_ptr<const Options> o, Log* l)
+       : Encoder (s, o, l)
+{
+       
+}
+
+void
+ImageMagickEncoder::process_video (shared_ptr<Image> image, int frame, shared_ptr<Subtitle> sub)
+{
+       shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _fs->scaler);
+
+       string tmp_file = _opt->frame_out_path (frame, true);
+       Magick::Image thumb (_opt->out_size.width, _opt->out_size.height, "RGB", MagickCore::CharPixel, scaled->data()[0]);
+       thumb.magick ("PNG");
+       thumb.write (tmp_file);
+       filesystem::rename (tmp_file, _opt->frame_out_path (frame, false));
+
+       if (sub) {
+               float const x_scale = float (_opt->out_size.width) / _fs->size.width;
+               float const y_scale = float (_opt->out_size.height) / _fs->size.height;
+
+               string tmp_metadata_file = _opt->frame_out_path (frame, false, ".sub");
+               ofstream metadata (tmp_metadata_file.c_str ());
+               
+               list<shared_ptr<SubtitleImage> > images = sub->images ();
+               int n = 0;
+               for (list<shared_ptr<SubtitleImage> >::iterator i = images.begin(); i != images.end(); ++i) {
+                       stringstream ext;
+                       ext << ".sub." << n << ".png";
+
+                       Size new_size = (*i)->image()->size ();
+                       new_size.width *= x_scale;
+                       new_size.height *= y_scale;
+                       shared_ptr<Image> scaled = (*i)->image()->scale (new_size, _fs->scaler);
+                       
+                       string tmp_sub_file = _opt->frame_out_path (frame, true, ext.str ());
+                       Magick::Image sub_thumb (scaled->size().width, scaled->size().height, "RGBA", MagickCore::CharPixel, scaled->data()[0]);
+                       sub_thumb.magick ("PNG");
+                       sub_thumb.write (tmp_sub_file);
+                       filesystem::rename (tmp_sub_file, _opt->frame_out_path (frame, false, ext.str ()));
+
+                       metadata << "image " << n << "\n"
+                                << "x " << (*i)->position().x << "\n"
+                                << "y " << (*i)->position().y << "\n";
+
+                       metadata.close ();
+                       filesystem::rename (tmp_metadata_file, _opt->frame_out_path (frame, false, ".sub"));
+               }
+
+       }
+       
+       frame_done (frame);
+}
diff --git a/src/lib/imagemagick_encoder.h b/src/lib/imagemagick_encoder.h
new file mode 100644 (file)
index 0000000..ce6ca3e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/imagemagick_encoder.h
+ *  @brief An encoder that writes image files using ImageMagick (and does nothing with audio).
+ */
+
+#include <string>
+#include <sndfile.h>
+#include "encoder.h"
+
+class FilmState;
+class Log;
+
+/** @class ImageMagickEncoder
+ *  @brief An encoder that writes image files using ImageMagick files (and does nothing with audio).
+ */
+class ImageMagickEncoder : public Encoder
+{
+public:
+       ImageMagickEncoder (boost::shared_ptr<const FilmState> s, boost::shared_ptr<const Options> o, Log* l);
+
+       void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {}
+       void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
+       void process_audio (uint8_t *, int) {}
+       void process_end () {}
+};
diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc
new file mode 100644 (file)
index 0000000..18dded0
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle.h"
+#include "image.h"
+#include "exceptions.h"
+
+using namespace std;
+using namespace boost;
+
+Subtitle::Subtitle (AVSubtitle const & sub)
+{
+       /* subtitle PTS in seconds */
+       float const packet_time = (sub.pts / AV_TIME_BASE) + float (sub.pts % AV_TIME_BASE) / 1e6;
+       
+       /* hence start time for this sub */
+       _from = packet_time + (double (sub.start_display_time) / 1e3);
+       _to = packet_time + (double (sub.end_display_time) / 1e3);
+
+       for (unsigned int i = 0; i < sub.num_rects; ++i) {
+               _images.push_back (shared_ptr<SubtitleImage> (new SubtitleImage (sub.rects[i])));
+       }
+}
+
+/** @param t Time in seconds from the start of the film */
+bool
+Subtitle::displayed_at (double t)
+{
+       return t >= _from && t <= _to;
+}
+
+SubtitleImage::SubtitleImage (AVSubtitleRect const * rect)
+       : _position (rect->x, rect->y)
+       , _image (new SimpleImage (PIX_FMT_RGBA, Size (rect->w, rect->h)))
+{
+       if (rect->type != SUBTITLE_BITMAP) {
+               throw DecodeError ("non-bitmap subtitles not yet supported");
+       }
+
+       /* Start of the first line in the subtitle */
+       uint8_t* sub_p = rect->pict.data[0];
+       /* sub_p looks up into a RGB palette which is here */
+       uint32_t const * palette = (uint32_t *) rect->pict.data[1];
+       /* Start of the output data */
+       uint32_t* out_p = (uint32_t *) _image->data()[0];
+       
+       for (int y = 0; y < rect->h; ++y) {
+               uint8_t* sub_line_p = sub_p;
+               for (int x = 0; x < rect->w; ++x) {
+                       *out_p++ = palette[*sub_line_p++];
+               }
+               sub_p += rect->pict.linesize[0];
+       }
+}
diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h
new file mode 100644 (file)
index 0000000..18d2590
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <list>
+#include <boost/shared_ptr.hpp>
+#include "util.h"
+
+struct AVSubtitle;
+class SubtitleImage;
+class SimpleImage;
+
+class Subtitle
+{
+public:
+       Subtitle (AVSubtitle const &);
+
+       bool displayed_at (double t);
+
+       std::list<boost::shared_ptr<SubtitleImage> > images () const {
+               return _images;
+       }
+
+private:
+       /** display from time in seconds from the start of the film */
+       double _from;
+       /** display to time in seconds from the start of the film */
+       double _to;
+       std::list<boost::shared_ptr<SubtitleImage> > _images;
+};
+
+class SubtitleImage
+{
+public:
+       SubtitleImage (AVSubtitleRect const *);
+
+       Position position () const {
+               return _position;
+       }
+       
+       boost::shared_ptr<SimpleImage> image () const {
+               return _image;
+       }
+
+private:
+       Position _position;
+       boost::shared_ptr<SimpleImage> _image;
+};
index 779a1d5d19972eaef6dcfc2ee9573d0994b7fadd..16a8a7b016637bc0da96ad3481d74d4ed3071610 100644 (file)
@@ -24,7 +24,7 @@
 #include <exception>
 #include "thumbs_job.h"
 #include "film_state.h"
-#include "tiff_encoder.h"
+#include "imagemagick_encoder.h"
 #include "transcoder.h"
 #include "options.h"
 
@@ -51,7 +51,7 @@ void
 ThumbsJob::run ()
 {
        try {
-               shared_ptr<TIFFEncoder> e (new TIFFEncoder (_fs, _opt, _log));
+               shared_ptr<ImageMagickEncoder> e (new ImageMagickEncoder (_fs, _opt, _log));
                Transcoder w (_fs, _opt, this, _log, e);
                w.go ();
                set_progress (1);
diff --git a/src/lib/tiff_encoder.cc b/src/lib/tiff_encoder.cc
deleted file mode 100644 (file)
index 9aa7b68..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/tiff_encoder.h
- *  @brief An encoder that writes TIFF files (and does nothing with audio).
- */
-
-#include <stdexcept>
-#include <vector>
-#include <sstream>
-#include <iomanip>
-#include <iostream>
-#include <fstream>
-#include <boost/filesystem.hpp>
-#include <tiffio.h>
-#include "tiff_encoder.h"
-#include "film.h"
-#include "film_state.h"
-#include "options.h"
-#include "exceptions.h"
-#include "image.h"
-#include "subtitle.h"
-
-using namespace std;
-using namespace boost;
-
-/** @param s FilmState of the film that we are encoding.
- *  @param o Options.
- *  @param l Log.
- */
-TIFFEncoder::TIFFEncoder (shared_ptr<const FilmState> s, shared_ptr<const Options> o, Log* l)
-       : Encoder (s, o, l)
-{
-       
-}
-
-void
-TIFFEncoder::process_video (shared_ptr<Image> image, int frame, shared_ptr<Subtitle> sub)
-{
-       shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _fs->scaler);
-       string tmp_file = _opt->frame_out_path (frame, true);
-       TIFF* output = TIFFOpen (tmp_file.c_str (), "w");
-       if (output == 0) {
-               throw CreateFileError (tmp_file);
-       }
-                                               
-       TIFFSetField (output, TIFFTAG_IMAGEWIDTH, _opt->out_size.width);
-       TIFFSetField (output, TIFFTAG_IMAGELENGTH, _opt->out_size.height);
-       TIFFSetField (output, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
-       TIFFSetField (output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
-       TIFFSetField (output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
-       TIFFSetField (output, TIFFTAG_BITSPERSAMPLE, 8);
-       TIFFSetField (output, TIFFTAG_SAMPLESPERPIXEL, 3);
-       
-       if (TIFFWriteEncodedStrip (output, 0, scaled->data()[0], _opt->out_size.width * _opt->out_size.height * 3) == 0) {
-               throw WriteFileError (tmp_file, 0);
-       }
-
-       TIFFClose (output);
-
-       filesystem::rename (tmp_file, _opt->frame_out_path (frame, false));
-
-       if (sub) {
-               float const x_scale = float (_opt->out_size.width) / _fs->size.width;
-               float const y_scale = float (_opt->out_size.height) / _fs->size.height;
-
-               string tmp_metadata_file = _opt->frame_out_path (frame, false, ".sub");
-               ofstream metadata (tmp_metadata_file.c_str ());
-               
-               list<shared_ptr<SubtitleImage> > images = sub->images ();
-               int n = 0;
-               for (list<shared_ptr<SubtitleImage> >::iterator i = images.begin(); i != images.end(); ++i) {
-                       stringstream ext;
-                       ext << ".sub." << n << ".tiff";
-                       
-                       string tmp_sub_file = _opt->frame_out_path (frame, true, ext.str ());
-                       output = TIFFOpen (tmp_sub_file.c_str(), "w");
-                       if (output == 0) {
-                               throw CreateFileError (tmp_file);
-                       }
-
-                       Size new_size = (*i)->image()->size ();
-                       new_size.width *= x_scale;
-                       new_size.height *= y_scale;
-                       shared_ptr<Image> scaled = (*i)->image()->scale (new_size, _fs->scaler);
-                       
-                       TIFFSetField (output, TIFFTAG_IMAGEWIDTH, scaled->size().width);
-                       TIFFSetField (output, TIFFTAG_IMAGELENGTH, scaled->size().height);
-                       TIFFSetField (output, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
-                       TIFFSetField (output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
-                       TIFFSetField (output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
-                       TIFFSetField (output, TIFFTAG_BITSPERSAMPLE, 8);
-                       TIFFSetField (output, TIFFTAG_SAMPLESPERPIXEL, 4);
-               
-                       if (TIFFWriteEncodedStrip (output, 0, scaled->data()[0], scaled->size().width * scaled->size().height * 4) == 0) {
-                               throw WriteFileError (tmp_file, 0);
-                       }
-               
-                       TIFFClose (output);
-                       filesystem::rename (tmp_sub_file, _opt->frame_out_path (frame, false, ext.str ()));
-
-                       metadata << "image " << n << "\n"
-                                << "x " << (*i)->position().x << "\n"
-                                << "y " << (*i)->position().y << "\n";
-
-                       metadata.close ();
-                       filesystem::rename (tmp_metadata_file, _opt->frame_out_path (frame, false, ".sub"));
-               }
-
-       }
-       
-       frame_done (frame);
-}
diff --git a/src/lib/tiff_encoder.h b/src/lib/tiff_encoder.h
deleted file mode 100644 (file)
index 1c9f33f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
-    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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/tiff_encoder.h
- *  @brief An encoder that writes TIFF files (and does nothing with audio).
- */
-
-#include <string>
-#include <sndfile.h>
-#include "encoder.h"
-
-class FilmState;
-class Log;
-
-/** @class TIFFEncoder
- *  @brief An encoder that writes TIFF files (and does nothing with audio).
- */
-class TIFFEncoder : public Encoder
-{
-public:
-       TIFFEncoder (boost::shared_ptr<const FilmState> s, boost::shared_ptr<const Options> o, Log* l);
-
-       void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {}
-       void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
-       void process_audio (uint8_t *, int) {}
-       void process_end () {}
-};
index 67292047c31fb10e936521d487f4ab52fd1ed167..9539d57a116a38727f15d38ad3f8c4baf7484943 100644 (file)
@@ -30,6 +30,7 @@ def build(bld):
                 format.cc
                  image.cc
                  imagemagick_decoder.cc
+                 imagemagick_encoder.cc
                 j2k_still_encoder.cc
                 j2k_wav_encoder.cc
                 job.cc
@@ -45,7 +46,6 @@ def build(bld):
                  subtitle.cc
                 thumbs_job.cc
                  tiff_decoder.cc
-                tiff_encoder.cc
                  timer.cc
                 transcode_job.cc
                 transcoder.cc
index 8c298ea57d3087915204efaa2b5f826ff5c0a150..e49532cdbcc7a40939f1e45e6f903b90147e1202 100644 (file)
@@ -326,7 +326,7 @@ FilmViewer::update_thumbs ()
        _film->update_thumbs_pre_gui ();
 
        shared_ptr<const FilmState> s = _film->state_copy ();
-       shared_ptr<Options> o (new Options (s->dir ("thumbs"), ".tiff", ""));
+       shared_ptr<Options> o (new Options (s->dir ("thumbs"), ".png", ""));
        o->out_size = _film->size ();
        o->apply_crop = false;
        o->decode_audio = false;