Skip to content

Commit

Permalink
Add inverted blur feature #322
Browse files Browse the repository at this point in the history
  • Loading branch information
zenden2k committed Feb 19, 2024
1 parent 40679ad commit 23f49aa
Show file tree
Hide file tree
Showing 21 changed files with 494 additions and 314 deletions.
278 changes: 142 additions & 136 deletions Lang/imageuploader.pot

Large diffs are not rendered by default.

280 changes: 143 additions & 137 deletions Lang/locale/ru/LC_MESSAGES/imageuploader.po

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions Source/Core/Images/Utils.cpp
Expand Up @@ -173,7 +173,7 @@ std::unique_ptr<Gdiplus::Bitmap> IconToBitmap(HICON ico)
return image;
}

void ApplyGaussianBlur(Gdiplus::Bitmap* bm, int x,int y, int w, int h, int radius) {
void ApplyGaussianBlur(Gdiplus::Bitmap* bm, int x,int y, int w, int h, int radius, Gdiplus::Rect exclude) {
using namespace Gdiplus;
Rect rc(x, y, w, h);

Expand Down Expand Up @@ -214,7 +214,16 @@ void ApplyGaussianBlur(Gdiplus::Bitmap* bm, int x,int y, int w, int h, int radiu
bufCur = buf;
sourceCur = source;
for (int i = 0; i < h; i++) {
memcpy(sourceCur, bufCur, myStride);
if (exclude.IsEmptyArea()) {
memcpy(sourceCur, bufCur, myStride);
} else {
for (int j = 0; j < w; j++) {
if (!exclude.Contains(j, i)) {
memcpy(sourceCur + j * 4, bufCur + j * 4, 4);
}
}
}

bufCur += myStride;
sourceCur += stride;
}
Expand All @@ -225,7 +234,7 @@ void ApplyGaussianBlur(Gdiplus::Bitmap* bm, int x,int y, int w, int h, int radiu
}
}

void ApplyPixelateEffect(Gdiplus::Bitmap* bm, int xPos, int yPos, int w, int h, int blockSize) {
void ApplyPixelateEffect(Gdiplus::Bitmap* bm, int xPos, int yPos, int w, int h, int blockSize, Gdiplus::Rect exclude) {
using namespace Gdiplus;
Rect rc(xPos, yPos, w, h);

Expand Down Expand Up @@ -261,7 +270,9 @@ void ApplyPixelateEffect(Gdiplus::Bitmap* bm, int xPos, int yPos, int w, int h,
}
}
uint32_t pixel = (alpha / numPixels << 24) + (red / numPixels << 16) + (green / numPixels << 8) + blue / numPixels;

if (exclude.Contains(x, y)) {
continue;
}
for (int i = x; i < maxX; i++) {
for (int j = y; j < maxY; j++) {
uint32_t* data = (uint32_t*)(source + j * stride + i*4);
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Images/Utils.h
Expand Up @@ -35,8 +35,8 @@ std::unique_ptr<Gdiplus::Bitmap> BitmapFromResource(HINSTANCE hInstance, LPCTSTR
void PrintRichEdit(HWND hwnd, Gdiplus::Graphics* graphics, Gdiplus::Bitmap* background, Gdiplus::Rect layoutArea);
void DrawRoundedRectangle(Gdiplus::Graphics* gr, Gdiplus::Rect r, int d, Gdiplus::Pen* p, Gdiplus::Brush* br);
std::unique_ptr<Gdiplus::Bitmap> IconToBitmap(HICON ico);
void ApplyGaussianBlur(Gdiplus::Bitmap* bm, int x, int y, int w, int h, int radius);
void ApplyPixelateEffect(Gdiplus::Bitmap* bm, int xPos, int yPos, int w, int h, int blockSize);
void ApplyGaussianBlur(Gdiplus::Bitmap* bm, int x, int y, int w, int h, int radius, Gdiplus::Rect exclude = {});
void ApplyPixelateEffect(Gdiplus::Bitmap* bm, int xPos, int yPos, int w, int h, int blockSize, Gdiplus::Rect exclude = {});
std::unique_ptr<Gdiplus::Bitmap> LoadImageFromFileWithoutLocking(const WCHAR* fileName, bool* isAnimated);
Gdiplus::Color StringToColor(const std::string& str);
CComPtr<IStream> CreateMemStream(const BYTE* pInit, UINT cbInit);
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/Settings/WtlGuiSettings.cpp
Expand Up @@ -819,6 +819,9 @@ void WtlGuiSettings::BindToManager() {
imageEditor.nm_bind(ImageEditorSettings, RoundingRadius);
imageEditor.nm_bind(ImageEditorSettings, ArrowType);
imageEditor.nm_bind(ImageEditorSettings, Font);
imageEditor.nm_bind(ImageEditorSettings, FillTextBackground);
imageEditor.nm_bind(ImageEditorSettings, InvertSelection);

imageEditor.nm_bind(ImageEditorSettings, AllowAltTab);
screenshot.nm_bind(ImageEditorSettings, AllowEditingInFullscreen);
//screenshot.nm_bind(ImageEditorSettings, SearchEngine);
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/Settings/WtlGuiSettings.h
Expand Up @@ -33,6 +33,7 @@ struct ImageEditorSettingsStruct {
bool AllowEditingInFullscreen;
SearchByImage::SearchEngine SearchEngine;
bool FillTextBackground = false;
bool InvertSelection = false;
int ArrowType;
};

Expand Down Expand Up @@ -170,4 +171,4 @@ class WtlGuiSettings : public CommonGuiSettings {
TCHAR m_Directory[MAX_PATH];
CFloatingWindow* floatWnd_;
};
#endif
#endif
2 changes: 2 additions & 0 deletions Source/Func/ImageEditorConfigurationProvider.cpp
Expand Up @@ -16,6 +16,7 @@ ImageEditorConfigurationProvider::ImageEditorConfigurationProvider()
searchEngine_ = settings->ImageEditorSettings.SearchEngine;
fillTextBackground_ = settings->ImageEditorSettings.FillTextBackground;
arrowMode_ = settings->ImageEditorSettings.ArrowType;
invertSelection_ = settings->ImageEditorSettings.InvertSelection;
}

void ImageEditorConfigurationProvider::saveConfiguration()
Expand All @@ -32,5 +33,6 @@ void ImageEditorConfigurationProvider::saveConfiguration()
settings->ImageEditorSettings.StepForegroundColor = stepForegroundColor_;
settings->ImageEditorSettings.StepBackgroundColor = stepBackgroundColor_;
settings->ImageEditorSettings.ArrowType = arrowMode_;
settings->ImageEditorSettings.InvertSelection = invertSelection_;
}

53 changes: 52 additions & 1 deletion Source/ImageEditor/Canvas.cpp
Expand Up @@ -568,7 +568,7 @@ AbstractDrawingTool* Canvas::setDrawingToolType(DrawingToolType toolType, bool n
type = ElementType::etArrow;
} else if ( toolType == DrawingToolType::dtRectangle ) {
type = ElementType::etRectangle;
} else if ( toolType == DrawingToolType::dtBlurrringRectangle ) {
} else if ( toolType == DrawingToolType::dtBlurringRectangle ) {
type = ElementType::etBlurringRectangle;
} else if (toolType == DrawingToolType::dtPixelateRectangle) {
type = ElementType::etPixelateRectangle;
Expand Down Expand Up @@ -681,6 +681,10 @@ bool Canvas::addDrawingElementToDoc(DrawingElement* element)
return true;
}

void Canvas::beginDocDrawing() {
beginManipulation();
currentDocument()->beginDrawing();
}

void Canvas::endDocDrawing()
{
Expand All @@ -690,6 +694,18 @@ void Canvas::endDocDrawing()
addUndoHistoryItem(historyItem);
}

void Canvas::beginManipulation() {
manipulationStarted_ = true;
}

void Canvas::endManipulation() {
manipulationStarted_ = false;
}

bool Canvas::manipulationStarted() const {
return manipulationStarted_;
}

int Canvas::deleteSelectedElements()
{
int deletedCount = 0;
Expand Down Expand Up @@ -1290,6 +1306,41 @@ bool Canvas::getFillTextBackground() const {
return fillTextBackground_;
}

void Canvas::setInvertSelection(bool invert) {
invertSelection_ = invert;
int count = 0;
UndoHistoryItem uhi;
uhi.type = UndoHistoryItemType::uitInvertSelectionChanged;

for (auto& el : elementsOnCanvas_) {
if (el->isSelected() && (el->getType() == ElementType::etBlurringRectangle || el->getType() == ElementType::etPixelateRectangle)) {
auto* blurEl = dynamic_cast<BlurringRectangle*>(el);
if (blurEl) {
bool prev = blurEl->getInvertSelection();
if (prev == invert) {
continue;
}
blurEl->setInvertSelection(invert);

UndoHistoryItemElement uhie;
uhie.pos = 0;
uhie.movableElement = el;
uhie.penSize = prev;
uhi.elements.push_back(uhie);
count++;
}
}
}
if (count) {
addUndoHistoryItem(uhi);
updateView();
}
}

bool Canvas::getInvertSelection() const {
return invertSelection_;
}

void Canvas::setArrowMode(Arrow::ArrowMode arrowMode) {
arrowMode_ = arrowMode;
}
Expand Down
15 changes: 13 additions & 2 deletions Source/ImageEditor/Canvas.h
Expand Up @@ -25,7 +25,7 @@ class InputBoxControl;

enum class DrawingToolType {
dtNone, dtPen, dtBrush, dtLine, dtArrow, dtRectangle, dtFilledRectangle, dtText, dtCrop, dtMove, dtSelection,
dtBlur, dtBlurrringRectangle, dtPixelateRectangle, dtColorPicker,dtRoundedRectangle, dtEllipse,
dtBlur, dtBlurringRectangle, dtPixelateRectangle, dtColorPicker,dtRoundedRectangle, dtEllipse,
dtFilledRoundedRectangle, dtFilledEllipse, dtMarker, dtStepNumber
};

Expand All @@ -41,7 +41,7 @@ class Canvas {
enum class UndoHistoryItemType { uitDocumentChanged, uitElementAdded, uitElementRemoved,
uitElementPositionChanged, uitElementForegroundColorChanged, uitElementBackgroundColorChanged,
uitPenSizeChanged, uitFontChanged, uitTextChanged, uitRoundingRadiusChanged, uitFillBackgroundChanged,
uitCropApplied
uitCropApplied, uitInvertSelectionChanged
};
enum { kMaxPenSize = 50, kMaxRoundingRadius = 50, kDefaultStepFontSize = 14 };

Expand Down Expand Up @@ -137,6 +137,7 @@ class Canvas {
void updateView();
void updateView( RECT boundingRect );
bool addDrawingElementToDoc(DrawingElement* element);
void beginDocDrawing();
void endDocDrawing();
int deleteSelectedElements();
float getBlurRadius() const;
Expand All @@ -159,6 +160,9 @@ class Canvas {
void setFillTextBackground(bool fill);
bool getFillTextBackground() const;

void setInvertSelection(bool invert);
bool getInvertSelection() const;

void setArrowMode(Arrow::ArrowMode arrowMode);
Arrow::ArrowMode getArrowMode() const;
Gdiplus::Graphics* getGraphicsDevice() const;
Expand All @@ -174,6 +178,11 @@ class Canvas {

void setDpi(float dpiX, float dpiY);
std::pair<float, float> getDpi() const;

void beginManipulation();
void endManipulation();

bool manipulationStarted() const;
boost::signals2::signal<void(int,int,int,int)> onCropChanged;
boost::signals2::signal<void(int,int,int,int)> onCropFinished;
boost::signals2::signal<void(DrawingToolType)> onDrawingToolChanged;
Expand Down Expand Up @@ -237,6 +246,7 @@ class Canvas {
int nextNumber_; // next number for element StepNumber
int stepFontSize_;
bool fillTextBackground_;
bool invertSelection_;
Arrow::ArrowMode arrowMode_;

Gdiplus::Rect updatedRect_;
Expand All @@ -249,6 +259,7 @@ class Canvas {
bool cropOnExport_;
float dpiX_;
float dpiY_;
bool manipulationStarted_;
};

}
Expand Down
18 changes: 11 additions & 7 deletions Source/ImageEditor/Document.cpp
Expand Up @@ -53,15 +53,15 @@ Document::~Document()
for (auto& i : history_) {
delete[] i.data;
}
delete currentCanvas_;
delete currentPainter_;
}

void Document::init() {
currentCanvas_ = nullptr;
currentPainter_ = nullptr;
drawStarted_ = false;
originalImage_ = nullptr;
if ( currentImage_ ) {
currentCanvas_ = new Gdiplus::Graphics( currentImage_.get() );
currentPainter_ = new Gdiplus::Graphics( currentImage_.get() );
changedSegments_ = AffectedSegments(getWidth(), getHeight());
}
}
Expand All @@ -75,16 +75,16 @@ void Document::beginDrawing(bool cloneImage) {
}

void Document::addDrawingElement(DrawingElement *element) {
currentCanvas_->SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
currentCanvas_->SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBicubic );
currentPainter_->SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
currentPainter_->SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBicubic );
AffectedSegments segments;
element->getAffectedSegments( &segments );
changedSegments_ += segments;
if( !drawStarted_ ) {
saveDocumentState( );
changedSegments_.clear();
}
element->render( currentCanvas_ );
element->render( currentPainter_ );
}

void Document::endDrawing() {
Expand Down Expand Up @@ -280,7 +280,7 @@ bool Document::hasTransparentPixels() const
}

Painter* Document::getGraphicsObject() const {
return currentCanvas_;
return currentPainter_;
}

void Document::applyCrop(int cropX, int cropY, int cropWidth, int cropHeight) {
Expand All @@ -296,4 +296,8 @@ bool Document::isSrcMultiFrame() const {
return isSrcMultiFrame_;
}

bool Document::isInDrawingState() const {
return drawStarted_;
}

}
3 changes: 2 additions & 1 deletion Source/ImageEditor/Document.h
Expand Up @@ -46,10 +46,11 @@ class Document {
bool isNull() const;
bool hasTransparentPixels() const;
bool isSrcMultiFrame() const;
bool isInDrawingState() const;
private:
std::shared_ptr<Gdiplus::Bitmap> currentImage_;
Gdiplus::Bitmap* originalImage_;
Painter* currentCanvas_;
Painter* currentPainter_;
std::vector<HistoryItem> history_;
bool drawStarted_;
AffectedSegments changedSegments_;
Expand Down
4 changes: 2 additions & 2 deletions Source/ImageEditor/DrawingTools/BrushTool.cpp
Expand Up @@ -34,7 +34,7 @@ BrushTool::BrushTool( Canvas* canvas ) : AbstractDrawingTool( canvas ) {
void BrushTool::beginDraw( int x, int y ) {
Gdiplus::Region exclRegion(Gdiplus::Rect(0,0,canvas_->getWidth(), canvas_->getHeigth()));
affectedRegion_.Exclude(&exclRegion);
canvas_->currentDocument()->beginDrawing();
canvas_->beginDocDrawing();
oldPoint_.x = x;
oldPoint_.y = y;
startPoint_.x = x;
Expand Down Expand Up @@ -154,4 +154,4 @@ void BrushTool::drawLine(int x0, int y0, int x1, int y1) {
canvas_->updateView(updatedRect);
}

}
}
2 changes: 1 addition & 1 deletion Source/ImageEditor/DrawingTools/MarkerTool.cpp
Expand Up @@ -46,7 +46,7 @@ MarkerTool::~MarkerTool()
void MarkerTool::beginDraw( int x, int y ) {
Gdiplus::Region exclRegion(Gdiplus::Rect(0,0,canvas_->getWidth(), canvas_->getHeigth()));
affectedRegion_.Exclude(&exclRegion);
canvas_->currentDocument()->beginDrawing();
canvas_->beginDocDrawing();
oldPoint_.x = x;
oldPoint_.y = y;
startPoint_.x = x;
Expand Down
7 changes: 4 additions & 3 deletions Source/ImageEditor/DrawingTools/MoveAndResizeTool.cpp
Expand Up @@ -297,6 +297,7 @@ void MoveAndResizeTool::endDraw( int x, int y ) {
if ( isMoving_ ) {
isMoving_ = false;
}
canvas_->endManipulation();
}

void MoveAndResizeTool::render( Painter* gr ) {
Expand Down Expand Up @@ -348,10 +349,10 @@ void MoveAndResizeTool::createElement() {
currentElement_ = new FilledEllipse(canvas_);
break;
case ElementType::etPixelateRectangle:
currentElement_ = new PixelateRectangle(canvas_, float(canvas_->getPixelateBlockSize()), startPoint_.x, startPoint_.y, endPoint_.x, endPoint_.y);
currentElement_ = new PixelateRectangle(canvas_, float(canvas_->getPixelateBlockSize()), startPoint_.x, startPoint_.y, endPoint_.x, endPoint_.y, canvas_->getInvertSelection());
break;
case ElementType::etBlurringRectangle:
currentElement_ = new BlurringRectangle(canvas_, canvas_->getBlurRadius(), startPoint_.x,startPoint_.y, endPoint_.x, endPoint_.y);
currentElement_ = new BlurringRectangle(canvas_, canvas_->getBlurRadius(), startPoint_.x,startPoint_.y, endPoint_.x, endPoint_.y, false, canvas_->getInvertSelection());
break;
case ElementType::etFilledRectangle:
currentElement_ = new FilledRectangle(canvas_, startPoint_.x,startPoint_.y, endPoint_.x, endPoint_.y);
Expand Down Expand Up @@ -447,4 +448,4 @@ void MoveAndResizeTool::mouseDoubleClick(int x, int y)
}
}

}
}
5 changes: 2 additions & 3 deletions Source/ImageEditor/DrawingTools/PenTool.cpp
Expand Up @@ -37,7 +37,7 @@ PenTool::PenTool( Canvas* canvas ): AbstractDrawingTool( canvas ) {
}

void PenTool::beginDraw( int x, int y ) {
canvas_->currentDocument()->beginDrawing();
canvas_->beginDocDrawing();
oldPoint_.x = x;
oldPoint_.y = y;
}
Expand Down Expand Up @@ -68,10 +68,9 @@ void PenTool::render( Painter* gr ) {

}


CursorType PenTool::getCursor(int x, int y)
{
return CursorType::ctCross;
}

}
}

0 comments on commit 23f49aa

Please sign in to comment.