From 5da5adc3f8dff52ead31f4462283925a1759e660 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 2 Nov 2021 09:12:23 -0400 Subject: [PATCH] Move ImageMagick code out of Frame class --- src/CMakeLists.txt | 11 +++-- src/Frame.cpp | 85 +++----------------------------------- src/Frame.h | 26 ++---------- src/ImageReader.cpp | 82 +++++++++++++++++-------------------- src/ImageReader.h | 24 +++++------ src/ImageWriter.cpp | 91 ++++++++++++++++++++++------------------- src/ImageWriter.h | 26 ++++++------ src/MagickUtilities.cpp | 73 +++++++++++++++++++++++++++++++++ src/MagickUtilities.h | 23 +++++++++-- src/QtUtilities.h | 13 ++++++ src/TextReader.cpp | 10 +++-- src/TextReader.h | 15 +++---- 12 files changed, 246 insertions(+), 233 deletions(-) create mode 100644 src/MagickUtilities.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 115f975a..70797f0d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,9 +70,7 @@ set(OPENSHOT_SOURCES FrameMapper.cpp Json.cpp KeyFrame.cpp - TrackedObjectBase.cpp OpenShotVersion.cpp - ZmqLogger.cpp PlayerBase.cpp Point.cpp Profiles.cpp @@ -82,7 +80,10 @@ set(OPENSHOT_SOURCES QtTextReader.cpp Settings.cpp TimelineBase.cpp - Timeline.cpp) + Timeline.cpp + TrackedObjectBase.cpp + ZmqLogger.cpp + ) # OpenCV related classes set(OPENSHOT_CV_SOURCES @@ -216,9 +217,11 @@ if (ENABLE_MAGICK) # Add optional ImageMagic-dependent sources target_sources(openshot PRIVATE + MagickUtilities.cpp ImageReader.cpp ImageWriter.cpp - TextReader.cpp) + TextReader.cpp + ) # define a preprocessor macro (used in the C++ source) target_compile_definitions(openshot PUBLIC USE_IMAGEMAGICK=1) diff --git a/src/Frame.cpp b/src/Frame.cpp index 155ba2b4..b95a83cf 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -16,6 +16,8 @@ #include #include "Frame.h" +#include "QtUtilities.h" + #include #include @@ -32,10 +34,6 @@ #include #include -#ifdef USE_IMAGEMAGICK - #include "MagickUtilities.h" -#endif - using namespace std; using namespace openshot; @@ -43,7 +41,7 @@ using namespace openshot; Frame::Frame(int64_t number, int width, int height, std::string color, int samples, int channels) : audio(std::make_shared(channels, samples)), number(number), width(width), height(height), - pixel_ratio(1,1), color(color), qbuffer(NULL), + pixel_ratio(1,1), color(color), channels(channels), channel_layout(LAYOUT_STEREO), sample_rate(44100), has_audio_data(false), has_image_data(false), @@ -749,20 +747,14 @@ void Frame::AddImage( int new_width, int new_height, int bytes_per_pixel, QImage::Format type, const unsigned char *pixels_) { - // Create new buffer - { - const juce::GenericScopedLock lock(addingImageSection); - qbuffer = pixels_; - } // Release addingImageSection lock - // Create new image object from pixel data auto new_image = std::make_shared( - qbuffer, + pixels_, new_width, new_height, new_width * bytes_per_pixel, type, - (QImageCleanupFunction) &openshot::Frame::cleanUpBuffer, - (void*) qbuffer + (QImageCleanupFunction) &openshot::cleanUpBuffer, + (void*) pixels_ ); AddImage(new_image); } @@ -948,60 +940,6 @@ void Frame::SetImageCV(cv::Mat _image) } #endif -#ifdef USE_IMAGEMAGICK -// Get pointer to ImageMagick image object -std::shared_ptr Frame::GetMagickImage() -{ - // Check for blank image - if (!image) - // Fill with black - AddColor(width, height, "#000000"); - - // Get the pixels from the frame image - const QRgb *tmpBits = (const QRgb*)image->constBits(); - - // Create new image object, and fill with pixel data - auto magick_image = std::make_shared( - image->width(), image->height(),"RGBA", Magick::CharPixel, tmpBits); - - // Give image a transparent background color - magick_image->backgroundColor(Magick::Color("none")); - magick_image->virtualPixelMethod(Magick::TransparentVirtualPixelMethod); - MAGICK_IMAGE_ALPHA(magick_image, true); - - return magick_image; -} -#endif - -#ifdef USE_IMAGEMAGICK -// Get pointer to QImage of frame -void Frame::AddMagickImage(std::shared_ptr new_image) -{ - const int BPP = 4; - const std::size_t bufferSize = new_image->columns() * new_image->rows() * BPP; - - /// Use realloc for fast memory allocation. - /// TODO: consider locking the buffer for mt safety - //qbuffer = reinterpret_cast(realloc(qbuffer, bufferSize)); - qbuffer = new unsigned char[bufferSize](); - unsigned char *buffer = (unsigned char*)qbuffer; - - MagickCore::ExceptionInfo exception; - // TODO: Actually do something, if we get an exception here - MagickCore::ExportImagePixels(new_image->constImage(), 0, 0, new_image->columns(), new_image->rows(), "RGBA", Magick::CharPixel, buffer, &exception); - - // Create QImage of frame data - image = std::make_shared( - qbuffer, width, height, width * BPP, QImage::Format_RGBA8888_Premultiplied, - (QImageCleanupFunction) &cleanUpBuffer, (void*) qbuffer); - - // Update height and width - width = image->width(); - height = image->height(); - has_image_data = true; -} -#endif - // Play audio samples for this frame void Frame::Play() { @@ -1073,17 +1011,6 @@ void Frame::Play() } -// Clean up buffer after QImage is deleted -void Frame::cleanUpBuffer(void *info) -{ - if (info) - { - // Remove buffer since QImage tells us to - unsigned char* ptr_to_qbuffer = (unsigned char*) info; - delete[] ptr_to_qbuffer; - } -} - // Add audio silence void Frame::AddAudioSilence(int numSamples) { diff --git a/src/Frame.h b/src/Frame.h index fdf78239..ac917eff 100644 --- a/src/Frame.h +++ b/src/Frame.h @@ -34,13 +34,6 @@ #include #include -#ifdef USE_IMAGEMAGICK -// Forward declare Magick::Image -namespace Magick { - class Image; -} -#endif - class QApplication; namespace openshot @@ -98,8 +91,7 @@ namespace openshot std::shared_ptr previewApp; juce::CriticalSection addingImageSection; - juce::CriticalSection addingAudioSection; - const unsigned char *qbuffer; + juce::CriticalSection addingAudioSection; openshot::Fraction pixel_ratio; int channels; ChannelLayout channel_layout; @@ -146,7 +138,8 @@ namespace openshot /// Add (or replace) pixel data to the frame (based on a solid color) void AddColor(int new_width, int new_height, std::string new_color); - /// Add (or replace) pixel data (filled with new_color) + + /// Add (or replace) pixel data (filled with new_color) void AddColor(const QColor& new_color); /// Add (or replace) pixel data to the frame @@ -158,11 +151,6 @@ namespace openshot /// Add (or replace) pixel data to the frame (for only the odd or even lines) void AddImage(std::shared_ptr new_image, bool only_odd_lines); -#ifdef USE_IMAGEMAGICK - /// Add (or replace) pixel data to the frame from an ImageMagick Image - void AddMagickImage(std::shared_ptr new_image); -#endif - /// Add audio samples to a specific channel void AddAudio(bool replaceSamples, int destChannel, int destStartSample, const float* source, int numSamples, float gainToApplyToSource); @@ -179,9 +167,6 @@ namespace openshot // Set the channel layout of audio samples (i.e. mono, stereo, 5 point surround, etc...) void ChannelsLayout(openshot::ChannelLayout new_channel_layout) { channel_layout = new_channel_layout; }; - /// Clean up buffer after QImage is deleted - static void cleanUpBuffer(void *info); - /// Clear the waveform image (and deallocate its memory) void ClearWaveform(); @@ -220,11 +205,6 @@ namespace openshot /// Get pointer to Qt QImage image object std::shared_ptr GetImage(); -#ifdef USE_IMAGEMAGICK - /// Get pointer to ImageMagick image object - std::shared_ptr GetMagickImage(); -#endif - /// Set Pixel Aspect Ratio openshot::Fraction GetPixelRatio() { return pixel_ratio; }; diff --git a/src/ImageReader.cpp b/src/ImageReader.cpp index 6f6cbe04..1240a7f6 100644 --- a/src/ImageReader.cpp +++ b/src/ImageReader.cpp @@ -13,6 +13,9 @@ // Require ImageMagick support #ifdef USE_IMAGEMAGICK +#include "MagickUtilities.h" +#include "QtUtilities.h" + #include "ImageReader.h" #include "Exceptions.h" #include "Frame.h" @@ -57,39 +60,31 @@ void ImageReader::Open() info.vcodec = image->format(); info.width = image->size().width(); info.height = image->size().height(); - info.pixel_ratio.num = 1; - info.pixel_ratio.den = 1; + info.pixel_ratio = openshot::Fraction(1, 1); info.duration = 60 * 60 * 1; // 1 hour duration - info.fps.num = 30; - info.fps.den = 1; - info.video_timebase.num = 1; - info.video_timebase.den = 30; - info.video_length = round(info.duration * info.fps.ToDouble()); + info.fps = openshot::Fraction(30, 1); + info.video_timebase = info.fps.Reciprocal(); + info.video_length = std::round(info.duration * info.fps.ToDouble()); // Calculate the DAR (display aspect ratio) - Fraction size(info.width * info.pixel_ratio.num, info.height * info.pixel_ratio.den); + Fraction dar( + info.width * info.pixel_ratio.num, + info.height * info.pixel_ratio.den); - // Reduce size fraction - size.Reduce(); - - // Set the ratio based on the reduced fraction - info.display_ratio.num = size.num; - info.display_ratio.den = size.den; + // Reduce DAR fraction & set ratio + dar.Reduce(); + info.display_ratio = dar; // Mark as "open" is_open = true; } } -// Close image file void ImageReader::Close() { - // Close all objects, if reader is 'open' if (is_open) { - // Mark as "closed" is_open = false; - // Delete the image image.reset(); } @@ -98,19 +93,21 @@ void ImageReader::Close() // Get an openshot::Frame object for a specific frame number of this reader. std::shared_ptr ImageReader::GetFrame(int64_t requested_frame) { - // Check for open reader (or throw exception) - if (!is_open) - throw ReaderClosed("The FFmpegReader is closed. Call Open() before calling this method.", path); + if (!is_open) { + throw ReaderClosed( + "The ImageReader is closed. " + "Call Open() before calling this method.", path); + } // Create or get frame object auto image_frame = std::make_shared( - requested_frame, image->size().width(), image->size().height(), + requested_frame, + image->size().width(), image->size().height(), "#000000", 0, 2); // Add Image data to frame - image_frame->AddMagickImage(image); - - // return frame object + auto qimage = openshot::Magick2QImage(image); + image_frame->AddImage(qimage); return image_frame; } @@ -124,30 +121,29 @@ std::string ImageReader::Json() const { // Generate Json::Value for this object Json::Value ImageReader::JsonValue() const { - // Create root json object - Json::Value root = ReaderBase::JsonValue(); // get parent properties + // get parent properties + Json::Value root = ReaderBase::JsonValue(); + root["type"] = "ImageReader"; root["path"] = path; - - // return JsonValue return root; } // Load JSON string into this object void ImageReader::SetJson(const std::string value) { - // Parse JSON string into JSON objects - try - { - const Json::Value root = openshot::stringToJson(value); - // Set all values that match - SetJsonValue(root); - } - catch (const std::exception& e) - { - // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); - } + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception& e) + { + throw InvalidJSON( + "JSON is invalid (missing keys or invalid data types)"); + } } // Load Json::Value into this object @@ -160,9 +156,7 @@ void ImageReader::SetJsonValue(const Json::Value root) { if (!root["path"].isNull()) path = root["path"].asString(); - // Re-Open path, and re-init everything (if needed) - if (is_open) - { + if (is_open) { Close(); Open(); } diff --git a/src/ImageReader.h b/src/ImageReader.h index d123f33b..897a051f 100644 --- a/src/ImageReader.h +++ b/src/ImageReader.h @@ -16,23 +16,23 @@ // Require ImageMagick support #ifdef USE_IMAGEMAGICK -#include "ReaderBase.h" - -#include -#include -#include -#include -#include #include -#include "CacheMemory.h" +#include -#include "MagickUtilities.h" +#include "ReaderBase.h" +#include "Json.h" + +// Forward decls +namespace Magick { + class Image; +} +namespace openshot { + class CacheBase; + class Frame; +} namespace openshot { - // Forward decls - class CacheBase; - /** * @brief This class uses the ImageMagick++ libraries, to open image files, and return * openshot::Frame objects containing the image. diff --git a/src/ImageWriter.cpp b/src/ImageWriter.cpp index eb98d7e7..a9aabd09 100644 --- a/src/ImageWriter.cpp +++ b/src/ImageWriter.cpp @@ -13,8 +13,12 @@ //Require ImageMagick support #ifdef USE_IMAGEMAGICK -#include "ImageWriter.h" +#include "MagickUtilities.h" +#include "QtUtilities.h" #include "Exceptions.h" +#include "Frame.h" + +#include "ImageWriter.h" using namespace openshot; @@ -22,47 +26,51 @@ ImageWriter::ImageWriter(std::string path) : path(path), cache_size(8), write_video_count(0), image_quality(75), number_of_loops(1), combine_frames(true), is_open(false) { - // Disable audio & video (so they can be independently enabled) info.has_audio = false; info.has_video = true; } // Set video export options -void ImageWriter::SetVideoOptions(std::string format, Fraction fps, int width, int height, - int quality, int loops, bool combine) +void ImageWriter::SetVideoOptions( + std::string format, Fraction fps, int width, int height, + int quality, int loops, bool combine) { - // Set frames per second (if provided) - info.fps.num = fps.num; - info.fps.den = fps.den; + // Set frames per second (if provided) + info.fps = fps; - // Set image magic properties - image_quality = quality; - number_of_loops = loops; - combine_frames = combine; - info.vcodec = format; + // Set image magic properties + image_quality = quality; + number_of_loops = loops; + combine_frames = combine; + info.vcodec = format; - // Set the timebase (inverse of fps) - info.video_timebase.num = info.fps.den; - info.video_timebase.den = info.fps.num; + // Set the timebase (inverse of fps) + info.video_timebase = fps.Reciprocal(); - if (width >= 1) - info.width = width; - if (height >= 1) - info.height = height; + info.width = std::max(1, width); + info.height = std::max(1, height); - info.video_bit_rate = quality; + info.video_bit_rate = quality; - // Calculate the DAR (display aspect ratio) - Fraction size(info.width * info.pixel_ratio.num, info.height * info.pixel_ratio.den); + // Calculate the DAR (display aspect ratio) + Fraction size( + info.width * info.pixel_ratio.num, + info.height * info.pixel_ratio.den); - // Reduce size fraction - size.Reduce(); + // Reduce size fraction + size.Reduce(); - // Set the ratio based on the reduced fraction - info.display_ratio.num = size.num; - info.display_ratio.den = size.den; + // Set the ratio based on the reduced fraction + info.display_ratio = size; - ZmqLogger::Instance()->AppendDebugMethod("ImageWriter::SetVideoOptions (" + format + ")", "width", width, "height", height, "size.num", size.num, "size.den", size.den, "fps.num", fps.num, "fps.den", fps.den); + ZmqLogger::Instance()->AppendDebugMethod( + "ImageWriter::SetVideoOptions (" + format + ")", + "width", width, + "height", height, + "size.num", size.num, + "size.den", size.den, + "fps.num", fps.num, + "fps.den", fps.den); } // Open the writer @@ -75,12 +83,15 @@ void ImageWriter::Open() void ImageWriter::WriteFrame(std::shared_ptr frame) { // Check for open reader (or throw exception) - if (!is_open) - throw WriterClosed("The ImageWriter is closed. Call Open() before calling this method.", path); - + if (!is_open) { + throw WriterClosed( + "The ImageWriter is closed. " + "Call Open() before calling this method.", path); + } // Copy and resize image - std::shared_ptr frame_image = frame->GetMagickImage(); + auto qimage = frame->GetImage(); + auto frame_image = openshot::QImage2Magick(qimage); frame_image->magick( info.vcodec ); frame_image->backgroundColor(Magick::Color("none")); MAGICK_IMAGE_ALPHA(frame_image, true); @@ -89,11 +100,10 @@ void ImageWriter::WriteFrame(std::shared_ptr frame) frame_image->animationIterations(number_of_loops); // Calculate correct DAR (display aspect ratio) - int new_width = info.width; int new_height = info.height * frame->GetPixelRatio().Reciprocal().ToDouble(); // Resize image - Magick::Geometry new_size(new_width, new_height); + Magick::Geometry new_size(info.width, new_height); new_size.aspect(true); frame_image->resize(new_size); @@ -108,7 +118,10 @@ void ImageWriter::WriteFrame(std::shared_ptr frame) // Write a block of frames from a reader void ImageWriter::WriteFrame(ReaderBase* reader, int64_t start, int64_t length) { - ZmqLogger::Instance()->AppendDebugMethod("ImageWriter::WriteFrame (from Reader)", "start", start, "length", length); + ZmqLogger::Instance()->AppendDebugMethod( + "ImageWriter::WriteFrame (from Reader)", + "start", start, + "length", length); // Loop through each frame (and encoded it) for (int64_t number = start; number <= length; number++) @@ -124,16 +137,12 @@ void ImageWriter::WriteFrame(ReaderBase* reader, int64_t start, int64_t length) // Close the writer and encode/output final image to the disk. void ImageWriter::Close() { - // Write frame's image to file + // Write frame images to file Magick::writeImages(frames.begin(), frames.end(), path, combine_frames); - // Clear frames vector + // Clear frames vector & counters, close writer frames.clear(); - - // Reset frame counters write_video_count = 0; - - // Close writer is_open = false; ZmqLogger::Instance()->AppendDebugMethod("ImageWriter::Close"); diff --git a/src/ImageWriter.h b/src/ImageWriter.h index dd2d2b8a..6ed0af10 100644 --- a/src/ImageWriter.h +++ b/src/ImageWriter.h @@ -15,20 +15,19 @@ #ifdef USE_IMAGEMAGICK -#include "ReaderBase.h" -#include "WriterBase.h" - #include #include -#include "CacheMemory.h" -#include "Exceptions.h" -#include "Fraction.h" -#include "OpenMPUtilities.h" +#include "WriterBase.h" #include "MagickUtilities.h" +#include "Fraction.h" + namespace openshot { + // Forward decls + class Frame; + class ReaderBase; /** * @brief This class uses the ImageMagick library to write image files (including animated GIFs) @@ -69,7 +68,7 @@ namespace openshot int number_of_loops; bool combine_frames; - std::shared_ptr last_frame; + std::shared_ptr last_frame; public: @@ -102,8 +101,9 @@ namespace openshot /// @param quality Quality of image (0 to 100, 70 is default) /// @param loops Number of times to repeat the image (used on certain multi-frame image formats, such as GIF) /// @param combine Combine frames into a single image (if possible), or save each frame as its own image - void SetVideoOptions(std::string format, Fraction fps, int width, int height, - int quality, int loops, bool combine); + void SetVideoOptions( + std::string format, Fraction fps, int width, int height, + int quality, int loops, bool combine); /// @brief Add a frame to the stack waiting to be encoded. /// @param frame The openshot::Frame object to write to this image @@ -117,7 +117,7 @@ namespace openshot }; -} +} // namespace -#endif //USE_IMAGEMAGICK -#endif //OPENSHOT_IMAGE_WRITER_H +#endif //USE_IMAGEMAGICK +#endif //OPENSHOT_IMAGE_WRITER_H diff --git a/src/MagickUtilities.cpp b/src/MagickUtilities.cpp new file mode 100644 index 00000000..aa22ec1f --- /dev/null +++ b/src/MagickUtilities.cpp @@ -0,0 +1,73 @@ +/** + * @file + * @brief Implementation for MagickUtilities (conversions) + * @author Jonathan Thomas + * @author FeRD (Frank Dana) + */ + +// Copyright (c) 2008-2021 OpenShot Studios, LLC +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifdef USE_IMAGEMAGICK + +#include "MagickUtilities.h" +#include "QtUtilities.h" + +#include + +// Get pointer to Magick::Image conversion of a QImage +std::shared_ptr +openshot::QImage2Magick(std::shared_ptr image) +{ + // Check for blank image + if (!image || image->isNull()) + return nullptr; + + // Get the pixels from the frame image + const QRgb *tmpBits = (const QRgb*)image->constBits(); + + // Create new image object, and fill with pixel data + auto magick_image = std::make_shared( + image->width(), image->height(), + "RGBA", Magick::CharPixel, tmpBits); + + // Give image a transparent background color + magick_image->backgroundColor(Magick::Color("none")); + magick_image->virtualPixelMethod( + Magick::TransparentVirtualPixelMethod); + MAGICK_IMAGE_ALPHA(magick_image, true); + + return magick_image; +} + +// Get pointer to QImage conversion of a Magick::Image +std::shared_ptr +openshot::Magick2QImage(std::shared_ptr image) +{ + if (!image) + return nullptr; + + const int BPP = 4; + const std::size_t size = image->columns() * image->rows() * BPP; + + auto* qbuffer = new unsigned char[size](); + + MagickCore::ExceptionInfo exception; + // TODO: Actually do something, if we get an exception here + MagickCore::ExportImagePixels( + image->constImage(), 0, 0, + image->columns(), image->rows(), + "RGBA", Magick::CharPixel, + qbuffer, &exception); + + auto qimage = std::make_shared( + qbuffer, image->columns(), image->rows(), + image->columns() * BPP, + QImage::Format_RGBA8888_Premultiplied, + (QImageCleanupFunction) &openshot::cleanUpBuffer, + (void*) qbuffer); + return qimage; +} + +#endif // USE_IMAGEMAGICK diff --git a/src/MagickUtilities.h b/src/MagickUtilities.h index 9246da1e..d782b1aa 100644 --- a/src/MagickUtilities.h +++ b/src/MagickUtilities.h @@ -21,6 +21,9 @@ // namespace instead of the global namespace #include + #include + #include + // Exclude a warning message with IM6 headers #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wignored-qualifiers" @@ -30,8 +33,8 @@ // Determine ImageMagick version, as IM7 isn't fully // backwards compatible #ifndef NEW_MAGICK - #define NEW_MAGICK (MagickLibVersion >= 0x700) - #endif + #define NEW_MAGICK (MagickLibVersion >= 0x700) + #endif // IM7: ->alpha(bool) // IM6: ->matte(bool) @@ -50,5 +53,17 @@ #define MAGICK_DRAWABLE std::list #endif -#endif -#endif +namespace openshot { + + /// Convert QImage to Magick::Image + std::shared_ptr + QImage2Magick(std::shared_ptr); + + /// Convert Magick::Image to QImage + std::shared_ptr + Magick2QImage(std::shared_ptr); + +} // namespace + +#endif // USE_IMAGEMAGICK +#endif // OPENSHOT_MAGICK_UTILITIES_H diff --git a/src/QtUtilities.h b/src/QtUtilities.h index f2e36ffc..a827bc37 100644 --- a/src/QtUtilities.h +++ b/src/QtUtilities.h @@ -23,4 +23,17 @@ namespace Qt { } #endif + +namespace openshot { + // Clean up buffer after QImage is deleted + static inline void cleanUpBuffer(void *info) + { + if (!info) + return; + // Remove buffer since QImage tells us to + auto* qbuffer = reinterpret_cast(info); + delete[] qbuffer; + } +} // namespace + #endif // OPENSHOT_QT_UTILITIES_H diff --git a/src/TextReader.cpp b/src/TextReader.cpp index 58b7b14e..f67db3c8 100644 --- a/src/TextReader.cpp +++ b/src/TextReader.cpp @@ -13,6 +13,9 @@ // Require ImageMagick support #ifdef USE_IMAGEMAGICK +#include "QtUtilities.h" +#include "MagickUtilities.h" + #include "TextReader.h" #include "Exceptions.h" #include "Frame.h" @@ -152,14 +155,15 @@ std::shared_ptr TextReader::GetFrame(int64_t requested_frame) { // Create or get frame object auto image_frame = std::make_shared( - requested_frame, image->size().width(), image->size().height(), + requested_frame, + image->size().width(), image->size().height(), "#000000", 0, 2); // Add Image data to frame auto copy_image = std::make_shared(*image.get()); copy_image->modifyImage(); // actually copy the image data to this object - //TODO: Reimplement this with QImage - image_frame->AddMagickImage(copy_image); + auto qimage = openshot::Magick2QImage(copy_image); + image_frame->AddImage(qimage); // return frame object return image_frame; diff --git a/src/TextReader.h b/src/TextReader.h index f55d4863..03392e9f 100644 --- a/src/TextReader.h +++ b/src/TextReader.h @@ -16,21 +16,16 @@ // Require ImageMagick support #ifdef USE_IMAGEMAGICK -#include "ReaderBase.h" - -#include -#include -#include -#include -#include #include -#include "CacheMemory.h" -#include "Enums.h" +#include "ReaderBase.h" +#include "Enums.h" #include "MagickUtilities.h" namespace openshot { + class CacheBase; + class Frame; /** * @brief This class uses the ImageMagick++ libraries, to create frames with "Text", and return @@ -108,7 +103,7 @@ namespace openshot void Close() override; /// Get the cache object used by this reader (always returns NULL for this object) - openshot::CacheMemory* GetCache() override { return NULL; }; + openshot::CacheBase* GetCache() override { return nullptr; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data.