77 * SOURCE: https://lodev.org/cgtutor/floodfill.html
88 */
99
10+ using Imaging . Helpers ;
1011using System ;
1112using System . Diagnostics ;
1213using System . Drawing ;
1314using System . Drawing . Imaging ;
1415using System . IO ;
16+ using System . Windows ;
17+ using System . Windows . Media ;
1518using System . Windows . Media . Imaging ;
16- using Imaging . Helpers ;
1719
1820namespace Imaging ;
1921
2022/// <summary>
21- /// Handle the more newer wpf Libraries
23+ /// Handle the more newer wpf Libraries
2224/// </summary>
2325public static class ImageStreamMedia
2426{
@@ -140,52 +142,122 @@ internal static Bitmap BitmapImageToBitmap(BitmapImage image)
140142 }
141143
142144 /// <summary>
143- /// Converts to bitmap image.
144- /// https://stackoverflow.com/questions/5199205/how-do-i-rotate-image-then-move-to-the-top-left-0-0-without-cutting-off-the-imag/5200280#5200280
145+ /// Converts to bitmap image.
146+ /// https://stackoverflow.com/questions/5199205/how-do-i-rotate-image-then-move-to-the-top-left-0-0-without-cutting-off-the-imag/5200280#5200280
145147 /// </summary>
146148 /// <param name="image">The bitmap.</param>
149+ /// <param name="lossless">if set to <c>true</c> [lossless].</param>
150+ /// <returns>BitmpaImage from Bitmap</returns>
151+ /// <exception cref="ArgumentNullException">if Image is null</exception>
147152 /// The Image as
148153 /// <see cref="BitmapImage" />
149154 /// .
150- /// <exception cref="ArgumentNullException">if Image is null</exception>
151- internal static BitmapImage BitmapToBitmapImage ( Bitmap image )
155+ internal static BitmapImage BitmapToBitmapImage ( Bitmap image , bool lossless = false )
152156 {
157+ if ( ! lossless )
158+ return FastConvert ( image ) ;
159+
153160 ImageHelper . ValidateImage ( nameof ( BitmapToBitmapImage ) , image ) ;
154161
155- Bitmap tempImage = null ;
162+ Bitmap processed = image ;
163+ Bitmap ? tempImage = null ;
156164
157- // Convert the image to Format32bppArgb if necessary
158- if ( image . PixelFormat != PixelFormat . Format32bppArgb )
165+ // Normalize to 32bppArgb if needed
166+ if ( image . PixelFormat != System . Drawing . Imaging . PixelFormat . Format32bppArgb )
159167 {
160- tempImage = new Bitmap ( image . Width , image . Height , PixelFormat . Format32bppArgb ) ;
168+ tempImage = new Bitmap ( image . Width , image . Height , System . Drawing . Imaging . PixelFormat . Format32bppArgb ) ;
169+
161170 using ( var g = Graphics . FromImage ( tempImage ) )
162- {
163171 g . DrawImage ( image , 0 , 0 ) ;
164- }
165172
166- image = tempImage ;
173+ processed = tempImage ;
167174 }
168175
169176 try
170177 {
171- // Create a memory stream and save the image in a compatible format (e.g., PNG)
172- using var memoryStream = new MemoryStream ( ) ;
173- image . Save ( memoryStream , ImageFormat . Png ) ;
174- memoryStream . Position = 0 ;
175-
176- // Create a BitmapImage from the memory stream
177- var bitmapImage = new BitmapImage ( ) ;
178- bitmapImage . BeginInit ( ) ;
179- bitmapImage . StreamSource = memoryStream ;
180- bitmapImage . CacheOption = BitmapCacheOption . OnLoad ; // Ensures full load and availability
181- bitmapImage . EndInit ( ) ;
182- bitmapImage . Freeze ( ) ; // Makes it thread-safe and ready for WPF usage
183-
184- return bitmapImage ;
178+ using var ms = new MemoryStream ( ) ;
179+ processed . Save ( ms , ImageFormat . Png ) ;
180+ ms . Position = 0 ;
181+
182+ var bmp = new BitmapImage ( ) ;
183+ bmp . BeginInit ( ) ;
184+ bmp . StreamSource = ms ;
185+ bmp . CacheOption = BitmapCacheOption . OnLoad ;
186+ bmp . EndInit ( ) ;
187+ bmp . Freeze ( ) ;
188+
189+ return bmp ;
185190 }
186191 finally
187192 {
188- tempImage ? . Dispose ( ) ; // Dispose of the temporary image if created
193+ tempImage ? . Dispose ( ) ;
189194 }
190195 }
191- }
196+
197+ /// <summary>
198+ /// Fasts the convert.
199+ /// </summary>
200+ /// <param name="bmp">The BMP.</param>
201+ /// <returns>BitmapImage from Bitmap.</returns>
202+ private static BitmapImage FastConvert ( Bitmap bmp )
203+ {
204+ // Ensure 32bpp ARGB
205+ if ( bmp . PixelFormat != System . Drawing . Imaging . PixelFormat . Format32bppArgb )
206+ {
207+ var converted = new Bitmap ( bmp . Width , bmp . Height , System . Drawing . Imaging . PixelFormat . Format32bppArgb ) ;
208+ using var g = Graphics . FromImage ( converted ) ;
209+ g . DrawImage ( bmp , 0 , 0 ) ;
210+ bmp = converted ;
211+ }
212+
213+ var rect = new System . Drawing . Rectangle ( 0 , 0 , bmp . Width , bmp . Height ) ;
214+ var bmpData = bmp . LockBits ( rect , ImageLockMode . ReadOnly , System . Drawing . Imaging . PixelFormat . Format32bppArgb ) ;
215+
216+ try
217+ {
218+ // WPF erwartet Int32Rect und PixelFormats.Bgra32
219+ var wbRect = new Int32Rect ( 0 , 0 , bmp . Width , bmp . Height ) ;
220+
221+ var wb = new WriteableBitmap (
222+ bmp . Width ,
223+ bmp . Height ,
224+ 96 , 96 ,
225+ PixelFormats . Bgra32 ,
226+ null ) ;
227+
228+ // Verwende die IntPtr-Überladung: WritePixels(Int32Rect, IntPtr buffer, int bufferSize, int stride)
229+ wb . WritePixels ( wbRect , bmpData . Scan0 , Math . Abs ( bmpData . Stride ) * bmp . Height , Math . Abs ( bmpData . Stride ) ) ;
230+ wb . Freeze ( ) ;
231+
232+ return WriteableBitmapToBitmapImage ( wb ) ;
233+ }
234+ finally
235+ {
236+ bmp . UnlockBits ( bmpData ) ;
237+ }
238+ }
239+
240+ /// <summary>
241+ /// Writeables the bitmap to bitmap image.
242+ /// </summary>
243+ /// <param name="wb">The wb.</param>
244+ /// <returns>BitmapImage from Bitmap.</returns>
245+ private static BitmapImage WriteableBitmapToBitmapImage ( WriteableBitmap wb )
246+ {
247+ var encoder = new JpegBitmapEncoder ( ) ; // MUCH faster than PNG
248+ encoder . QualityLevel = 100 ; // visually lossless
249+
250+ using var ms = new MemoryStream ( ) ;
251+ encoder . Frames . Add ( BitmapFrame . Create ( wb ) ) ;
252+ encoder . Save ( ms ) ;
253+ ms . Position = 0 ;
254+
255+ var bmp = new BitmapImage ( ) ;
256+ bmp . BeginInit ( ) ;
257+ bmp . CacheOption = BitmapCacheOption . OnLoad ;
258+ bmp . StreamSource = ms ;
259+ bmp . EndInit ( ) ;
260+ bmp . Freeze ( ) ;
261+ return bmp ;
262+ }
263+ }
0 commit comments