GDI+ Convert Picture to 8-Bit (256 colors) Topic is solved

Ask gaming related questions (AHK v1.1 and older)
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

GDI+ Convert Picture to 8-Bit (256 colors)

12 Aug 2023, 02:21

The image loses quality, as if saved by MSPaint in 8-Bit (256 colors).
Basically it is not able to use all 256 colors, just a little more than 140 depending on the image.

Code: Select all

#SingleInstance Force
SetWorkingDir %A_ScriptDir%
#Include Gdip_All.ahk

; Check Gdip is Working
if (!pToken := Gdip_Startup())
{
	MsgBox, 0x30, Error, Error starting GDIP
	ExitApp
}

Hotkey IfWinActive, ahk_exe game.exe
Hotkey, F2, StartSnapshot
return

StartSnapshot:
if(!WinExist("ahk_exe game.exe"))
{
	MsgBox The game is not running!
	return
}
WinGet, GAMEHWND, ID, ahk_exe game.exe
pBitmap := Gdip_BitmapFromHWND(GAMEHWND, 1)
pBitmap8bpp := Gdip_CloneBitmapArea(pBitmap, 2, 2, A_ScreenWidth-2, A_ScreenHeight-2, "0x30803")
Gdip_SaveBitmapToFile(pBitmap8bpp, A_WorkingDir "\" A_YYYY A_MM A_DD A_Hour A_Min A_Sec A_MSec ".png")
Gdip_DisposeImage(pBitmap)
Gdip_DisposeImage(pBitmap8bpp)
return
Result:
Image
Reference: https://www.autohotkey.com/boards/viewtopic.php?p=391227#p391227

However using IrfanView I got the correct result, but I really don't want to be dependent on it:

Code: Select all

Run, % "i_view64.exe /capture=3 /bpp=8 /convert=" A_YYYY A_MM A_DD A_Hour A_Min A_Sec A_MSec ".png"
Result:
Image

I don't know if this is a GDI+ limitation, but if anyone has a solution or way to show me.
I look forward to it and thank you in advance


[Mod action: Moved topic to the gaming section.]
Last edited by DevWithCoffee on 15 Aug 2023, 23:17, edited 3 times in total.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Convert Picture to 8-Bit

12 Aug 2023, 11:41

Looks like it could be the format you are using. 0x30803

pBitmap := Gdip_CloneBitmapArea(pBitmap, 2, 2, A_ScreenWidth-2, A_ScreenHeight-2, "0x30803")

.
20230812123136.png
20230812123136.png (62.28 KiB) Viewed 1924 times
.

https://www.autohotkey.com/boards/viewtopic.php?p=391227#p391227



You should also use a new bitmap for the clone so that you can dispose of the original.

Code: Select all

pBitmap := Gdip_CloneBitmapArea( pBitmap  ;<<<<---- memory leak.
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: Convert Picture to 8-Bit

13 Aug 2023, 18:22

Hellbent wrote:
12 Aug 2023, 11:41
Looks like it could be the format you are using. 0x30803

pBitmap := Gdip_CloneBitmapArea(pBitmap, 2, 2, A_ScreenWidth-2, A_ScreenHeight-2, "0x30803")
(...)
Yeah, I think that's it too, but I don't understand how IrfanView manages to do it without losing quality, I've searched the whole list and none of the PixelFormat seem to work.
Hellbent wrote:
12 Aug 2023, 11:41

You should also use a new bitmap for the clone so that you can dispose of the original.

Code: Select all

pBitmap := Gdip_CloneBitmapArea( pBitmap  ;<<<<---- memory leak.
I had already done so, but I realized that it was just a waste of memory in this case.
Even so I edited the code in the main post, the result is the same.

The format I tried first was 0x800 (8bpp) but it returns 0

Edit:
I used Photoshop to reproduce the effect, I activated the Web Snap at 100% and the same thing happens with the image, it loses most of the colors of the patella
Image

Edit 2:
I did a test, I loaded an image from disk that was already in 8-Bit converted by Photoshop.
The script generates another exactly the same without losing quality.

Code: Select all

#SingleInstance Force
SetWorkingDir %A_ScriptDir%
#Include Gdip_All.ahk
if (!pToken := Gdip_Startup())
{
    MsgBox, 0x30, Error, Error starting GDIP
    ExitApp
}
pBitmapFile := Gdip_CreateBitmapFromFile("_png32.png")
pBitmap := Gdip_CreateBitmap(800, 600, "0x30803")
G := Gdip_GraphicsFromImage(pBitmap)
Gdip_SetSmoothingMode(G, 4)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmapFile, 0, 0, 800, 600)
Gdip_DisposeImage(pBitmapFile)
Gdip_SaveBitmapToFile(pBitmap, "png32-to-8_gdi.png")
Gdip_DisposeImage(pBitmap)
Gdip_DeleteGraphics(G)

pBitmapFile := Gdip_CreateBitmapFromFile("_png8.png")
pBitmap := Gdip_CreateBitmap(800, 600, "0x30803")
G := Gdip_GraphicsFromImage(pBitmap)
Gdip_SetSmoothingMode(G, 4)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmapFile, 0, 0, 800, 600)
Gdip_DisposeImage(pBitmapFile)
Gdip_SaveBitmapToFile(pBitmap, "png8-to-8_gdi.png")
Gdip_DisposeImage(pBitmap)
Gdip_DeleteGraphics(G)
ExitApp
Result:
PNG 32 to 8-bit
https://servimg.com/view/20244785/154

PNG 8 (Photoshop) to 8-bit:
https://servimg.com/view/20244785/155

I really don't know if it's possible to solve this anymore...
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Convert Picture to 8-Bit

14 Aug 2023, 01:04

DevWithCoffee wrote:
13 Aug 2023, 18:22
Hellbent wrote:
12 Aug 2023, 11:41
Looks like it could be the format you are using. 0x30803

pBitmap := Gdip_CloneBitmapArea(pBitmap, 2, 2, A_ScreenWidth-2, A_ScreenHeight-2, "0x30803")
(...)
Yeah, I think that's it too, but I don't understand how IrfanView manages to do it without losing quality, I've searched the whole list and none of the PixelFormat seem to work.
You can try 0x26200A



.
20230813235451.png
20230813235451.png (128.74 KiB) Viewed 1798 times
.


I also noticed that you are using a different bitmap from hwnd function than I am so I don't know what else you may have going on in it.

This is the function I am using.

Code: Select all

;#####################################################################################

; Function				Gdip_BitmapFromHWND
; Description			Uses PrintWindow to get a handle to the specified window and return a bitmap from it
;
; hwnd					handle to the window to get a bitmap from
;
; return				If the function succeeds, the return value is a pointer to a gdi+ bitmap
;
; notes					Window must not be not minimised in order to get a handle to it's client area

Gdip_BitmapFromHWND(hwnd)
{
	WinGetPos,,, Width, Height, ahk_id %hwnd%
	hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
	PrintWindow(hwnd, hdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
	return pBitmap
}

;#####################################################################################
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: Convert Picture to 8-Bit

14 Aug 2023, 01:52

0x26200A is Format32bppArgb
This is not the case, the image needs to be at 8bpp, the fact is that IrfanView or other converters can do this.
The problem is not in the function used, see the previous example I posted.

From what a discord channel user told me this is a limitation of the Libs used by GDI, it would be necessary to use other Libs
Due to the limited time I have I will have to use IrfanView as before.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Convert Picture to 8-Bit

14 Aug 2023, 02:53

DevWithCoffee wrote:
14 Aug 2023, 01:52
0x26200A is Format32bppArgb
This is not the case, the image needs to be at 8bpp, the fact is that IrfanView or other converters can do this.
The problem is not in the function used, see the previous example I posted.

From what a discord channel user told me this is a limitation of the Libs used by GDI, it would be necessary to use other Libs
Due to the limited time I have I will have to use IrfanView as before.
Ok. I misunderstood what you wanted.
This led me to believe that you didn't want it in 8 bit :D
The image loses quality, as if saved by MSPaint in 8-Bit (256 colors).


I don't understand what you are trying to do or why you would want or need to save it in 8 bit.
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: Convert Picture to 8-Bit

14 Aug 2023, 13:01

Hellbent wrote:
14 Aug 2023, 02:53
Ok. I misunderstood what you wanted.
This led me to believe that you didn't want it in 8 bit :D
The image loses quality, as if saved by MSPaint in 8-Bit (256 colors).
Sorry if I expressed myself badly, but that's what I explained here:
DevWithCoffee wrote:
13 Aug 2023, 18:22
(...) I don't understand how IrfanView manages to do it without losing quality, I've searched the whole list and none of the PixelFormat seem to work.
As I showed here the result:
DevWithCoffee wrote:
13 Aug 2023, 18:22
Result:
PNG 32 to 8-bit
https://servimg.com/view/20244785/154

PNG 8 (Photoshop) to 8-bit:
https://servimg.com/view/20244785/155

Hellbent wrote:
14 Aug 2023, 02:53
I don't understand what you are trying to do or why you would want or need to save it in 8 bit.
The reason is not relevant to the solution, but it is for a project that I need, there are a lot of images that I have in PNG 24-bit and 32-bit, but the system that I'm going to use needs them to be 8-Bit and not I want to do this manually and not even use third-party programs, just the WinAPI.

I think I'll have to separate pixel by pixel before converting and putting everything back together into a new Bitmap, but that will probably take a lot of time for the end user.
So I'll have to keep using IrfanView, but I'll keep this topic in case someone finds a solution.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Convert Picture to 8-Bit

14 Aug 2023, 17:12

DevWithCoffee wrote:
14 Aug 2023, 13:01
Hellbent wrote:
14 Aug 2023, 02:53
Ok. I misunderstood what you wanted.
This led me to believe that you didn't want it in 8 bit :D
The image loses quality, as if saved by MSPaint in 8-Bit (256 colors).
Sorry if I expressed myself badly,
I'm sure it makes sense to anyone that knows the difference between a MSPaint 8-Bit image and some other software's 8-bit image.
I honestly don't understand why there would be a difference or how saving it as a .png even fits in here.

but that's what I explained here:
DevWithCoffee wrote:
13 Aug 2023, 18:22
(...) I don't understand how IrfanView manages to do it without losing quality, I've searched the whole list and none of the PixelFormat seem to work.
I don't understand what that means. To me, downgrading an image from 32-bit to 8-bit is by definition a loss of quality.
At any rate, you are trying to do something that I don't have any experience in so I have nothing to offer.
Good luck with your project.
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: Convert Picture to 8-Bit

14 Aug 2023, 18:36

Hellbent wrote:
14 Aug 2023, 17:12
I don't understand what that means. To me, downgrading an image from 32-bit to 8-bit is by definition a loss of quality.
An 8-Bit image has a limit of 256 colors, but when MSPaint or GDI convert the image it reaches around 100 colors.
But when I convert with IrfanView, FastStone Photo Resizer, Paint.NET or PhotoShop it manages to use 256 colors.
The loss of quality that I am referring to is this, the images of the links that I passed earlier are 8-bits, and the difference in quality is visibly noticeable.
Hellbent wrote:
14 Aug 2023, 17:12
At any rate, you are trying to do something that I don't have any experience in so I have nothing to offer.
Good luck with your project.
Thank you so much for taking the time to try to help me.
If I ever find a solution I'll post it here.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Convert Picture to 8-Bit

14 Aug 2023, 20:19

DevWithCoffee wrote:
14 Aug 2023, 18:36
and the difference in quality is visibly noticeable.
That only became relevant once I knew that you were trying to convert to 8-bit from 8-bit.
As I said, I thought that you didn't want it in 8-bit so it was a no-brainer that you were losing quality, so you showing two different images (before/after) really didn't tell me much other than you were getting the outcome I actually expected you to be getting lol.


Thank you so much for taking the time to try to help me.
If I ever find a solution I'll post it here.
I look forward to it.
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: Convert Picture to 8-Bit  Topic is solved

15 Aug 2023, 19:39

I managed to find out the problem, the documentation doesn't have examples of some functions, but reading about the PNG format I understood that there are levels of color depth.
So I opened the GDI_All.ahk LIB and looked for the term "Depth" with a capital initial, and I ended up finding this function:
Gdip_BitmapSetColorDepth(pBitmap, bitsDepth, useDithering:=1) {
(...)


In this part I put a MsgBox to return the value of the local variable "Colors" and tested it level by level:

Code: Select all

Gdip_BitmapSetColorDepth(pBitmap, bitsDepth, useDithering:=1) {
; Return 0 = OK - Success

   ditheringMode := (useDithering=1) ? 9 : 1
   If (useDithering=1 && bitsDepth=16)
      ditheringMode := 2

   Colors := 2**bitsDepth
   If bitsDepth Between 2 and 4
      bitsDepth := "40s"
   If bitsDepth Between 5 and 8
      bitsDepth := "80s"
   MsgBox % "Colors: " Colors ; Total of coulors
Between 5 and 8 it uses "80s", but only in 8 it allows up to 256 colors, and each image I have doesn't reach 200.
I disabled "useDithering" when calling the function, which is enabled by default, because this creates a lot of mixed pixels and since the images are simple I don't need it:
Gdip_BitmapSetColorDepth(pBitmap, 8, 0)

As the image is already a PNG, the LIB itself will choose the amount of Bits, so I can't set it to "0x30803" why does it spoil the image why is this parameter used before defining the color depth that must be defined one step before save the image:

Code: Select all

pBitmapFile := Gdip_CreateBitmapFromFile("_png32.png")
pBitmap := Gdip_CreateBitmap(1600, 1200) ;, No use! 0x30803 0x26200A
G := Gdip_GraphicsFromImage(pBitmap)
Gdip_DrawImage(G, pBitmapFile, 0, 0, 1600, 1200, 0, 0, 1600, 1200)
Gdip_DisposeImage(pBitmapFile)
Gdip_BitmapSetColorDepth(pBitmap, 8, 0)
Gdip_SaveBitmapToFile(pBitmap, "png32_to_png8-gdi.png")
Gdip_DisposeImage(pBitmap)
Gdip_DeleteGraphics(G)
return
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: GDI+ Convert Picture to 8-Bit (256 colors)

18 Aug 2023, 00:12

@DevWithCoffee
Thanks for sharing that. It looks like I don't have a copy of that function you are using, would you mind sharing it.

Code: Select all

Gdip_BitmapSetColorDepth(pBitmap, bitsDepth, useDithering:=1 )
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: GDI+ Convert Picture to 8-Bit (256 colors)

18 Aug 2023, 00:25

This LIB version is from May of this year, but I can't say when it was implemented:
https://github.com/marius-sucan/AHK-GDIp-Library-Compilation/blob/master/ahk-v1-1/Gdip_All.ahk
User avatar
DevWithCoffee
Posts: 54
Joined: 13 Oct 2020, 12:16

Re: GDI+ Convert Picture to 8-Bit (256 colors)

20 Aug 2023, 18:27

If by any chance you're interested in this feature, here's a window capture (Hwnd) fix that works on Windows 7:
viewtopic.php?t=120476

Return to “Gaming Help (v1)”

Who is online

Users browsing this forum: mikeyww and 26 guests