Skip to content

Commit

Permalink
"Merge visible layers" now implemented
Browse files Browse the repository at this point in the history
More nuances to this than I expected, as you can have cases where the
number of visible (and by extension, hidden layers) extends from 0 to
numOfLayers, in any conceivable pattern.

This function required new helper functions for counting visible/hidden
layers, and those allowed me to knock out more "menu state synching"
issues, e.g. only allow "Merge Visible Layers" if there is more than one
layer visible.
  • Loading branch information
tannerhelland committed Apr 13, 2014
1 parent 9003b20 commit a1cc477
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 6 deletions.
29 changes: 28 additions & 1 deletion Classes/pdImage.cls
Expand Up @@ -460,7 +460,7 @@ Public Sub moveLayerByIndex(ByVal srcLayerIndex As Long, ByVal moveLayerUp As Bo
End Sub

'Used by various layer movement functions. Given two layer indices, swap them.
Private Sub swapTwoLayers(ByVal srcLayerID_1 As Long, ByVal srcLayerID_2 As Long)
Public Sub swapTwoLayers(ByVal srcLayerID_1 As Long, ByVal srcLayerID_2 As Long)

'Create a temporary reference to the first layer
Dim tmpLayerRef As pdLayer
Expand Down Expand Up @@ -1100,3 +1100,30 @@ Friend Sub fillRectForLayer(ByRef srcLayer As pdLayer, ByRef dstRect As RECT)
End With

End Sub

'Get number of visible/hidden layers
Public Function getNumOfVisibleLayers() As Long

Dim i As Long, visLayerCount As Long
visLayerCount = 0

For i = 0 To numOfLayers - 1
If imgLayers(i).getLayerVisibility Then visLayerCount = visLayerCount + 1
Next i

getNumOfVisibleLayers = visLayerCount

End Function

Public Function getNumOfHiddenLayers() As Long

Dim i As Long, hidLayerCount As Long
hidLayerCount = 0

For i = 0 To numOfLayers - 1
If Not imgLayers(i).getLayerVisibility Then hidLayerCount = hidLayerCount + 1
Next i

getNumOfHiddenLayers = hidLayerCount

End Function
2 changes: 1 addition & 1 deletion Forms/VBP_FormMain.frm
Expand Up @@ -1346,7 +1346,7 @@ Private Sub MnuLayer_Click(Index As Integer)

'Merge visible layers
Case 12
MsgBox "This action isn't implemented yet. I hope to get to it by the end of April 2014.", vbOKOnly + vbInformation + vbApplicationModal, "Under construction"
Process "Merge visible layers", , , 1

End Select

Expand Down
63 changes: 63 additions & 0 deletions Modules/VBP_LayerHandler.bas
Expand Up @@ -111,6 +111,9 @@ Public Sub setLayerVisibilityByIndex(ByVal dLayerIndex As Long, ByVal layerVisib
'Redraw the layer box, but note that thumbnails don't need to be re-cached
toolbar_Layers.forceRedraw False

'Synchronize the interface to the new image
syncInterfaceToCurrentImage

'Redraw the viewport, but only if requested
If alsoRedrawViewport Then ScrollViewport pdImages(g_CurrentImage), FormMain.mainCanvas(0)

Expand Down Expand Up @@ -333,3 +336,63 @@ Public Sub flattenImage()
ScrollViewport pdImages(g_CurrentImage), FormMain.mainCanvas(0)

End Sub

'Given a multi-layered image, merge all visible layers, while ignoring any hidden ones. Note that flattening does *not*
' remove alpha! It simply merges all visible layers.
Public Sub mergeVisibleLayers()

'If there's only one visible layer, this function should not be called - but just in case, exit in advance.
If pdImages(g_CurrentImage).getNumOfLayers = 1 Then Exit Sub

'SIf there's only one visible layer, this function should not be called - but just in case, exit in advance.
If pdImages(g_CurrentImage).getNumOfVisibleLayers = 1 Then Exit Sub

'By this point, we can assume there are at least two visible layers in the image. Rather than deal with the messiness
' of finding the lowest base layer and gradually merging everything into it, we're going to just create a new blank
' layer at the base of the image, then merge everything with it until finally all visible layers have been merged.

'Insert a new layer at the bottom of the layer stack.
pdImages(g_CurrentImage).createBlankLayer 0

'Technically, the command above does not actually insert a new layer at the base of the image. Per convention,
' it always inserts the requested layer at the spot one *above* the requested spot. To work around this, swap
' our newly created layer with the layer at position 0.
pdImages(g_CurrentImage).swapTwoLayers 0, 1

'Fill that new layer with a blank DIB at the dimensions of the image.
Dim tmpDIB As pdDIB
Set tmpDIB = New pdDIB
tmpDIB.createBlank pdImages(g_CurrentImage).Width, pdImages(g_CurrentImage).Height, 32, 0
pdImages(g_CurrentImage).getLayerByIndex(0).CreateNewImageLayer tmpDIB, , g_Language.TranslateMessage("Merged layers")

'With that done, merging visible layers is actually not that hard. Loop through the layer collection,
' merging visible layers with the base layer, until all visible layers have been merged.
Dim i As Long
For i = 1 To pdImages(g_CurrentImage).getNumOfLayers - 1

'If this layer is visible, merge it with the base layer
If pdImages(g_CurrentImage).getLayerByIndex(i).getLayerVisibility Then
pdImages(g_CurrentImage).mergeTwoLayers pdImages(g_CurrentImage).getLayerByIndex(i), pdImages(g_CurrentImage).getLayerByIndex(0), True
End If

Next i

'Now that our base layer contains the result of merging all visible layers, we can now delete all
' other visible layers.
For i = pdImages(g_CurrentImage).getNumOfLayers - 1 To 1 Step -1
If pdImages(g_CurrentImage).getLayerByIndex(i).getLayerVisibility Then
pdImages(g_CurrentImage).deleteLayerByIndex i
End If
Next i

'Mark the new merged layer as the active one. (This will also re-synchronize the interface against the new image.)
setActiveLayerByIndex 0, False

'Redraw the layer box, and note that thumbnails need to be re-cached
toolbar_Layers.forceRedraw True

'Redraw the viewport
ScrollViewport pdImages(g_CurrentImage), FormMain.mainCanvas(0)

End Sub

18 changes: 15 additions & 3 deletions Modules/VBP_MiscInterface.bas
Expand Up @@ -244,7 +244,8 @@ Public Sub syncInterfaceToCurrentImage()
metaToggle tSelectionTransform, False
End If

'Update all layer menus; some will be disabled under certain circumstances
'Update all layer menus; some will be disabled depending on just how many layers are available, how many layers
' are visible, and other criteria.
If pdImages(g_CurrentImage).getNumOfLayers > 0 Then

'If only one layer is present, a number of layer menu items (Delete, Flatten, Merge, Order) will be disabled.
Expand All @@ -271,6 +272,13 @@ Public Sub syncInterfaceToCurrentImage()

'Delete
If Not FormMain.MnuLayer(1).Enabled Then FormMain.MnuLayer(1).Enabled = True

'Delete hidden layers is only available if one or more layers are hidden
If pdImages(g_CurrentImage).getNumOfHiddenLayers > 0 Then
FormMain.MnuLayerDelete(1).Visible = False
Else
FormMain.MnuLayerDelete(1).Visible = True
End If

'Merge up/down are not available for layers at the top and bottom of the image
If isLayerAllowedToMergeAdjacent(pdImages(g_CurrentImage).getActiveLayerIndex, False) <> -1 Then
Expand Down Expand Up @@ -307,8 +315,12 @@ Public Sub syncInterfaceToCurrentImage()
'Flatten
If Not FormMain.MnuLayer(11).Enabled Then FormMain.MnuLayer(11).Enabled = True

'Merge visible
If Not FormMain.MnuLayer(12).Enabled Then FormMain.MnuLayer(12).Enabled = True
'Merge visible is only available if two or more layers are visible
If pdImages(g_CurrentImage).getNumOfVisibleLayers > 1 Then
If Not FormMain.MnuLayer(12).Enabled Then FormMain.MnuLayer(12).Enabled = True
Else
FormMain.MnuLayer(12).Enabled = False
End If

End If

Expand Down
3 changes: 3 additions & 0 deletions Modules/VBP_ProcessorModule.bas
Expand Up @@ -468,6 +468,9 @@ Public Sub Process(ByVal processID As String, Optional showDialog As Boolean = F
Case "Flatten image"
Layer_Handler.flattenImage

'Merge visible layers
Case "Merge visible layers"
Layer_Handler.mergeVisibleLayers

'SELECTION FUNCTIONS
' Any action that operates on selections - creating them, moving them, erasing them, etc
Expand Down
2 changes: 1 addition & 1 deletion PhotoDemon.vbp
Expand Up @@ -219,7 +219,7 @@ Description="PhotoDemon Photo Editor"
CompatibleMode="0"
MajorVer=6
MinorVer=3
RevisionVer=113
RevisionVer=114
AutoIncrementVer=1
ServerSupportFiles=0
VersionComments="�2000-2014 Tanner Helland - photodemon.org"
Expand Down

0 comments on commit a1cc477

Please sign in to comment.