DB_Image.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. <?php
  2. class DB_Image {
  3. public static function calculateThumbImageSize($width, $height, $maxWidth, $maxHeight) {
  4. $width = intval($width);
  5. $height = intval($height);
  6. $maxWidth = intval($maxWidth);
  7. $maxHeight = intval($maxHeight);
  8. if ($width <= 0 || $height <= 0 || $maxWidth <= 0 || $maxHeight <= 0) {
  9. throw new Exception("Wrong params");
  10. }
  11. list($newWidth, $newHeight) = array($width, $height);
  12. if ($width >= $maxWidth || $height >= $maxWidth) {
  13. $ratioWidth = $maxWidth / $width;
  14. $ratioHeight = $maxHeight / $height;
  15. if ($ratioWidth > $ratioHeight) {
  16. $ratio = $ratioHeight;
  17. } else {
  18. $ratio = $ratioWidth;
  19. }
  20. $newWidth = intval($width * $ratio);
  21. $newHeight = intval($height * $ratio);
  22. }
  23. return array($newWidth, $newHeight);
  24. }
  25. public static function resizeImageFromBlob($imageBlob, $type, $maxWidth, $maxHeight) {
  26. $resizedImageBlob = null;
  27. list($w, $h) = self::getImageGeometryFromBlob($imageBlob);
  28. list($newWidth, $newHeight) = self::calculateThumbImageSize($w, $h, $maxWidth, $maxHeight);
  29. if ($newW == $w && $newH == $h) {
  30. return $imageBlob;
  31. }
  32. if (class_exists('Imagick')) {
  33. $im = new Imagick();
  34. $im->readImageBlob($imageBlob);
  35. $im->thumbnailImage($newWidth, $newHeight, true);
  36. $resizedImageBlob = $im->getImageBlob();
  37. } else {
  38. $im = imagecreatefromstring($imageBlob);
  39. $image_resized = self::resize_image_from_data($im, $newWidth, $newHeight);
  40. ob_start();
  41. if ($type == 'image/png') {
  42. imagepng($image_resized);
  43. } else if ($type == 'image/jpeg' || $type == 'image/jpg') {
  44. imagejpeg($image_resized);
  45. } else if ($type == 'image/gif') {
  46. imagegif($image_resized);
  47. }
  48. $resizedImageBlob = ob_get_contents();
  49. ob_clean();
  50. }
  51. return $resizedImageBlob;
  52. }
  53. public static function getImageGeometryFromBlob($imageBlob) {
  54. if (class_exists('Imagick')) {
  55. $im = new Imagick();
  56. $im->readImageBlob($imageBlob);
  57. $geometry = $im->getImageGeometry();
  58. $w = $geometry['width'];
  59. $h = $geometry['height'];
  60. } else {
  61. $im = imagecreatefromstring($imageBlob);
  62. $w = imagesx($im);
  63. $h = imagesy($im);
  64. }
  65. return array($w, $h);
  66. }
  67. public static function getImage($remote_table, $remote_id, $number = 0) {
  68. $db = DB::getDB();
  69. $sql = "select `ID`, `TYPE`, `SIZE`, `IMAGE`, `WIDTH`, `HEIGHT`
  70. , UNIX_TIMESTAMP(`A_CREATE_DATE`) as A_CREATE_DATE_TS
  71. from `".self::conf_get_table_name()."`
  72. where
  73. `REMOTE_ID`='{$remote_id}'
  74. and `REMOTE_TABLE`='{$remote_table}'
  75. order by `ID` asc
  76. limit 1 offset {$number}
  77. ";
  78. $res = $db->query($sql);
  79. if (!$db->num_rows($res)) {
  80. return null;
  81. }
  82. return $db->fetch($res);
  83. }
  84. public static function getImageById($imageId) {
  85. $db = DB::getDB();
  86. $sql = "select `ID`, `TYPE`, `SIZE`, `IMAGE`, `WIDTH`, `HEIGHT`
  87. , UNIX_TIMESTAMP(`A_CREATE_DATE`) as A_CREATE_DATE_TS
  88. from `".self::conf_get_table_name()."`
  89. where
  90. `ID`='{$imageId}'
  91. ";
  92. $res = $db->query($sql);
  93. return $db->fetch($res);
  94. }
  95. public static function tableIsAllowed($remote_table) {
  96. $remote_tables = self::conf_get('remote_tables');
  97. return in_array($remote_table, $remote_tables);
  98. }
  99. public static function conf_get($key) {
  100. static $conf;
  101. if (empty($conf)) {
  102. $conf['table_name'] = 'CRM_IMAGE';
  103. $conf['max_size'] = 1024 * 1024 * 16;// MAX for MEDIUMBLOB field
  104. $conf['allowed_types'] = array();
  105. $conf['allowed_types'][] = 'image/png';
  106. $conf['allowed_types'][] = 'image/jpeg';
  107. $conf['allowed_types'][] = 'image/gif';
  108. $conf['remote_tables'] = array();
  109. $conf['remote_tables'][] = 'CRM_LISTA_ZASOBOW';
  110. $conf['remote_tables'][] = 'CRM_PROCES';
  111. $conf['remote_tables'][] = 'CRM_WSKAZNIK';
  112. $conf['desc_options'] = array();
  113. $conf['desc_options']['CRM_LISTA_ZASOBOW'] = array();
  114. $conf['desc_options']['CRM_PROCES'] = array();
  115. $conf['desc_options']['CRM_WSKAZNIK'] = array();
  116. $conf['desc_options_conf'] = array();
  117. $conf['desc_options_conf']['CRM_LISTA_ZASOBOW'] = array();
  118. $conf['desc_options_conf']['CRM_PROCES'] = array();
  119. $conf['desc_options_conf']['CRM_WSKAZNIK'] = array();
  120. $options = array();
  121. $options['screenshot'] = "screenshot (800x600)";
  122. $options['icon'] = "icon (16x16)";
  123. $conf['desc_options']['CRM_LISTA_ZASOBOW'] = $options;
  124. $conf['desc_options']['CRM_PROCES'] = $options;
  125. $conf['desc_options']['CRM_WSKAZNIK'] = $options;
  126. $desc_options_conf = array();
  127. $desc_options_conf['screenshot']['max_width'] = 800;
  128. $desc_options_conf['screenshot']['max_height'] = 600;
  129. $desc_options_conf['icon']['max_width'] = 16;
  130. $desc_options_conf['icon']['max_height'] = 16;
  131. $conf['desc_options_conf']['CRM_LISTA_ZASOBOW'] = $desc_options_conf;
  132. $conf['desc_options_conf']['CRM_PROCES'] = $desc_options_conf;
  133. $conf['desc_options_conf']['CRM_WSKAZNIK'] = $desc_options_conf;
  134. }
  135. if (array_key_exists($key, $conf)) {
  136. return $conf[$key];
  137. }
  138. return null;
  139. }
  140. public static function conf_get_table_name() {// TODO: RM Legacy
  141. return self::getStorageTableName();
  142. }
  143. public static function getStorageTableName() {
  144. return self::conf_get('table_name');
  145. }
  146. public static function conf_get_options($table) {// TODO: RM Legacy
  147. return self::getTableConfig($table);
  148. }
  149. public static function getTableConfig($table) {
  150. $ret = array();
  151. $arr = self::conf_get('desc_options');
  152. if (array_key_exists($table, $arr)) {
  153. return $arr[$table];
  154. }
  155. return $ret;
  156. }
  157. public static function conf_get_options_conf($table) {// TODO: RM Not used ?
  158. $ret = array();
  159. $arr = self::conf_get('desc_options_conf');
  160. if (array_key_exists($table, $arr)) {
  161. return $arr[$table];
  162. }
  163. return $ret;
  164. }
  165. public static function conf_get_option_conf($table, $key) {// TODO: used only in upload_image
  166. $ret = array();
  167. $arr = self::conf_get('desc_options_conf');
  168. if (array_key_exists($table, $arr)) {
  169. if (array_key_exists($key, $arr[$table])) {
  170. return $arr[$table][$key];
  171. }
  172. }
  173. return $ret;
  174. }
  175. public static function is_allowed_type($type) {// TODO: used only in upload_image
  176. $allowed_types = self::conf_get('allowed_types');
  177. if (in_array($type, $allowed_types)) {
  178. return true;
  179. }
  180. return false;
  181. }
  182. public static function readImageBlobFromFile($file, $mimeType) {
  183. $imBlob = null;
  184. if (class_exists('Imagick')) {
  185. $im = new Imagick($file);
  186. $imBlob = $im->getImageBlob();
  187. } else {
  188. if ($mimeType == 'image/jpeg') {
  189. $im = imagecreatefromjpeg($file);
  190. } else if ($mimeType == 'image/png') {
  191. $im = imagecreatefrompng($file);
  192. } else if ($mimeType == 'image/gif') {
  193. $im = imagecreatefromgif($file);
  194. }
  195. ob_start();
  196. if ($mimeType == 'image/png') {
  197. imagepng($im);
  198. } else if ($mimeType == 'image/jpeg' || $mimeType == 'image/jpg') {
  199. imagejpeg($im);
  200. } else if ($mimeType == 'image/gif') {
  201. imagegif($im);
  202. }
  203. $imBlob = ob_get_contents();
  204. ob_clean();
  205. }
  206. return $imBlob;
  207. }
  208. public static function writeImageBlobToFile($imBlob, $mimeType, $destFile) {
  209. if (class_exists('Imagick')) {
  210. $im = new Imagick();
  211. $im->readImageBlob($imBlob);
  212. $im->writeImage($destFile);
  213. } else {
  214. throw new Exception("Can't save image to file (no ImageMagick)");
  215. }
  216. return true;
  217. }
  218. public static function read_image_data($file, $mime_type) {// TODO: used only in upload_image
  219. $im = null;
  220. if ($mime_type == 'image/jpeg') {
  221. $im = imagecreatefromjpeg($file);
  222. } else if ($mime_type == 'image/png') {
  223. $im = imagecreatefrompng($file);
  224. } else if ($mime_type == 'image/gif') {
  225. $im = imagecreatefromgif($file);
  226. }
  227. return $im;
  228. }
  229. public static function get_images($remote_table, $remote_id) {// TODO: RM Legacy
  230. return self::getImages($remote_table, $remote_id);
  231. }
  232. public static function getImages($remote_table, $remote_id) {
  233. $db = DB::getDB();
  234. $images = array();
  235. $sql = "select
  236. t.`ID`, t.`NAME`, t.`SIZE`, t.`TYPE`, t.`WIDTH`, t.`HEIGHT`
  237. , t.`DEST`, t.`A_CREATE_DATE`
  238. , t.`REMOTE_TABLE`, t.`REMOTE_ID`
  239. , UNIX_TIMESTAMP(`A_CREATE_DATE`) as A_CREATE_DATE_TS
  240. from `".self::conf_get_table_name()."` as t
  241. where
  242. t.`REMOTE_TABLE`='{$remote_table}'
  243. and t.`REMOTE_ID`='{$remote_id}'
  244. ";
  245. $res = $db->query($sql);
  246. while ($r = $db->fetch($res)) {
  247. $images[] = $r;
  248. }
  249. return $images;
  250. }
  251. /**
  252. * Try to upload image to DB.
  253. * @returns Array of errors
  254. */
  255. public static function upload_image($remote_table, $remote_id, $req_file_data) {// TODO: RM -> moved to uploadImage
  256. return self::uploadImage($remote_table, $remote_id, $req_file_data);
  257. }
  258. public static function uploadImage($remote_table, $remote_id, $req_file_data) {
  259. $errors = array();
  260. $maxsize = self::conf_get('max_size');
  261. if (is_uploaded_file($req_file_data['tmp_name'])) {
  262. if ($req_file_data['size'] < $maxsize) {
  263. $fp = fopen($req_file_data['tmp_name'], 'r');
  264. $imgData = fread($fp, filesize($req_file_data['tmp_name']));
  265. $imgData = addslashes($imgData);
  266. fclose($fp);
  267. $size = getimagesize($req_file_data['tmp_name']);
  268. $sqlObj = array();
  269. $sqlObj['DEST'] = (isset($_REQUEST['DEST']))? $_REQUEST['DEST'] : '';
  270. $sqlObj['TYPE'] = $size['mime'];
  271. $sqlObj['IMAGE'] = $imgData;
  272. $sqlObj['WIDTH'] = $size[0];
  273. $sqlObj['HEIGHT'] = $size[1];
  274. $sqlObj['NAME'] = $req_file_data['name'];
  275. $sqlObj['SIZE'] = $req_file_data['size'];
  276. $sqlObj['REMOTE_TABLE'] = $remote_table;
  277. $sqlObj['REMOTE_ID'] = $remote_id;
  278. // check if type is allowed to upload
  279. if (!self::is_allowed_type($sqlObj['TYPE'])) {
  280. $errors[] = 'File type "'.$sqlObj['TYPE'].'" is not allowed.';
  281. return $errors;
  282. }
  283. // convert image if selected option
  284. if ($sqlObj['DEST']) {
  285. $options_conf = self::conf_get_option_conf($remote_table, $sqlObj['DEST']);
  286. if (!empty($options_conf)) {
  287. $max_width = V::get('max_width', 0, $options_conf, 'int');
  288. $max_height = V::get('max_height', 0, $options_conf, 'int');
  289. if ($max_height > 0 && $max_width > 0) {
  290. $imBlob = self::readImageBlobFromFile($req_file_data['tmp_name'], $sqlObj['TYPE']);
  291. $sqlObj['IMAGE'] = self::resizeImageFromBlob($imBlob, $sqlObj['TYPE'], $max_width, $max_height);
  292. list($sqlObj['WIDTH'], $sqlObj['HEIGHT']) = self::getImageGeometryFromBlob($sqlObj['IMAGE']);
  293. $sqlObj['SIZE'] = strlen($sqlObj['IMAGE']);
  294. $sqlObj['IMAGE'] = addslashes($sqlObj['IMAGE']);
  295. }
  296. }
  297. }
  298. $sql_arr = array();
  299. foreach ($sqlObj as $key => $val) {
  300. $sql_arr["`{$key}`"] = "'{$val}'";
  301. }
  302. $sql = "insert into `".self::conf_get_table_name()."` (".implode(",", array_keys($sql_arr)).") values (".implode(",", array_values($sql_arr)).") ; ";
  303. $db = DB::getDB();
  304. if (!$db->query($sql)) {
  305. $errors[] = 'Unable to upload file - sql error';
  306. }
  307. self::update_remote_table_stat($remote_table, $remote_id);
  308. }
  309. }
  310. else {
  311. // if the file is not less than the maximum allowed, print an error
  312. $errors[] = 'File exceeds the Maximum File limit';
  313. }
  314. return $errors;
  315. }
  316. public static function delete_image($id, $remote_table, $remote_id) {// TODO: RM Legacy
  317. return self::deleteImage($id, $remote_table, $remote_id);
  318. }
  319. public static function deleteImage($id, $remote_table, $remote_id) {
  320. $db = DB::getDB();
  321. $sql = "delete from `".self::conf_get_table_name()."`
  322. where
  323. `ID`='{$id}'
  324. and `REMOTE_ID`='{$remote_id}'
  325. and `REMOTE_TABLE`='{$remote_table}'
  326. limit 1
  327. ";
  328. //echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">sql delete = ';print_r($sql);echo'</pre>';
  329. $db->query($sql);
  330. $affected = $db->affected_rows();
  331. self::update_remote_table_stat($remote_table, $remote_id);
  332. return $affected;
  333. }
  334. /**
  335. * Updates field ITEM_IMAGE_REMOTE in remote table.
  336. * TODO: check if field exists!
  337. */
  338. public static function update_remote_table_stat($remote_table, $remote_id) {// TODO: used only in this file
  339. // update stat `ITEM_IMAGE_REMOTE`
  340. $sql = "update `{$remote_table}`
  341. set `A_HAS_IMAGE`=(
  342. select count(1)
  343. from `".self::conf_get('table_name')."`
  344. where
  345. `REMOTE_ID`='{$remote_id}'
  346. and `REMOTE_TABLE`='{$remote_table}'
  347. )
  348. where `ID`='{$remote_id}'
  349. limit 1;
  350. ";
  351. $db = DB::getDB();
  352. $res = $db->query($sql);
  353. $affected = $db->affected_rows();
  354. }
  355. public static function resize_image($file, $w, $h, $crop = FALSE) {
  356. // TODO: image type
  357. $im = imagecreatefromjpeg($file);
  358. return self::resize_image_from_data($im, $w, $h, $crop);
  359. }
  360. public static function resize_image_from_data($im, $w, $h, $crop = FALSE) {
  361. if ($w == 0) $w = $h;
  362. if ($h == 0) $h = $w;
  363. $width = imagesx($im);
  364. $height = imagesy($im);
  365. if ($width < $w && $height < $h) {
  366. return $im;
  367. }
  368. $r = $width / $height;
  369. if ($crop) {
  370. if ($width > $height) {
  371. $width = ceil($width-($width*($r-$w/$h)));
  372. } else {
  373. $height = ceil($height-($height*($r-$w/$h)));
  374. }
  375. $newwidth = $w;
  376. $newheight = $h;
  377. } else {
  378. if ($w/$h > $r) {
  379. $newwidth = $h*$r;
  380. $newheight = $h;
  381. } else {
  382. $newheight = $w/$r;
  383. $newwidth = $w;
  384. }
  385. }
  386. $dst = imagecreatetruecolor($newwidth, $newheight);
  387. imagecopyresampled($dst, $im, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
  388. return $dst;
  389. }
  390. public static function show_size($size) {// TODO: RM -> moved to showSize
  391. return self::showSize($size);
  392. }
  393. public static function showSize($size) {
  394. $ret_unit = 'B';
  395. if ($size > 1024 * 1024) {
  396. $size = $size / (1024 * 1024);
  397. $ret_unit = 'MB';
  398. } else if ($size > 1024) {
  399. $size = $size / 1024;
  400. $ret_unit = 'KB';
  401. }
  402. return number_format($size, 2, '.', ' ').''.$ret_unit;
  403. }
  404. }