Write image subs to DCPs. bitmap-subs
authorCarl Hetherington <cth@carlh.net>
Sun, 8 Jul 2018 22:26:21 +0000 (23:26 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 8 Jul 2018 22:26:21 +0000 (23:26 +0100)
hacks/pixfmts.c
src/lib/image.cc
src/lib/image.h
src/lib/reel_writer.cc
src/lib/reel_writer.h
src/lib/writer.cc

index 8aa5c4a..e1dd00a 100644 (file)
@@ -5,6 +5,10 @@
 int main()
 {
        SHOW(AV_PIX_FMT_YUV420P);
+       SHOW(AV_PIX_FMT_ARGB);
+       SHOW(AV_PIX_FMT_RGBA);
+       SHOW(AV_PIX_FMT_ABGR);
+       SHOW(AV_PIX_FMT_BGRA);
        SHOW(AV_PIX_FMT_YUV420P16LE);
        SHOW(AV_PIX_FMT_YUV422P10LE);
        SHOW(AV_PIX_FMT_YUV444P9BE);
index 792bf3a..bdd4f61 100644 (file)
@@ -30,6 +30,7 @@
 #include "dcpomatic_socket.h"
 #include <dcp/rgb_xyz.h>
 #include <dcp/transfer_function.h>
+#include <Magick++.h>
 extern "C" {
 #include <libswscale/swscale.h>
 #include <libavutil/pixfmt.h>
@@ -825,7 +826,8 @@ Image::allocate ()
 }
 
 Image::Image (Image const & other)
-       : _size (other._size)
+       : enable_shared_from_this<Image>(other)
+       , _size (other._size)
        , _pixel_format (other._pixel_format)
        , _aligned (other._aligned)
        , _extra_pixels (other._extra_pixels)
@@ -1125,8 +1127,8 @@ Image::fade (float f)
        }
 }
 
-shared_ptr<Image>
-Image::ensure_aligned (shared_ptr<Image> image)
+shared_ptr<const Image>
+Image::ensure_aligned (shared_ptr<const Image> image)
 {
        if (image->aligned()) {
                return image;
@@ -1144,3 +1146,38 @@ Image::memory_used () const
        }
        return m;
 }
+
+dcp::Data
+Image::as_png () const
+{
+#ifdef DCPOMATIC_IMAGE_MAGICK
+               using namespace MagickCore;
+#else
+               using namespace MagickLib;
+#endif
+
+       string format;
+       switch (_pixel_format) {
+       case AV_PIX_FMT_RGB24:
+               format = "RGB";
+               break;
+       case AV_PIX_FMT_BGRA:
+               format = "BGRA";
+               break;
+       default:
+               DCPOMATIC_ASSERT (false);
+               break;
+       }
+
+       shared_ptr<const Image> use;
+       if (aligned()) {
+               use.reset (new Image(shared_from_this(), false));
+       }
+
+       Magick::Image m (size().width, size().height, format, CharPixel, (void *) use->data()[0]);
+       m.magick ("PNG");
+       Magick::Blob blob;
+       m.write (&blob);
+       /* XXX: could use a subclass of Data here (storing its data in a Blob) */
+       return dcp::Data (static_cast<const uint8_t*>(blob.data()), blob.length());
+}
index f71a47b..73f2313 100644 (file)
@@ -33,11 +33,12 @@ extern "C" {
 }
 #include <dcp/colour_conversion.h>
 #include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
 
 struct AVFrame;
 class Socket;
 
-class Image
+class Image : public boost::enable_shared_from_this<Image>
 {
 public:
        Image (AVPixelFormat p, dcp::Size s, bool aligned, int extra_pixels = 0);
@@ -80,7 +81,9 @@ public:
 
        size_t memory_used () const;
 
-       static boost::shared_ptr<Image> ensure_aligned (boost::shared_ptr<Image> image);
+       dcp::Data as_png () const;
+
+       static boost::shared_ptr<const Image> ensure_aligned (boost::shared_ptr<const Image> image);
 
 private:
        friend struct pixel_formats_test;
index 7fca9e2..24ab1c5 100644 (file)
@@ -27,6 +27,7 @@
 #include "font.h"
 #include "compose.hpp"
 #include "audio_buffers.h"
+#include "image.h"
 #include <dcp/mono_picture_asset.h>
 #include <dcp/stereo_picture_asset.h>
 #include <dcp/sound_asset.h>
@@ -42,6 +43,7 @@
 #include <dcp/interop_subtitle_asset.h>
 #include <dcp/smpte_subtitle_asset.h>
 #include <dcp/raw_convert.h>
+#include <dcp/subtitle_image.h>
 #include <boost/foreach.hpp>
 
 #include "i18n.h"
@@ -526,7 +528,7 @@ ReelWriter::write (shared_ptr<const AudioBuffers> audio)
 }
 
 void
-ReelWriter::write (PlayerSubtitles subs)
+ReelWriter::write (PlayerSubtitles subs, DCPTimePeriod period)
 {
        if (!_subtitle_asset) {
                string lang = _film->subtitle_language ();
@@ -555,10 +557,25 @@ ReelWriter::write (PlayerSubtitles subs)
        }
 
        BOOST_FOREACH (SubtitleString i, subs.text) {
+               /* XXX: couldn't / shouldn't we use period here rather than getting time from the subtitle? */
                i.set_in  (i.in()  - dcp::Time (_period.from.seconds(), i.in().tcr));
                i.set_out (i.out() - dcp::Time (_period.from.seconds(), i.out().tcr));
                _subtitle_asset->add (shared_ptr<dcp::Subtitle>(new dcp::SubtitleString(i)));
        }
+
+       BOOST_FOREACH (ImageSubtitle i, subs.image) {
+               _subtitle_asset->add (
+                       shared_ptr<dcp::Subtitle>(
+                               new dcp::SubtitleImage(
+                                       i.image->as_png(),
+                                       dcp::Time(period.from.seconds(), _film->video_frame_rate()),
+                                       dcp::Time(period.to.seconds(), _film->video_frame_rate()),
+                                       i.rectangle.x, dcp::HALIGN_LEFT, i.rectangle.y, dcp::VALIGN_TOP,
+                                       dcp::Time(), dcp::Time()
+                                       )
+                               )
+                       );
+       }
 }
 
 bool
index c0e98f6..4357a28 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -60,7 +60,7 @@ public:
        void fake_write (Frame frame, Eyes eyes, int size);
        void repeat_write (Frame frame, Eyes eyes);
        void write (boost::shared_ptr<const AudioBuffers> audio);
-       void write (PlayerSubtitles subs);
+       void write (PlayerSubtitles subs, DCPTimePeriod period);
 
        void finish ();
        boost::shared_ptr<dcp::Reel> create_reel (std::list<ReferencedReelAsset> const & refs, std::list<boost::shared_ptr<Font> > const & fonts);
index cd5b6d7..2eec811 100644 (file)
@@ -665,10 +665,6 @@ Writer::can_fake_write (Frame frame) const
 void
 Writer::write (PlayerSubtitles subs, DCPTimePeriod period)
 {
-       if (subs.text.empty ()) {
-               return;
-       }
-
        while (_subtitle_reel->period().to <= period.from) {
                ++_subtitle_reel;
                DCPOMATIC_ASSERT (_subtitle_reel != _reels.end());
@@ -676,7 +672,7 @@ Writer::write (PlayerSubtitles subs, DCPTimePeriod period)
 
        DCPOMATIC_ASSERT (_subtitle_reel != _reels.end());
 
-       _subtitle_reel->write (subs);
+       _subtitle_reel->write (subs, period);
 }
 
 void