@@ -85,10 +85,9 @@ public static void Main(string[] args)
85
85
string frontCoverResized = Path . Combine ( outputFolder , "05-FrontCover.png" ) ;
86
86
string frontCoverFileMirrored = Path . Combine ( outputFolder , "03-FrontCoverMirrored.png" ) ;
87
87
Directory . CreateDirectory ( outputFolder ) ;
88
- ProcessSpine ( spineFile , spineFileFaded ) ;
89
88
ProcessCover ( backCoverFile , backCoverFileResized , backCoverFileMirrored , true ) ;
90
89
ProcessCover ( frontCoverFile , frontCoverResized , frontCoverFileMirrored , false ) ;
91
-
90
+ ProcessSpine ( spineFile , spineFileFaded ) ;
92
91
Console . WriteLine ( "Image processing complete. You can now take the files from the output folder at {0} and put them into your template image as individual layers." ) ;
93
92
Console . WriteLine ( "Top down order is: " ) ;
94
93
Console . WriteLine ( "01-SpineBlend.png" ) ;
@@ -187,45 +186,77 @@ private static void AssignVariables(Dictionary<string, string> dict)
187
186
backCoverMirrorRectDest = new ( spineRect . X , 0 , spineRect . Width / 2 , spineRect . Height ) ;
188
187
backCoverMirrorRectSource = new ( 0 , 0 , spineRect . Width / 2 , spineRect . Height ) ;
189
188
frontCoverRect = new ( backWidth + spineWidth , 0 , frontWidth , finalHeight ) ;
190
- frontCoverMirrorRectDest = new ( spineRect . Left + ( spineRect . Width / 2 ) , 0 , spineRect . Width / 2 , 0 ) ;
189
+ frontCoverMirrorRectDest = new ( spineRect . Left + ( spineRect . Width / 2 ) , 0 , spineRect . Width / 2 , spineRect . Height ) ;
191
190
frontCoverMirrorSource = new ( frontCoverRect . Width - ( spineRect . Width / 2 ) , 0 , ( spineRect . Width / 2 ) , spineRect . Height ) ;
192
191
}
193
192
194
193
private static void ProcessCover ( string inputFilePath , string outputFileResized , string outputFileMirrored , bool isBackCover )
195
194
{
196
- using Image < Rgba32 > coverImage = Image . Load < Rgba32 > ( inputFilePath ) ;
197
- Crop ( coverImage , aspectRatioCover ) ;
195
+ using var coverImage = Image . Load < Rgba32 > ( inputFilePath ) ;
196
+ using var croppedImage = Crop ( coverImage , aspectRatioCover ) ;
198
197
199
198
// Create the final image
200
- using Image < Rgba32 > finalImage = new ( finalRect . Width , finalRect . Height , Color . Transparent ) ;
199
+ var finalImage = new Image < Rgba32 > ( finalRect . Width , finalRect . Height , Color . Transparent ) ;
201
200
202
201
// Calculate positions to position the resized image
203
202
Rectangle coverRectDest = isBackCover ? backCoverRect : frontCoverRect ;
204
203
Rectangle mirrorRectDest = isBackCover ? backCoverMirrorRectDest : frontCoverMirrorRectDest ;
205
204
Rectangle mirrorRectSource = isBackCover ? backCoverMirrorRectSource : frontCoverMirrorSource ;
206
205
207
-
208
206
// Draw the resized image onto the final image
209
- coverImage . Mutate ( ctx => ctx . Resize ( new Size ( coverRectDest . Width , coverRectDest . Height ) ) ) ;
210
- finalImage . Mutate ( ctx => ctx . DrawImage ( coverImage , new Point ( coverRectDest . X , coverRectDest . Y ) , 1.0f ) ) ;
207
+ using var croppedImageResized = croppedImage . Clone ( ctx => ctx . Resize ( new Size ( coverRectDest . Width , coverRectDest . Height ) ) ) ;
208
+ finalImage . Mutate ( ctx => ctx . DrawImage ( croppedImageResized , new Point ( coverRectDest . X , coverRectDest . Y ) , 1.0f ) ) ;
211
209
212
210
// Save the final image
213
211
finalImage . Save ( outputFileResized ) ;
214
212
215
- // Create the mirrored image
216
- using Image < Rgba32 > mirroredImage = new ( coverRectDest . Width , coverRectDest . Height ) ;
217
- mirroredImage . Mutate ( ctx => ctx . DrawImage ( coverImage , new Point ( 0 , 0 ) , 1.0f ) ) ;
218
- mirroredImage . Mutate ( ctx => ctx . Flip ( FlipMode . Horizontal ) ) ;
213
+ // Re-use final image for mirroring
214
+ finalImage . Dispose ( ) ;
215
+ finalImage = new Image < Rgba32 > ( finalRect . Width , finalRect . Height , Color . Transparent ) ;
216
+
217
+ // If we have space, extend the image instead of mirroring
218
+ float widthRatio = ( float ) croppedImageResized . Width / ( float ) croppedImage . Width ;
219
+
220
+ // Convert from cropt resize measures to original image measures
221
+ int neededGap = ( int ) ( ( float ) mirrorRectSource . Width / widthRatio ) ;
222
+ int actualGap = ( coverImage . Width - croppedImage . Width ) / 2 ;
223
+ if ( neededGap <= actualGap )
224
+ {
225
+ // Extract the edge of the cover, using the right side for back and left side for front,
226
+ // then draw this onto the final image at the mirror position
227
+ // Create a crop rect that takes into account the original cover size and the final cover size
228
+ int croppedX = ( ( coverImage . Width - croppedImage . Width ) / 2 ) ;
229
+ int x = isBackCover ? croppedImage . Width + croppedX : croppedX - neededGap ;
230
+ int y = ( croppedImage . Height - coverImage . Height ) / 2 ;
231
+ int width = neededGap ;
232
+ int height = croppedImage . Height ;
233
+ var cropRect = new Rectangle ( x , y , width , height ) ;
234
+ using var edgeImage = coverImage . Clone ( ctx =>
235
+ {
236
+ ctx . Crop ( cropRect ) ;
237
+ ctx . Resize ( mirrorRectDest . Width , mirrorRectDest . Height ) ;
238
+ } ) ;
239
+ finalImage . Mutate ( ctx => ctx . DrawImage ( edgeImage , new Point ( mirrorRectDest . X , mirrorRectDest . Y ) , 1.0f ) ) ;
240
+ }
241
+ else
242
+ {
243
+ // Create the mirrored image
244
+ using var mirroredImage = new Image < Rgba32 > ( coverRectDest . Width , coverRectDest . Height ) ;
245
+
246
+ // Draw image and mirror it
247
+ mirroredImage . Mutate ( ctx => ctx . DrawImage ( croppedImageResized , new Point ( 0 , 0 ) , 1.0f ) ) ;
248
+ mirroredImage . Mutate ( ctx => ctx . Flip ( FlipMode . Horizontal ) ) ;
219
249
220
- // extract the mirror rect source from the mirrored image
221
- using Image < Rgba32 > mirroredImageSource = mirroredImage . Clone ( ctx => ctx . Crop ( mirrorRectSource ) ) ;
250
+ // Extract the mirror rect source from the mirrored image
251
+ using var mirroredImageSource = mirroredImage . Clone ( ctx => ctx . Crop ( mirrorRectSource ) ) ;
222
252
223
- // Draw the mirrored image onto the final image
224
- finalImage . Mutate ( ctx => ctx . Clear ( Color . Transparent ) ) ;
225
- finalImage . Mutate ( ctx => ctx . DrawImage ( mirroredImageSource , new Point ( mirrorRectDest . X , mirrorRectDest . Y ) , 1.0f ) ) ;
253
+ // Draw the mirrored image onto the final image
254
+ finalImage . Mutate ( ctx => ctx . DrawImage ( mirroredImageSource , new Point ( mirrorRectDest . X , mirrorRectDest . Y ) , 1.0f ) ) ;
255
+ }
226
256
227
257
// Save the mirrored image
228
258
finalImage . Save ( outputFileMirrored ) ;
259
+ finalImage . Dispose ( ) ;
229
260
}
230
261
231
262
private static void ProcessSpine ( string inputFilePath , string outputFilePath )
@@ -252,7 +283,7 @@ private static void ProcessSpine(string inputFilePath, string outputFilePath)
252
283
finalImage . Save ( outputFilePath ) ;
253
284
}
254
285
255
- private static void Crop ( Image < Rgba32 > image , double aspectRatio )
286
+ private static Image < Rgba32 > Crop ( Image < Rgba32 > image , double aspectRatio )
256
287
{
257
288
// Calculate the desired dimensions of the cropped image
258
289
var imageAspectRatio = ( double ) image . Width / ( double ) image . Height ;
@@ -264,7 +295,9 @@ private static void Crop(Image<Rgba32> image, double aspectRatio)
264
295
var y = ( image . Height - cropHeight ) / 2 ;
265
296
266
297
// Crop the image
267
- image . Mutate ( ctx => ctx . Crop ( new Rectangle ( x , y , cropWidth , cropHeight ) ) ) ;
298
+ var croppedImage = image . Clone ( ) ;
299
+ croppedImage . Mutate ( ctx => ctx . Crop ( new Rectangle ( x , y , cropWidth , cropHeight ) ) ) ;
300
+ return croppedImage ;
268
301
}
269
302
270
303
private static void RemoveBlackRows ( Image < Rgba32 > image )
0 commit comments