Commit 2e6b4142 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Split image compression in multiple classes

parent 3216ac48
......@@ -125,6 +125,7 @@ noinst_HEADERS = \
src/metadata_services/MetadataParser.h \
src/metadata_services/vlc/VLCMetadataService.h \
src/metadata_services/vlc/VLCThumbnailer.h \
src/metadata_services/vlc/imagecompressors/IImageCompressor.h \
src/Movie.h \
src/parser/Parser.h \
src/parser/ParserService.h \
......@@ -163,15 +164,25 @@ libmedialibrary_la_CPPFLAGS = \
$(SQLITE_CFLAGS) \
$(VLC_CFLAGS) \
$(VLCPP_CFLAGS) \
$(LIBJPEG_CFLAGS) \
$(NULL)
libmedialibrary_la_LIBADD = \
$(SQLITE_LIBS) \
$(VLC_LIBS) \
$(LIBJPEG_LIBS) \
$(NULL)
if HAVE_EVAS
libmedialibrary_la_SOURCES += src/metadata_services/vlc/imagecompressors/EvasCompressor.cpp
noinst_HEADERS += src/metadata_services/vlc/imagecompressors/EvasCompressor.h
else
if HAVE_LIBJPEG
libmedialibrary_la_SOURCES += src/metadata_services/vlc/imagecompressors/JpegCompressor.cpp
noinst_HEADERS += src/metadata_services/vlc/imagecompressors/JpegCompressor.h
libmedialibrary_la_CPPFLAGS += $(LIBJPEG_CFLAGS)
libmedialibrary_la_LIBADD += $(LIBJPEG_LIBS)
endif
endif
lib_LTLIBRARIES = libmedialibrary.la
if HAVE_TESTS
......
......@@ -249,6 +249,12 @@ PKG_CHECK_MODULES(LIBJPEG, libjpeg, [
])
AM_CONDITIONAL([HAVE_LIBJPEG], [test "${have_libjpeg}" = "yes"])
PKG_CHECK_MODULES(EVAS, evas, [
have_evas="yes"
AC_DEFINE(HAVE_EVAS, 1, [Define to 1 if evas is available])
], [have_evas="no"])
AM_CONDITIONAL([HAVE_EVAS], [test "${have_evas}" = "yes"])
AC_ARG_ENABLE(tests,AC_HELP_STRING([--disable-tests], [Disable build of automated tests suites]))
AM_CONDITIONAL([HAVE_TESTS], [test "${enable_tests}" = "yes"])
AS_IF([test "${enable_tests}" = "yes"], [
......
......@@ -20,23 +20,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "VLCThumbnailer.h"
#include <cstring>
#ifdef HAVE_JPEG
#include <jpeglib.h>
#if ( ( !defined(JPEG_LIB_VERSION_MAJOR) && !defined(JPEG_LIB_VERSION_MINOR) ) || \
( JPEG_LIB_VERSION_MAJOR <= 8 && JPEG_LIB_VERSION_MINOR < 4 ) ) && \
( !defined( JPEG_LIB_VERSION ) || JPEG_LIB_VERSION < 62 )
//FIXME: I don't think we can expect this to work without VLC outputing BGR...
#define JPEG_COLORSPACE JCS_EXT_BGR
#else
#define JPEG_COLORSPACE JCS_RGB
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#elif defined(HAVE_EVAS)
#include <Evas_Engine_Buffer.h>
#endif
#include <setjmp.h>
#include "VLCThumbnailer.h"
#include "Media.h"
#include "File.h"
......@@ -45,48 +33,28 @@
#include "utils/VLCInstance.h"
#include "ToString.h"
#ifdef HAVE_JPEG
#include "imagecompressors/JpegCompressor.h"
#elif defined(HAVE_EVAS)
#include "imagecompressors/EvasCompressor.h"
#else
#error No image compressor available
#endif
namespace medialibrary
{
VLCThumbnailer::VLCThumbnailer()
: m_instance( VLCInstance::get() )
#ifdef HAVE_EVAS
, m_canvas( nullptr, &evas_free )
#endif
, m_thumbnailRequired( false )
, m_width( 0 )
, m_height( 0 )
, m_prevSize( 0 )
{
#ifdef HAVE_EVAS
static int fakeBuffer;
#ifndef TIZEN
evas_init();
#endif
auto method = evas_render_method_lookup("buffer");
m_canvas.reset( evas_new() );
if ( m_canvas == nullptr )
throw std::runtime_error( "Failed to allocate canvas" );
evas_output_method_set( m_canvas.get(), method );
evas_output_size_set(m_canvas.get(), 1, 1 );
evas_output_viewport_set( m_canvas.get(), 0, 0, 1, 1 );
auto einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get( m_canvas.get() );
einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
einfo->info.dest_buffer = &fakeBuffer;
einfo->info.dest_buffer_row_bytes = 4;
einfo->info.use_color_key = 0;
einfo->info.alpha_threshold = 0;
einfo->info.func.new_update_region = NULL;
einfo->info.func.free_update_region = NULL;
evas_engine_info_set( m_canvas.get(), (Evas_Engine_Info *)einfo );
m_cropBuffer.reset( new uint8_t[ DesiredWidth * DesiredHeight * Bpp ] );
#endif
}
VLCThumbnailer::~VLCThumbnailer()
{
#if defined(HAVE_EVAS) && !defined(TIZEN)
evas_shutdown();
#ifdef HAVE_JPEG
m_compressor.reset( new JpegCompressor );
#elif defined(HAVE_EVAS)
m_compressor.reset( new EvasCompressor );
#endif
}
......@@ -193,7 +161,7 @@ void VLCThumbnailer::setupVout( VLC::MediaPlayer& mp )
mp.setVideoFormatCallbacks(
// Setup
[this, &mp](char* chroma, unsigned int* width, unsigned int *height, unsigned int *pitches, unsigned int *lines) {
strcpy( chroma, VLC_FOURCC );
strcpy( chroma, m_compressor->fourCC() );
const float inputAR = (float)*width / *height;
......@@ -205,7 +173,7 @@ void VLCThumbnailer::setupVout( VLC::MediaPlayer& mp )
m_width = inputAR * DesiredHeight;
m_height = DesiredHeight;
}
auto size = m_width * m_height * Bpp;
auto size = m_width * m_height * m_compressor->bpp();
// If our buffer isn't enough anymore, reallocate a new one.
if ( size > m_prevSize )
{
......@@ -214,7 +182,7 @@ void VLCThumbnailer::setupVout( VLC::MediaPlayer& mp )
}
*width = m_width;
*height = m_height;
*pitches = m_width * Bpp;
*pitches = m_width * m_compressor->bpp();
*lines = m_height;
return 1;
},
......@@ -260,107 +228,18 @@ parser::Task::Status VLCThumbnailer::takeThumbnail( std::shared_ptr<Media> media
return compress( media, file );
}
#ifdef HAVE_JPEG
struct jpegError : public jpeg_error_mgr
{
jmp_buf buff;
char message[JMSG_LENGTH_MAX];
static void jpegErrorHandler(j_common_ptr common)
{
auto error = reinterpret_cast<jpegError*>(common->err);
(*error->format_message)( common, error->message );
longjmp(error->buff, 1);
}
};
#endif
parser::Task::Status VLCThumbnailer::compress( std::shared_ptr<Media> media, std::shared_ptr<File> file )
{
auto path = m_ml->thumbnailPath();
path += "/";
path += toString( media->id() ) +
#ifdef HAVE_EVAS
".png";
#else
".jpg";
#endif
path += toString( media->id() ) + "." + m_compressor->extension();
auto hOffset = m_width > DesiredWidth ? ( m_width - DesiredWidth ) / 2 : 0;
auto vOffset = m_height > DesiredHeight ? ( m_height - DesiredHeight ) / 2 : 0;
const auto stride = m_width * Bpp;
#ifdef HAVE_JPEG
//FIXME: Abstract this away, though libjpeg requires a FILE*...
auto fOut = std::unique_ptr<FILE, int(*)(FILE*)>( fopen( path.c_str(), "wb" ), &fclose );
if ( fOut == nullptr )
{
LOG_ERROR("Failed to open thumbnail file ", path);
return parser::Task::Status::Error;
}
jpeg_compress_struct compInfo;
JSAMPROW row_pointer[1];
//libjpeg's default error handling is to call exit(), which would
//be slightly problematic...
jpegError err;
compInfo.err = jpeg_std_error(&err);
err.error_exit = jpegError::jpegErrorHandler;
if ( setjmp( err.buff ) )
{
LOG_ERROR("JPEG failure: ", err.message);
jpeg_destroy_compress(&compInfo);
return parser::Task::Status::Error;
}
jpeg_create_compress(&compInfo);
jpeg_stdio_dest(&compInfo, fOut.get());
compInfo.image_width = DesiredWidth;
compInfo.image_height = DesiredHeight;
compInfo.input_components = Bpp;
compInfo.in_color_space = JPEG_COLORSPACE;
jpeg_set_defaults( &compInfo );
jpeg_set_quality( &compInfo, 85, TRUE );
jpeg_start_compress( &compInfo, TRUE );
while (compInfo.next_scanline < DesiredHeight)
{
row_pointer[0] = &m_buff[(compInfo.next_scanline + vOffset ) * stride + hOffset];
jpeg_write_scanlines(&compInfo, row_pointer, 1);
}
jpeg_finish_compress(&compInfo);
jpeg_destroy_compress(&compInfo);
#elif defined(HAVE_EVAS)
auto evas_obj = std::unique_ptr<Evas_Object, void(*)(Evas_Object*)>( evas_object_image_add( m_canvas.get() ), evas_object_del );
if ( evas_obj == nullptr )
return parser::Task::Status::Error;
uint8_t *p_buff = m_buff.get();
if ( DesiredWidth != m_width )
{
p_buff += vOffset * stride;
for ( auto y = 0u; y < DesiredHeight; ++y )
{
memcpy( m_cropBuffer.get() + y * DesiredWidth * Bpp, p_buff + (hOffset * Bpp), DesiredWidth * Bpp );
p_buff += stride;
}
vOffset = 0;
p_buff = m_cropBuffer.get();
}
evas_object_image_colorspace_set( evas_obj.get(), EVAS_COLORSPACE_ARGB8888 );
evas_object_image_size_set( evas_obj.get(), DesiredWidth, DesiredHeight );
evas_object_image_data_set( evas_obj.get(), p_buff + vOffset * stride );
evas_object_image_save( evas_obj.get(), path.c_str(), NULL, "quality=100 compress=9");
#else
#error FIXME
#endif
if ( m_compressor->compress( m_buff.get(), path, m_width, m_height, DesiredWidth, DesiredHeight,
hOffset, vOffset ) == false )
return parser::Task::Status::Fatal;
media->setThumbnail( path );
LOG_INFO( "Done generating ", file->mrl(), " thumbnail" );
......
......@@ -22,30 +22,13 @@
#pragma once
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <condition_variable>
#include <vlcpp/vlc.hpp>
#if defined(HAVE_EVAS)
#include <Evas.h>
#endif
#include "imagecompressors/IImageCompressor.h"
#include "parser/ParserService.h"
#ifdef HAVE_JPEG
#define BPP 3
#define VLC_FOURCC "RV24"
#elif defined(HAVE_EVAS)
#define BPP 4
#define VLC_FOURCC "RV32"
#else
#error No compression strategy
#endif
namespace medialibrary
{
......@@ -53,7 +36,7 @@ class VLCThumbnailer : public ParserService
{
public:
explicit VLCThumbnailer();
virtual ~VLCThumbnailer();
virtual ~VLCThumbnailer() = default;
virtual parser::Task::Status run( parser::Task& task ) override;
virtual bool initialize() override;
......@@ -71,17 +54,13 @@ private:
// Force a base width, let height be computed depending on A/R
static const uint32_t DesiredWidth = 320;
static const uint32_t DesiredHeight = 200; // Aim for a 16:10 thumbnail
static const uint8_t Bpp = BPP;
private:
VLC::Instance m_instance;
std::mutex m_mutex;
std::condition_variable m_cond;
std::unique_ptr<IImageCompressor> m_compressor;
// Per thumbnail variables
#ifdef HAVE_EVAS
std::unique_ptr<Evas, void(*)(Evas*)> m_canvas;
std::unique_ptr<uint8_t[]> m_cropBuffer;
#endif
std::unique_ptr<uint8_t[]> m_buff;
std::atomic_bool m_thumbnailRequired;
uint32_t m_width;
......
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "EvasCompressor.h"
#include <Evas_Engine_Buffer.h>
#include <cstring>
namespace medialibrary
{
EvasCompressor::EvasCompressor()
: m_canvas( nullptr, &evas_free )
{
static int fakeBuffer;
#ifndef TIZEN
evas_init();
#endif
auto method = evas_render_method_lookup("buffer");
m_canvas.reset( evas_new() );
if ( m_canvas == nullptr )
throw std::runtime_error( "Failed to allocate canvas" );
evas_output_method_set( m_canvas.get(), method );
evas_output_size_set(m_canvas.get(), 1, 1 );
evas_output_viewport_set( m_canvas.get(), 0, 0, 1, 1 );
auto einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get( m_canvas.get() );
einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
einfo->info.dest_buffer = &fakeBuffer;
einfo->info.dest_buffer_row_bytes = 4;
einfo->info.use_color_key = 0;
einfo->info.alpha_threshold = 0;
einfo->info.func.new_update_region = NULL;
einfo->info.func.free_update_region = NULL;
evas_engine_info_set( m_canvas.get(), (Evas_Engine_Info *)einfo );
m_cropBuffer.reset( new uint8_t[ DesiredWidth * DesiredHeight * Bpp ] );
}
EvasCompressor::~EvasCompressor()
{
#if !defined(TIZEN)
evas_shutdown();
#endif
}
const char* EvasCompressor::extension() const
{
return "png";
}
const char* EvasCompressor::fourCC() const
{
return "RV32";
}
uint32_t EvasCompressor::bpp() const
{
return 4;
}
bool EvasCompressor::compress( const uint8_t* buffer, const std::string& output,
uint32_t inputWidth, uint32_t inputHeight,
uint32_t outputWidth, uint32_t outputHeight,
uint32_t hOffset, uint32_t vOffset )
{
const auto stride = inputWidth * 4u;
auto evas_obj = std::unique_ptr<Evas_Object, void(*)(Evas_Object*)>( evas_object_image_add( m_canvas.get() ), evas_object_del );
if ( evas_obj == nullptr )
return false;
auto p_buff = buffer;
if ( outputWidth != inputWidth )
{
p_buff += vOffset * stride;
for ( auto y = 0u; y < DesiredHeight; ++y )
{
memcpy( m_cropBuffer.get() + y * outputWidth * 4, p_buff + (hOffset * 4),
outputWidth * 4 );
p_buff += stride;
}
vOffset = 0;
p_buff = m_cropBuffer.get();
}
evas_object_image_colorspace_set( evas_obj.get(), EVAS_COLORSPACE_ARGB8888 );
evas_object_image_size_set( evas_obj.get(), outputWidth, outputHeight );
evas_object_image_data_set( evas_obj.get(), p_buff + vOffset * stride );
evas_object_image_save( evas_obj.get(), output.c_str(), NULL, "quality=100 compress=9");
return true;
}
}
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
#include "IImageCompressor.h"
#include <Evas.h>
#include <memory>
namespace medialibrary
{
class EvasCompressor : public IImageCompressor
{
public:
EvasCompressor();
virtual ~EvasCompressor();
virtual const char* extension() const override;
virtual const char* fourCC() const override;
virtual uint32_t bpp() const override;
virtual bool compress( const uint8_t* buffer, const std::string& output,
uint32_t inputWidth, uint32_t inputHeight,
uint32_t outputWidth, uint32_t outputHeight,
uint32_t hOffset, uint32_t vOffset ) override;
private:
std::unique_ptr<Evas, void(*)(Evas*)> m_canvas;
std::unique_ptr<uint8_t[]> m_cropBuffer;
};
}
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
#include <string>
namespace medialibrary
{
class IImageCompressor
{
public:
virtual ~IImageCompressor() = default;
/**
* @return
*/
virtual const char* extension() const = 0;
/**
* @return Returns the desired input fourcc for this compressor
*/
virtual const char* fourCC() const = 0;
virtual uint32_t bpp() const = 0;
virtual bool compress( const uint8_t* buffer, const std::string& output,
uint32_t inputWidth, uint32_t inputHeight,
uint32_t outputWidth, uint32_t outputHeight,
uint32_t hOffset, uint32_t vOffset ) = 0;
};
}
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "JpegCompressor.h"
#include "logging/Logger.h"
#include <jpeglib.h>
#if ( ( !defined(JPEG_LIB_VERSION_MAJOR) && !defined(JPEG_LIB_VERSION_MINOR) ) || \
( JPEG_LIB_VERSION_MAJOR <= 8 && JPEG_LIB_VERSION_MINOR < 4 ) ) && \
( !defined( JPEG_LIB_VERSION ) || JPEG_LIB_VERSION < 62 )
//FIXME: I don't think we can expect this to work without VLC outputing BGR...
#define JPEG_COLORSPACE JCS_EXT_BGR
#else
#define JPEG_COLORSPACE JCS_RGB
#endif
#include <memory>
#include <setjmp.h>
namespace medialibrary
{
const char* JpegCompressor::extension() const
{
return "jpg";
}
const char* JpegCompressor::fourCC() const
{
return "RV24";
}
uint32_t JpegCompressor::bpp() const
{
return 3;
}
struct jpegError : public jpeg_error_mgr
{
jmp_buf buff;
char message[JMSG_LENGTH_MAX];
static void jpegErrorHandler( j_common_ptr common )
{
auto error = reinterpret_cast<jpegError*>( common->err );
(*error->format_message)( common, error->message );
longjmp( error->buff, 1 );
}
};
bool JpegCompressor::compress( const uint8_t* buffer, const std::string& outputFile,
uint32_t inputWidth, uint32_t,
uint32_t outputWidth, uint32_t outputHeight,
uint32_t hOffset, uint32_t vOffset )
{
const auto stride = inputWidth * 3;
//FIXME: Abstract this away, though libjpeg requires a FILE*...
auto fOut = std::unique_ptr<FILE, int(*)(FILE*)>( fopen( outputFile.c_str(), "wb" ), &fclose );
if ( fOut == nullptr )
{
LOG_ERROR( "Failed to open thumbnail file ", outputFile );
return false;
}
jpeg_compress_struct compInfo;
JSAMPROW row_pointer[1];
//libjpeg's default error handling is to call exit(), which would
//be slightly problematic...
jpegError err;
compInfo.err = jpeg_std_error(&err);
err.error_exit = jpegError::jpegErrorHandler;
if ( setjmp( err.buff ) )
{
LOG_ERROR("JPEG failure: ", err.message);
jpeg_destroy_compress(&compInfo);
return false;
}
jpeg_create_compress(&compInfo);
jpeg_stdio_dest(&compInfo, fOut.get());
compInfo.image_width = outputWidth;
compInfo.image_height = outputHeight;
compInfo.input_components = 3;
compInfo.in_color_space = JPEG_COLORSPACE;
jpeg_set_defaults( &compInfo );
jpeg_set_quality( &compInfo, 85, TRUE );
jpeg_start_compress( &compInfo, TRUE );
while ( compInfo.next_scanline < outputHeight )
{
row_pointer[0] = const_cast<uint8_t*>( &buffer[(compInfo.next_scanline + vOffset ) * stride + hOffset] );
jpeg_write_scanlines(&compInfo, row_pointer, 1);
}
jpeg_finish_compress(&compInfo);
jpeg_destroy_compress(&compInfo);
return true;
}
}
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
#include "IImageCompressor.h"
namespace medialibrary
{
class JpegCompressor : public IImageCompressor
{
public:
virtual const char* extension() const override;
virtual const char* fourCC() const override;
virtual uint32_t bpp() const override;
virtual bool compress(const uint8_t* buffer, const std::string& output,
uint32_t inputWidth, uint32_t inputHeight,