Skip to content

Commit

Permalink
Cherry Picks Part 1
Browse files Browse the repository at this point in the history
* Various cherry picks from upstream. E.g. : PSD images, always on top upon startup
  • Loading branch information
sdneon committed Apr 27, 2024
1 parent a185496 commit 588ec4e
Show file tree
Hide file tree
Showing 48 changed files with 969 additions and 152 deletions.
6 changes: 3 additions & 3 deletions src/JPEGView/AboutDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
static LPCTSTR GetSIMDModeString() {
Helpers::CPUType cpuType = CSettingsProvider::This().AlgorithmImplementation();
if (cpuType == Helpers::CPU_MMX) {
return _T("64 bit MMX");
return _T("64-bit MMX");
} else if (cpuType == Helpers::CPU_SSE) {
return _T("128 bit SSE2");
return _T("128-bit SSE2");
} else if (cpuType == Helpers::CPU_AVX2) {
return _T("256 bit AVX2");
return _T("256-bit AVX2");
}
else {
return _T("Generic CPU");
Expand Down
4 changes: 2 additions & 2 deletions src/JPEGView/BatchCopyDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ int CBatchCopyDlg::CreateItemList() {
int nIndex = 0;
for (iter = fileList.begin( ); iter != fileList.end( ); iter++ ) {
m_lvFiles.InsertItem(nIndex, iter->GetTitle());
SYSTEMTIME systemTime;
SYSTEMTIME systemTime{ 0 };
FileTimeToLocalSystemTime(iter->GetLastModTime(), systemTime);
TCHAR dateBuff[64];
::GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime, NULL, dateBuff, 64);
Expand Down Expand Up @@ -382,7 +382,7 @@ CString CBatchCopyDlg::ReplacePlaceholders(LPCTSTR strPattern, int nIndex, const
CString sExtension(pStartExt + 1);
strNewName.Replace(_T("%e"), sExtension);
}
SYSTEMTIME systemTime;
SYSTEMTIME systemTime{ 0 };
FileTimeToLocalSystemTime(fileDesc.GetLastModTime(), systemTime);
if (strNewName.Find(_T("%h")) != -1) {
CString sHour;
Expand Down
22 changes: 22 additions & 0 deletions src/JPEGView/Config/JPEGView.ini
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ FileNameColor=255 255 255
; Example: DefaultGUIFont="Arial" 9.0 bold
DefaultGUIFont=Default


; -----------------------------------------------
; - WINDOW BEHAVIOR OPTIONS
; -----------------------------------------------

; If set to 'true', window starts in always-on-top mode (window will always be visible on top of other windows)
; The window mode can be changed after startup
WindowAlwaysOnTopOnStartup=false


; -----------------------------------------------
; - ADVANCED IMAGE CORRECTION PARAMETERS
; -----------------------------------------------

; Contrast correction to apply to all images. Must be in -0.5 .. 0.5
; Values > 0 increase contrast, values < 0 decrease contrast
Contrast=0.0
Expand All @@ -91,6 +105,14 @@ Saturation=1.0
; Note that for 100 % zoom, the BestQuality filter will not apply any sharpening, only the other filters do
Sharpen=0.3



; *****************************************************************************
; * DEFAULT IMAGE EDITING OPTIONS
; *
; * These options are related to JPEGView defaults for image editing
; *****************************************************************************

; Default parameters for unsharp masking: Radius Amount Threshold
; Note that no unsharp masking can be applied automatically to every image - this setting only provides the default parameters
; when entering the unsharp mask mode
Expand Down
11 changes: 5 additions & 6 deletions src/JPEGView/DirectoryWatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ static BOOL GetLastModificationTime(LPCTSTR fileName, FILETIME & lastModificatio
// Public
/////////////////////////////////////////////////////////////////////////////////////////////

CDirectoryWatcher::CDirectoryWatcher(HWND hTargetWindow) {
CDirectoryWatcher::CDirectoryWatcher(HWND hTargetWindow)
: m_lock{ 0 }
{
m_hTargetWindow = hTargetWindow;
memset(&m_lock, 0, sizeof(CRITICAL_SECTION));
::InitializeCriticalSection(&m_lock);
m_terminateEvent = ::CreateEvent(0, TRUE, FALSE, NULL);
m_newDirectoryEvent = ::CreateEvent(0, TRUE, FALSE, NULL);
Expand Down Expand Up @@ -75,8 +76,7 @@ void CDirectoryWatcher::SetCurrentFile(LPCTSTR fileName)

void CDirectoryWatcher::SetCurrentDirectory(LPCTSTR directoryName)
{
TCHAR fullName[MAX_PATH];
memset(fullName, 0, sizeof(TCHAR) * MAX_PATH);
TCHAR fullName[MAX_PATH]{ 0 };
GetFullPathName(directoryName, MAX_PATH, (LPTSTR)fullName, NULL);

::EnterCriticalSection(&m_lock);
Expand All @@ -98,8 +98,7 @@ void CDirectoryWatcher::ThreadFunc(void* arg) {
CDirectoryWatcher* thisPtr = (CDirectoryWatcher*) arg;
bool bTerminate = false;
bool bSetupNewDirectory = true;
HANDLE waitHandles[4];
memset(waitHandles, 0, sizeof(HANDLE) * 4);
HANDLE waitHandles[4]{ 0 };
do {
waitHandles[0] = thisPtr->m_terminateEvent;
waitHandles[1] = thisPtr->m_newDirectoryEvent;
Expand Down
19 changes: 16 additions & 3 deletions src/JPEGView/EXIFReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,10 @@ bool CEXIFReader::ParseDateString(SYSTEMTIME & date, const CString& str) {
}

CEXIFReader::CEXIFReader(void* pApp1Block, EImageFormat eImageFormat)
: m_exposureTime(0, 0) {

memset(&m_acqDate, 0, sizeof(SYSTEMTIME));
: m_exposureTime{ 0, 0 },
m_acqDate{ 0 },
m_dateTime{ 0 }
{
m_bFlashFired = false;
m_bFlashFlagPresent = false;
m_dFocalLength = m_dExposureBias = m_dFNumber = UNKNOWN_DOUBLE_VALUE;
Expand Down Expand Up @@ -327,6 +328,14 @@ CEXIFReader::CEXIFReader(void* pApp1Block, EImageFormat eImageFormat)
}
}

uint8* pTagSoftware = FindTag(pIFD0, pLastIFD0, 0x0131, bLittleEndian);
ReadStringTag(m_sSoftware, pTagSoftware, pTIFFHeader, bLittleEndian);

uint8* pTagModDate = FindTag(pIFD0, pLastIFD0, 0x0132, bLittleEndian);
CString sModDate;
ReadStringTag(sModDate, pTagModDate, pTIFFHeader, bLittleEndian);
ParseDateString(m_dateTime, sModDate);

uint8* pTagEXIFIFD = FindTag(pIFD0, pLastIFD0, 0x8769, bLittleEndian);
if (pTagEXIFIFD == NULL) {
return;
Expand Down Expand Up @@ -507,6 +516,10 @@ void CEXIFReader::ReadGPSData(uint8* pTIFFHeader, uint8* pTagGPSIFD, int nApp1Si
uint8* pTagAltitude = FindTag(pGPSIFD, pLastGPS, 0x6, bLittleEndian);
if (pTagAltitude != NULL) {
m_dAltitude = ReadDoubleTag(pTagAltitude, pTIFFHeader, bLittleEndian);
uint8* pTagAltitudeRef = FindTag(pGPSIFD, pLastGPS, 0x5, bLittleEndian);
if (pTagAltitudeRef != NULL && *(pTagAltitudeRef + 8) == 1) {
m_dAltitude *= -1;
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/JPEGView/EXIFReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ class GPSCoordinate {
public:
GPSCoordinate(LPCTSTR reference, double degrees, double minutes, double seconds) {
m_sReference = CString(reference);
if (minutes == 0.0 && seconds == 0.0) {
minutes = 60 * abs(degrees - (int)degrees);
degrees = (int)degrees;
}
if (seconds == 0.0) {
seconds = 60 * abs(minutes - (int)minutes);
minutes = (int)minutes;
}
Degrees = degrees;
Minutes = minutes;
Seconds = seconds;
Expand Down Expand Up @@ -49,10 +57,15 @@ class CEXIFReader {
LPCTSTR GetCameraModel() { return m_sModel; }
LPCTSTR GetUserComment() { return m_sUserComment; }
LPCTSTR GetImageDescription() { return m_sImageDescription; }
LPCTSTR GetSoftware() { return m_sSoftware; }
bool GetCameraModelPresent() { return !m_sModel.IsEmpty(); }
bool GetSoftwarePresent() { return !m_sSoftware.IsEmpty(); }
// Date-time the picture was taken
const SYSTEMTIME& GetAcquisitionTime() { return m_acqDate; }
bool GetAcquisitionTimePresent() { return m_acqDate.wYear > 1600; }
// Date-time the picture was saved/modified (used by editing software)
const SYSTEMTIME& GetDateTime() { return m_dateTime; }
bool GetDateTimePresent() { return m_dateTime.wYear > 1600; }
// Exposure time
const Rational& GetExposureTime() { return m_exposureTime; }
bool GetExposureTimePresent() { return m_exposureTime.Denominator != 0; }
Expand Down Expand Up @@ -106,7 +119,9 @@ class CEXIFReader {
CString m_sModel;
CString m_sUserComment;
CString m_sImageDescription;
CString m_sSoftware;
SYSTEMTIME m_acqDate;
SYSTEMTIME m_dateTime;
Rational m_exposureTime;
double m_dExposureBias;
bool m_bFlashFired;
Expand Down
3 changes: 2 additions & 1 deletion src/JPEGView/FileExtensionsDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ LRESULT CFileExtensionsDlg::OnListViewKeyDown(WPARAM /*wParam*/, LPNMHDR lpnmhdr
}

void CFileExtensionsDlg::FillFileExtensionsList() {
InsertExtension(_T("*.jpg;*.jpeg"), FormatHint(CNLS::GetString(_T("%s images")), _T("JPEG")));
InsertExtension(_T("*.jpg;*.jpeg;*.jfif"), FormatHint(CNLS::GetString(_T("%s images")), _T("JPEG")));
InsertExtension(_T("*.png"), FormatHint(CNLS::GetString(_T("%s images")), _T("PNG")));
InsertExtension(_T("*.avif"), FormatHint(CNLS::GetString(_T("%s images")), _T("AVIF")));
InsertExtension(_T("*.bmp"), FormatHint(CNLS::GetString(_T("%s images")), _T("Windows bitmap")));
Expand All @@ -292,6 +292,7 @@ void CFileExtensionsDlg::FillFileExtensionsList() {
InsertExtension(_T("*.webp"), FormatHint(CNLS::GetString(_T("%s images")), _T("Google WEBP")));
InsertExtension(_T("*.jxl"), FormatHint(CNLS::GetString(_T("%s images")), _T("JPEG XL")));
InsertExtension(_T("*.qoi"), FormatHint(CNLS::GetString(_T("%s images")), _T("Quite OK Image")));
InsertExtension(_T("*.psd"), FormatHint(CNLS::GetString(_T("%s images")), _T("Photoshop Document")));
InsertExtensions(CSettingsProvider::This().FilesProcessedByWIC(), CNLS::GetString(_T("%s images (processed by Window Imaging Component - WIC)")));
InsertExtensions(CSettingsProvider::This().FileEndingsRAW(), CNLS::GetString(_T("%s camera raw images (embedded JPEGs only)")));
}
Expand Down
5 changes: 2 additions & 3 deletions src/JPEGView/FileExtensionsRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ static RegResult ResetPermissionsForRegistryKey(LPCTSTR subKeyRelativeToHKCU)

const int MAX_SIZE_SEC_DESC = 1024;
SECURITY_DESCRIPTOR* pExistingSecDesc = (SECURITY_DESCRIPTOR*)new char[MAX_SIZE_SEC_DESC];
std::auto_ptr<char> auto_ptr_sec_desc((char*)pExistingSecDesc);
std::unique_ptr<char> auto_ptr_sec_desc((char*)pExistingSecDesc);

// Get the existing DACL of the registry key
DWORD sizeDecDesc = MAX_SIZE_SEC_DESC;
Expand All @@ -394,8 +394,7 @@ static RegResult ResetPermissionsForRegistryKey(LPCTSTR subKeyRelativeToHKCU)
}

// Obtain DACL information.
ACL_SIZE_INFORMATION asi;
memset(&asi, 0, sizeof(ACL_SIZE_INFORMATION));
ACL_SIZE_INFORMATION asi{ 0 };
if (pACL != NULL && !::GetAclInformation(pACL, (LPVOID)&asi, (DWORD)sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
return Reg_ErrorChangeDACL;
}
Expand Down
18 changes: 14 additions & 4 deletions src/JPEGView/FileList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ Helpers::ENavigationMode CFileList::sm_eMode = Helpers::NM_LoopDirectory;

// Helper to add the current file of filefind object to the list
static void AddToFileList(std::list<CFileDesc> & fileList, CFindFile &fileFind, LPCTSTR expectedExtension, int nMinFilesize = 1, bool bHideHidden = false) {
//std::list<CFileDesc>::iterator iter = fileList.begin();
//if (iter != fileList.end())
//{
// CString fileName = fileFind.GetFilePath(),
// fileName0 = (*iter).GetName();
// if (fileName == fileName0)
// {
// return; //already exists
// }
//}
if (!fileFind.IsDirectory()) {
if (expectedExtension != NULL) {
// compare if the extension is the expected extension
Expand Down Expand Up @@ -130,9 +140,10 @@ void CFileDesc::SetModificationDate(const FILETIME& lastModDate) {
///////////////////////////////////////////////////////////////////////////////////

// image file types supported internally (there are additional endings for RAW and WIC - these come from INI file)
static const int cnNumEndingsInternal = 15;
// NOTE: when adding more supported filetypes, update installer to add another extension for "SupportedTypes"
static const int cnNumEndingsInternal = 17;
static const TCHAR* csFileEndingsInternal[cnNumEndingsInternal] = {_T("jpg"), _T("jpeg"), _T("png"),
_T("avif"), _T("bmp"), _T("gif"), _T("heic"), _T("heif"), _T("ico"), _T("jxl"), _T("qoi"), _T("tif"), _T("tiff"), _T("tga"), _T("webp")};
_T("avif"), _T("bmp"), _T("gif"), _T("heic"), _T("heif"), _T("ico"), _T("jxl"), _T("psb"), _T("psd"), _T("qoi"), _T("tif"), _T("tiff"), _T("tga"), _T("webp")};
// supported camera RAW formats
static const TCHAR* csFileEndingsRAW = _T("*.pef;*.dng;*.crw;*.nef;*.cr2;*.mrw;*.rw2;*.orf;*.x3f;*.arw;*.kdc;*.nrw;*.dcr;*.sr2;*.raf");

Expand Down Expand Up @@ -358,8 +369,7 @@ bool CFileList::DeleteFile(LPCTSTR fileNameWithPath) const {
_tcscpy(fileName, fileNameWithPath);
fileName[_tcslen(fileName) + 1] = 0;

SHFILEOPSTRUCT fileOp;
memset(&fileOp, 0, sizeof(SHFILEOPSTRUCT));
SHFILEOPSTRUCT fileOp{ 0 };
fileOp.hwnd = NULL;
fileOp.wFunc = FO_DELETE;
fileOp.pFrom = fileName;
Expand Down
9 changes: 8 additions & 1 deletion src/JPEGView/GUIControls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,14 @@ bool CTextCtrl::EnterEditMode() {
m_pEdit->LimitText(256);
m_pEdit->ShowWindow(SW_SHOW);
m_pEdit->SetFocus();
m_pEdit->SetSelAll();
int last_dot_pos = m_sText.ReverseFind(_T('.'));
if (last_dot_pos == -1) {
// this selects the whole box
m_pEdit->SetSelAll();
} else {
// select up till the extension
m_pEdit->SetSel(0, last_dot_pos, FALSE);
}
return true;
}

Expand Down
43 changes: 27 additions & 16 deletions src/JPEGView/HEIFWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,16 @@ void * HeifReader::ReadImage(int &width,
}
std::vector<uint8_t> iccp = image.get_raw_color_profile();
void* transform = ICCProfileTransform::CreateTransform(iccp.data(), iccp.size(), ICCProfileTransform::FORMAT_RGBA);
uint8_t* p;
size_t i, j;
if (!ICCProfileTransform::DoTransform(transform, data, pPixelData, width, height, stride=stride)) {
memcpy(pPixelData, data, size);
unsigned char* o = pPixelData;
for (i = 0; i < height; i++) {
p = data + i * stride;
for (j = 0; j < width; j++) {
unsigned int* o = (unsigned int*)pPixelData;
for (i = 0; i < height; ++i) {
unsigned int* p = (unsigned int*)(data + i * stride);
for (j = 0; j < width; ++j) {
// RGBA -> BGRA conversion
o[0] = p[2];
o[1] = p[1];
o[2] = p[0];
o[3] = p[3];
p += nchannels;
o += nchannels;
*o = _rotr(_byteswap_ulong(*p), 8);
++p;
++o;
}
}
}
Expand All @@ -75,12 +70,28 @@ void * HeifReader::ReadImage(int &width,

if (!exif_blocks.empty()) {
std::vector<uint8_t> exif = handle.get_metadata(exif_blocks[0]);
if (exif.size() > 8 && exif.size() < 65538) {
exif_chunk = malloc(exif.size());
// 65538 magic number comes from investigations by qbnu
// see https://github.com/sylikc/jpegview/pull/213#pullrequestreview-1494451359 for more details
/*
* These libraries all have their own ideas about where to start the Exif data from.
* JPEG Exif blocks are in the format
FF E1 SS SS 45 78 69 66 00 00 [data]
The SS SS is a big-endian unsigned short representing the size of everything after FF E1.
libjxl gives 00 00 00 00 [data]
libheif gives 00 00 00 00 45 78 69 66 00 00 [data]
libavif, libwebp and libpng give [data], so they have different limits for size.
If you want I can change it to 65536 + an offset and add notes explaining why.
*/
size_t size = exif.size();
if (size > 8 && size < 65538) {
exif_chunk = malloc(size);
if (exif_chunk != NULL) {
memcpy(exif_chunk, exif.data(), exif.size());
memcpy(exif_chunk, exif.data(), size);
*((unsigned short*)exif_chunk) = _byteswap_ushort(0xFFE1);
*((unsigned short*)exif_chunk + 1) = _byteswap_ushort(exif.size() - 2);
*((unsigned short*)exif_chunk + 1) = _byteswap_ushort(size - 2);
}
}
}
Expand Down
30 changes: 25 additions & 5 deletions src/JPEGView/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,27 @@ CRect GetWindowRectMatchingImageSize(HWND hWnd, CSize minSize, CSize maxSize, do
int nOrigWidth = (pImage == NULL) ? ::GetSystemMetrics(SM_CXSCREEN) / 2 : pImage->OrigWidth();
int nOrigWidthUnzoomed = nOrigWidth;
int nOrigHeight = (pImage == NULL) ? ::GetSystemMetrics(SM_CYSCREEN) / 2 : pImage->OrigHeight();
if (dZoom > 0) {
if (dZoom == ZoomMax) {
// NOTE: somewhat hacky, but the original code did not account for ZoomMax == DBL_MAX, causing overflows
// This workaround artificially calculates an image that is == the maximum allowed dimensions,
// so as to not overflow int or double
//
// when dZoom was unbounded to DBL_MAX in 1.1.44, doing any arithmetic would cause the nOrig* to overflow
// So just set to scaled maximum allowed image dimension on one side
// the math below will not overflow, and it stays within the bounds of an integer
if (nOrigWidth == nOrigHeight) {
// ratio is 1:1
nOrigWidth = nOrigHeight = MAX_IMAGE_DIMENSION;
} else if (nOrigWidth > nOrigHeight) {
// wider than high
nOrigHeight = (int)((double)nOrigHeight / nOrigWidth * MAX_IMAGE_DIMENSION); // max * height/width ratio
nOrigWidth = MAX_IMAGE_DIMENSION;
} else {
// higher than wide
nOrigWidth = (int)((double)nOrigWidth / nOrigHeight * MAX_IMAGE_DIMENSION); // max * width/height ratio
nOrigHeight = MAX_IMAGE_DIMENSION;
}
} else if (dZoom > 0) {
nOrigWidth = (int)(nOrigWidth * dZoom + 0.5);
nOrigHeight = (int)(nOrigHeight * dZoom + 0.5);
}
Expand Down Expand Up @@ -733,7 +753,7 @@ EImageFormat GetImageFormat(LPCTSTR sFileName) {
LPCTSTR sEnding = _tcsrchr(sFileName, _T('.'));
if (sEnding != NULL) {
sEnding += 1;
if (_tcsicmp(sEnding, _T("JPG")) == 0 || _tcsicmp(sEnding, _T("JPEG")) == 0) {
if (_tcsicmp(sEnding, _T("JPG")) == 0 || _tcsicmp(sEnding, _T("JPEG")) == 0 || _tcsicmp(sEnding, _T("JFIF")) == 0) {
return IF_JPEG;
} else if (_tcsicmp(sEnding, _T("BMP")) == 0) {
return IF_WindowsBMP;
Expand All @@ -745,16 +765,16 @@ EImageFormat GetImageFormat(LPCTSTR sFileName) {
return IF_WEBP;
} else if (_tcsicmp(sEnding, _T("JXL")) == 0) {
return IF_JXL;
} else if (_tcsicmp(sEnding, _T("HEIF")) == 0) {
return IF_HEIF;
} else if (_tcsicmp(sEnding, _T("HEIC")) == 0) {
} else if (_tcsicmp(sEnding, _T("HEIF")) == 0 || _tcsicmp(sEnding, _T("HEIC")) == 0) {
return IF_HEIF;
} else if (_tcsicmp(sEnding, _T("TGA")) == 0) {
return IF_TGA;
} else if (_tcsicmp(sEnding, _T("AVIF")) == 0) {
return IF_AVIF;
} else if (_tcsicmp(sEnding, _T("QOI")) == 0) {
return IF_QOI;
} else if ((_tcsicmp(sEnding, _T("PSD")) == 0) || (_tcsicmp(sEnding, _T("PSB")) == 0)) {
return IF_PSD;
} else if (IsInFileEndingList(CSettingsProvider::This().FilesProcessedByWIC(), sEnding)) {
return IF_WIC;
} else if (IsInFileEndingList(CSettingsProvider::This().FileEndingsRAW(), sEnding)) {
Expand Down
Loading

0 comments on commit 588ec4e

Please sign in to comment.