hlzxcjx 发表于 2024-7-12 21:57:24

[已解决]请问用什么函数检测JPG或BMP的颜色?DllCall方式检测颜色有BUG!

本帖最后由 hlzxcjx 于 2024-7-16 21:26 编辑

请问有没有好用的函数检测JPG或BMP的颜色?用函数DllCall($ghGDIPDll, 'uint', 'GdipBitmapGetPixel', 'ptr', $hImage, 'int', $iX, 'int', $iY, 'ptr*', 0)检测颜色,当检测的图片达一定量的时候就会出现错误,检测不出来!

下面的源码,当检测图片数达25个时,就出现错误:





#include <gdiplus.au3>

For $i = 2 To 30
      FileCopy("1.jpg", $i & ".jpg")
Next

_GDIPlus_Startup()

For $k = 1 To 30
      $hBitmap = _GDIPlus_BitmapCreateFromFile($k & ".jpg")
      $aRet = _GDIPlus_ImageGetPixelFormat($hBitmap)

      $h = _GDIPlus_ImageGetHeight($hBitmap)
      $w = _GDIPlus_ImageGetWidth($hBitmap)

      For $j = 0 To 100
                For $i = 0 To $w - 1
                        $colour = _myBitmapGetPixel($hBitmap, $i, $j)
                        $colour2 = Dec(StringTrimLeft($colour, 4))
                        If $colour2 <> 16777215 Then
                              MsgBox(0, "颜色值=" & $colour & "--" & $colour2, "检测颜色出错!" & "第" & $k & "个图片,第" & $j & "行 第" & $i & "列")
                        EndIf
                Next
                ToolTip("第" & $k & "个图片,第" & $j & "行 第" & $i & "列")
      Next
Next

MsgBox(0, 0, "end   第" & $k & "个图片,第" & $j & "行 第" & $i & "列")

_GDIPlus_ImageDispose($hBitmap)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_Shutdown()


Func _myBitmapCreate($iWidth, $iHeight, $iFormat = $GDIP_PXF24RGB);创建位图方式1, 此方法效率最高, 同时与Gdiplus兼容
      Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", 0, "int", $iFormat, "ptr", 0, "int*", 0)
      If @error Then Return SetError(@error, @extended, 0)
      Return $aResult
EndFunc   ;==>_myBitmapCreate

Func _myBitmapCreate2($iWidth, $iHeight, $iFormat = $GDIP_PXF32RGB);备忘: 我在2009年采用的WinApi方式创建位图方式, 只支持1,32 Bpp
      Local $hRet, $hBitmap
      Switch $iFormat
                Case $GDIP_PXF01INDEXED
                        $iFormat = 1
                Case Else
                        $iFormat = 32
      EndSwitch
      $hRet = _WinAPI_CreateBitmap($iWidth, $iHeight, 1, $iFormat)
      $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hRet)
      _WinAPI_DeleteObject($hRet)
      Return $hBitmap
EndFunc   ;==>_myBitmapCreate2

Func _myBitmapSetPixel($hImage, $iX, $iY, $iArgb)
      DllCall($ghGDIPDll, "int", "GdipBitmapSetPixel", "hwnd", $hImage, "int", $iX, "int", $iY, "dword", $iArgb)
      If @error Then Return SetError(@error, @extended, 0)
EndFunc   ;==>_myBitmapSetPixel

Func _myBitmapGetPixel($hImage, $iX, $iY)
      Local $aResult = DllCall($ghGDIPDll, 'uint', 'GdipBitmapGetPixel', 'ptr', $hImage, 'int', $iX, 'int', $iY, 'ptr*', 0)
      If @error Then
                Return SetError(@error, @extended, 0)
      Else
                Return $aResult
      EndIf
EndFunc   ;==>_myBitmapGetPixel

3131210 发表于 2024-7-14 23:19:17

bmp完全没问题






#include <GDIPlus.au3>

For $i = 1 To 30
        FileCopy("1.bmp", $i & ".bmp")
Next

_GDIPlus_Startup()

For $k = 1 To 30
        $hBitmap = _GDIPlus_BitmapCreateFromFile($k & ".bmp")
        $h = _GDIPlus_ImageGetHeight($hBitmap)
        $w = _GDIPlus_ImageGetWidth($hBitmap)

        For $j = 0 To $h - 1
                For $i = 0 To $w - 1
                        $colour = Dec(StringTrimLeft(Hex(_GDIPlus_BitmapGetPixel($hBitmap, $i, $j), 8), 2))
                        If $colour <> 16777215 Then
                                ConsoleWrite("颜色值=" & $colour & '' & "检测颜色出错!" & "第" & $k & "个图片,第" & $j & "行 第" & $i & "列" & @CRLF)
                        EndIf
                Next
        Next
Next

_GDIPlus_ImageDispose($hBitmap)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_Shutdown()


hlzxcjx 发表于 2024-7-15 14:55:38

3131210 发表于 2024-7-14 23:19
bmp完全没问题

首先你的附件里都没有BMP图片,只有JPG图片,测试几秒就完成?
其次测试行数不要太多,否则一个图片扫描太久,每个图片测试100行够了:For $j = 0 To 100;
虽然新版有了内置函数_GDIPlus_BitmapGetPixel,但扫描图片多了仍然会出错!

3131210 发表于 2024-7-15 15:39:17

jpg 你的图片 没报错

hlzxcjx 发表于 2024-7-15 15:49:46

本帖最后由 hlzxcjx 于 2024-7-15 16:10 编辑

3131210 发表于 2024-7-15 15:39
jpg 你的图片 没报错
几秒完成且不出错?难道与电脑配置有关?测试100个或以上图片试试!
还是与版本有关?我用的是稳定版:v3.3.13.12, 请问你用的什么版本?

3131210 发表于 2024-7-15 18:05:35

我能想到的就是你内存爆了
#include <GDIPlus.au3>

Local $num = 100

For $i = 1 To $num
        FileCopy("1.jpg", $i & ".jpg")
Next

_GDIPlus_Startup()

For $k = 1 To $num
        $hBitmap = _GDIPlus_BitmapCreateFromFile($k & ".jpg")
        $h = _GDIPlus_ImageGetHeight($hBitmap)
        $w = _GDIPlus_ImageGetWidth($hBitmap)

        For $j = 0 To $h - 1
                For $i = 0 To $w - 1
                        $colour = Dec(StringTrimLeft(Hex(_GDIPlus_BitmapGetPixel($hBitmap, $i, $j), 8), 2))
                        If $colour <> 16777215 Then
                                ConsoleWrite("颜色值=" & $colour & '' & "检测颜色出错!" & "第" & $k & "个图片,第" & $j & "行 第" & $i & "列" & @CRLF)
                        EndIf
                Next
        Next
        _GDIPlus_ImageDispose($hBitmap)
Next
_GDIPlus_Shutdown()

hlzxcjx 发表于 2024-7-15 23:47:48

3131210 发表于 2024-7-15 18:05
我能想到的就是你内存爆了

好像与没有释放资源有关!检测每个图片后都加如下语句:
   _GDIPlus_ImageDispose($hBitmap)
似乎不出错了!
页: [1]
查看完整版本: [已解决]请问用什么函数检测JPG或BMP的颜色?DllCall方式检测颜色有BUG!