From 8414af176d732dfb8a2f93809f4361295bbfbdcb Mon Sep 17 00:00:00 2001 From: Alex Kent Hajnal Date: Fri, 17 May 2024 18:16:23 -0400 Subject: Adds WebP read support to kimgio Signed-off-by: Alex Kent Hajnal (cherry picked from commit 347a546d9dfb3210bcf907c3c622d6843d2ae9ce) --- CMakeLists.txt | 27 +++++++++ kimgio/CMakeLists.txt | 13 +++++ kimgio/webp.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ kimgio/webp.h | 17 ++++++ kimgio/webp.kimgio | 85 +++++++++++++++++++++++++++++ 5 files changed, 290 insertions(+) create mode 100644 kimgio/webp.cpp create mode 100644 kimgio/webp.h create mode 100644 kimgio/webp.kimgio diff --git a/CMakeLists.txt b/CMakeLists.txt index 631e7a5a7..d03faf8aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ option( WITH_IMAGETOPS_BINARY "Enable installation of imagetops binary" ${WITH_A option( WITH_LUA "Enable LUA support" ${WITH_ALL_OPTIONS} ) option( WITH_TIFF "Enable tiff support" ${WITH_ALL_OPTIONS} ) option( WITH_JASPER "Enable jasper (jpeg2k) support" ${WITH_ALL_OPTIONS} ) +option( WITH_WEBP "Enable WebP support" ${WITH_ALL_OPTIONS} ) option( WITH_OPENEXR "Enable openexr support" ${WITH_ALL_OPTIONS} ) option( WITH_UTEMPTER "Use utempter for utmp management" ${WITH_ALL_OPTIONS} ) option( WITH_AVAHI "Enable AVAHI support" ${WITH_ALL_OPTIONS} ) @@ -891,6 +892,32 @@ if( WITH_JASPER ) endif( WITH_JASPER ) +##### check for webp ############################ + +if( WITH_WEBP ) + pkg_search_module( WEBP libwebp ) + if( WEBP_FOUND ) + set( HAVE_WEBP 1 ) + else ( NOT WEBP_FOUND ) + check_include_file( "webp/decode.h" HAVE_WEBP_DECODE_H) + if ( HAVE_WEBP_DECODE_H ) + check_library_exists( webp WebPGetInfo "" HAVE_WEBP__WEBPGETINFO ) + check_library_exists( webp WebPDecodeARGBInto "" HAVE_WEBP__WEBPDECODEARGBINTO ) + check_library_exists( webp WebPDecodeBGRAInto "" HAVE_WEBP__WEBPDECODEBGRAINTO ) + if( HAVE_WEBP__WEBPGETINFO AND HAVE_WEBP__WEBPDECODEARGBINTO AND HAVE_WEBP__WEBPDECODEBGRAINTO ) + set( HAVE_WEBP 1 ) + endif( ) + endif( HAVE_WEBP_DECODE_H ) + endif( WEBP_FOUND ) + if ( HAVE_WEBP ) + set( WEBP_LIBRARIES webp ) + message( STATUS "WebP support enabled" ) + else ( NOT HAVE_WEBP ) + tde_message_fatal( "WebP support requested, but not found on your system" ) + endif( HAVE_WEBP) +endif( WITH_WEBP ) + + ##### check for openexr ######################### if( WITH_OPENEXR ) diff --git a/kimgio/CMakeLists.txt b/kimgio/CMakeLists.txt index be10cf809..325f136f1 100644 --- a/kimgio/CMakeLists.txt +++ b/kimgio/CMakeLists.txt @@ -167,6 +167,19 @@ tde_add_kpart( ${target} ) +##### kimg_webp ################################# + +if( HAVE_WEBP ) + set( target kimg_webp ) + tde_add_kpart( ${target} + SOURCES webp.cpp + LINK tdecore-shared ${WEBP_LIBRARIES} + DESTINATION ${PLUGIN_INSTALL_DIR} + ) + install( FILES webp.kimgio DESTINATION ${SERVICES_INSTALL_DIR} ) +endif( HAVE_WEBP ) + + ##### other data ################################ install( FILES diff --git a/kimgio/webp.cpp b/kimgio/webp.cpp new file mode 100644 index 000000000..ea50ee3b6 --- /dev/null +++ b/kimgio/webp.cpp @@ -0,0 +1,148 @@ +// WebP read support +// © 2024 Alexander Hajnal +// Based loosely on jp2.cpp +// +// If implementing write support it's suggested to use lossless mode with exact +// mode enabled when the quality setting is 100 and for other qualities to use +// lossy mode with the default settings. +// +// This library is distributed under the conditions of the GNU LGPL. +#include "config.h" + +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +TDE_EXPORT void kimgio_webp_read( TQImageIO* io ) +{ + int width, height; + FILE* in; + + // === Read the source file === + // Based on code in jp2.cpp + + // for QIODevice's other than TQFile, a temp. file is used. + KTempFile* tempf = 0; + + TQFile* qf = 0; + if( ( qf = dynamic_cast( io->ioDevice() ) ) ) { + // great, it's a TQFile. Let's just take the filename. + in = fopen( TQFile::encodeName( qf->name() ), "rb" ); + } else { + // not a TQFile. Copy the whole data to a temp. file. + tempf = new KTempFile(); + if( tempf->status() != 0 ) { + delete tempf; + return; + } // if + tempf->setAutoDelete( true ); + TQFile* out = tempf->file(); + // 4096 (=4k) is a common page size. + TQByteArray b( 4096 ); + TQ_LONG size; + // 0 or -1 is EOF / error + while( ( size = io->ioDevice()->readBlock( b.data(), 4096 ) ) > 0 ) { + // in case of a write error, still give the decoder a try + if( ( out->writeBlock( b.data(), size ) ) == -1 ) break; + } // while + // flush everything out to disk + out->flush(); + + in = fopen( TQFile::encodeName( tempf->name() ), "rb" ); + } // else + if( ! in ) { + delete tempf; + return; + } // if + + // File is now open + + // === Load compressed data === + + // Find file's size + fseek(in, 0L, SEEK_END); // Seek to end of file + long size = ftell(in); // Get position (i.e. the file size) + fseek(in, 0L, SEEK_SET); // Seek back to start of file + + // Sanity check + if ( size > SIZE_MAX ) { + // File size is larger than a size_t can hold + fclose( in ); + delete tempf; + return; + } + + // Allocate a buffer for the compressed data + uint8_t* compressed_image = (uint8_t*)malloc(size); + if( ! compressed_image ) { + // malloc failed + fclose( in ); + delete tempf; + return; + } // if + + // Read compressed image into buffer + size_t bytes_read = fread( compressed_image, sizeof(uint8_t), size, in ); + + // Close the compressed image file + fclose( in ); + delete tempf; + + if ( bytes_read < size ) { + // Read failed + free( compressed_image ); + return; + } + + // === Decompress image === + + // Get image dimensions + if ( ! WebPGetInfo( compressed_image, size, &width, &height ) ) { + // Error + free( compressed_image ); + return; + } + + // Create an appropriately sized image + TQImage image; + if( ! image.create( width, height, 32 ) ) { + // Error + free( compressed_image ); + return; + } + + // Enable alpha channel + image.setAlphaBuffer(true); + + // Get the image buffer + uint32_t* data = (uint32_t*)image.bits(); + + // Decompress the image +#ifdef WORDS_BIGENDIAN + if ( ! WebPDecodeARGBInto( compressed_image, size, (uint8_t*)data, width*height*4, width*4) ) { +#else + if ( ! WebPDecodeBGRAInto( compressed_image, size, (uint8_t*)data, width*height*4, width*4) ) { +#endif + // Error + free( compressed_image ); + return; + } + + // Free the compressed image buffer + free( compressed_image ); + + // Finalize load + io->setImage( image ); + io->setStatus( 0 ); +} // kimgio_webp_read + +#ifdef __cplusplus +} +#endif diff --git a/kimgio/webp.h b/kimgio/webp.h new file mode 100644 index 000000000..6fc576c98 --- /dev/null +++ b/kimgio/webp.h @@ -0,0 +1,17 @@ +// WebP read support +// © 2024 Alexander Hajnal +// Based on jp2.h +// +// This library is distributed under the conditions of the GNU LGPL. +#ifndef KIMG_WEBP_H +#define KIMG_WEBP_H + +class TQImageIO; + +extern "C" { + void kimgio_webp_read( TQImageIO* io ); +// void kimgio_webp_write( TQImageIO* io ); // Not currently supported +} // extern "C" + +#endif + diff --git a/kimgio/webp.kimgio b/kimgio/webp.kimgio new file mode 100644 index 000000000..90bba6248 --- /dev/null +++ b/kimgio/webp.kimgio @@ -0,0 +1,85 @@ +[Image Format] +Type=webp +Header=^RIFF[\x00-\xFF]{4}WEBP +Name=WebP Image +Name[af]=WebP Beeld +Name[ar]=صورة من نوع WebP +Name[az]=WebP Rəsmi +Name[be]=Малюнак WebP +Name[bg]=WebP изображение +Name[bn]=WebP চিত্র +Name[br]=Skeudenn WebP +Name[bs]=WebP slika +Name[ca]=Imatge WebP +Name[cs]=Obrázek ve formátu WebP +Name[csb]=Òbrôzk WebP +Name[cy]=Delwedd WebP +Name[da]=WebP-billede +Name[de]=WebP-Bild +Name[el]=Εικόνα WebP +Name[eo]=WebP bildo +Name[es]=Imagen WebP +Name[et]=WebP pildifail +Name[eu]=WebP irudia +Name[fa]=تصویر WebP +Name[fi]=WebP -kuva +Name[fr]=Image WebP +Name[fy]=WebP ôfbylding +Name[ga]=Íomhá WebP +Name[gl]=Imaxe WebP +Name[he]=תמונת WebP +Name[hi]=WebP छवि +Name[hr]=WebP slika +Name[hu]=WebP-kép +Name[id]=Gambar WebP +Name[is]=WebP mynd +Name[it]=Immagine WebP +Name[ja]=WebP 画像 +Name[ka]=WebP ნახატი +Name[kk]=WebP кескіні +Name[km]=រូបភាព WebP +Name[ko]=WebP 그림 +Name[lb]=WebP-Bild +Name[lt]=WebP paveiksliukas +Name[lv]=WebP attēls +Name[mk]=WebP слика +Name[mn]=WebP Зураг +Name[ms]=Imej WebP +Name[nb]=WebP bilde +Name[nds]=WebP-Bild +Name[ne]=WebP छवि +Name[nl]=WebP-afbeelding +Name[nn]=WebP-bilete +Name[pa]=WebP ਚਿੱਤਰ +Name[pl]=Obrazek WebP +Name[pt]=Imagem WebP +Name[pt_BR]=Imagem WebP +Name[ro]=Imagine WebP +Name[ru]=Рисунок WebP +Name[rw]=WebP Ishusho +Name[se]=WebP-govva +Name[sk]=WebP obrázok +Name[sl]=Slika WebP +Name[sq]=Imazh WebP +Name[sr]=WebP слика +Name[sr@Latn]=WebP slika +Name[sv]=WebP-bild +Name[ta]=WebP பிம்பம் +Name[te]=WebP ప్రతిబింబం +Name[tg]=Тасвири WebP +Name[th]=แฟ้มภาพ WebP +Name[tr]=WebP Resim Dosyası +Name[tt]=WebP Süräte +Name[uk]=Зображення WebP +Name[uz]=WebP-rasm +Name[uz@cyrillic]=WebP-расм +Name[vi]=Ảnh WebP +Name[wa]=Imådje WebP +Name[zh_CN]=WebP 图像 +Name[zh_HK]=WebP 圖檔 +Name[zh_TW]=WebP 影像 +Read=true +Write=false +Suffices=webp,WEBP +Mimetype=image/webp +Library=kimg_webp.la -- cgit v1.2.1