#NoEnv
SetBatchLines, -1
; указать правильные пути к файлам
background := A_ScriptDir . "\Основной рисунок.jpg"
picture := A_ScriptDir . "\Вставка.jpg"
outFile := A_ScriptDir . "\Out.jpg"
frameColor := 0xED1B24 ; указать цвет рамки
frameVariations := 20 ; +- значение по каждой цветовой компоненте
backgroundColor := 0xFFFFFF ; указать цвет фона основной картинки
backgroundVariations := 20 ; +- значение по каждой цветовой компоненте
gdip := new GDIplus
pBitmap1 := gdip.CreateBitmapFromFile(background)
rightBottomInnerCornerY := ""
if SearchPixel(gdip, pBitmap1, frameColor, frameVariations, leftTopOuterCornerX := 0, leftTopOuterCornerY := 0) {
if SearchPixel(gdip, pBitmap1, backgroundColor, backgroundVariations, leftTopInnerCornerX := leftTopOuterCornerX, Y := leftTopOuterCornerY + 30) {
if SearchPixel(gdip, pBitmap1, backgroundColor, backgroundVariations, X := leftTopInnerCornerX + 10, leftTopInnerCornerY := leftTopOuterCornerY + 10, "DownRight") {
if SearchPixel(gdip, pBitmap1, frameColor, frameVariations, rightTopInnerCornerX := leftTopInnerCornerX + 10, Y := leftTopInnerCornerY + 10) {
SearchPixel(gdip, pBitmap1, frameColor, frameVariations, X := rightTopInnerCornerX - 10, rightBottomInnerCornerY := leftTopInnerCornerY + 10, "DownRight")
}
}
}
}
if !rightBottomInnerCornerY {
MsgBox, Не удалось определить размеры рамки
gdip.DisposeImage(pBitmap1)
ExitApp
}
G1 := gdip.GraphicsFromImage(pBitmap1)
gdip.SetInterpolationMode(G, 7)
pBrush := gdip.BrushCreateSolid(0xFFFFFFFF)
gdip.FillRectangle(G1, pBrush, (X1 := leftTopInnerCornerX + 1) + 1
, (Y1 := leftTopInnerCornerY) + 1
, (W1 := rightTopInnerCornerX - leftTopInnerCornerX - 2) - 2
, (H1 := rightBottomInnerCornerY - leftTopInnerCornerY - 2) - 2)
gdip.DeleteBrush(pBrush)
pBitmap2 := gdip.CreateBitmapFromFile(picture)
gdip.GetImageDimensions(pBitmap2, W2, H2)
ratio2 := H2/W2
newW := W1
newH := newW*ratio2
if (newH > H1) {
newH := H1
newW := newH/ratio2
}
X := newW = W1 ? 0 : (W1 - newW)/2
Y := newH = H1 ? 0 : (H1 - newH)/2
gdip.DrawImage(G1, pBitmap2, X + X1, Y + Y1, newW, newH, 0, 0, W2, H2)
gdip.SaveBitmap(pBitmap1, outFile, 100)
gdip.DeleteGraphics(G1)
gdip.DisposeImage(pBitmap2)
gdip.DisposeImage(pBitmap1)
Return
SearchPixel(gdi, pBitmap, colorRGB, variations, ByRef X, ByRef Y, direction := "RightDown") {
sR := (colorRGB & 0xFF0000) >> 16
sG := (colorRGB & 0xFF00) >> 8
sB := (colorRGB & 0xFF)
gdi.GetImageDimensions(pBitmap, W, H)
bool := direction = "RightDown"
Loop % (bool ? H - Y : W - X) - 1 {
i := A_Index + (bool ? Y : X)
Loop % (bool ? W - X : H - Y) - 1 {
pixelARGB := bool ? gdi.GetPixel(pBitmap, A_Index + X, i) : gdi.GetPixel(pBitmap, i, A_Index + Y)
R := (pixelARGB & 0xFF0000) >> 16
G := (pixelARGB & 0xFF00) >> 8
B := (pixelARGB & 0xFF)
if ( R + variations >= sR && R - variations <= sR
&& G + variations >= sG && G - variations <= sG
&& B + variations >= sB && B - variations <= sB )
{
if bool
Y := i, X += A_Index
else
X := i, Y += A_Index
found := true
break 2
}
}
}
Return found
}
class GDIplus {
__New() {
if !DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
DllCall("LoadLibrary", Str, "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", UPtrP, pToken, Ptr, &si, Ptr, 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", Ptr, this.token)
if hModule := DllCall("GetModuleHandle", Str, "gdiplus", Ptr)
DllCall("FreeLibrary", Ptr, hModule)
}
CreateBitmapFromFile(sFile) {
DllCall("gdiplus\GdipCreateBitmapFromFile", WStr, sFile, PtrP, pBitmap)
Return pBitmap
}
CreateBitmap(Width, Height, Format=0x26200A) {
DllCall("gdiplus\GdipCreateBitmapFromScan0", Int, Width, Int, Height, Int, 0, Int, Format, Ptr, 0, PtrP, pBitmap)
Return pBitmap
}
GetImageDimensions(pBitmap, ByRef Width, ByRef Height) {
DllCall("gdiplus\GdipGetImageWidth", Ptr, pBitmap, UIntP, Width)
DllCall("gdiplus\GdipGetImageHeight", Ptr, pBitmap, UIntP, Height)
}
GraphicsFromImage(pBitmap) {
DllCall("gdiplus\GdipGetImageGraphicsContext", Ptr, pBitmap, PtrP, pGraphics)
return pGraphics
}
SetInterpolationMode(pGraphics, InterpolationMode) {
; Default = 0
; LowQuality = 1
; HighQuality = 2
; Bilinear = 3
; Bicubic = 4
; NearestNeighbor = 5
; HighQualityBilinear = 6
; HighQualityBicubic = 7
return DllCall("gdiplus\GdipSetInterpolationMode", Ptr, pGraphics, Int, InterpolationMode)
}
GetPixel(pBitmap, x, y) {
DllCall("gdiplus\GdipBitmapGetPixel", Ptr, pBitmap, Int, x, Int, y, UIntP, ARGB)
return ARGB
}
BrushCreateSolid(ARGB=0xff000000) {
DllCall("gdiplus\GdipCreateSolidFill", UInt, ARGB, PtrP, pBrush)
return pBrush
}
FillRectangle(pGraphics, pBrush, x, y, w, h) {
return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush
, Float, x, Float, y, Float, w, Float, h)
}
DrawImage(pGraphics, pBitmap, dx, dy, dw, dh, sx, sy, sw, sh) {
Return DllCall("gdiplus\GdipDrawImageRectRect", Ptr, pGraphics, Ptr, pBitmap
, Float, dx, Float, dy, Float, dw, Float, dh
, Float, sx, Float, sy, Float, sw, Float, sh
, Int, 2, Ptr, 0, Ptr, 0, Ptr, 0)
}
SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "")
{
; info — если копируем в буфер, тогда расширение файла, если в файл, тогда путь к файлу
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", UintP, nCount, UintP, nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", UInt, nCount, UInt, nSize, Ptr, &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, UintP, nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, UInt, nSize, Ptr, &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, WStr, info, Ptr, pCodec, UInt, p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", UInt, 0, Int, 1, PtrP, pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", Ptr, pBitmap, Ptr, pStream, Ptr, pCodec, UInt, p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", Ptr, pStream, PtrP, hData )
pData := DllCall( "GlobalLock", Ptr, hData, Ptr )
nSize := DllCall( "GlobalSize", Ptr, hData, Ptr )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", Ptr, &info, Ptr, pData, UInt, nSize )
DllCall( "GlobalUnlock", Ptr, hData )
DllCall( "GlobalFree", Ptr, hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DeleteBrush(pBrush) {
return DllCall("gdiplus\GdipDeleteBrush", Ptr, pBrush)
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", Ptr, pBitmap)
}
DeleteGraphics(pGraphics) {
return DllCall("gdiplus\GdipDeleteGraphics", Ptr, pGraphics)
}
}
Пока всё это работает весьма приблизительно.