image_location_factory.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "ui/image/image_location_factory.h"
  8. #include "ui/image/image.h"
  9. #include "main/main_session.h"
  10. #include <QtCore/QBuffer>
  11. namespace Images {
  12. namespace {
  13. QSize GetSizeForDocument(const QVector<MTPDocumentAttribute> &attributes) {
  14. for (const auto &attribute : attributes) {
  15. if (attribute.type() == mtpc_documentAttributeImageSize) {
  16. auto &size = attribute.c_documentAttributeImageSize();
  17. return QSize(size.vw().v, size.vh().v);
  18. }
  19. }
  20. return QSize();
  21. }
  22. } // namespace
  23. ImageWithLocation FromPhotoSize(
  24. not_null<Main::Session*> session,
  25. const MTPDphoto &photo,
  26. const MTPPhotoSize &size) {
  27. if (!photo.vaccess_hash().v && photo.vfile_reference().v.isEmpty()) {
  28. // Locally created fake photo.
  29. return ImageWithLocation();
  30. }
  31. return size.match([&](const MTPDphotoSize &data) {
  32. return ImageWithLocation{
  33. .location = ImageLocation(
  34. DownloadLocation{ StorageFileLocation(
  35. photo.vdc_id().v,
  36. session->userId(),
  37. MTP_inputPhotoFileLocation(
  38. photo.vid(),
  39. photo.vaccess_hash(),
  40. photo.vfile_reference(),
  41. data.vtype())) },
  42. data.vw().v,
  43. data.vh().v),
  44. .bytesCount = data.vsize().v
  45. };
  46. }, [&](const MTPDphotoCachedSize &data) {
  47. const auto bytes = qba(data.vbytes());
  48. return ImageWithLocation{
  49. .location = ImageLocation(
  50. DownloadLocation{ StorageFileLocation(
  51. photo.vdc_id().v,
  52. session->userId(),
  53. MTP_inputPhotoFileLocation(
  54. photo.vid(),
  55. photo.vaccess_hash(),
  56. photo.vfile_reference(),
  57. data.vtype())) },
  58. data.vw().v,
  59. data.vh().v),
  60. .bytes = bytes,
  61. .bytesCount = int(bytes.size()),
  62. };
  63. }, [&](const MTPDphotoSizeProgressive &data) {
  64. // #TODO layer118
  65. if (data.vsizes().v.isEmpty()) {
  66. return ImageWithLocation();
  67. }
  68. return ImageWithLocation{
  69. .location = ImageLocation(
  70. DownloadLocation{ StorageFileLocation(
  71. photo.vdc_id().v,
  72. session->userId(),
  73. MTP_inputPhotoFileLocation(
  74. photo.vid(),
  75. photo.vaccess_hash(),
  76. photo.vfile_reference(),
  77. data.vtype())) },
  78. data.vw().v,
  79. data.vh().v),
  80. .bytesCount = data.vsizes().v.back().v
  81. };
  82. }, [&](const MTPDphotoStrippedSize &data) {
  83. return ImageWithLocation();
  84. //const auto bytes = ExpandInlineBytes(qba(data.vbytes()));
  85. //return ImageWithLocation{
  86. // .location = ImageLocation(
  87. // DownloadLocation{ StorageFileLocation(
  88. // photo.vdc_id().v,
  89. // session->userId(),
  90. // MTP_inputPhotoFileLocation(
  91. // photo.vid(),
  92. // photo.vaccess_hash(),
  93. // photo.vfile_reference(),
  94. // data.vtype())) },
  95. // width, // ???
  96. // height), // ???
  97. // .bytes = bytes,
  98. // .bytesCount = bytes.size(),
  99. //};
  100. }, [&](const MTPDphotoPathSize &) {
  101. return ImageWithLocation();
  102. }, [&](const MTPDphotoSizeEmpty &) {
  103. return ImageWithLocation();
  104. });
  105. }
  106. ImageWithLocation FromProgressiveSize(
  107. not_null<Main::Session*> session,
  108. const MTPPhotoSize &size,
  109. int index) {
  110. Expects(size.type() == mtpc_photoSizeProgressive);
  111. const auto &data = size.c_photoSizeProgressive();
  112. if (data.vsizes().v.size() <= index) {
  113. return ImageWithLocation();
  114. }
  115. return ImageWithLocation{
  116. .progressivePartSize = data.vsizes().v[index].v,
  117. };
  118. }
  119. ImageWithLocation FromPhotoSize(
  120. not_null<Main::Session*> session,
  121. const MTPDdocument &document,
  122. const MTPPhotoSize &size) {
  123. return size.match([&](const MTPDphotoSize &data) {
  124. return ImageWithLocation{
  125. .location = ImageLocation(
  126. DownloadLocation{ StorageFileLocation(
  127. document.vdc_id().v,
  128. session->userId(),
  129. MTP_inputDocumentFileLocation(
  130. document.vid(),
  131. document.vaccess_hash(),
  132. document.vfile_reference(),
  133. data.vtype())) },
  134. data.vw().v,
  135. data.vh().v),
  136. .bytesCount = data.vsize().v
  137. };
  138. }, [&](const MTPDphotoCachedSize &data) {
  139. const auto bytes = qba(data.vbytes());
  140. return ImageWithLocation{
  141. .location = ImageLocation(
  142. DownloadLocation{ StorageFileLocation(
  143. document.vdc_id().v,
  144. session->userId(),
  145. MTP_inputDocumentFileLocation(
  146. document.vid(),
  147. document.vaccess_hash(),
  148. document.vfile_reference(),
  149. data.vtype())) },
  150. data.vw().v,
  151. data.vh().v),
  152. .bytes = bytes,
  153. .bytesCount = int(bytes.size()),
  154. };
  155. }, [&](const MTPDphotoSizeProgressive &data) {
  156. if (data.vsizes().v.isEmpty()) {
  157. return ImageWithLocation();
  158. }
  159. return ImageWithLocation{
  160. .location = ImageLocation(
  161. DownloadLocation{ StorageFileLocation(
  162. document.vdc_id().v,
  163. session->userId(),
  164. MTP_inputDocumentFileLocation(
  165. document.vid(),
  166. document.vaccess_hash(),
  167. document.vfile_reference(),
  168. data.vtype())) },
  169. data.vw().v,
  170. data.vh().v),
  171. .bytesCount = data.vsizes().v.back().v
  172. };
  173. }, [&](const MTPDphotoStrippedSize &data) {
  174. return ImageWithLocation();
  175. //const auto bytes = ExpandInlineBytes(qba(data.vbytes()));
  176. //return ImageWithLocation{
  177. // .location = ImageLocation(
  178. // DownloadLocation{ StorageFileLocation(
  179. // document.vdc_id().v,
  180. // session->userId(),
  181. // MTP_inputDocumentFileLocation(
  182. // document.vid(),
  183. // document.vaccess_hash(),
  184. // document.vfile_reference(),
  185. // data.vtype())) },
  186. // width, // ???
  187. // height), // ???
  188. // .bytes = bytes,
  189. // .bytesCount = bytes.size(),
  190. //};
  191. }, [&](const MTPDphotoPathSize &data) {
  192. return ImageWithLocation();
  193. }, [&](const MTPDphotoSizeEmpty &) {
  194. return ImageWithLocation();
  195. });
  196. }
  197. ImageWithLocation FromPhotoSize(
  198. not_null<Main::Session*> session,
  199. const MTPDstickerSet &set,
  200. const MTPPhotoSize &size) {
  201. if (!set.vthumb_dc_id() || !set.vthumb_version()) {
  202. return ImageWithLocation();
  203. }
  204. return size.match([&](const MTPDphotoSize &data) {
  205. return ImageWithLocation{
  206. .location = ImageLocation(
  207. DownloadLocation{ StorageFileLocation(
  208. set.vthumb_dc_id()->v,
  209. session->userId(),
  210. MTP_inputStickerSetThumb(
  211. MTP_inputStickerSetID(set.vid(), set.vaccess_hash()),
  212. MTP_int(set.vthumb_version()->v))) },
  213. data.vw().v,
  214. data.vh().v),
  215. .bytesCount = data.vsize().v
  216. };
  217. }, [&](const MTPDphotoCachedSize &data) {
  218. const auto bytes = qba(data.vbytes());
  219. return ImageWithLocation{
  220. .location = ImageLocation(
  221. DownloadLocation{ StorageFileLocation(
  222. set.vthumb_dc_id()->v,
  223. session->userId(),
  224. MTP_inputStickerSetThumb(
  225. MTP_inputStickerSetID(set.vid(), set.vaccess_hash()),
  226. MTP_int(set.vthumb_version()->v))) },
  227. data.vw().v,
  228. data.vh().v),
  229. .bytes = bytes,
  230. .bytesCount = int(bytes.size()),
  231. };
  232. }, [&](const MTPDphotoSizeProgressive &data) {
  233. if (data.vsizes().v.isEmpty()) {
  234. return ImageWithLocation();
  235. }
  236. return ImageWithLocation{
  237. .location = ImageLocation(
  238. DownloadLocation{ StorageFileLocation(
  239. set.vthumb_dc_id()->v,
  240. session->userId(),
  241. MTP_inputStickerSetThumb(
  242. MTP_inputStickerSetID(set.vid(), set.vaccess_hash()),
  243. MTP_int(set.vthumb_version()->v))) },
  244. data.vw().v,
  245. data.vh().v),
  246. .bytesCount = data.vsizes().v.back().v
  247. };
  248. }, [&](const MTPDphotoStrippedSize &data) {
  249. return ImageWithLocation();
  250. //const auto bytes = ExpandInlineBytes(qba(data.vbytes()));
  251. //return ImageWithLocation{
  252. // .location = ImageLocation(
  253. // DownloadLocation{ StorageFileLocation(
  254. // document.vdc_id().v,
  255. // session->userId(),
  256. // MTP_inputDocumentFileLocation(
  257. // document.vid(),
  258. // document.vaccess_hash(),
  259. // document.vfile_reference(),
  260. // data.vtype())) },
  261. // width, // ???
  262. // height), // ???
  263. // .bytes = bytes,
  264. // .bytesCount = bytes.size(),
  265. //};
  266. }, [&](const MTPDphotoPathSize &data) {
  267. return ImageWithLocation();
  268. }, [&](const MTPDphotoSizeEmpty &) {
  269. return ImageWithLocation();
  270. });
  271. }
  272. ImageWithLocation FromImageInMemory(
  273. const QImage &image,
  274. const char *format,
  275. QByteArray bytes) {
  276. if (image.isNull()) {
  277. return ImageWithLocation();
  278. }
  279. if (bytes.isEmpty()) {
  280. auto buffer = QBuffer(&bytes);
  281. image.save(&buffer, format);
  282. }
  283. return ImageWithLocation{
  284. .location = ImageLocation(
  285. DownloadLocation{ InMemoryLocation{ bytes } },
  286. image.width(),
  287. image.height()),
  288. .bytes = bytes,
  289. .preloaded = image,
  290. .bytesCount = int(bytes.size()),
  291. };
  292. }
  293. ImageLocation FromWebDocument(const MTPWebDocument &document) {
  294. return document.match([](const MTPDwebDocument &data) {
  295. const auto size = GetSizeForDocument(data.vattributes().v);
  296. // We don't use size from WebDocument, because it is not reliable.
  297. // It can be > 0 and different from the real size
  298. // that we get in upload.WebFile result.
  299. //auto filesize = int64(); // data.vsize().v;
  300. return ImageLocation(
  301. DownloadLocation{ WebFileLocation(
  302. data.vurl().v,
  303. data.vaccess_hash().v) },
  304. size.width(),
  305. size.height());
  306. }, [](const MTPDwebDocumentNoProxy &data) {
  307. const auto size = GetSizeForDocument(data.vattributes().v);
  308. // We don't use size from WebDocument, because it is not reliable.
  309. // It can be > 0 and different from the real size
  310. // that we get in upload.WebFile result.
  311. //auto filesize = int64(); // data.vsize().v;
  312. return ImageLocation(
  313. DownloadLocation{ PlainUrlLocation{ qs(data.vurl()) } },
  314. size.width(),
  315. size.height());
  316. });
  317. }
  318. ImageWithLocation FromVideoSize(
  319. not_null<Main::Session*> session,
  320. const MTPDdocument &document,
  321. const MTPVideoSize &size) {
  322. return size.match([&](const MTPDvideoSize &data) {
  323. return ImageWithLocation{
  324. .location = ImageLocation(
  325. DownloadLocation{ StorageFileLocation(
  326. document.vdc_id().v,
  327. session->userId(),
  328. MTP_inputDocumentFileLocation(
  329. document.vid(),
  330. document.vaccess_hash(),
  331. document.vfile_reference(),
  332. data.vtype())) },
  333. data.vw().v,
  334. data.vh().v),
  335. .bytesCount = data.vsize().v,
  336. };
  337. }, [](const MTPDvideoSizeEmojiMarkup &) {
  338. return ImageWithLocation();
  339. }, [](const MTPDvideoSizeStickerMarkup &) {
  340. return ImageWithLocation();
  341. });
  342. }
  343. ImageWithLocation FromVideoSize(
  344. not_null<Main::Session*> session,
  345. const MTPDphoto &photo,
  346. const MTPVideoSize &size) {
  347. return size.match([&](const MTPDvideoSize &data) {
  348. return ImageWithLocation{
  349. .location = ImageLocation(
  350. DownloadLocation{ StorageFileLocation(
  351. photo.vdc_id().v,
  352. session->userId(),
  353. MTP_inputPhotoFileLocation(
  354. photo.vid(),
  355. photo.vaccess_hash(),
  356. photo.vfile_reference(),
  357. data.vtype())) },
  358. data.vw().v,
  359. data.vh().v),
  360. .bytesCount = data.vsize().v,
  361. };
  362. }, [](const MTPDvideoSizeEmojiMarkup &) {
  363. return ImageWithLocation();
  364. }, [](const MTPDvideoSizeStickerMarkup &) {
  365. return ImageWithLocation();
  366. });
  367. }
  368. } // namespace Images