Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 124 additions & 31 deletions src/WinIMergeLib/ImgDiffBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ class CImgDiffBuffer
, m_overlayAlpha(0.3)
, m_wipeMode(WIPE_NONE)
, m_wipePosition(0)
, m_wipePosition_old(INT_MAX)
, m_diffBlockSize(8)
, m_selDiffColor(Image::Rgb(0xff, 0x40, 0x40))
, m_selDiffDeletedColor(Image::Rgb(0xf0, 0xc0, 0xc0))
Expand All @@ -522,6 +523,10 @@ class CImgDiffBuffer
{
for (int i = 0; i < 3; ++i)
m_currentPage[i] = 0;
for (int i = 0; i < 3; ++i)
{
m_imgDiffIsTransparent[i] = false;
}
}

virtual ~CImgDiffBuffer()
Expand All @@ -541,6 +546,19 @@ class CImgDiffBuffer
return m_nImages;
}

bool IsAnyPaneTransparent() const
{
for (int i = 0; i < m_nImages; ++i)
if (m_imgDiffIsTransparent[i])
return true;
return false;
}

bool IsPaneTransparent(int pane) const
{
return (pane >= 0 && pane < m_nImages) ? m_imgDiffIsTransparent[pane] : false;
}

Image::Color GetPixelColor(int pane, int x, int y) const
{
return m_imgPreprocessed[pane].pixel(x - m_offset[pane].x, y - m_offset[pane].y);
Expand Down Expand Up @@ -768,6 +786,7 @@ class CImgDiffBuffer
return;
m_wipeMode = wipeMode;
RefreshImages();
UpdateDiffTransparencyCache();
}

int GetWipePosition() const
Expand All @@ -780,16 +799,39 @@ class CImgDiffBuffer
if (m_wipePosition == pos)
return;
m_wipePosition = pos;
RefreshImages();
bool anyTransparent = IsAnyPaneTransparent();
for (int i = 0; i < m_nImages; ++i)
{
if (m_imgDiffIsTransparent[i])
{
// Dummy operation with less performance to retrigger redrawing
// setPixelColor leads to _bHasChanged = TRUE which will enable redrawing
RGBQUAD color;
m_imgDiff[i].getFipImage()->getPixelColor(0, 0, &color);
m_imgDiff[i].getFipImage()->setPixelColor(0, 0, &color);
Comment thread
Edi61 marked this conversation as resolved.
}
else if (anyTransparent)
{
// In mixed transparency scenarios (at least one transparent pane),
// non-transparent images must also be marked as modified so FreeImage
// rebuilds their internal DIB cache.
m_imgDiff[i].getFipImage()->setModified(true);
}
}
WipeEffect();
}


void SetWipeModePosition(WIPE_MODE wipeMode, int pos)
{
if (m_wipeMode == wipeMode && m_wipePosition == pos)
return;
m_wipeMode = wipeMode;
m_wipePosition = pos;
RefreshImages();
UpdateDiffTransparencyCache();
if (m_wipeMode != WIPE_NONE)
WipeEffect();
}

bool GetShowDifferences() const
Expand Down Expand Up @@ -1137,10 +1179,6 @@ class CImgDiffBuffer
(this->*func)(1, 2);
}
}
if (m_wipeMode != WIPE_NONE)
{
WipeEffect();
}
if (m_showDifferences)
{
bool showDiff = true;
Expand All @@ -1160,6 +1198,20 @@ class CImgDiffBuffer
MarkDiff(i, m_diff);
}
}
m_wipePosition_old = INT_MAX;
Comment thread
Edi61 marked this conversation as resolved.
if (m_wipeMode != WIPE_NONE)
{
WipeEffect();
}
UpdateDiffTransparencyCache();
}

void UpdateDiffTransparencyCache()
{
for (int i = 0; i < m_nImages; ++i)
{
m_imgDiffIsTransparent[i] = m_imgDiff[i].getFipImage()->isTransparent() ? true : false;
}
}

bool OpenImages(int nImages, const wchar_t * const filename[3])
Expand Down Expand Up @@ -1898,49 +1950,88 @@ class CImgDiffBuffer
const unsigned w = m_imgDiff[0].width();
const unsigned h = m_imgDiff[0].height();

if (m_wipePosition <= 0)
m_wipePosition = 0;

if (m_wipeMode == WIPE_VERTICAL)
{
auto tmp = new unsigned char[w * 4];
for (unsigned y = m_wipePosition; y < h; ++y)
if (m_wipePosition >= h)
m_wipePosition = h;
if (m_wipePosition_old == INT_MAX)
m_wipePosition_old = h;
const size_t lineBytes = w * 4;
std::vector<unsigned char> tmp(lineBytes);
if (m_wipePosition <= m_wipePosition_old)
Comment thread
Edi61 marked this conversation as resolved.
{
for (int pane = 0; pane < m_nImages - 1; ++pane)
for (unsigned y = m_wipePosition; y < m_wipePosition_old; ++y)
{
for (int pane = 0; pane < m_nImages - 1; ++pane)
{
unsigned char* scanline = m_imgDiff[pane].scanLine(y);
unsigned char* scanline2 = m_imgDiff[pane + 1].scanLine(y);
memcpy(tmp.data(), scanline, lineBytes);
memcpy(scanline, scanline2, lineBytes);
memcpy(scanline2, tmp.data(), lineBytes);
}
}
}
else
{
for (unsigned y = m_wipePosition_old; y < m_wipePosition; ++y)
{
unsigned char *scanline = m_imgDiff[pane].scanLine(y);
unsigned char *scanline2 = m_imgDiff[pane + 1].scanLine(y);
memcpy(tmp, scanline, w * 4);
memcpy(scanline, scanline2, w * 4);
memcpy(scanline2, tmp, w * 4);
for (int pane = m_nImages - 1; pane > 0; --pane)
{
unsigned char* scanline = m_imgDiff[pane].scanLine(y);
unsigned char* scanline2 = m_imgDiff[pane - 1].scanLine(y);
memcpy(tmp.data(), scanline, lineBytes);
memcpy(scanline, scanline2, lineBytes);
memcpy(scanline2, tmp.data(), lineBytes);
}
}
}
delete[] tmp;
}
else if (m_wipeMode = WIPE_HORIZONTAL)
else if (m_wipeMode == WIPE_HORIZONTAL)
{
if (m_wipePosition >= w)
m_wipePosition = w;
if (m_wipePosition_old == INT_MAX)
m_wipePosition_old = w;

const size_t pixelBytes = 4;
unsigned char tmp[4];

for (unsigned y = 0; y < h; ++y)
{
for (int pane = 0; pane < m_nImages - 1; ++pane)
{
unsigned char *scanline = m_imgDiff[pane].scanLine(y);
unsigned char *scanline2 = m_imgDiff[pane + 1].scanLine(y);
for (unsigned x = m_wipePosition; x < w; ++x)
unsigned char* scanline;
unsigned char* scanline2;
if (m_wipePosition <= m_wipePosition_old)
{
unsigned char tmp[4];
tmp[0] = scanline[x * 4 + 0];
tmp[1] = scanline[x * 4 + 1];
tmp[2] = scanline[x * 4 + 2];
tmp[3] = scanline[x * 4 + 3];
scanline[x * 4 + 0] = scanline2[x * 4 + 0];
scanline[x * 4 + 1] = scanline2[x * 4 + 1];
scanline[x * 4 + 2] = scanline2[x * 4 + 2];
scanline[x * 4 + 3] = scanline2[x * 4 + 3];
scanline2[x * 4 + 0] = tmp[0];
scanline2[x * 4 + 1] = tmp[1];
scanline2[x * 4 + 2] = tmp[2];
scanline2[x * 4 + 3] = tmp[3];
scanline = m_imgDiff[pane].scanLine(y);
scanline2 = m_imgDiff[pane + 1].scanLine(y);
for (unsigned x = m_wipePosition; x < m_wipePosition_old; ++x)
{
memcpy(tmp, scanline + x * pixelBytes, pixelBytes);
memcpy(scanline + x * pixelBytes, scanline2 + x * pixelBytes, pixelBytes);
memcpy(scanline2 + x * pixelBytes, tmp, pixelBytes);
}
}
else
{
scanline = m_imgDiff[m_nImages - 2 - pane].scanLine(y);
scanline2 = m_imgDiff[m_nImages - 1 - pane].scanLine(y);
for (unsigned x = m_wipePosition_old; x < m_wipePosition; ++x)
{
memcpy(tmp, scanline + x * pixelBytes, pixelBytes);
memcpy(scanline + x * pixelBytes, scanline2 + x * pixelBytes, pixelBytes);
memcpy(scanline2 + x * pixelBytes, tmp, pixelBytes);
}
}
}
}
}
m_wipePosition_old = m_wipePosition;
}

void CopyPreprocessedImageToDiffImage(int dst)
Expand Down Expand Up @@ -2277,6 +2368,7 @@ class CImgDiffBuffer
double m_overlayAlpha;
WIPE_MODE m_wipeMode;
int m_wipePosition;
int m_wipePosition_old;
unsigned m_diffBlockSize;
Image::Color m_selDiffColor;
Image::Color m_selDiffDeletedColor;
Expand All @@ -2298,4 +2390,5 @@ class CImgDiffBuffer
int m_blinkInterval;
int m_overlayAnimationInterval;
int m_lastErrorCode;
bool m_imgDiffIsTransparent[3]{};
};
24 changes: 22 additions & 2 deletions src/WinIMergeLib/ImgMergeWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,15 +1815,35 @@ class CImgMergeWindow : public IImgMergeWindow
}
else if (m_draggingModeCurrent == DRAGGING_MODE::VERTICAL_WIPE)
{
int oldWipePos = m_buffer.GetWipePosition();
imgWindow.SetRectangleSelection(0, pt.y, m_buffer.GetImageWidth(evt.pane), pt.y);
m_buffer.SetWipePosition(pt.y);
Invalidate();
if (m_buffer.GetWipePosition() != oldWipePos)
{
bool anyTransparent = m_buffer.IsAnyPaneTransparent();
for (int i = 0; i < m_nImages; ++i)
{
if (m_buffer.IsPaneTransparent(i) || (anyTransparent && m_nImages >= 3))
RedrawWindow(m_imgWindow[i].GetHWND(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOERASE);
}
Invalidate();
}
}
else if (m_draggingModeCurrent == DRAGGING_MODE::HORIZONTAL_WIPE)
{
int oldWipePos = m_buffer.GetWipePosition();
imgWindow.SetRectangleSelection(pt.x, 0, pt.x, m_buffer.GetImageHeight(evt.pane));
m_buffer.SetWipePosition(pt.x);
Invalidate();
if (m_buffer.GetWipePosition() != oldWipePos)
{
bool anyTransparent = m_buffer.IsAnyPaneTransparent();
for (int i = 0; i < m_nImages; ++i)
{
if (m_buffer.IsPaneTransparent(i) || (anyTransparent && m_nImages >= 3))
RedrawWindow(m_imgWindow[i].GetHWND(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOERASE);
}
Invalidate();
}
}
else if (m_draggingModeCurrent == DRAGGING_MODE::RECTANGLE_SELECT)
{
Expand Down