Что нового

Как самому сделать иконку которая имела бы три разрешения

assch

Новичок
Сообщения
166
Репутация
4
Как делается класическая иконка которая имела бы в себе (например три разных размера 16х16 32х32 48х48)
Делаются три иконки с этими размерами а потом как то объединяются?
Или как то по другому
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Любым редактором иконок. Самый лучший из них, IMHO Axialis IconWorkshop. А вообще, я сначала рисую или модифицирую уже готовые иконки в Adobe Photoshop и сохраняю каждую в .png, а затем объединяю их в .ico с помощью вышеупомянутой программы.

Вот несколько ссылок, где можно найти практически любые иконки разнообразного размера:

CrystalXP.net (средненько)
Customize.org (тоже, что и предыдущий)
deviantART (все, что душе угодно)
Iconfinder (не самый большой выбор, но очень удобный поиск)
WinCustomize (неплохой выбор, но раньше было намного лучше и удобнее)
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
СпасибоYashied
Я наверное просто не правильно поставил вопрос.
Скажем берёш файл PNG конвертируешь его в формат ICO с размерами 48х48 получается
готовая иконка (для рабочего стола) но в проводнике она будет смотрется чуть не корректно,
для проводника желателен размер 16х16.
То есть можно ли на языке Аутоит сделать такую иконку
с необходимыми размерами (три в одном 16х16 32х32 48х48)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Это делается одним кликом в Axialis IconWorkshop.
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Я знаю
Просто хотел это действие в свою утилитку вставить
На Аутоите это сложно реализовать?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Не не сложно. GDI+ для каждого размера, а затем _WinAPI_SaveHICONToFile(). Но часто, качество может быть неудовлетворительным при сильном уменьшении изображения.
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Спасибо за обнадёживающию информацию
Только чуть чуть не понял GDI+ для каждого размера это как?

PS.
Кстати твоя функция _WinAPI_SaveHICONToFile() просто класс
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Include <GDIPlus.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $Path = FileOpenDialog('Select Image File', @ScriptDir, 'All Images (*.bmp;*.dib;*.jpe;*.jpeg;*.jpg;*.png)', 1 + 2)

If Not $Path Then
	Exit
EndIf

Global $hIcon[5] = [256, 64, 48, 32, 16]
Global $hBitmap, $Result = 1

_GDIPlus_Startup()
For $i = 0 To UBound($hIcon) - 1
	$hBitmap = _GDIPlus_ImageLoadFromFile($Path)
	$hIcon[$i] = _GDIPlus_BitmapCreate32BitHICONFromBitmap($hBitmap, $hIcon[$i], $hIcon[$i])
	_GDIPlus_ImageDispose($hBitmap)
	If Not $hIcon[$i] Then
		$Result = 0
		ExitLoop
	EndIf
Next
_GDIPlus_Shutdown()
If $Result Then
	_WinAPI_SaveHICONToFile(_WinAPI_PathRenameExtension($Path, '.ico'), $hIcon)
EndIf
For $i = 0 To UBound($hIcon) - 1
	If IsPtr($hIcon[$i]) Then
		_WinAPI_DestroyIcon($hIcon[$i])
	EndIf
Next

Func _GDIPlus_BitmapCreate32BitHICONFromBitmap($hBitmap, $iX = -1, $iY = -1, $iARGB = 0)

	Local $tBIHDR, $K1, $K2, $Size, $tData, $pBits, $hGraphics, $hPng, $hIcon, $hMask, $hResult = 0

	$Size = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)
	If (@error) Or ($Size[0]) Then
		Return 0
	EndIf
	If $iX = -1 Then
		$iX = $Size[2]
	EndIf
	If $iY = -1 Then
		$iY = $Size[3]
	EndIf
	$K1 = $iX / $Size[2]
	$K2 = $iY / $Size[3]
	If $K1 > $K2 Then
		$K1 = $K2
	EndIf
	$Size[2] *= $K1
	$Size[3] *= $K1
	$hPng = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromScan0', 'int', $iX, 'int', $iY, 'int', 0, 'int', $GDIP_PXF32ARGB, 'ptr', 0, 'ptr*', 0)
	$hGraphics = _GDIPlus_ImageGetGraphicsContext($hPng[6])
	_GDIPlus_GraphicsClear($hGraphics, $iARGB)
	_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, ($iX - $Size[2]) / 2, ($iY - $Size[3]) / 2, $Size[2], $Size[3])
	_GDIPlus_GraphicsDispose($hGraphics)
	Do
		$tData = _GDIPlus_BitmapLockBits($hPng[6], 0, 0, $iX, $iY, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
		$pBits = DllStructGetData($tData, 'Scan0')
		If Not $pBits Then
			ExitLoop
		EndIf
		$tBIHDR = DllStructCreate($tagBITMAPINFOHEADER)
		DllStructSetData($tBIHDR, 'biSize', DllStructGetSize($tBIHDR))
		DllStructSetData($tBIHDR, 'biWidth', $iX)
		DllStructSetData($tBIHDR, 'biHeight', $iY)
		DllStructSetData($tBIHDR, 'biPlanes', 1)
		DllStructSetData($tBIHDR, 'biBitCount', 32)
		DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
		$hResult = _WinAPI_CreateDIBSection(0, $tBIHDR, $DIB_RGB_COLORS, $pBits)
		If @error Then
			ExitLoop
		EndIf
		_WinAPI_SetBitmapBits($hResult, $iX * $iY * 4, DllStructGetData($tData, 'Scan0'))
		_GDIPlus_BitmapUnlockBits($hBitmap, $tData)
	Until 1
	_GDIPlus_BitmapDispose($hPng[6])
	If Not $hResult Then
		Return 0
	EndIf
	$hMask = _WinAPI_CreateBitmap($iX, $iY, 1, 1)
	$hIcon = _WinAPI_CreateIconIndirect($hResult, $hMask)
	_WinAPI_DeleteObject($hResult)
	_WinAPI_DeleteObject($hMask)
	Return $hIcon
EndFunc   ;==>_GDIPlus_BitmapCreate32BitHICONFromBitmap

Func _WinAPI_SaveHICONToFile($sFile, $aIcon, $iStart = 0, $iEnd = -1)

	Local $Icon, $Count = 1

	If IsArray($aIcon) Then
		If UBound($aIcon, 2) Then
			Return SetError(2, 0, 0)
		EndIf
		If $iStart < 0 Then
			$iStart = 0
		EndIf
		If ($iEnd < 0) Or ($iEnd > UBound($aIcon) - 1) Then
			$iEnd = UBound($aIcon) - 1
		EndIf
		$Count = $iEnd - $iStart + 1
		If $Count < 1 Then
			Return SetError(1, 0, 0)
		EndIf
		Dim $Icon[$Count]
		For $i = 0 To $Count - 1
			$Icon[$i] = $aIcon[$iStart + $i]
		Next
	Else
		Dim $Icon[1] = [$aIcon]
	EndIf

	Local $hFile = _WinAPI_CreateFileEx($sFile, 2, 0x40000000, 0)

	If @error Then
		Return SetError(1, 0, 0)
	EndIf

	Local $tData, $W, $H, $Info, $Bytes, $Error, $Result = 0
	Local $tIco = DllStructCreate('ushort Reserved;ushort Type;ushort Count;byte Data[' & (16 * $Count) & ']')
	Local $Lenght = DllStructGetSize($tIco)
	Local $pIco = DllStructGetPtr($tIco)
	Local $tBI = DllStructCreate($tagBITMAPINFOHEADER)
	Local $pBI = DllStructGetPtr($tBI)
	Local $tDIB = DllStructCreate($tagDIBSECTION)
	Local $Size = DllStructGetSize($tDIB)
	Local $pDIB = DllStructGetPtr($tDIB)
	Local $Offset = $Lenght

	DllStructSetData($tIco, 'Reserved', 0)
	DllStructSetData($tIco, 'Type', 1)
	DllStructSetData($tIco, 'Count', $Count)

	DllStructSetData($tBI, 'biSize', 40)
	DllStructSetData($tBI, 'biPlanes', 1)
	DllStructSetData($tBI, 'biBitCount', 32)
	DllStructSetData($tBI, 'biCompression', 0)
	DllStructSetData($tBI, 'biXPelsPerMeter', 0)
	DllStructSetData($tBI, 'biYPelsPerMeter', 0)
	DllStructSetData($tBI, 'biClrUsed', 0)
	DllStructSetData($tBI, 'biClrImportant', 0)

	Do
		If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
			ExitLoop
		EndIf
		For $i = 0 To $Count - 1
			$Info = _WinAPI_GetIconInfo($Icon[$i])
			If Not IsArray($Info) Then
				ExitLoop 2
			EndIf
			For $j = 4 To 5
				$Info[$j] = _WinAPI_CopyImage($Info[$j], 0, 0, 0, BitOR(0x2000, 0x0008))
				If _WinAPI_GetObject($Info[$j], $Size, $pDIB) Then
					$Info[$j - 4] = DllStructGetData($tDIB, 'biSizeImage')
					$Info[$j - 2] = DllStructGetData($tDIB, 'bmBits')
				Else
					$Info[$j - 4] = 0
					$Info[$j - 2] = 0
				EndIf
			Next
			$W = DllStructGetData($tDIB, 'bmWidth')
			$H = DllStructGetData($tDIB, 'bmHeight')
			$tData = DllStructCreate('byte Width;byte Height;byte Colors;byte Reserved;word Planes;word BPP;long Size;long Offset', $pIco + 6 + 16 * $i)
			DllStructSetData($tData, 'Width', $W)
			DllStructSetData($tData, 'Height', $H)
			DllStructSetData($tData, 'Colors', 0)
			DllStructSetData($tData, 'Reserved', 0)
			DllStructSetData($tData, 'Planes', 1)
			DllStructSetData($tData, 'BPP', 32)
			DllStructSetData($tData, 'Size', 40 + $Info[0] + $Info[1])
			DllStructSetData($tData, 'Offset', $Offset)
			DllStructSetData($tBI, 'biWidth', $W)
			DllStructSetData($tBI, 'biHeight', 2 * $H)
			DllStructSetData($tBI, 'biSizeImage', $Info[0] + $Info[1])
			$Offset += 40 + $Info[0] + $Info[1]
			Do
				$Error = 1
				If Not _WinAPI_WriteFile($hFile, $pBI, 40, $Bytes) Then
					ExitLoop
				EndIf
				For $j = 1 To 0 Step -1
					If Not _WinAPI_WriteFile($hFile, $Info[$j + 2], $Info[$j], $Bytes) Then
						ExitLoop 2
					EndIf
				Next
				$Error = 0
			Until 1
			For $j = 4 To 5
				_WinAPI_DeleteObject($Info[$j])
			Next
			If $Error Then
				ExitLoop 2
			EndIf
		Next
		_WinAPI_SetFilePointer($hFile, 0)
		If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
			ExitLoop
		EndIf
		$Result = 1
	Until 1
	_WinAPI_CloseHandle($hFile)
	If Not $Result Then
		FileDelete($sFile)
	EndIf
	Return SetError(Number(Not $Result), 0, $Result)
EndFunc   ;==>_WinAPI_SaveHICONToFile
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Спасибо Yashied
Попробую потестить этот чудо код
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Yashied
Код отличный. Есть возможность посмотреть алгоритм этого чудо действия (сложновато конечно но можно)
Ещё раз спасибо тебе. Ради интереса в професиональных утилитах этого класса посмотрел,
а что ещё может быть запечатано в иконке. И увидел что помимо 32bpp иконок там встречаются
и иконки 16 цветов и 256 цветов. Интересно а твой код сможет сделать такие иконки, или как я
понимаю он заточен только на 32 битный формат.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Только 32-битные иконки, да и неактуальны сейчас другие форматы. На худой конец, система сама переведт изображения в нужный ей формат.
 
Автор
A

assch

Новичок
Сообщения
166
Репутация
4
Спасибо Yashied за пояснение.
Да системы у нас всё умней и умней.
Я просто ради кругозора хотел узнать этот алгоритм.
Ещё раз спасибо.
 
Верх