Implemented scaling images

This commit is contained in:
Klaus Schmidinger 2024-01-18 12:04:57 +01:00
parent 35c8b3d22c
commit b1418b6bcd
4 changed files with 118 additions and 2 deletions

View File

@ -3750,3 +3750,6 @@ Timo Weing
Jose Angel <joseangelpp@gmail.com>
for reporting a bug in default values for DVB-T
Andreas Baierl <post@andreasbaierl.de>
for implementing scaling images

View File

@ -9871,3 +9871,4 @@ Video Disk Recorder Revision History
Ehrnsperger).
- Using a dummy OSD if no OSD provider is available is not considered an error any
more (thanks to Markus Ehrnsperger).
- Implemented scaling images (thanks to Andreas Baierl).

77
osd.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.c 5.1 2024/01/18 11:06:45 kls Exp $
* $Id: osd.c 5.2 2024/01/18 12:04:57 kls Exp $
*/
#include "osd.h"
@ -1139,6 +1139,49 @@ void cImage::Fill(tColor Color)
data[i] = Color;
}
cImage *cImage::Scaled(double FactorX, double FactorY, bool AntiAlias) const
{
int w = max(1, int(round(Width() * FactorX)));
int h = max(1, int(round(Height() * FactorY)));
cImage *i = new cImage(cSize(w, h));
int RatioX = (Width() << 16) / i->Width();
int RatioY = (Height() << 16) / i->Height();
if (!AntiAlias || FactorX <= 1.0 && FactorY <= 1.0) {
// Downscaling - no anti-aliasing:
int SourceY = 0;
for (int y = 0; y < i->Height(); y++) {
int SourceX = 0;
for (int x = 0; x < i->Width(); x++) {
tColor c1 = GetPixel(cPoint(SourceX >> 16, SourceY >> 16));
i->SetPixel(cPoint(x, y), c1);
SourceX += RatioX;
}
SourceY += RatioY;
}
}
else {
// Upscaling - anti-aliasing:
int SourceY = 0;
for (int y = 0; y < i->Height(); y++) {
int SourceX = 0;
int sy = min(SourceY >> 16, Height() - 2);
uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF);
for (int x = 0; x < i->Width(); x++) {
int sx = min(SourceX >> 16, Width() - 2);
uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF);
tColor c1 = AlphaBlend(GetPixel(cPoint(sx, sy)), GetPixel(cPoint(sx + 1, sy)), BlendX);
tColor c2 = AlphaBlend(GetPixel(cPoint(sx, sy + 1)), GetPixel(cPoint(sx + 1, sy + 1)), BlendX);
tColor c3 = AlphaBlend(c1, c2, BlendY);
i->SetPixel(cPoint(x, y), c3);
SourceX += RatioX;
}
SourceY += RatioY;
}
}
return i;
}
// --- cPixmapMemory ---------------------------------------------------------
cPixmapMemory::cPixmapMemory(void)
@ -1259,6 +1302,26 @@ void cPixmapMemory::DrawImage(const cPoint &Point, int ImageHandle)
Unlock();
}
void cPixmapMemory::DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY, bool AntiAlias)
{
Lock();
const cImage *i = &Image;
if (!DoubleEqual(FactorX, 1.0) || !DoubleEqual(FactorY, 1.0))
i = i->Scaled(FactorX, FactorY, AntiAlias);
DrawImage(Point, *i);
if (i != &Image)
delete i;
Unlock();
}
void cPixmapMemory::DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY, bool AntiAlias)
{
Lock();
if (const cImage *Image = cOsdProvider::GetImageData(ImageHandle))
DrawScaledImage(Point, *Image, FactorX, FactorY, AntiAlias);
Unlock();
}
void cPixmapMemory::DrawPixel(const cPoint &Point, tColor Color)
{
Lock();
@ -2118,6 +2181,18 @@ void cOsd::DrawImage(const cPoint &Point, int ImageHandle)
pixmaps[0]->DrawImage(Point, ImageHandle);
}
void cOsd::DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY, bool AntiAlias)
{
if (isTrueColor)
pixmaps[0]->DrawScaledImage(Point, Image, FactorX, FactorY, AntiAlias);
}
void cOsd::DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY, bool AntiAlias)
{
if (isTrueColor)
pixmaps[0]->DrawScaledImage(Point, ImageHandle, FactorX, FactorY, AntiAlias);
}
void cOsd::DrawPixel(int x, int y, tColor Color)
{
if (isTrueColor)

39
osd.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.h 5.1 2021/05/21 12:54:08 kls Exp $
* $Id: osd.h 5.2 2024/01/18 12:04:57 kls Exp $
*/
#ifndef __OSD_H
@ -447,6 +447,11 @@ public:
///< Clears the image data by setting all pixels to be fully transparent.
void Fill(tColor Color);
///< Fills the image data with the given Color.
cImage *Scaled(double FactorX, double FactorY, bool AntiAlias = false) const;
///< Creates a copy of this image, scaled by the given factors.
///< If AntiAlias is true and either of the factors is greater than 1.0,
///< anti-aliasing is applied.
///< The caller must delete the returned image once it is no longer used.
};
#define MAXPIXMAPLAYERS 8
@ -602,6 +607,23 @@ public:
///< the given Point. ImageHandle must be a value that has previously been
///< returned by a call to cOsdProvider::StoreImage(). If ImageHandle
///< has an invalid value, nothing happens.
virtual void DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY, bool AntiAlias = false) {};
///< Draws the given Image into this pixmap at the given Point and scales it.
///< If AntiAlias is true and either of the factors is greater than
///< 1.0, anti-aliasing is applied.
///< This function should be 'pure', just like all the others. However, since it was
///< introduced when this class was already in widespread use, the default was made
///< empty, so that existing code will still compile.
virtual void DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY, bool AntiAlias = false) {};
///< Draws the image referenced by the given ImageHandle into this pixmap at
///< the given Point and scales it. ImageHandle must be a value that has
///< previously been returned by a call to cOsdProvider::StoreImage().
///< If ImageHandle has an invalid value, nothing happens.
///< If AntiAlias is true and either of the factors is greater than
///< 1.0, anti-aliasing is applied.
///< This function should be 'pure', just like all the others. However, since it was
///< introduced when this class was already in widespread use, the default was made
///< empty, so that existing code will still compile.
virtual void DrawPixel(const cPoint &Point, tColor Color) = 0;
///< Sets the pixel at the given Point to the given Color, which is
///< a full 32 bit ARGB value. If the alpha value of Color is not 0xFF
@ -700,6 +722,8 @@ public:
virtual void Fill(tColor Color);
virtual void DrawImage(const cPoint &Point, const cImage &Image);
virtual void DrawImage(const cPoint &Point, int ImageHandle);
virtual void DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY, bool AntiAlias = false);
virtual void DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY, bool AntiAlias = false);
virtual void DrawPixel(const cPoint &Point, tColor Color);
virtual void DrawBlendedPixel(const cPoint &Point, tColor Color, uint8_t AlphaLayer = ALPHA_OPAQUE);
virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false);
@ -857,6 +881,19 @@ public:
///< returned by a call to cOsdProvider::StoreImage(). If ImageHandle
///< has an invalid value, nothing happens.
///< If this is not a true color OSD, this function does nothing.
virtual void DrawScaledImage(const cPoint &Point, const cImage &Image, double FactorX, double FactorY, bool AntiAlias = false);
///< Draws the given Image on this OSD at the given Point and scales it.
///< If AntiAlias is true and either of the factors is greater than
///< 1.0, anti-aliasing is applied.
///< If this is not a true color OSD, this function does nothing.
virtual void DrawScaledImage(const cPoint &Point, int ImageHandle, double FactorX, double FactorY, bool AntiAlias = false);
///< Draws the image referenced by the given ImageHandle on this OSD at
///< the given Point and scales it. ImageHandle must be a value that has
///< previously been returned by a call to cOsdProvider::StoreImage().
///< If ImageHandle has an invalid value, nothing happens.
///< If AntiAlias is true and either of the factors is greater than
///< 1.0, anti-aliasing is applied.
///< If this is not a true color OSD, this function does nothing.
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
///< Checks whether the OSD can display the given set of sub-areas.
///< The return value indicates whether a call to SetAreas() with this