Skip to content
Open
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
154 changes: 124 additions & 30 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 < m_nImages; ++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,13 @@ class CImgDiffBuffer
return;
m_wipeMode = wipeMode;
RefreshImages();
for (int i = 0; i < m_nImages; ++i)
{
if (m_imgDiff[i].getFipImage()->isTransparent())
m_imgDiffIsTransparent[i] = true;
else
m_imgDiffIsTransparent[i] = false;
}
}

int GetWipePosition() const
Expand All @@ -780,16 +805,45 @@ 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);
}
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();
for (int i = 0; i < m_nImages; ++i)
{
if (m_imgDiff[i].getFipImage()->isTransparent())
m_imgDiffIsTransparent[i] = true;
else
m_imgDiffIsTransparent[i] = false;
}
if (m_wipeMode != WIPE_NONE)
WipeEffect();
}

bool GetShowDifferences() const
Expand Down Expand Up @@ -1137,10 +1191,6 @@ class CImgDiffBuffer
(this->*func)(1, 2);
}
}
if (m_wipeMode != WIPE_NONE)
{
WipeEffect();
}
if (m_showDifferences)
{
bool showDiff = true;
Expand All @@ -1160,6 +1210,7 @@ class CImgDiffBuffer
MarkDiff(i, m_diff);
}
}
m_wipePosition_old = INT_MAX;
}

bool OpenImages(int nImages, const wchar_t * const filename[3])
Expand Down Expand Up @@ -1898,49 +1949,90 @@ 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;
auto tmp = new unsigned char[lineBytes];
if (m_wipePosition <= m_wipePosition_old)
{
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, scanline, lineBytes);
memcpy(scanline, scanline2, lineBytes);
memcpy(scanline2, tmp, 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, scanline, lineBytes);
memcpy(scanline, scanline2, lineBytes);
memcpy(scanline2, tmp, 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 +2369,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 +2391,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