Skip to content

Commit

Permalink
Added a Merge pages options.
Browse files Browse the repository at this point in the history
closes #53, see Changes.txt for instructions
  • Loading branch information
maforget committed Jun 25, 2024
1 parent 01477df commit e014052
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 28 deletions.
15 changes: 12 additions & 3 deletions ComicRack/Changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ Community Edition Build 0.9.180:

* NEW: RAR5 Support (Default & SharpCompress)
* NEW: New PDF Engine using Google's PDFium, this is now the default. Check in the ComicRack.ini file to change the default engine or to change the rendering size. (See below for additional changes).
* NEW: Added Virtual Tags. You can set any combination of field in a single one. Can be used with grouping, sorting, smart lists. Configure them in Preferences => Library => Virtual Tags. BACKUP YOUR DB, IF YOU PLAN ON GOING BACK TO AN OLDER VERSION. USING A VIRTUAL TAG IN A SMART LIST AND OPENING AN OLDER VERSION WOULD RESULT IN A DATABASE CORRUPTED MESSAGE. YOU NEED TO REMOVE ANY OF THESE LISTS BEFORE GOING BACK.
* NEW: Built-in "Open With" external programs. You can also set it to override the reader and that program will replace the normal reader when double-clicking (you can still right-click open for the default viewer). There are no validation that the program will support the filetype.
* NEW: Added Virtual Tags. You can set any combination of field in a single one. Can be used with grouping, sorting, smart lists.
- Configure them in Preferences => Library => Virtual Tags.
- BACKUP YOUR DB, IF YOU PLAN ON GOING BACK TO AN OLDER VERSION. USING A VIRTUAL TAG IN A SMART LIST AND OPENING AN OLDER VERSION WOULD RESULT IN A DATABASE CORRUPTED MESSAGE. YOU NEED TO REMOVE ANY OF THESE LISTS BEFORE GOING BACK.
* NEW: Built-in "Open With" external programs.
- You can also set it to override the reader and that program will replace the normal reader when double-clicking (you can still right-click open for the default viewer). There are no validation that the program will support the filetype.
* NEW: Added the Git version to the Splash Screen, to more easily identify bugs in specific releases.
* NEW: Added the "-local" command line switch, to have the program load in portable mode.
* NEW: Added links to The Organizer guide to the online manual help system
Expand All @@ -19,9 +22,15 @@ Community Edition Build 0.9.180:
* NEW: Images smaller than 256 bytes will be ignored inside archives.
* NEW: Added a "Published (Regional)" column that will use the OS regional setting for the Published date (like the other dates).
* NEW: Added support for wildcard for "KeepFiles" in a script "Package.ini" (used for Data Manager multiple profiles).
* NEW: Added a Merge Pages functionality, that will merge pages together.
- This is only in Cache and the book will need to be exported for the changes to be saved.
- Can be easily reversed by using Refresh on a page.
- The sort order is important in determining the left & right images.
- Unless Manga is set to : Yes (Right to Left), then the sort order doesn't matter.
(So for Manga, either just sort by descending to see the images in the correct order, set the comic to be Right to Left or both)

* CHANGE: Updated to .NET Framework v4.8.
* CHANGE: Updated the Splash Screen and Renamed the Program to Community Edition, this means that a new config folder will be used %appdata%\cYo\ComicRack Community Edition.
* CHANGE: Updated the Splash Screen and Renamed the Program to Community Edition, this means that a new config folder will be used %appdata%\cYo\ComicRack Community Edition.
* CHANGE: Removed Android Validation of apk signature (so we can use the cracked version). Has no incidence on whether the sync icon appears.
* CHANGE: Updated default sort to be natural sorting (numeric).
* CHANGE: Switched MySQl library to MySQLConnector for better speed & compatibility with MariaDB (Yes current versions work).
Expand Down
11 changes: 10 additions & 1 deletion ComicRack/Controls/PagesView.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 69 additions & 23 deletions ComicRack/Controls/PagesView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ protected override void OnLoad(EventArgs e)
command.Add(itemView.SelectAll, miSelectAll, toolStripMenuItem);
command.Add(itemView.InvertSelection, miInvertSelection);
command.Add(CopyPage, miCopy);
command.Add(RefreshDisplay, miRefreshThumbnail);
command.Add(MergePages, miMergePages);
command.Add(RefreshDisplay, miRefreshThumbnail);
command.Add(MarkAsDeleted, miMarkDeleted);
command.Add(SetBookmark, () => CanBookmark, miSetBookmark);
command.Add(delegate
Expand Down Expand Up @@ -345,56 +346,61 @@ private void RotateMenuValueChanged(object sender, EventArgs e)
}
}

private void contextPages_Opening(object sender, CancelEventArgs e)
{
private void contextPages_Opening(object sender, CancelEventArgs e)
{
miMergePages.Visible = false;
miPageType.Visible = tsPageTypeSeparator.Visible = book.Comic.EditMode.CanEditPages();
miSetBookmark.Visible = miRemoveBookmark.Visible = tsBookmarkSeparator.Visible = book.Comic.EditMode.CanEditPages();
miMoveToTop.Visible = miMoveToBottom.Visible = miResetOriginalOrder.Visible = tsMovePagesSeparator.Visible = book.Comic.EditMode.CanEditPages();
miCopy.Enabled = itemView.FocusedItem != null;
miCopy.Enabled = itemView.FocusedItem != null;

ComicPageType? pageType = null;
foreach (ComicPageInfo selectedPage in GetSelectedPages())
{
foreach (ComicPageInfo selectedPage in GetSelectedPages())
{
if (pageType is null)
pageType = selectedPage.PageType;
else if (pageType != selectedPage.PageType)
{
{
pageType = null;
break;
}
}
break;
}
}
pageMenu.Value = pageType.HasValue ? (int)pageType.Value : -1;

ImageRotation? imageRotation = null;
foreach (ComicPageInfo selectedPage in GetSelectedPages())
{
{
if (imageRotation == null)
imageRotation = selectedPage.Rotation;
else if (imageRotation != selectedPage.Rotation)
{
{
imageRotation = null;
break;
}
}
break;
}
}
rotateMenu.Value = imageRotation.HasValue ? (int)imageRotation.Value : -1;

ComicPagePosition? pageInfo = null;
foreach (ComicPageInfo selectedPage in GetSelectedPages())
{
{
if (pageInfo == null)
pageInfo = selectedPage.PagePosition;
else if (pageInfo != selectedPage.PagePosition)
{
{
pageInfo = null;
break;
}
}
break;
}
}
miPagePositionDefault.Checked = pageInfo == ComicPagePosition.Default;
miPagePositionNear.Checked = pageInfo == ComicPagePosition.Near;
miPagePositionFar.Checked = pageInfo == ComicPagePosition.Far;
}

private void ItemViewMouseWheel(object sender, MouseEventArgs e)
IEnumerable<ComicPageInfo> selectedPages = GetSelectedPages();
if (selectedPages?.Count() == 2)
miMergePages.Visible = true;
}

private void ItemViewMouseWheel(object sender, MouseEventArgs e)
{
if ((Control.ModifierKeys & Keys.Control) != 0 && itemView.ItemViewMode != ItemViewMode.Detail)
{
Expand Down Expand Up @@ -783,5 +789,45 @@ private void itemView_GiveFeedback(object sender, GiveFeedbackEventArgs e)
Cursor.Current = dragCursor.Cursor;
}
}
}

private void MergePages()
{
//If any other quantity than 2 or any of the pages are marked as Deleted, abort
List<PageViewItem> selectedPages = itemView.SelectedItems.Cast<PageViewItem>().ToList();
if (selectedPages?.Count() != 2 && selectedPages.Any((PageViewItem p) => p.PageInfo.PageType == ComicPageType.Deleted))
return;

//Check the reading direction to determine the first and second page.
bool reversed = this.Book.RightToLeftReading == YesNo.Yes || this.Book.Comic.Manga == MangaYesNo.YesAndRightToLeft;
//If the sort order is descending the pages will be reversed already, so no need to reverse the order
reversed = reversed && itemView.ItemSorter != null && itemView.ItemSortOrder == SortOrder.Descending ? false : reversed;
PageViewItem firstPage = (reversed ? selectedPages[^1] : selectedPages[0]);
PageViewItem secondPage = (reversed ? selectedPages[0] : selectedPages[^1]);

//Get the bitmaps and merge them
int firstImageIndex = firstPage.ImageIndex;
Bitmap firstImage = book.GetImage(firstImageIndex);
Bitmap secondImage = book.GetImage(secondPage.ImageIndex);
Bitmap mergedImage = BitmapExtensions.Merge(firstImage, secondImage);

//Get the PageKey (includes color ajustements) & ThumbnailKey for future reference
PageKey pageKey = Book.GetPageKey(firstImageIndex);
ThumbnailKey thumbKey = Book.GetThumbnailKey(firstImageIndex);

//Remove the original cached version
Program.ImagePool.Pages.RefreshImage(pageKey);
Program.ImagePool.Thumbs.RefreshImage(thumbKey);

//Add pages to the ImagePool because if they aren't the Export will retrieve the original image instead
using IItemLock<PageImage> itemLock = Program.ImagePool.Pages.AddImage(pageKey, p => PageImage.CreateFrom(mergedImage));
using IItemLock<ThumbnailImage> itemLock2 = Program.ImagePool.Thumbs.AddImage(thumbKey, p => ThumbnailImage.CreateFrom(mergedImage, mergedImage.Size));

//Mark the second image as Deleted
secondPage.SetPageType(ComicPageType.Deleted);

//Update UI
UpdateList(true);//will update the pages lists so if Deleted are uncheck, they will dissapear
RefreshDisplay();
}
}
}
24 changes: 23 additions & 1 deletion cYo.Common/Drawing/BitmapExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -606,5 +606,27 @@ private static float GetAngularCoefficientRads(PointF from, PointF to)
}
return num;
}
}

public static Bitmap Merge(Bitmap firstImage, Bitmap secondImage)
{
try
{
var width = firstImage.Width + secondImage.Width;
var height = Math.Max(firstImage.Height, secondImage.Height);

Bitmap result = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(result))
{
g.DrawImage(firstImage, 0, 0, firstImage.Width, firstImage.Height);
g.DrawImage(secondImage, firstImage.Width, 0, secondImage.Width, secondImage.Height);
}

return result;
}
catch
{
return null;
}
}
}
}

0 comments on commit e014052

Please sign in to comment.