101

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

А вы пока найдите другие книги с такой же структурой и проверьте, все ли они не хотят загружаться.

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

102

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

Не захотят, так как там через другой вьюер загружается - openseadragon.
У него данные в dzi прописываются.

                for (var file in seadragon.files) {
                    tileSources.push(seadragon.iipsrvURL + '/fcgi-bin/iipsrv.fcgi?DeepZoom=' + seadragon.filesPath + '/' + seadragon.files[file] + '.dzi');

Я не понимаю одного, почему эти библиотеки не дают скачать?
Ведь всё-равно кому надо выкачает.

103

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

Если знаешь, как с ними обходиться, напиши, мне пока лень разбираться.

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

104

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

Не, не знаю, я просто посмотрел что подгружается.
Мне тоже лень.

105

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

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

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

106 (изменено: teadrinker, 2020-03-06 15:54:25)

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

Нет, не так всё просто оказалось. Здесь тоже есть этот самый seadragon-viewer, однако обычным способом размер определяется и скачивается правильно. Значит, неважно, какой там вьювер, tiff-файлы с одинаковой нумерацией есть в любом случае. Вопрос, как правильно определить их количество в ряду и соответственно общее количество.

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

107 (изменено: teadrinker, 2020-03-06 16:39:43)

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

Вроде понял:

#NoEnv
SetBatchLines, -1
CoordMode, ToolTip
PrLibDownload(362052, 11)  ; 377452
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
      }
      try Json := GetJS().eval("(" . metadataJson . ")")
      catch {
         error := "Bad Json data"
         break
      }
      maxPage := Json["pgs"].length
      if (page > maxPage) {
         MsgBox, There is no page %page%, max page number is %maxPage%
         Return
      }
      try maxZoom := Json.max_zoom
      catch {
         error := "Failed to get max_zoom value: unknown json format"
         break
      }
      (zoom = "max" && zoom := maxZoom)
      if (maxZoom < zoom) {
         error := "Zoom " . zoom . " is not supported. Max zoom is " . maxZoom
         break
      }
      Page := Json["pgs"][page - 1]
      Dim := Page["d"][zoom]
      try width := Dim.w
      catch {
         error := "Failed to get image width: unknown json format"
         break
      }
      try height := Dim.h
      catch {
         error := "Failed to get image height: unknown json format"
         break
      }
      try file := Page.f
      catch {
         error := "Failed to get image fileName: unknown json format"
         break
      }
      try m := Page.m
      catch {
         error := "Failed to get m-value: unknown json format"
         break
      }
      zoom += m - maxZoom
   }
   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
+ DD

108

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

Malcev пишет:

Я не понимаю одного, почему эти библиотеки не дают скачать?
Ведь всё-равно кому надо выкачает.

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

109

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

Хотя в этом случае уже с экрана можно было бы скринить).

110

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

DD пишет:

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

Вы ссылку приведите, а там посмотрим.
Думаю, что всё, что мы получаем на монитор, можно перехватить.

111

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

Да я просто спросил, теоретически).

112

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

Единственный способ защитить контент - это накладывать вотермарки.
Но всё-равно, если ваш товар будет пользоваться спросом, то найдутся умельцы, которые взломают сервер и будут продавать раз в 10 дешевле.