imagecropperdemo.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. #include "imagecropperdemo.h"
  2. #include <QFormLayout>
  3. #include <QColorDialog>
  4. #include <QVBoxLayout>
  5. #include <QFileDialog>
  6. #include <QMessageBox>
  7. #include <QDebug>
  8. ImageCropperDemo::ImageCropperDemo(QWidget* parent) :
  9. QDialog(parent)
  10. {
  11. setupLayout();
  12. init();
  13. this->setAttribute(Qt::WA_DeleteOnClose, true);
  14. this->setWindowTitle("图片裁剪工具");
  15. }
  16. void ImageCropperDemo::setupLayout() {
  17. imgCropperLabel = new ImageCropperLabel(600, 500, this);
  18. imgCropperLabel->setFrameStyle(1);
  19. comboOutputShape = new QComboBox(this);
  20. comboCropperShape = new QComboBox(this);
  21. labelPreviewImage = new QLabel(this);
  22. editOriginalImagePath = new QLineEdit(this);
  23. btnChooseOriginalImagePath = new QPushButton(this);
  24. QHBoxLayout* hOriginalImagePathLayout = new QHBoxLayout();
  25. hOriginalImagePathLayout->addWidget(editOriginalImagePath);
  26. hOriginalImagePathLayout->addWidget(btnChooseOriginalImagePath);
  27. //图片分辨率设置
  28. editResolution = new QLineEdit("500",this);
  29. QHBoxLayout* hResolutionLayout = new QHBoxLayout();
  30. hResolutionLayout->addWidget(editResolution);
  31. //裁剪尺寸,单位像素
  32. editCropperFixedWidth = new QLineEdit(this);
  33. editCropperFixedHeight = new QLineEdit(this);
  34. QHBoxLayout* hCropperFixedSizeLayout = new QHBoxLayout();
  35. hCropperFixedSizeLayout->addWidget(editCropperFixedWidth);
  36. hCropperFixedSizeLayout->addWidget(editCropperFixedHeight);
  37. editCropperMinWidth = new QLineEdit("8", this);
  38. editCropperMinHeight = new QLineEdit("8", this);
  39. QHBoxLayout* hCropperMinSizeLayout = new QHBoxLayout();
  40. hCropperMinSizeLayout->addWidget(editCropperMinWidth);
  41. hCropperMinSizeLayout->addWidget(editCropperMinHeight);
  42. //裁剪尺寸,单位厘米
  43. editFixedWidth = new QLineEdit(this);
  44. editFixedHeight = new QLineEdit(this);
  45. QHBoxLayout* hFixedSizeLayout = new QHBoxLayout();
  46. hFixedSizeLayout->addWidget(editFixedWidth);
  47. hFixedSizeLayout->addWidget(editFixedHeight);
  48. checkEnableOpacity = new QCheckBox(this);
  49. sliderOpacity = new QSlider(Qt::Horizontal, this);
  50. checkShowDragSquare = new QCheckBox(this);
  51. editDragSquareEdge = new QLineEdit("8", this);
  52. checkShowRectBorder = new QCheckBox(this);
  53. labelRectBorderColor = new QLabel(this);
  54. btnChooseRectBorderCorlor = new QPushButton(this);
  55. QHBoxLayout* hRectBorderColorLayout = new QHBoxLayout();
  56. hRectBorderColorLayout->addWidget(labelRectBorderColor);
  57. hRectBorderColorLayout->addWidget(btnChooseRectBorderCorlor);
  58. labelDragSquareColor = new QLabel(this);
  59. btnChooseDragSquareColor = new QPushButton(this);
  60. QHBoxLayout* hDragSquareColorLayout = new QHBoxLayout();
  61. hDragSquareColorLayout->addWidget(labelDragSquareColor);
  62. hDragSquareColorLayout->addWidget(btnChooseDragSquareColor);
  63. QFormLayout* formLayout1 = new QFormLayout();
  64. formLayout1->addRow(new QLabel("预览:"), labelPreviewImage);
  65. formLayout1->addRow(new QLabel("原图路径:", this), hOriginalImagePathLayout);
  66. formLayout1->addRow(new QLabel("输出形状:", this), comboOutputShape);
  67. formLayout1->addRow(new QLabel("裁剪形状:", this), comboCropperShape);
  68. formLayout1->addRow(new QLabel("分辨率:", this), hResolutionLayout);
  69. formLayout1->addRow(new QLabel("像素尺寸:", this), hCropperFixedSizeLayout);
  70. formLayout1->addRow(new QLabel("厘米尺寸:", this), hFixedSizeLayout);
  71. formLayout1->addRow(new QLabel("最小尺寸:", this), hCropperMinSizeLayout);
  72. QFormLayout* formLayout2 = new QFormLayout();
  73. formLayout2->addRow(new QLabel("透明度:", this), checkEnableOpacity);
  74. formLayout2->addRow(new QLabel("透明度:", this), sliderOpacity);
  75. QFormLayout* formLayout3 = new QFormLayout();
  76. formLayout3->addRow(new QLabel("显示拖拽方框:", this), checkShowDragSquare);
  77. formLayout3->addRow(new QLabel("拖拽方框尺寸:", this), editDragSquareEdge);
  78. formLayout3->addRow(new QLabel("拖拽方框颜色:", this), hDragSquareColorLayout);
  79. QFormLayout* formLayout4 = new QFormLayout();
  80. formLayout4->addRow(new QLabel("显示边框:", this), checkShowRectBorder);
  81. formLayout4->addRow(new QLabel("边框颜色:", this), hRectBorderColorLayout);
  82. btnSavePreview = new QPushButton("保存", this);
  83. btnQuit = new QPushButton("退出", this);
  84. QHBoxLayout* btnLayout = new QHBoxLayout();
  85. btnLayout->addStretch();
  86. btnLayout->addWidget(btnSavePreview);
  87. btnLayout->addStretch();
  88. btnLayout->addWidget(btnQuit);
  89. btnLayout->addStretch();
  90. QVBoxLayout* vLayout = new QVBoxLayout();
  91. vLayout->addLayout(formLayout1);
  92. vLayout->addStretch();
  93. vLayout->addLayout(formLayout2);
  94. vLayout->addStretch();
  95. vLayout->addLayout(formLayout3);
  96. vLayout->addStretch();
  97. vLayout->addLayout(formLayout4);
  98. vLayout->addStretch();
  99. vLayout->addLayout(btnLayout);
  100. mainLayout = new QHBoxLayout(this);
  101. mainLayout->addWidget(imgCropperLabel);
  102. mainLayout->addLayout(vLayout);
  103. }
  104. void ImageCropperDemo::init() {
  105. imgCropperLabel->setRectCropper();
  106. editCropperFixedWidth->setEnabled(false);
  107. editCropperFixedHeight->setEnabled(false);
  108. editFixedWidth->setEnabled(false);
  109. editFixedHeight->setEnabled(false);
  110. labelPreviewImage->setFixedSize(96, 96);
  111. labelPreviewImage->setAlignment(Qt::AlignCenter);
  112. labelPreviewImage->setFrameStyle(QFrame::Panel | QFrame::Sunken);
  113. connect(imgCropperLabel, &ImageCropperLabel::croppedImageChanged,
  114. this, &ImageCropperDemo::onUpdatePreview);
  115. btnChooseOriginalImagePath->setIcon(QIcon(":/new/prefix1/images/select-file.ico"));
  116. btnChooseOriginalImagePath->setFixedWidth(30);
  117. connect(btnChooseOriginalImagePath, &QPushButton::clicked,
  118. this, &ImageCropperDemo::onChooseOriginalImage);
  119. comboOutputShape->addItem("矩形/长方形");
  120. comboOutputShape->addItem("椭圆/圆");
  121. connect(comboOutputShape, SIGNAL(currentIndexChanged(int)),
  122. this, SLOT(onOutputShapeChanged(int)));
  123. comboCropperShape->addItem("矩形");
  124. comboCropperShape->addItem("正方形");
  125. comboCropperShape->addItem("固定矩形尺寸");
  126. comboCropperShape->addItem("椭圆");
  127. comboCropperShape->addItem("圆");
  128. comboCropperShape->addItem("固定椭圆尺寸");
  129. connect(comboCropperShape, SIGNAL(currentIndexChanged(int)),
  130. this, SLOT(onCropperShapeChanged(int)));
  131. connect(editCropperFixedWidth, &QLineEdit::textChanged,
  132. this, &ImageCropperDemo::onFixedWidthChanged);
  133. connect(editCropperFixedHeight, &QLineEdit::textChanged,
  134. this, &ImageCropperDemo::onFixedHeightChanged);
  135. connect(editFixedWidth, &QLineEdit::textChanged,
  136. this, &ImageCropperDemo::onWidthChanged);
  137. connect(editFixedHeight, &QLineEdit::textChanged,
  138. this, &ImageCropperDemo::onHeightChanged);
  139. connect(editCropperMinWidth, &QLineEdit::textChanged,
  140. this, &ImageCropperDemo::onMinWidthChanged);
  141. connect(editCropperMinHeight, &QLineEdit::textChanged,
  142. this, &ImageCropperDemo::onMinHeightChanged);
  143. checkEnableOpacity->setCheckState(Qt::Checked);
  144. imgCropperLabel->enableOpacity(true);
  145. connect(checkEnableOpacity, &QCheckBox::stateChanged,
  146. this, &ImageCropperDemo::onEnableOpacityChanged);
  147. checkShowDragSquare->setCheckState(Qt::Checked);
  148. imgCropperLabel->setShowDragSquare(true);
  149. connect(checkShowDragSquare, &QCheckBox::stateChanged,
  150. this, &ImageCropperDemo::onShowDragSquareChanged);
  151. connect(editDragSquareEdge, &QLineEdit::textChanged,
  152. this, &ImageCropperDemo::onDragSquareEdgeChanged);
  153. sliderOpacity->setRange(0, 100);
  154. sliderOpacity->setValue(60);
  155. connect(sliderOpacity, &QSlider::valueChanged,
  156. this, &ImageCropperDemo::onOpacityChanged);
  157. checkShowRectBorder->setCheckState(Qt::Checked);
  158. connect(checkShowRectBorder, &QCheckBox::stateChanged,
  159. this, &ImageCropperDemo::onShowRectBorder);
  160. setLabelColor(labelRectBorderColor, Qt::white);
  161. btnChooseRectBorderCorlor->setIcon(QIcon(":/new/prefix1/images/color-palette.ico"));
  162. btnChooseRectBorderCorlor->setFixedWidth(40);
  163. connect(btnChooseRectBorderCorlor, &QPushButton::clicked,
  164. this, &ImageCropperDemo::onChooseRectBorderColor);
  165. setLabelColor(labelDragSquareColor, Qt::white);
  166. btnChooseDragSquareColor->setIcon(QIcon(":/new/prefix1/images/color-palette.ico"));
  167. btnChooseDragSquareColor->setFixedWidth(40);
  168. connect(btnChooseDragSquareColor, &QPushButton::clicked,
  169. this, &ImageCropperDemo::onChooseDragSquareColor);
  170. connect(btnSavePreview, &QPushButton::clicked,
  171. this, &ImageCropperDemo::onSaveCroppedImage);
  172. connect(btnQuit, &QPushButton::clicked,
  173. this, &ImageCropperDemo::close);
  174. imgCropperLabel->update();
  175. }
  176. /*****************************************************************************
  177. *
  178. * slots
  179. *
  180. *****************************************************************************/
  181. void ImageCropperDemo::onChooseOriginalImage() {
  182. QString filename = QFileDialog::getOpenFileName(this, "选择图片", "",
  183. "picture (*.jpg *.png *.bmp *.jpeg)");
  184. if (filename.isNull())
  185. return;
  186. QPixmap pixmap;
  187. if (!pixmap.load(filename)) {
  188. QMessageBox::critical(this, "Error", "加载图片失败!", QMessageBox::Ok);
  189. return;
  190. }
  191. editOriginalImagePath->setText(filename);
  192. imgCropperLabel->setOriginalImage(pixmap);
  193. imgCropperLabel->update();
  194. onUpdatePreview();
  195. labelPreviewImage->setFrameStyle(0);
  196. }
  197. void ImageCropperDemo::onOutputShapeChanged(int idx) {
  198. // Output: Rectangular
  199. if (idx == 0)
  200. imgCropperLabel->setOutputShape(OutputShape::RECT);
  201. else
  202. imgCropperLabel->setOutputShape(OutputShape::ELLIPSE);
  203. onUpdatePreview();
  204. }
  205. void ImageCropperDemo::onCropperShapeChanged(int idx) {
  206. switch (CropperShape(idx + 1)) {
  207. case CropperShape::RECT: {
  208. imgCropperLabel->setRectCropper();
  209. editCropperFixedWidth->setEnabled(false);
  210. editCropperFixedHeight->setEnabled(false);
  211. editFixedWidth->setEnabled(false);
  212. editFixedHeight->setEnabled(false);
  213. editCropperMinWidth->setEnabled(true);
  214. editCropperMinHeight->setEnabled(true);
  215. checkShowDragSquare->setEnabled(true);
  216. editDragSquareEdge->setEnabled(true);
  217. btnChooseDragSquareColor->setEnabled(true);
  218. break;
  219. }
  220. case CropperShape::SQUARE: {
  221. imgCropperLabel->setSquareCropper();
  222. editCropperFixedWidth->setEnabled(false);
  223. editCropperFixedHeight->setEnabled(false);
  224. editFixedWidth->setEnabled(false);
  225. editFixedHeight->setEnabled(false);
  226. editCropperMinWidth->setEnabled(true);
  227. editCropperMinHeight->setEnabled(true);
  228. checkShowDragSquare->setEnabled(true);
  229. editDragSquareEdge->setEnabled(true);
  230. btnChooseDragSquareColor->setEnabled(true);
  231. break;
  232. }
  233. case CropperShape::FIXED_RECT: {
  234. imgCropperLabel->setFixedRectCropper(QSize(64, 64));
  235. editCropperFixedWidth->setEnabled(true);
  236. editCropperFixedHeight->setEnabled(true);
  237. editFixedWidth->setEnabled(true);
  238. editFixedHeight->setEnabled(true);
  239. editCropperMinWidth->setEnabled(false);
  240. editCropperMinHeight->setEnabled(false);
  241. editCropperFixedWidth->setText("64");
  242. editCropperFixedHeight->setText("64");
  243. checkShowDragSquare->setEnabled(false);
  244. editDragSquareEdge->setEnabled(false);
  245. btnChooseDragSquareColor->setEnabled(false);
  246. break;
  247. }
  248. case CropperShape::ELLIPSE: {
  249. imgCropperLabel->setEllipseCropper();
  250. editCropperFixedWidth->setEnabled(false);
  251. editCropperFixedHeight->setEnabled(false);
  252. editFixedWidth->setEnabled(false);
  253. editFixedHeight->setEnabled(false);
  254. editCropperMinWidth->setEnabled(true);
  255. editCropperMinHeight->setEnabled(true);
  256. checkShowDragSquare->setEnabled(true);
  257. editDragSquareEdge->setEnabled(true);
  258. btnChooseDragSquareColor->setEnabled(true);
  259. break;
  260. }
  261. case CropperShape::CIRCLE: {
  262. imgCropperLabel->setCircleCropper();
  263. editCropperFixedWidth->setEnabled(false);
  264. editCropperFixedHeight->setEnabled(false);
  265. editFixedWidth->setEnabled(false);
  266. editFixedHeight->setEnabled(false);
  267. editCropperMinWidth->setEnabled(true);
  268. editCropperMinHeight->setEnabled(true);
  269. checkShowDragSquare->setEnabled(true);
  270. editDragSquareEdge->setEnabled(true);
  271. btnChooseDragSquareColor->setEnabled(true);
  272. break;
  273. }
  274. case CropperShape::FIXED_ELLIPSE:
  275. imgCropperLabel->setFixedEllipseCropper(QSize(64, 64));
  276. editCropperFixedWidth->setEnabled(true);
  277. editCropperFixedHeight->setEnabled(true);
  278. editFixedWidth->setEnabled(true);
  279. editFixedHeight->setEnabled(true);
  280. editCropperMinWidth->setEnabled(false);
  281. editCropperMinHeight->setEnabled(false);
  282. editCropperFixedWidth->setText("64");
  283. editCropperFixedHeight->setText("64");
  284. checkShowDragSquare->setEnabled(false);
  285. editDragSquareEdge->setEnabled(false);
  286. btnChooseDragSquareColor->setEnabled(false);
  287. break;
  288. case CropperShape::UNDEFINED:
  289. break;
  290. }
  291. imgCropperLabel->update();
  292. onUpdatePreview();
  293. }
  294. void ImageCropperDemo::onEnableOpacityChanged(int state) {
  295. if (state == Qt::Checked) {
  296. sliderOpacity->setEnabled(true);
  297. imgCropperLabel->enableOpacity(true);
  298. }
  299. else {
  300. sliderOpacity->setEnabled(false);
  301. imgCropperLabel->enableOpacity(false);
  302. }
  303. imgCropperLabel->update();
  304. }
  305. void ImageCropperDemo::onShowDragSquareChanged(int state) {
  306. if (state == Qt::Checked) {
  307. editDragSquareEdge->setEnabled(true);
  308. btnChooseDragSquareColor->setEnabled(true);
  309. imgCropperLabel->setShowDragSquare(true);
  310. }
  311. else {
  312. editDragSquareEdge->setEnabled(false);
  313. btnChooseDragSquareColor->setEnabled(false);
  314. imgCropperLabel->setShowDragSquare(false);
  315. }
  316. imgCropperLabel->update();
  317. }
  318. void ImageCropperDemo::onDragSquareEdgeChanged(QString edge) {
  319. imgCropperLabel->setDragSquareEdge(edge.toInt());
  320. imgCropperLabel->update();
  321. }
  322. void ImageCropperDemo::onOpacityChanged(int val) {
  323. imgCropperLabel->setOpacity(val / 100.0);
  324. imgCropperLabel->update();
  325. }
  326. void ImageCropperDemo::onFixedWidthChanged(QString width) {
  327. if(editCropperFixedWidth->hasFocus()){
  328. int dpi=editResolution->text().toInt();//获取分辨率
  329. double cm=width.toDouble()/dpi*2.54;
  330. editFixedWidth->setText(QString::number(cm,'f',1));
  331. }
  332. imgCropperLabel->setCropperFixedWidth(width.toInt());
  333. imgCropperLabel->update();
  334. }
  335. void ImageCropperDemo::onFixedHeightChanged(QString height) {
  336. if(editCropperFixedHeight->hasFocus()){
  337. int dpi=editResolution->text().toInt();//获取分辨率
  338. int cm=height.toDouble()/dpi*2.54;
  339. editFixedHeight->setText(QString::number(cm,10));
  340. }
  341. imgCropperLabel->setCropperFixedHeight(height.toInt());
  342. imgCropperLabel->update();
  343. }
  344. //厘米宽度事件
  345. void ImageCropperDemo::onWidthChanged(QString width) {
  346. if(editFixedWidth->hasFocus()){
  347. int dpi=editResolution->text().toInt();//获取分辨率
  348. int px=width.toDouble()*dpi/2.54;
  349. editCropperFixedWidth->setText(QString::number(px,10));
  350. }
  351. // imgCropperLabel->setCropperFixedWidth(width.toInt());
  352. // imgCropperLabel->update();
  353. }
  354. //厘米高度事件
  355. void ImageCropperDemo::onHeightChanged(QString height) {
  356. if(editFixedHeight->hasFocus()){
  357. int dpi=editResolution->text().toInt();//获取分辨率
  358. int px=height.toDouble()*dpi/2.54;
  359. editCropperFixedHeight->setText(QString::number(px,10));
  360. }
  361. // imgCropperLabel->setCropperFixedHeight(height.toInt());
  362. // imgCropperLabel->update();
  363. }
  364. void ImageCropperDemo::onMinWidthChanged(QString width) {
  365. imgCropperLabel->setCropperMinimumWidth(width.toInt());
  366. imgCropperLabel->update();
  367. }
  368. void ImageCropperDemo::onMinHeightChanged(QString height) {
  369. imgCropperLabel->setMinimumHeight(height.toInt());
  370. imgCropperLabel->update();
  371. }
  372. void ImageCropperDemo::onShowRectBorder(int state) {
  373. if (state == Qt::Checked) {
  374. btnChooseRectBorderCorlor->setEnabled(true);
  375. imgCropperLabel->setShowRectBorder(true);
  376. }
  377. else {
  378. btnChooseRectBorderCorlor->setEnabled(false);
  379. imgCropperLabel->setShowRectBorder(false);
  380. }
  381. imgCropperLabel->update();
  382. }
  383. void ImageCropperDemo::onChooseRectBorderColor() {
  384. QColor color = QColorDialog::getColor(imgCropperLabel->getBorderPen().color(), this);
  385. if (color.isValid()) {
  386. setLabelColor(labelRectBorderColor, color);
  387. QPen pen = imgCropperLabel->getBorderPen();
  388. pen.setColor(color);
  389. imgCropperLabel->setBorderPen(pen);
  390. imgCropperLabel->update();
  391. }
  392. }
  393. void ImageCropperDemo::onChooseDragSquareColor() {
  394. QColor color = QColorDialog::getColor(Qt::white, this);
  395. if (color.isValid()) {
  396. setLabelColor(labelDragSquareColor, color);
  397. imgCropperLabel->setDragSquareColor(color);
  398. imgCropperLabel->update();
  399. }
  400. }
  401. void ImageCropperDemo::onUpdatePreview() {
  402. QPixmap preview = imgCropperLabel->getCroppedImage();
  403. preview = preview.scaled(labelPreviewImage->width(), labelPreviewImage->height(),
  404. Qt::KeepAspectRatio, Qt::SmoothTransformation);
  405. labelPreviewImage->setPixmap(preview);
  406. }
  407. void ImageCropperDemo::onSaveCroppedImage() {
  408. const QPixmap* pixmap = labelPreviewImage->pixmap();
  409. if (!pixmap) {
  410. QMessageBox::information(this, "Error", "There is no cropped image to save.", QMessageBox::Ok);
  411. return ;
  412. }
  413. QString filename = QFileDialog::getSaveFileName(this, "保存图片", "", "picture (*.png)");
  414. if (!filename.isNull()) {
  415. if (imgCropperLabel->getCroppedImage().save(filename, "PNG"))
  416. QMessageBox::information(this, "Prompt", "保存成功!", QMessageBox::Ok);
  417. else
  418. QMessageBox::information(this, "Error", "保存失败!", QMessageBox::Ok);
  419. }
  420. }