Files
s7/Resources/StampWidget/StampWorker.cpp
Saleem Edah-Tally a2045aa1f6 Add a 'Stamp' widget.
Place one or multiple stamps on scanned pages in defined locations.

A stamp is understood here as
 - a transparent text in a transparent frame with no borders
 - an opaque text on an opaque background with no borders.

Stamp parameters:
 - text
 - font
 - foreground colour
 - background colour
 - angle of rotation
 - transparency.

Locations:
 - centre
 - cardinal directions
 - inter-cardinal directions.
2025-07-09 21:12:02 +02:00

122 lines
3.6 KiB
C++

// /*
// * File: StampWorker.cpp
// * Author: Saleem Edah-Tally - nmset@yandex.com
// * License : CeCILL-C
// * Copyright Saleem Edah-Tally - © 2025
// *
// * Created on 02 07 2025, 21:23
// */
#include "StampWorker.h"
#include <math.h> // M_PI
wxImage StampWorker::CreateStamp(StampDescriptor * descriptor, int scanResolution)
{
/*
* Rescale the font point size of the stamp according to the scan resolution.
* Exclude rescaling on v4l that does not have a resolution parameter.
*/
wxFont dcFont(descriptor->font);
double scale = (scanResolution > 0)
? (double) scanResolution / 72.0
:1.0;
wxCoord extentWidth, extentHeight, textLineHeight;
{
wxMemoryDC dc;
if (scale != 1.0)
dcFont.SetFractionalPointSize(descriptor->font.GetFractionalPointSize() * scale);
dc.SetFont(dcFont); // Mandatory despite set below.
dc.GetMultiLineTextExtent(descriptor->text, &extentWidth, &extentHeight, &textLineHeight, &dcFont);
}
wxBitmap bmp;
// bmp.UseAlpha(true); // Not mandatory.
bmp.Create(extentWidth, extentHeight); // Memo: See CreateWithDIPSize
wxImage img0, img;
wxMemoryDC dc(bmp);
dc.SetFont(dcFont);
if (descriptor->transparent)
{
// +++, Use the red channel only: used by ConvertColourToAlpha().
// The chosen value is inversely proportional to the transparency of the text itself.
dc.SetTextForeground(wxColour(128, 0, 0)); // A good mean is reasonable.
dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
}
else
{
dc.SetTextForeground(descriptor->foregroundColour);
dc.SetTextBackground(descriptor->backgroundColour);
dc.SetBackgroundMode(wxBRUSHSTYLE_SOLID);
}
dc.DrawText(descriptor->text, wxPoint(0, 0));
img0 = bmp.ConvertToImage();
if (!descriptor->transparent)
img0.InitAlpha(); // So that there is no dark surrounding if it is rotated.
img = img0.Rotate((M_PI / 180.0) * descriptor->rotationAngle, wxPoint(0, 0));
if (descriptor->transparent)
{
img.ConvertColourToAlpha(descriptor->foregroundColour.GetRed(),
descriptor->foregroundColour.GetGreen(),
descriptor->foregroundColour.GetBlue()); // The target colour is passed in.
img.ChangeSaturation(-0.7); // Slightly better looking.
}
return img;
}
void StampWorker::StampBackground(wxImage& background,
const wxImage& stamp, int location)
{
// Simply pasting the stamp on the background, i.e., the scanned page.
wxPoint bgCentre(background.GetWidth() / 2, background.GetHeight() / 2);
wxPoint stampCentre(stamp.GetWidth() / 2, stamp.GetHeight() / 2);
int x = 0, y = 0;
switch (location)
{
case NORTH:
x = bgCentre.x - stampCentre.x;
y = 0;
break;
case SOUTH:
x = bgCentre.x - stampCentre.x;
y = background.GetHeight() - stamp.GetHeight();
break;
case EAST:
x = background.GetWidth() - stamp.GetWidth();
y = bgCentre.y - stampCentre.y;
break;
case WEST:
x = 0;
y = bgCentre.y - stampCentre.y;
break;
case NORTH_EAST:
x = background.GetWidth() - stamp.GetWidth();
y = 0;
break;
case NORTH_WEST:
x = 0;
y = 0;
break;
case SOUTH_EAST:
x = background.GetWidth() - stamp.GetWidth();
y = background.GetHeight() - stamp.GetHeight();
break;
case SOUTH_WEST:
x = 0;
y = background.GetHeight() - stamp.GetHeight();
break;
default: // CENTRE
x = bgCentre.x - stampCentre.x;
y = bgCentre.y - stampCentre.y;
break;
}
wxPoint stampLocation(x, y);
background.Paste(stamp, stampLocation.x, stampLocation.y, wxIMAGE_ALPHA_BLEND_COMPOSE);
}