1 (изменено: Karagiozis, 2018-03-17 23:55:27)

Тема: AHK: Объединить кусочки картинок в одно целое

Здравствуйте. Помогите пожалуйста. Как можно объединить 121 кусочков разрозненных изображений в одно изображение и сохранить его в формате bmp или другом?
Прочитал что можно как-то с помощью gdip создать пустой bitmap, заполнить его, а затем сохранить.
Есть 121 картинок формата bmp с названиями 1.bmp, 2.bmp, 3.bmp и так до 121.bmp.
Размер у всех одинаковый 256x256.
По горизонтали(по Х) влазит 11 картинок и по вертикали(по Y) тоже 11 картинок.
Я понимаю что получается 2816 пикселей на 2816, но можно и уменьшить.
На каждом изображено часть изображения и я не знаю как объединить все в одно полноценное изображение.

2

Re: AHK: Объединить кусочки картинок в одно целое

В том-то и дело что как-то
Вот, левой пяткой написал, стоя на правом ухе, думаю поможет:

#Include Gdip.ahk
If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}
OnExit, Exit

Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA
hwnd1 := WinExist()															
hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight)						
hdc := CreateCompatibleDC()													
obm := SelectObject(hdc, hbm)												
G := Gdip_GraphicsFromHDC(hdc)												
Gdip_SetSmoothingMode(G, 0) 												
Gdip_GraphicsClear(G,"0xff000000")

bitmap:=Gdip_CreateBitmapFromFile("кек.bmp")
loop 121
	Gdip_DrawImage(G,bitmap,((A_Index-1)-(A_Index-1)//11*11)*64,(A_Index-1)//11*64,"64","64")

UpdateLayeredWindow(hwnd1, hdc, 0, 0, A_ScreenWidth, A_ScreenHeight)
return

f1::
pBitmap:=Gdip_BitmapFromScreen("0|0|" 11*64 "|" 11*64)
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir "\" SubStr(A_ScriptName,1,-4) "_1.png", 100)
return

Esc::
Exit:
Gdip_Shutdown(pToken)
ExitApp
Post's attachments

кек.bmp 2.12 kb, 13 downloads since 2018-03-21 

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

3

Re: AHK: Объединить кусочки картинок в одно целое

shahlik002 пишет:

Вот, левой пяткой написал

Это точно! Окно-то здесь зачем?

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

4

Re: AHK: Объединить кусочки картинок в одно целое

teadrinker
В том-то и дело что незачем
Я еще учусь)

5

Re: AHK: Объединить кусочки картинок в одно целое

Многие библиотеки переходят на такой формат, когда изображение разбивается на кусочки. Интересно, есть ли возможность сделать скрин для страницы, которая была предварительно собрана в окно IE? Иначе говоря: сделать на AHK скрин в натуральную величину для содержимого окна, которое может выходить за края экрана?

6 (изменено: teadrinker, 2020-03-03 14:28:49)

Re: AHK: Объединить кусочки картинок в одно целое

Вроде возможно джаваскриптом, но не разбирался.

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

7

Re: AHK: Объединить кусочки картинок в одно целое

Если это канвас, то можно так:

oIE := ComObjCreate("InternetExplorer.Application")
oIE.visible := True
oIE.Navigate("https://www.w3schools.com/html/html5_canvas.asp")
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
   Sleep, 10
canvas := oIE.document.getElementById("myCanvas")
oIE.document.parentwindow.navigator.msSaveBlob(canvas.msToBlob(), "canvas.png")
msgbox done

8

Re: AHK: Объединить кусочки картинок в одно целое

К сожалению, яваскрипт не умею настраивать. На AHK не было такого?

9

Re: AHK: Объединить кусочки картинок в одно целое

Malcev
Запустил код, файл не образовался.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

10

Re: AHK: Объединить кусочки картинок в одно целое

А в IE не вышел попап о сохранении файла?

11

Re: AHK: Объединить кусочки картинок в одно целое

Да, я не внимателен. Всё ок.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

12

Re: AHK: Объединить кусочки картинок в одно целое

Malcev
Пока смотрел ссылку stackoverflow, не заметил Ваш код. Так понимаю, сохраняется какой-то элемент со страницы?

13

Re: AHK: Объединить кусочки картинок в одно целое

Сохраняется canvas.

14

Re: AHK: Объединить кусочки картинок в одно целое

А для изображений со страницы можно применять?

15

Re: AHK: Объединить кусочки картинок в одно целое

Не понимаю о чем вы.

16

Re: AHK: Объединить кусочки картинок в одно целое

Имею в виду возможность скриншота изображения, открытого в окне IE. При этом изображение может выступать за края экрана, но скрин нужен целого изображения.

17

Re: AHK: Объединить кусочки картинок в одно целое

Конкретно пример приведите.

18

Re: AHK: Объединить кусочки картинок в одно целое

Способ планируется использовать для сохранения изображений из библиотек, разбивающих страницы книг на кусочки. Останется собрать эти куски через HTML-код в целое изображение в окне IE, а потом сохранить как скрин.

19 (изменено: DD, 2020-03-03 19:09:12)

Re: AHK: Объединить кусочки картинок в одно целое

Пример — любое изображение, которое открыто в IE и выступает в нём за границы экрана. Сейчас приведу.

20

Re: AHK: Объединить кусочки картинок в одно целое

Добавил в архив картинку и HTML, в котором она открыта в натуральную величину — https://yadi.sk/d/yQ07YA5ujD8c8A. В реальном примере картинка будет разбита на кусочки и собрана в  HTML-коде в единое целое.

21

Re: AHK: Объединить кусочки картинок в одно целое

Всё-равно непонятно.
Если картинка собирается в канвасе, то мой способ годится.
Если как-то по другому, то надо смотреть как.

22 (изменено: DD, 2020-03-03 20:16:51)

Re: AHK: Объединить кусочки картинок в одно целое

Конечная цель — сохранять разбитые на фрагменты изображения из библиотек, в целые изображения. Так как размеры кусков и правило их сбора в целое изображение может меняться от сайта к сайту (и что потребует менять код собирающего их скрипта) мне показалось более простым вариантом собирать их в HTML-коде, где необязательно указывать размеры фрагментов и затем делать скрин. К примеру, в начале в HTML-шаблоне (программно создаваемый HTML-файл) указываются ссылки на фрагменты, из которых будет составляться целое изображение, затем файл будет открываться в невидимом окне, ожидаться, пока они все подгрузятся из интернета и делаться скрин этого окна.

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

23

Re: AHK: Объединить кусочки картинок в одно целое

А зачем собирать в IE, Собирайте в gdi.

24

Re: AHK: Объединить кусочки картинок в одно целое

А есть код, который соберет фрагменты из архива, а то у меня не получилось доработать скрипт из архива, чтобы он собирал больше двух изображений?

25

Re: AHK: Объединить кусочки картинок в одно целое

У меня нету.

26 (изменено: serzh82saratov, 2020-03-03 22:39:49)

Re: AHK: Объединить кусочки картинок в одно целое

#Include Gdip_All.ahk
#NoEnv
SetBatchLines, -1

	ext = jpg
    OutputFile := A_ScriptDir "\__merged.png" ; Target file (both file merged) - 4480x1440
	
	w := h := 0 
	Loop, %A_ScriptDir%\*.%ext%
	{
		If !RegExMatch(A_LoopFileName, "(\d+)_(\d+)\.", F)
			Continue 
		w := w > ++F1 ? w : F1
		h := h > ++F2 ? h : F2 
	} 
	If !w || !h
		ExitApp
    pToken := Gdip_Startup()
		
	pBitmap := Gdip_CreateBitmapFromFile("0_0." ext)
	Gdip_GetImageDimensions(pBitmap, Width, Height) 
	Gdip_DisposeImage(pBitmap)
	
    pBitmapNew := Gdip_CreateBitmap(Width * w, Height * h) 
    G := Gdip_GraphicsFromImage(pBitmapNew)
    Gdip_SetSmoothingMode(G, 4)
    Gdip_SetInterpolationMode(G, 7)
	
	Loop %w%
	{
		col := A_Index - 1
		Loop %h%
		{
			row := A_Index - 1
			pBitmap := Gdip_CreateBitmapFromFile(col "_" row "." ext)
			Gdip_DrawImage(G, pBitmap, col * Width, row * Height, Width, Height, 0, 0, Width, Height)
			Gdip_DisposeImage(pBitmap) 
		}
	} 
	
    Gdip_SaveBitmapToFile(pBitmapNew, OutputFile)
    Gdip_DisposeImage(pBitmapNew)
    Gdip_DeleteGraphics(G)
    Gdip_Shutdown(pToken)
	run %OutputFile%
	ExitApp
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui
+ DD

27 (изменено: DD, 2020-03-04 00:19:10)

Re: AHK: Объединить кусочки картинок в одно целое

Спасибо, мощно!) Уважаемый, а как скрипт узнаёт, где край изображения — где надо остановиться и снизу начать новый сбор? Я протестировал на 647-ми фрагментах страницы манускрипта из британской библиотеки (https://yadi.sk/d/dcWSZKAwtTXWWA), которая состоит не из четырёх — как у меня в архиве, — а из 22-х в ширину и 28-ми в высоту фрагментов, и скрипт их правильно собрал)).

+ открыть спойлер

https://i111.fastpic.ru/thumb/2020/0303/e3/_7ec490745b4a46005b9ae592cb4de8e3.jpeg

28

Re: AHK: Объединить кусочки картинок в одно целое

DD пишет:

скрипт их правильно собрал

Не совсем, там картинки разных размеров, а это не учитывается в коде. Предполагается что все такого же размера как 0_0.

DD пишет:

а как скрипт узнаёт, где край изображения — где надо остановиться и снизу начать новый сбор?

		w := w > ++F1 ? w : F1
		h := h > ++F2 ? h : F2 

Он сначала перебирает все файлы, и узнаёт максимальные числа в их названиях. Первое число - колонки, второе - строки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

29 (изменено: DD, 2020-03-04 00:41:02)

Re: AHK: Объединить кусочки картинок в одно целое

Судя по размерам, там вроде пиксель будет съедаться в левой колонке и в верхней строке, где полезного изображения особо нет.

30 (изменено: serzh82saratov, 2020-03-04 11:01:14)

Re: AHK: Объединить кусочки картинок в одно целое

Может перемудрил, но лучше так.


#NoEnv
SetBatchLines, -1
pToken := Gdip_Startup()

offset := -1
ext = jpg
OutputFile := A_ScriptDir "\__merged.png"

arr := []  
off := []
off.X[1] := off.Y[1] := aw := ah := 0

Loop, %A_ScriptDir%\*.%ext%
{
	If !RegExMatch(A_LoopFileName, "S)^(\d+)_(\d+)\." ext "$", F)
		Continue
	col := F1 + 1, row := F2 + 1
	If !arr[col]
		arr[col] := []
	arr[col][row] := A_LoopFileFullPath
} 
 
If !arr[1][1]
	ExitApp 

for col, rows in arr
	for row, path in rows
	{
		pBitmap := Gdip_CreateBitmapFromFile(path)
		Gdip_GetImageDimensions(pBitmap, w, h) 
		If (row = 1) 
			aw := off.X[col + 1] := aw + w + offset
		If (col = 1)
			ah := off.Y[row + 1] := ah + h + offset
		arr[col][row] := {pBitmap: pBitmap, w: w, h: h}
	} 
	
pBitmapNew := Gdip_CreateBitmap(aw, ah)
G := Gdip_GraphicsFromImage(pBitmapNew)
Gdip_SetSmoothingMode(G, 4)
Gdip_SetInterpolationMode(G, 7)

for col, rows in arr 
	for row, obj in rows 
		Gdip_DrawImage(G, obj.pBitmap, off.X[col], off.Y[row], obj.w, obj.h, 0, 0, obj.w, obj.h)
		, Gdip_DisposeImage(obj.pBitmap)   

Gdip_SaveBitmapToFile(pBitmapNew, OutputFile)
Gdip_DisposeImage(pBitmapNew)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
run %OutputFile%
ExitApp
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui
+ DD

31

Re: AHK: Объединить кусочки картинок в одно целое

Спасибо! Второй скрипт работает с учётом размеров?

32

Re: AHK: Объединить кусочки картинок в одно целое

Да, всё должно быть точно.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

33 (изменено: DD, 2020-03-04 06:53:06)

Re: AHK: Объединить кусочки картинок в одно целое

Судя по сравнению — были отличия. Причём, даже если собирать в HTML, точно указав размеры каждого. В фотошопе стало понятно, что фрагменты недостаточно состыковать между собой, надо ещё наложить их друг на друга на 1 пиксель. Умеют там контент защищать).

На всякий случай, в архиве сравнение скринов, а также 4 фрагмента изображения, на стыках которых видно, что они впритык кое-где явно не стыкуются (особенно на стеблях) — https://yadi.sk/d/iFLYxgukmIJqLA.

34 (изменено: Malcev, 2020-03-04 10:58:28)

Re: AHK: Объединить кусочки картинок в одно целое

DD пишет:

Умеют там контент защищать

Там это где? Почему не скидываете ссылку?
Открыл ваши куски в фотошопе - там не один пиксель, а два.
Как собираетесь определять сдвиг?
А с канвасом в предыдущем посте я немного перемудрил:

oHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
oHTTP.Open("GET", "https://www.w3schools.com/html/html5_canvas.asp")
oHTTP.Send()
oHTTP.WaitForResponse()
oHTML := ComObjCreate("HTMLFile")
oHTML.open()
oHTML.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=edge"">")
oHTML.write(oHTTP.ResponseText)
oHTML.close()
canvas := oHTML.getElementById("myCanvas")
nBytes := Base64Dec(SubStr(canvas.toDataURL(), 23), Bin)
File := FileOpen("canvas.png", "w")
File.RawWrite(Bin, nBytes)
File.Close()
msgbox done

Base64Dec( ByRef B64, ByRef Bin ) {  ; By SKAN / 18-Aug-2017
Local Rqd := 0, BLen := StrLen(B64)                 ; CRYPT_STRING_BASE64 := 0x1
  DllCall( "Crypt32.dll\CryptStringToBinary", "Str",B64, "UInt",BLen, "UInt",0x1
         , "UInt",0, "UIntP",Rqd, "Int",0, "Int",0 )
  VarSetCapacity( Bin, 128 ), VarSetCapacity( Bin, 0 ),  VarSetCapacity( Bin, Rqd, 0 )
  DllCall( "Crypt32.dll\CryptStringToBinary", "Str",B64, "UInt",BLen, "UInt",0x1
         , "Ptr",&Bin, "UIntP",Rqd, "Int",0, "Int",0 )
Return Rqd
}

35

Re: AHK: Объединить кусочки картинок в одно целое

Поправил последний код, можете offset задать как надо, но я нестыковок не заметил.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

36

Re: AHK: Объединить кусочки картинок в одно целое

Если там везде разные сдвиги, то я бы если всё это рисуется в канвасе, сохранял канвас, если же нет, то перекодировал бы dom в канвас по ссылке teadrinkera.

37 (изменено: DD, 2020-03-15 10:12:31)

Re: AHK: Объединить кусочки картинок в одно целое

Ссылка вот — http://www...._ms_36_fs001ar, я ее ещё приводил в архиве. Определить сдвиг наверно проще всего будет в html-коде, назначив каждой колонке свой класс и двигая через стили. Сейчас попробую.

38

Re: AHK: Объединить кусочки картинок в одно целое

serzh82saratov
Если указать минус 2 пикселя — Ваш скрипт делает в точности как на сайте).

39

Re: AHK: Объединить кусочки картинок в одно целое

Да, тут только собирать самому, наверное, придется.

40 (изменено: DD, 2020-03-04 15:58:16)

Re: AHK: Объединить кусочки картинок в одно целое

В смысле, собирать самому?

41

Re: AHK: Объединить кусочки картинок в одно целое

Через gdi. Основное изображение где они прячут я не нашел.

42

Re: AHK: Объединить кусочки картинок в одно целое

А-а, они его типа разбивают и на два пикселя с краёв дублируют ближайшие цвета?

43

Re: AHK: Объединить кусочки картинок в одно целое

А для президентской библиотеки будет шанс основное изображение получить?

44

Re: AHK: Объединить кусочки картинок в одно целое

А в чём там проблема? Вижу, что источник прямо указан.

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

45

Re: AHK: Объединить кусочки картинок в одно целое

В смысле, целая не разбитая картинка из ПБ?

46

Re: AHK: Объединить кусочки картинок в одно целое

teadrinker пишет:

Вижу, что источник прямо указан.

Ссылку скинь.

47

Re: AHK: Объединить кусочки картинок в одно целое

А вы проверяли?

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

48

Re: AHK: Объединить кусочки картинок в одно целое

Вроде, если там увеличивать в под-окне страницы — они разбиваются на фрагменты.

49

Re: AHK: Объединить кусочки картинок в одно целое

Malcev пишет:

Ссылку скинь.

Ты тоже не можешь найти?
https://www.prlib.ru/sites/default/file … 3F24EE.jpg

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

50

Re: AHK: Объединить кусочки картинок в одно целое

А это неувеличенный вариант. При ещё большем увеличении она шинкуется.

51

Re: AHK: Объединить кусочки картинок в одно целое

В смысле, не увеличенный? У меня в полный экран.

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

52

Re: AHK: Объединить кусочки картинок в одно целое

Тут видно — https://yadi.sk/d/N7mAObVwc3aoAw. В максимальном качестве первая и вторая.

53 (изменено: DD, 2020-03-04 16:51:00)

Re: AHK: Объединить кусочки картинок в одно целое

Хотя и возможно они формально увеличивают то же самое и просто добавляют резкости. Хотя в таком случае зачем их разбивать?

54

Re: AHK: Объединить кусочки картинок в одно целое

Не понял, сравнение чего с чем? У вас по ссылке маленькая картинка открывается?
А так:

SetBatchLines, -1
url := "https://www.prlib.ru/item/357159"
if !html := GetHtml(url) {
   MsgBox, Failed to get HTML
   ExitApp
}
Doc :=  DocumentFromHtml(html)
elem := Doc.GetElementById("md10")
if !imgUrl := elem.GetElementsByTagName("img")[0].src {
    MsgBox, Failed to get image source
    ExitApp
}
hBitmap := GetHBitmapFromImageURL(imgUrl)

Gui, -Caption +ToolWindow
Gui, Margin, 0, 0
Gui, Add, Pic,, HBITMAP:%hBitmap%
Gui, Show
Return

GuiClose() {
   ExitApp
}

GetHtml(url) {
   whr := ComObjCreate("Msxml2.XMLHTTP.6.0")
   whr.Open("GET", url, false)
   whr.SetRequestHeader("Pragma", "no-cache")
   whr.SetRequestHeader("Cache-Control", "no-cache, no-store")
   whr.Send()
   Return html := whr.ResponseText
}

DocumentFromHtml(html) {
   doc := ComObjCreate("htmlfile")
   doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
   doc.write(html)
   Return doc
}

GetHBitmapFromImageURL(url)  {
   whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   whr.Open("GET", url, false)
   whr.Send()
   if (whr.Status != 200)  {
      MsgBox, Failed to load the image!
      Return
   }
   contentType := whr.GetResponseHeader("Content-Type")
   if !InStr(contentType, "image")  {
      MsgBox, URL doesn't link to an image!
      Return
   }
   Return (new GDIp).HBitmapFromIStream(whr.ResponseStream)
}

class GDIp   {
   __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)
   }
   
   HBitmapFromIStream(IStream)  {
      pStream := ComObjQuery(IStream, "{0000000C-0000-0000-C000-000000000046}")
      DllCall("gdiplus\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap)
      ObjRelease(pStream)
      DllCall("OleAut32\VariantClear", "PtrP", IStream)
      DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0xFFFFFFFF)
      DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
      Return hBitmap
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

55

Re: AHK: Объединить кусочки картинок в одно целое

А откуда эта обложка берётся? По Вашей предыдущей ссылке вроде другая обложка была. И как сохранить файл на диск из Вашего скрипта, для оценки качества?

56

Re: AHK: Объединить кусочки картинок в одно целое

А, просто цифру в адресе перепутал. Замените на

url := "https://www.prlib.ru/item/357158"

Ссылка на картинку в переменной imgUrl. Как по ссылке файл сохранять, знаете?

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

57 (изменено: DD, 2020-03-04 17:15:17)

Re: AHK: Объединить кусочки картинок в одно целое

Всё-таки, там явное несоответствие по качеству имеет место: превью из скрипта хуже по качеству чем основное изображение, которое можно увеличивать в под-окне и которое поэтому разбивается на куски.

58

Re: AHK: Объединить кусочки картинок в одно целое

А я вижу, что у картинки, которая открывается при клике на превью тот же адрес:
https://www.prlib.ru/sites/default/files/book_preview/9b8544e3-018f-468d-bd53-53302c121972/6268039_doc1_217B5A79-176E-4309-AF80-4BF5C83F24EE.jpg

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

59

Re: AHK: Объединить кусочки картинок в одно целое

Судя по качеству, оно и есть превью, а исходное ниже в под-окне выводится только в нарезанном виде.

60

Re: AHK: Объединить кусочки картинок в одно целое

Превью с размером 800х1051?

https://i.imgur.com/1hprR2n.png

Я не понимаю, про какой нарезанный вид вы толкуете. Есть ссылки на кусочки нарезки?

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

61

Re: AHK: Объединить кусочки картинок в одно целое

Если Вы посмотрите через вкладку Network, увеличив картинку из под-окна до предела —
https://i111.fastpic.ru/thumb/2020/0304/2d/_11467570a82c953c25b836fd169bfa2d.jpeg

62

Re: AHK: Объединить кусочки картинок в одно целое

И что? Эти кусочки меньше размером, чем они же на полной картинке, вот и кажется, что качество лучше.

https://i.imgur.com/sEb7bna.png

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

63

Re: AHK: Объединить кусочки картинок в одно целое

Посмотрите кусочки, с цифрой 4 перед запятой с числом — они больше. 4 — это масштаб.

64

Re: AHK: Объединить кусочки картинок в одно целое

https://content.prlib.ru/fcgi-bin/iipsr … mp;JTL=4,8.

65

Re: AHK: Объединить кусочки картинок в одно целое

У меня таких нету, у меня все с двойками:

https://i.imgur.com/5OTY6MR.png

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

66 (изменено: DD, 2020-03-04 17:53:59)

Re: AHK: Объединить кусочки картинок в одно целое

Если вы очистите результаты и несколько раз нажмёте на + (увеличение масштаба) над под-окном, они начнут подгружаться.

67

Re: AHK: Объединить кусочки картинок в одно целое

Не, тут такая же история - вручную собирать придётся.

68

Re: AHK: Объединить кусочки картинок в одно целое

А, теперь понял, я не ту картинку оказывается смотрел. Сейчас ту гляну.

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

69

Re: AHK: Объединить кусочки картинок в одно целое

DD, а зачем вам нужны эти книги, если не секрет?

70

Re: AHK: Объединить кусочки картинок в одно целое

Зарегался как-то на сайте книголюбов, там меня просят некоторые товарищи).

71

Re: AHK: Объединить кусочки картинок в одно целое

Хотя, нет, наверное всё-таки можно получить.

72

Re: AHK: Объединить кусочки картинок в одно целое

Качайте питоном, либо переводите на автохотки.
https://github.com/hda-technical/danceb … b.py#L689
Мне заниматься этим лень.

73

Re: AHK: Объединить кусочки картинок в одно целое

Хотя там тоже вроде по кусочкам собирает.

74 (изменено: DD, 2020-03-04 18:21:10)

Re: AHK: Объединить кусочки картинок в одно целое

Этот Чайковский входит в библиофильскую серию «Academia», издания которой там собирают для публикации и на которые цена, если покупать, может доходить до нескольких тысяч долларов. А из Британской — это иллюминированные манускрипты, репринт которых тоже доходит до нескольких тысяч уе.

75

Re: AHK: Объединить кусочки картинок в одно целое

Это понятно, только зачем это у себя хранить?
Или цель - скачать и распечатать?

76 (изменено: DD, 2020-03-04 18:22:03)

Re: AHK: Объединить кусочки картинок в одно целое

Да, там иллюминированные один для себя распечатывает, а серия нужна просто чтобы ее собрать и обнародовать, собрав в pdf/djvu. На Рутрекере знаете, разные серии публикуют? Вот и ее так же.

77

Re: AHK: Объединить кусочки картинок в одно целое

Тогда через json узнавать количество частей замерять отступ и соединять.
Питон действует по такому алгоритму.
А оригиналы, наверное, не достать.
https://iipimage.sourceforge.io/

+ DD

78

Re: AHK: Объединить кусочки картинок в одно целое

Интересно, а этим скриптом на питоне можно скачивать что-то помимо танцевальной тематики? Из инструкции не понятно, как его запускать. Что-то говорится о папке на Яндекс.Диске, которую по определенным правилам наполняют и тп.

79

Re: AHK: Объединить кусочки картинок в одно целое

А зачем вам питон, если алгоритм там не отличается - так же картинки соединяются.

80

Re: AHK: Объединить кусочки картинок в одно целое

Сложновато) К тому же там в списке и британская библа есть, и ряд других). Если работает, хотелось бы питоном обойтись.

81

Re: AHK: Объединить кусочки картинок в одно целое

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

82 (изменено: DD, 2020-03-05 00:29:09)

Re: AHK: Объединить кусочки картинок в одно целое

А не могли бы Вы взглянуть, на этом сайте тоже кусочками представлен размером с ладонь манускрипт — молитвенник Клод Французской.

Не удаётся выяснить, откуда формируются ссылки на эти нарезки, которые по линкам не грузятся, несмотря на полное указание хедеров:

HTTP := ComObjCreate("Msxml2.XMLHTTP.6.0")
;HTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")

url := "https://host.themorgan.org/facsimile/images/claude/m1166_03v-04r.zif?t1583353275432n104"

HTTP.Open("Get", url, 0)
HTTP.SetRequestHeader("Accept", "*/*")
HTTP.SetRequestHeader("Content-Type", "image/zif")
HTTP.SetRequestHeader("Accept-Encoding", "identity")
HTTP.SetRequestHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7")
HTTP.SetRequestHeader("Connection", "keep-alive")
HTTP.SetRequestHeader("Cookie", "ASPSESSIONIDAUACRDAQ=NBFFGICBJJNAMOPDFJDBMBDH; ASPSESSIONIDAUDCQCBR=GKCHLGDBDEDIBNGNAEPOPHNA; ASPSESSIONIDAUCDRCBR=NBHJNJDBDAFMPBHBFGOFNNKF; ASPSESSIONIDCUCBSCBR=NJOPCMEDLNMFJDMIAGBDBCFI; ASPSESSIONIDCWBCQDBQ=PAODHDFDFGKGDOFBJEBIJIJG; __extfc=1; ASPSESSIONIDAUDAQDBQ=GANDFMPDGLHKPFKIAPIGDOBD; ")
HTTP.SetRequestHeader("Host", "host.themorgan.org")
HTTP.SetRequestHeader("Range", "bytes=2322490-2336957")
HTTP.SetRequestHeader("Referer", "https://host.themorgan.org/facsimile/claude/default.asp?id=10&width=100%25&height=100%25&iframe=true")
HTTP.SetRequestHeader("Server", "Microsoft-IIS/8.5")
HTTP.SetRequestHeader("X-Powered-By", "ASP.NET")
HTTP.SetRequestHeader("X-Powered-By-Plesk", "PleskWin")
HTTP.SetRequestHeader("Accept-Encoding", "identity")
HTTP.SetRequestHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7")
HTTP.SetRequestHeader("Range", "bytes=2156004-2173480")
HTTP.SetRequestHeader("Sec-Fetch-Mode", "cors")
HTTP.SetRequestHeader("Sec-Fetch-Site", "same-origin")

HTTP.SetRequestHeader("ETag", "808272af52d0d41:0")
HTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36")
HTTP.Send()
MsgBox % HTTP.ResponseText

83

Re: AHK: Объединить кусочки картинок в одно целое

zif - это tiff.

+ DD

84

Re: AHK: Объединить кусочки картинок в одно целое

В готовом виде положили).

85

Re: AHK: Объединить кусочки картинок в одно целое

Однако, там не для всех такой формат. Здесь уже собирать надо вроде — https://www.themorgan.org/collection/An … gne/thumbs.

86

Re: AHK: Объединить кусочки картинок в одно целое

Ну да. Тут уже запрятали.

87 (изменено: teadrinker, 2020-03-05 16:19:26)

Re: AHK: Объединить кусочки картинок в одно целое

В качестве компенсации за то, что вчера так тупил:

#NoEnv
SetBatchLines, -1
CoordMode, ToolTip
PrLibDownload(357030, 10, 4, A_Desktop . "\test.tif")
MsgBox, Completed!

PrLibDownload(item, page, zoom, outputTif) {
   if !GetItemInfo(item, page, zoom, width, height, file, id1, id2)
      Return
   
   if !GetChunkDimension(id1, id2, file, zoom, chunkWidth, chunkHeight)
      Return
   
   BuildImg(id1, id2, file, zoom, width, height, chunkWidth, chunkHeight, outputTif)
}

GetItemInfo(item, page, zoom, ByRef width, ByRef height, ByRef file, ByRef id1, ByRef id2) {
   ToolTip, Getting item info ..., 2, 2, 1
   Loop 1 {
      if !html := GetHtml("https://www.prlib.ru/item/" . item) {
         error := "Failed to load html"
         break
      }
      if !RegExMatch(html, "i)public\\/([a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12})\\/(\d+)", id) {
         error := "Failed to get IDs"
         break
      }
      if !metadataJson := GetHtml("https://content.prlib.ru/metadata/public/" . id1 . "/" . id2 . "/" . id1 . ".json") {
         error := "Failed to get metadata"
         break
      }
      JS := GetJS()
      try jsObj := JS.eval("(" . metadataJson . ")")
      catch {
         error := "Bad Json data"
         break
      }
      try maxZoom := jsObj.max_zoom
      catch {
         error := "Unknown json format"
         break
      }
      if (maxZoom < zoom) {
         error := "Zoom " . zoom . " is not supported. Max zoom is " . maxZoom
         break
      }
      try width := jsObj["pgs"][page - 1]["d"][zoom].w
      catch {
         error := "Filed to get image width: unknown json format"
         break
      }
      try height := jsObj["pgs"][page - 1]["d"][zoom].h
      catch {
         error := "Filed to get image height: unknown json format"
         break
      }
      try file := jsObj["pgs"][page - 1].f
      catch {
         error := "Filed to get image fileName: unknown json format"
         break
      }
   }
   ToolTip,,,, 1
   if !error
      Return true
   else
      MsgBox, % error
}

GetChunkDimension(id1, id2, file, zoom, ByRef chunkWidth, ByRef chunkHeight) {
   static preUrl := "https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF=/var/data/scans/public/"
   if !hBitmap := GetHBitmapFromImageURL(preUrl . id1 . "/" . id2 . "/" . file . "&JTL=" . zoom . ",0") {
      MsgBox, Failed to get bitmap from url
      Return
   }
   VarSetCapacity(BITMAP, sz := 4*4 + A_PtrSize*2, 0)
   DllCall("GetObject", "Ptr", hBitmap, "Int", sz, "Ptr", &BITMAP)
   DllCall("DeleteObject", "Ptr", hBitmap)
   chunkWidth  := NumGet(BITMAP, 4, "UInt")
   chunkHeight := NumGet(BITMAP, 8, "UInt")
   Return true
}

BuildImg(id1, id2, file, zoom, width, height, chunkWidth, chunkHeight, outputTif) {
   static preUrl := "https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF=/var/data/scans/public/"
   
   countWidth  := Ceil(width/chunkWidth)
   countHeight := Ceil(height/chunkHeight)
   chunkCount := countWidth*countHeight
   
   GdipInst := new GDIp
   pBitmap := GdipInst.CreateBitmap(width, height)
   G := GdipInst.GraphicsFromImage(pBitmap)
   
   Loop % chunkCount {
      ToolTip % A_Index . " of " . chunkCount . " is downloading ...", 2, 2, 1
      pIUnknown := GetImgResponseStream(preUrl . id1 . "/" . id2 . "/" . file . "&JTL=" . zoom . "," . A_Index - 1)
      pBitmapChunk := GdipInst.BitmapFromIStream(pIUnknown)
      DllCall("OleAut32\VariantClear", "PtrP", pIUnknown)
      GdipInst.DrawImage(G, pBitmapChunk, chunkWidth*mod((A_Index - 1), countWidth)
                                        , chunkHeight*(A_Index//(countWidth + 0.01))
                                        , chunkWidth, chunkHeight, 0, 0, chunkWidth, chunkHeight)
      GdipInst.DisposeImage(pBitmapChunk)
   }
   ToolTip,,,, 1
   GdipInst.SaveBitmap(pBitmap, outputTif)
   GdipInst.DeleteGraphics(G)
   GdipInst.DisposeImage(pBitmap)
}

GetHtml(url) {
   whr := ComObjCreate("Msxml2.XMLHTTP.6.0")
   whr.Open("GET", url, false)
   whr.SetRequestHeader("Pragma", "no-cache")
   whr.SetRequestHeader("Cache-Control", "no-cache, no-store")
   whr.Send()
   Return html := whr.ResponseText
}

GetJS() {
   static doc, JS
   if !doc {
       doc := ComObjCreate("htmlfile")
       doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
       JS := doc.parentWindow
   }
   Return JS
}

GetHBitmapFromImageURL(url)  {
   if !pIUnknown := GetImgResponseStream(url)
      Return
   GdipInst := new GDIp
   pBitmap := GdipInst.BitmapFromIStream(pIUnknown)
   DllCall("OleAut32\VariantClear", "PtrP", pIUnknown)
   hBitmap := GdipInst.CreateHBitmapFromBitmap(pBitmap)
   GdipInst.DisposeImage(pBitmap)
   Return hBitmap
}

GetImgResponseStream(url) {
   whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   whr.Open("GET", url, false)
   whr.Send()
   if (whr.Status != 200)  {
      MsgBox, Failed to load the image!
      Return
   }
   contentType := whr.GetResponseHeader("Content-Type")
   if !InStr(contentType, "image")  {
      MsgBox, URL doesn't link to an image!
      Return
   }
   Return whr.ResponseStream
}

class GDIp   {
   __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)
   }
   
   BitmapFromIStream(pIUnknown)  {
      static IID_IStream := "{0000000C-0000-0000-C000-000000000046}"
      pIStream := ComObjQuery(pIUnknown, IID_IStream)
      DllCall("gdiplus\GdipCreateBitmapFromStream", "Ptr", pIStream, "PtrP", pBitmap)
      ObjRelease(pIStream)
      Return pBitmap
   }
   
   CreateHBitmapFromBitmap(pBitmap) {
      DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0xFFFFFFFF)
      Return hBitmap
   }
   
	CreateBitmap(Width, Height, Format=0x26200A) {
		 DllCall("gdiplus\GdipCreateBitmapFromScan0", "Int", Width, "Int", Height, "Int", 0, "Int", Format, "Ptr", 0, "PtrP", pBitmap)
		 Return pBitmap
	}
   
	GraphicsFromImage(pBitmap) {
		DllCall("gdiplus\GdipGetImageGraphicsContext", "Ptr", pBitmap, "PtrP", pGraphics)
		return pGraphics
	}
   
   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, "Ptr", nSize )
            DllCall( "GlobalUnlock", "Ptr", hData )
            DllCall( "GlobalFree", "Ptr", hData )
         }
         ObjRelease(pStream)
      }
      return E ? -4 : tobuff ? nSize : 0
   }
   
	DisposeImage(pBitmap) {
		return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
	}
   
	DeleteGraphics(pGraphics) {
		return DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
	}
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg
+ DD

88

Re: AHK: Объединить кусочки картинок в одно целое

У некоторых страниц зум может быть больше четырёх.

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

89

Re: AHK: Объединить кусочки картинок в одно целое

Круто сделано, спасибо!

90

Re: AHK: Объединить кусочки картинок в одно целое

teadrinker, а когда зум больше четырёх, что скрипт делает? Когда меньше — он не скачивает, а выводит сообщение о несоответствии.

91

Re: AHK: Объединить кусочки картинок в одно целое

Когда указанный зум больше возможного, выводит сообщение, если меньше или равен — скачивает, какой указан.

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

92 (изменено: DD, 2020-03-05 20:47:52)

Re: AHK: Объединить кусочки картинок в одно целое

Можно ли задать скачивание по умолчанию в максимальном разрешении — в том, которое прописано в json'е, в "max_zoom"?

93

Re: AHK: Объединить кусочки картинок в одно целое

Вношу такой код, но это не срабатывает:

      If InStr(metadataJson, """max_zoom"": 3") ;!!
      {
         maxZoom := "3"
         zoom := "3"
      }

94

Re: AHK: Объединить кусочки картинок в одно целое

#NoEnv
SetBatchLines, -1
CoordMode, ToolTip
PrLibDownload(377452, 1)
MsgBox, Completed!

PrLibDownload(item, page, zoom := "max") {
   if !GetItemInfo(item, page, zoom, width, height, file, id1, id2)
      Return
   
   if !GetChunkDimension(id1, id2, file, zoom, chunkWidth, chunkHeight)
      Return
   
   BuildImg(id1, id2, file, zoom, width, height, chunkWidth, chunkHeight, item . "-" . page . ".tif")
}

GetItemInfo(item, page, ByRef zoom, ByRef width, ByRef height, ByRef file, ByRef id1, ByRef id2) {
   ToolTip, Getting item info ..., 2, 2, 1
   Loop 1 {
      if !html := GetHtml("https://www.prlib.ru/item/" . item) {
         error := "Failed to load html"
         break
      }
      if !RegExMatch(html, "i)public\\/([a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12})\\/(\d+)", id) {
         error := "Failed to get IDs"
         break
      }
      if !metadataJson := GetHtml("https://content.prlib.ru/metadata/public/" . id1 . "/" . id2 . "/" . id1 . ".json") {
         error := "Failed to get metadata"
         break
      }
      JS := GetJS()
      try jsObj := JS.eval("(" . metadataJson . ")")
      catch {
         error := "Bad Json data"
         break
      }
      maxPage := jsObj["pgs"].length
      if (page > maxPage) {
         MsgBox, There is no page %page%, max page number is %maxPage%
         Return
      }
      try maxZoom := jsObj.max_zoom
      catch {
         error := "Unknown json format"
         break
      }
      (zoom = "max" && zoom := maxZoom)
      if (maxZoom < zoom) {
         error := "Zoom " . zoom . " is not supported. Max zoom is " . maxZoom
         break
      }
      try width := jsObj["pgs"][page - 1]["d"][zoom].w
      catch {
         error := "Filed to get image width: unknown json format"
         break
      }
      try height := jsObj["pgs"][page - 1]["d"][zoom].h
      catch {
         error := "Filed to get image height: unknown json format"
         break
      }
      try file := jsObj["pgs"][page - 1].f
      catch {
         error := "Filed to get image fileName: unknown json format"
         break
      }
   }
   ToolTip,,,, 1
   if !error
      Return true
   else
      MsgBox, % error
}

GetChunkDimension(id1, id2, file, zoom, ByRef chunkWidth, ByRef chunkHeight) {
   static preUrl := "https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF=/var/data/scans/public/"
   if !hBitmap := GetHBitmapFromImageURL(preUrl . id1 . "/" . id2 . "/" . file . "&JTL=" . zoom . ",0") {
      MsgBox, Failed to get bitmap from url
      Return
   }
   VarSetCapacity(BITMAP, sz := 4*4 + A_PtrSize*2, 0)
   DllCall("GetObject", "Ptr", hBitmap, "Int", sz, "Ptr", &BITMAP)
   DllCall("DeleteObject", "Ptr", hBitmap)
   chunkWidth  := NumGet(BITMAP, 4, "UInt")
   chunkHeight := NumGet(BITMAP, 8, "UInt")
   Return true
}

BuildImg(id1, id2, file, zoom, width, height, chunkWidth, chunkHeight, outputTif) {
   static preUrl := "https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF=/var/data/scans/public/"
   
   countWidth  := Ceil(width/chunkWidth)
   countHeight := Ceil(height/chunkHeight)
   chunkCount := countWidth*countHeight
   
   GdipInst := new GDIp
   pBitmap := GdipInst.CreateBitmap(width, height)
   G := GdipInst.GraphicsFromImage(pBitmap)
   
   Loop % chunkCount {
      ToolTip % A_Index . " of " . chunkCount . " is downloading ...", 2, 2, 1
      if !pIUnknown := GetImgResponseStream(preUrl . id1 . "/" . id2 . "/" . file . "&JTL=" . zoom . "," . A_Index - 1) {
         MsgBox, 4,, Failed to load a chunk. Continue?
         IfMsgBox, No
            break
         else
            continue
      }
      pBitmapChunk := GdipInst.BitmapFromIStream(pIUnknown)
      DllCall("OleAut32\VariantClear", "PtrP", pIUnknown)
      GdipInst.DrawImage(G, pBitmapChunk, chunkWidth*mod((A_Index - 1), countWidth)
                                        , chunkHeight*(A_Index//(countWidth + 0.01))
                                        , chunkWidth, chunkHeight, 0, 0, chunkWidth, chunkHeight)
      GdipInst.DisposeImage(pBitmapChunk)
   }
   ToolTip,,,, 1
   GdipInst.SaveBitmap(pBitmap, outputTif)
   GdipInst.DeleteGraphics(G)
   GdipInst.DisposeImage(pBitmap)
}

GetHtml(url) {
   whr := ComObjCreate("Msxml2.XMLHTTP.6.0")
   whr.Open("GET", url, false)
   whr.SetRequestHeader("Pragma", "no-cache")
   whr.SetRequestHeader("Cache-Control", "no-cache, no-store")
   whr.Send()
   Return html := whr.ResponseText
}

GetJS() {
   static doc, JS
   if !doc {
       doc := ComObjCreate("htmlfile")
       doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
       JS := doc.parentWindow
   }
   Return JS
}

GetHBitmapFromImageURL(url)  {
   if !pIUnknown := GetImgResponseStream(url)
      Return
   GdipInst := new GDIp
   pBitmap := GdipInst.BitmapFromIStream(pIUnknown)
   DllCall("OleAut32\VariantClear", "PtrP", pIUnknown)
   hBitmap := GdipInst.CreateHBitmapFromBitmap(pBitmap)
   GdipInst.DisposeImage(pBitmap)
   Return hBitmap
}

GetImgResponseStream(url) {
   whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   whr.Open("GET", url, false)
   whr.Send()
   if (whr.Status != 200)  {
      MsgBox, Failed to load the image!
      Return
   }
   contentType := whr.GetResponseHeader("Content-Type")
   if !InStr(contentType, "image")  {
      MsgBox, URL doesn't link to an image!
      Return
   }
   Return whr.ResponseStream
}

class GDIp   {
   __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)
   }
   
   BitmapFromIStream(pIUnknown)  {
      static IID_IStream := "{0000000C-0000-0000-C000-000000000046}"
      pIStream := ComObjQuery(pIUnknown, IID_IStream)
      DllCall("gdiplus\GdipCreateBitmapFromStream", "Ptr", pIStream, "PtrP", pBitmap)
      ObjRelease(pIStream)
      Return pBitmap
   }
   
   CreateHBitmapFromBitmap(pBitmap) {
      DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0xFFFFFFFF)
      Return hBitmap
   }
   
   CreateBitmap(Width, Height, Format=0x26200A) {
       DllCall("gdiplus\GdipCreateBitmapFromScan0", "Int", Width, "Int", Height, "Int", 0, "Int", Format, "Ptr", 0, "PtrP", pBitmap)
       Return pBitmap
   }
   
   GraphicsFromImage(pBitmap) {
      DllCall("gdiplus\GdipGetImageGraphicsContext", "Ptr", pBitmap, "PtrP", pGraphics)
      return pGraphics
   }
   
   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, "Ptr", nSize )
            DllCall( "GlobalUnlock", "Ptr", hData )
            DllCall( "GlobalFree", "Ptr", hData )
         }
         ObjRelease(pStream)
      }
      return E ? -4 : tobuff ? nSize : 0
   }
   
   DisposeImage(pBitmap) {
      return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
   }
   
   DeleteGraphics(pGraphics) {
      return DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

95

Re: AHK: Объединить кусочки картинок в одно целое

Изображение скачивается в папку скрипта и называется по номеру item и страницы.

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

96

Re: AHK: Объединить кусочки картинок в одно целое

Спасибо!

97

Re: AHK: Объединить кусочки картинок в одно целое

С чем может быть связано, что при загрузке следующего item, на 33 шаге Tooltip'а скрипт завершается? —

PrLibDownload(362052, 1)

Если заглянуть в этот json, там всего 33 tiff-файла, хотя при загрузке Tooltip показывает "33 из 128".

98

Re: AHK: Объединить кусочки картинок в одно целое

А где вы в джейсоне нашли количество файлов? По-моему, там этого нет.

https://i.imgur.com/VWq61mj.png

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

99 (изменено: DD, 2020-03-06 07:05:36)

Re: AHK: Объединить кусочки картинок в одно целое

В формате книг, которые скачиваются скриптом без ошибок — количество страниц совпадает с количеством .tiff файлов в них. Общее количество страниц я узнавал, подсчитывая, сколько в джейсоне следующих сочетаний — «"m":». Но в данном случае формат отличается.

То есть, в первом случае, там ссылка на джейсон есть в коде страницы и в под-окне просмотра все страницы представлены отдельно. А во втором случае, джейсона в коде нет и в под-окне просмотра все страницы показываются в уменьшенном виде, но с возможностью увеличения.

По последней ссылке кстати сказано, что файлов 34 — «Электронные данные (34 файла : 53,3 МБ)» — может поэтому скрипт останавливается на 34-м файле?

По этой ссылке файл соберётся, а по приводившейся — скачивание фрагментов останавливается на 33-м номере из 128-ми.

100 (изменено: teadrinker, 2020-03-06 14:18:59)

Re: AHK: Объединить кусочки картинок в одно целое

Вы просто путаете количество уже собранных файлов и количество кусочков в них, из которых скрипт их собирает. Количество собранных файлов конечно совпадает с количеством страниц, мы ведь собираем страницу в один файл. У меня в ToolTip выводится информация о номере скачиваемого кусочка в данный момент.
Действительно, во втором случае другой формат, возможно, он как-то по-другому устроен, попозже попробую посмотреть.

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