@@ -832,167 +832,182 @@ ImageHandle initNative(String filename, int zoom) {
832832 * The fix is to not use GDI+ image loading in this case.
833833 */
834834 if (filename .toLowerCase ().endsWith (".gif" )) gdip = false ;
835- if (gdip ) {
836- int length = filename .length ();
837- char [] chars = new char [length +1 ];
838- filename .getChars (0 , length , chars , 0 );
839- long bitmap = Gdip .Bitmap_new (chars , false );
840- if (bitmap != 0 ) {
841- int error = SWT .ERROR_NO_HANDLES ;
842- int status = Gdip .Image_GetLastStatus (bitmap );
843- if (status == 0 ) {
844- if (filename .toLowerCase ().endsWith (".ico" )) {
845- this .type = SWT .ICON ;
846- long [] hicon = new long [1 ];
847- status = Gdip .Bitmap_GetHICON (bitmap , hicon );
848- handle = hicon [0 ];
849- imageMetadata = new ImageHandle (handle , zoom );
850- } else {
851- this .type = SWT .BITMAP ;
852- width = Gdip .Image_GetWidth (bitmap );
853- height = Gdip .Image_GetHeight (bitmap );
854- int pixelFormat = Gdip .Image_GetPixelFormat (bitmap );
855- switch (pixelFormat ) {
856- case Gdip .PixelFormat16bppRGB555 :
857- case Gdip .PixelFormat16bppRGB565 :
858- handle = createDIB (width , height , 16 );
859- break ;
860- case Gdip .PixelFormat24bppRGB :
861- case Gdip .PixelFormat32bppCMYK :
862- handle = createDIB (width , height , 24 );
863- break ;
864- case Gdip .PixelFormat32bppRGB :
865- // These will lose either precision or transparency
866- case Gdip .PixelFormat16bppGrayScale :
867- case Gdip .PixelFormat48bppRGB :
868- case Gdip .PixelFormat32bppPARGB :
869- case Gdip .PixelFormat64bppARGB :
870- case Gdip .PixelFormat64bppPARGB :
871- handle = createDIB (width , height , 32 );
872- break ;
835+
836+ if (!gdip ) return null ;
837+
838+ int length = filename .length ();
839+ char [] chars = new char [length +1 ];
840+ filename .getChars (0 , length , chars , 0 );
841+ long bitmap = Gdip .Bitmap_new (chars , false );
842+ if (bitmap == 0 ) return null ;
843+
844+ int error = SWT .ERROR_NO_HANDLES ;
845+ int status = Gdip .Image_GetLastStatus (bitmap );
846+ if (status == 0 ) {
847+ if (filename .toLowerCase ().endsWith (".ico" )) {
848+ this .type = SWT .ICON ;
849+ long [] hicon = new long [1 ];
850+ status = Gdip .Bitmap_GetHICON (bitmap , hicon );
851+ handle = hicon [0 ];
852+ imageMetadata = new ImageHandle (handle , zoom );
853+ } else {
854+ this .type = SWT .BITMAP ;
855+ width = Gdip .Image_GetWidth (bitmap );
856+ height = Gdip .Image_GetHeight (bitmap );
857+ int pixelFormat = Gdip .Image_GetPixelFormat (bitmap );
858+ handle = extractHandleForPixelFormat (width , height , pixelFormat );
859+ if (handle != 0 ) {
860+ /*
861+ * This performs better than getting the bits with Bitmap.LockBits(),
862+ * but it cannot be used when there is transparency.
863+ */
864+ long hDC = device .internal_new_GC (null );
865+ long srcHDC = OS .CreateCompatibleDC (hDC );
866+ long oldSrcBitmap = OS .SelectObject (srcHDC , handle );
867+ long graphics = Gdip .Graphics_new (srcHDC );
868+ if (graphics != 0 ) {
869+ Rect rect = new Rect ();
870+ rect .Width = width ;
871+ rect .Height = height ;
872+ status = Gdip .Graphics_DrawImage (graphics , bitmap , rect , 0 , 0 , width , height , Gdip .UnitPixel , 0 , 0 , 0 );
873+ if (status != 0 ) {
874+ error = SWT .ERROR_INVALID_IMAGE ;
875+ OS .DeleteObject (handle );
876+ handle = 0 ;
873877 }
874- if (handle != 0 ) {
875- /*
876- * This performs better than getting the bits with Bitmap.LockBits(),
877- * but it cannot be used when there is transparency.
878- */
879- long hDC = device .internal_new_GC (null );
880- long srcHDC = OS .CreateCompatibleDC (hDC );
881- long oldSrcBitmap = OS .SelectObject (srcHDC , handle );
882- long graphics = Gdip .Graphics_new (srcHDC );
883- if (graphics != 0 ) {
884- Rect rect = new Rect ();
885- rect .Width = width ;
886- rect .Height = height ;
887- status = Gdip .Graphics_DrawImage (graphics , bitmap , rect , 0 , 0 , width , height , Gdip .UnitPixel , 0 , 0 , 0 );
888- if (status != 0 ) {
889- error = SWT .ERROR_INVALID_IMAGE ;
890- OS .DeleteObject (handle );
891- handle = 0 ;
878+ Gdip .Graphics_delete (graphics );
879+ }
880+ OS .SelectObject (srcHDC , oldSrcBitmap );
881+ OS .DeleteDC (srcHDC );
882+ device .internal_dispose_GC (hDC , null );
883+ imageMetadata = new ImageHandle (handle , zoom );
884+ } else {
885+ long lockedBitmapData = Gdip .BitmapData_new ();
886+ if (lockedBitmapData != 0 ) {
887+ status = Gdip .Bitmap_LockBits (bitmap , 0 , 0 , pixelFormat , lockedBitmapData );
888+ if (status == 0 ) {
889+ BitmapData bitmapData = new BitmapData ();
890+ Gdip .MoveMemory (bitmapData , lockedBitmapData );
891+ int stride = bitmapData .Stride ;
892+ long pixels = bitmapData .Scan0 ;
893+ int depth = 0 , scanlinePad = 4 , transparentPixel = -1 ;
894+ depth = extractDepthForPixelFormat (bitmapData );
895+ if (depth != 0 ) {
896+ PaletteData paletteData = null ;
897+ switch (bitmapData .PixelFormat ) {
898+ case Gdip .PixelFormat1bppIndexed :
899+ case Gdip .PixelFormat4bppIndexed :
900+ case Gdip .PixelFormat8bppIndexed :
901+ int paletteSize = Gdip .Image_GetPaletteSize (bitmap );
902+ long hHeap = OS .GetProcessHeap ();
903+ long palette = OS .HeapAlloc (hHeap , OS .HEAP_ZERO_MEMORY , paletteSize );
904+ if (palette == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
905+ Gdip .Image_GetPalette (bitmap , palette , paletteSize );
906+ ColorPalette colorPalette = new ColorPalette ();
907+ Gdip .MoveMemory (colorPalette , palette , ColorPalette .sizeof );
908+ int [] entries = new int [colorPalette .Count ];
909+ OS .MoveMemory (entries , palette + 8 , entries .length * 4 );
910+ OS .HeapFree (hHeap , 0 , palette );
911+ RGB [] rgbs = new RGB [colorPalette .Count ];
912+ paletteData = new PaletteData (rgbs );
913+ for (int i = 0 ; i < entries .length ; i ++) {
914+ if (((entries [i ] >> 24 ) & 0xFF ) == 0 && (colorPalette .Flags & Gdip .PaletteFlagsHasAlpha ) != 0 ) {
915+ transparentPixel = i ;
916+ }
917+ rgbs [i ] = new RGB (((entries [i ] & 0xFF0000 ) >> 16 ), ((entries [i ] & 0xFF00 ) >> 8 ), ((entries [i ] & 0xFF ) >> 0 ));
918+ }
919+ break ;
920+ case Gdip .PixelFormat16bppARGB1555 :
921+ case Gdip .PixelFormat16bppRGB555 : paletteData = new PaletteData (0x7C00 , 0x3E0 , 0x1F ); break ;
922+ case Gdip .PixelFormat16bppRGB565 : paletteData = new PaletteData (0xF800 , 0x7E0 , 0x1F ); break ;
923+ case Gdip .PixelFormat24bppRGB : paletteData = new PaletteData (0xFF , 0xFF00 , 0xFF0000 ); break ;
924+ case Gdip .PixelFormat32bppRGB :
925+ case Gdip .PixelFormat32bppARGB : paletteData = new PaletteData (0xFF00 , 0xFF0000 , 0xFF000000 ); break ;
892926 }
893- Gdip .Graphics_delete (graphics );
894- }
895- OS .SelectObject (srcHDC , oldSrcBitmap );
896- OS .DeleteDC (srcHDC );
897- device .internal_dispose_GC (hDC , null );
898- imageMetadata = new ImageHandle (handle , zoom );
899- } else {
900- long lockedBitmapData = Gdip .BitmapData_new ();
901- if (lockedBitmapData != 0 ) {
902- status = Gdip .Bitmap_LockBits (bitmap , 0 , 0 , pixelFormat , lockedBitmapData );
903- if (status == 0 ) {
904- BitmapData bitmapData = new BitmapData ();
905- Gdip .MoveMemory (bitmapData , lockedBitmapData );
906- int stride = bitmapData .Stride ;
907- long pixels = bitmapData .Scan0 ;
908- int depth = 0 , scanlinePad = 4 , transparentPixel = -1 ;
909- switch (bitmapData .PixelFormat ) {
910- case Gdip .PixelFormat1bppIndexed : depth = 1 ; break ;
911- case Gdip .PixelFormat4bppIndexed : depth = 4 ; break ;
912- case Gdip .PixelFormat8bppIndexed : depth = 8 ; break ;
913- case Gdip .PixelFormat16bppARGB1555 :
914- case Gdip .PixelFormat16bppRGB555 :
915- case Gdip .PixelFormat16bppRGB565 : depth = 16 ; break ;
916- case Gdip .PixelFormat24bppRGB : depth = 24 ; break ;
917- case Gdip .PixelFormat32bppRGB :
918- case Gdip .PixelFormat32bppARGB : depth = 32 ; break ;
919- }
920- if (depth != 0 ) {
921- PaletteData paletteData = null ;
922- switch (bitmapData .PixelFormat ) {
923- case Gdip .PixelFormat1bppIndexed :
924- case Gdip .PixelFormat4bppIndexed :
925- case Gdip .PixelFormat8bppIndexed :
926- int paletteSize = Gdip .Image_GetPaletteSize (bitmap );
927- long hHeap = OS .GetProcessHeap ();
928- long palette = OS .HeapAlloc (hHeap , OS .HEAP_ZERO_MEMORY , paletteSize );
929- if (palette == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
930- Gdip .Image_GetPalette (bitmap , palette , paletteSize );
931- ColorPalette colorPalette = new ColorPalette ();
932- Gdip .MoveMemory (colorPalette , palette , ColorPalette .sizeof );
933- int [] entries = new int [colorPalette .Count ];
934- OS .MoveMemory (entries , palette + 8 , entries .length * 4 );
935- OS .HeapFree (hHeap , 0 , palette );
936- RGB [] rgbs = new RGB [colorPalette .Count ];
937- paletteData = new PaletteData (rgbs );
938- for (int i = 0 ; i < entries .length ; i ++) {
939- if (((entries [i ] >> 24 ) & 0xFF ) == 0 && (colorPalette .Flags & Gdip .PaletteFlagsHasAlpha ) != 0 ) {
940- transparentPixel = i ;
941- }
942- rgbs [i ] = new RGB (((entries [i ] & 0xFF0000 ) >> 16 ), ((entries [i ] & 0xFF00 ) >> 8 ), ((entries [i ] & 0xFF ) >> 0 ));
943- }
944- break ;
945- case Gdip .PixelFormat16bppARGB1555 :
946- case Gdip .PixelFormat16bppRGB555 : paletteData = new PaletteData (0x7C00 , 0x3E0 , 0x1F ); break ;
947- case Gdip .PixelFormat16bppRGB565 : paletteData = new PaletteData (0xF800 , 0x7E0 , 0x1F ); break ;
948- case Gdip .PixelFormat24bppRGB : paletteData = new PaletteData (0xFF , 0xFF00 , 0xFF0000 ); break ;
949- case Gdip .PixelFormat32bppRGB :
950- case Gdip .PixelFormat32bppARGB : paletteData = new PaletteData (0xFF00 , 0xFF0000 , 0xFF000000 ); break ;
927+ byte [] data = new byte [stride * height ], alphaData = null ;
928+ OS .MoveMemory (data , pixels , data .length );
929+ switch (bitmapData .PixelFormat ) {
930+ case Gdip .PixelFormat16bppARGB1555 :
931+ alphaData = new byte [width * height ];
932+ for (int i = 1 , j = 0 ; i < data .length ; i += 2 , j ++) {
933+ alphaData [j ] = (byte )((data [i ] & 0x80 ) != 0 ? 255 : 0 );
951934 }
952- byte [] data = new byte [stride * height ], alphaData = null ;
953- OS .MoveMemory (data , pixels , data .length );
954- switch (bitmapData .PixelFormat ) {
955- case Gdip .PixelFormat16bppARGB1555 :
956- alphaData = new byte [width * height ];
957- for (int i = 1 , j = 0 ; i < data .length ; i += 2 , j ++) {
958- alphaData [j ] = (byte )((data [i ] & 0x80 ) != 0 ? 255 : 0 );
959- }
960- break ;
961- case Gdip .PixelFormat32bppARGB :
962- alphaData = new byte [width * height ];
963- for (int i = 3 , j = 0 ; i < data .length ; i += 4 , j ++) {
964- alphaData [j ] = data [i ];
965- }
966- break ;
935+ break ;
936+ case Gdip .PixelFormat32bppARGB :
937+ alphaData = new byte [width * height ];
938+ for (int i = 3 , j = 0 ; i < data .length ; i += 4 , j ++) {
939+ alphaData [j ] = data [i ];
967940 }
968- ImageData img = new ImageData (width , height , depth , paletteData , scanlinePad , data );
969- img .transparentPixel = transparentPixel ;
970- img .alphaData = alphaData ;
971-
972- ImageData newData = adaptImageDataIfDisabledOrGray (img );
973- init (newData , zoom );
974- imageMetadata = zoomLevelToImageHandle .get (zoom );
975- handle = imageMetadata .handle ;
976- }
977- Gdip .Bitmap_UnlockBits (bitmap , lockedBitmapData );
978- } else {
979- error = SWT .ERROR_INVALID_IMAGE ;
941+ break ;
980942 }
981- Gdip .BitmapData_delete (lockedBitmapData );
943+ ImageData img = new ImageData (width , height , depth , paletteData , scanlinePad , data );
944+ img .transparentPixel = transparentPixel ;
945+ img .alphaData = alphaData ;
946+
947+ ImageData newData = adaptImageDataIfDisabledOrGray (img );
948+ init (newData , zoom );
949+ imageMetadata = zoomLevelToImageHandle .get (zoom );
950+ handle = imageMetadata .handle ;
982951 }
952+ Gdip .Bitmap_UnlockBits (bitmap , lockedBitmapData );
953+ } else {
954+ error = SWT .ERROR_INVALID_IMAGE ;
983955 }
956+ Gdip .BitmapData_delete (lockedBitmapData );
984957 }
985958 }
986- Gdip .Bitmap_delete (bitmap );
987- if (status == 0 ) {
988- if (handle == 0 ) SWT .error (error );
989- if (imageMetadata == null ) SWT .error (error );
990- }
991959 }
992960 }
961+ Gdip .Bitmap_delete (bitmap );
962+ if (status == 0 ) {
963+ if (handle == 0 ) SWT .error (error );
964+ if (imageMetadata == null ) SWT .error (error );
965+ }
966+
993967 return imageMetadata ;
994968}
995969
970+ private int extractDepthForPixelFormat (BitmapData bitmapData ) {
971+ int depth = 0 ;
972+ switch (bitmapData .PixelFormat ) {
973+ case Gdip .PixelFormat1bppIndexed : depth = 1 ; break ;
974+ case Gdip .PixelFormat4bppIndexed : depth = 4 ; break ;
975+ case Gdip .PixelFormat8bppIndexed : depth = 8 ; break ;
976+ case Gdip .PixelFormat16bppARGB1555 :
977+ case Gdip .PixelFormat16bppRGB555 :
978+ case Gdip .PixelFormat16bppRGB565 : depth = 16 ; break ;
979+ case Gdip .PixelFormat24bppRGB : depth = 24 ; break ;
980+ case Gdip .PixelFormat32bppRGB :
981+ case Gdip .PixelFormat32bppARGB : depth = 32 ; break ;
982+ }
983+ return depth ;
984+ }
985+
986+ private long extractHandleForPixelFormat (int width , int height , int pixelFormat ) {
987+ long handle = 0 ;
988+ switch (pixelFormat ) {
989+ case Gdip .PixelFormat16bppRGB555 :
990+ case Gdip .PixelFormat16bppRGB565 :
991+ handle = createDIB (width , height , 16 );
992+ break ;
993+ case Gdip .PixelFormat24bppRGB :
994+ case Gdip .PixelFormat32bppCMYK :
995+ handle = createDIB (width , height , 24 );
996+ break ;
997+ case Gdip .PixelFormat32bppRGB :
998+ // These will lose either precision or transparency
999+ case Gdip .PixelFormat16bppGrayScale :
1000+ case Gdip .PixelFormat48bppRGB :
1001+ case Gdip .PixelFormat32bppPARGB :
1002+ case Gdip .PixelFormat64bppARGB :
1003+ case Gdip .PixelFormat64bppPARGB :
1004+ handle = createDIB (width , height , 32 );
1005+ break ;
1006+ }
1007+ return handle ;
1008+ }
1009+
1010+
9961011long [] createGdipImage () {
9971012 return createGdipImage (this .getZoom ());
9981013}
@@ -1185,6 +1200,17 @@ private void destroyHandle () {
11851200 zoomLevelToImageHandle .clear ();
11861201}
11871202
1203+ private void destroyHandle (int zoom ) {
1204+ zoomLevelToImageHandle .entrySet ().removeIf (entry -> {
1205+ final Integer zoomKey = entry .getKey ();
1206+ if (zoom == zoomKey ) {
1207+ destroyHandle (entry .getValue ().handle );
1208+ return true ;
1209+ }
1210+ return false ;
1211+ });
1212+ }
1213+
11881214@ Override
11891215void destroyHandlesExcept (Set <Integer > zoomLevels ) {
11901216 zoomLevelToImageHandle .entrySet ().removeIf (entry -> {
@@ -2136,16 +2162,11 @@ ImageData getImageData(int zoom) {
21362162 @ Override
21372163 ImageHandle getImageMetadata (int zoom ) {
21382164 ElementAtZoom <String > fileForZoom = DPIUtil .validateAndGetImagePathAtZoom (provider , zoom );
2139- ImageHandle nativeInitializedImage = null ;
2140- if (fileForZoom .zoom () == zoom ) {
2141- nativeInitializedImage = initNative (fileForZoom .element (), zoom );
2142- }
2143- if (nativeInitializedImage == null ) {
2144- ImageData imageData = new ImageData (fileForZoom .element ());
2145- if (fileForZoom .zoom () != zoom ) {
2146- imageData = DPIUtil .scaleImageData (device , imageData , zoom , fileForZoom .zoom ());
2147- }
2165+ ImageHandle nativeInitializedImage = initNative (fileForZoom .element (), zoom );
2166+ if (fileForZoom .zoom () != zoom ) {
2167+ ImageData imageData = DPIUtil .scaleImageData (device , nativeInitializedImage .getImageData (), zoom , fileForZoom .zoom ());
21482168 imageData = adaptImageDataIfDisabledOrGray (imageData );
2169+ destroyHandle (zoom );
21492170 init (imageData , zoom );
21502171 }
21512172 return zoomLevelToImageHandle .get (zoom );
0 commit comments