1 (изменено: ОсиповаТатьяна, 2019-09-03 18:20:06)

Тема: AHK: Замена области на растровом рисунке - на определенную картинку.

Здравствуйте, уважаемые форумчане.

Подскажите - как удалить из растрового рисунка - ту область, которая находится внутри красной рамки (то есть заменить то что внутри - белым цветом), а потом на это место внутри красной рамки (которое было очищено) вставить рисунок "Вставка.jpg" с сохранением пропорций ?

Post's attachments

1.rar 74.38 kb, 5 downloads since 2019-09-03 

You don't have the permssions to download the attachments of this post.

2

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

ОсиповаТатьяна, добавьте в название темы префикс скриптового языка.

3

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

Попробуйте почитать примеры отсюда.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

teadrinker, там все примеры на английском.
Их особо не почитаешь, если не очень хорошо разбираешься в языке.

5

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

Зачем вам нужно делать это в ахк?
Используйте графический редактор.

6

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

Я когда начинал, тоже совсем не разбирался. Сейчас уже свободно на форуме болтаю, а начинал именно с разбора справки на английском.

ОсиповаТатьяна пишет:

как удалить из растрового рисунка - ту область, которая находится внутри красной рамки

Для начала нужно её координаты определить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

teadrinker пишет:

Для начала нужно её координаты определить.

А как определить ?
В автоите - используется функция PixelSearch
А в языке autohotkey -  как ?

8 (изменено: teadrinker, 2019-09-03 19:21:07)

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

PixelSearch тоже есть. Если точно известно, что цвет пикселей рамки отличается от любых других, тогда можно использовать. Если нет, тогда проще вручную указать, либо придётся какой-то сложный алгоритм разрабатывать, чтобы именно рамку определить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

teadrinker пишет:

Если точно известно, что цвет пикселей рамки отличается от любых других, тогда можно использовать.

Да, точно известно, что рамка красного цвета и нигде больше на рисунке красный цвет не используется кроме как в рамке.

10 (изменено: teadrinker, 2019-09-04 04:55:47)

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

С файлами из вложения так вышло:

#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)
   }
}

Пока всё это работает весьма приблизительно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: Замена области на растровом рисунке - на определенную картинку.

teadrinker. спасибо.
Вроде все нормально работает.