17 #include "bitmapimage.h"
23 #include <QPainterPath>
26 BitmapImage::BitmapImage()
29 mBounds =
QRect(0, 0, 0, 0);
36 mEnableAutoCrop = a.mEnableAutoCrop;
37 mImage.reset(
new QImage(*a.mImage));
40 BitmapImage::BitmapImage(
const QRect& rectangle,
const QColor& color)
44 mImage->fill(color.
rgba());
48 BitmapImage::BitmapImage(
const QPoint& topLeft,
const QImage& image)
52 mImage.reset(
new QImage(image));
55 BitmapImage::BitmapImage(
const QPoint& topLeft,
const QString& path)
65 BitmapImage::~BitmapImage()
69 void BitmapImage::setImage(
QImage* img)
82 mImage.reset(
new QImage(*a.mImage));
92 void BitmapImage::loadFile()
94 if (mImage ==
nullptr)
96 mImage.reset(
new QImage(fileName()));
97 mBounds.
setSize(mImage->size());
102 void BitmapImage::unloadFile()
104 if (isModified() ==
false)
110 bool BitmapImage::isLoaded()
112 return (mImage !=
nullptr);
115 quint64 BitmapImage::memoryUsage()
119 return imageSize(*mImage);
124 void BitmapImage::paintImage(
QPainter& painter)
136 QImage* BitmapImage::image()
158 if(bitmapImage->width() <= 0 || bitmapImage->height() <= 0)
165 QImage* image2 = bitmapImage->image();
175 void BitmapImage::moveTopLeft(
QPoint point)
182 void BitmapImage::transform(
QRect newBoundaries,
bool smoothTransform)
184 mBounds = newBoundaries;
193 painter.
drawImage(newBoundaries, *image());
195 mImage.reset(newImage);
202 Q_ASSERT(!selection.
isEmpty());
214 transformedImage = selectedPart.image()->
transformed(transform);
219 BitmapImage BitmapImage::transformed(
QRect newBoundaries,
bool smoothTransform)
222 QPainter painter(transformedImage.image());
225 painter.
drawImage(newBoundaries, *image());
227 return transformedImage;
240 if (mBounds == newBoundaries)
return;
250 mImage.reset( newImage );
251 mBounds = newBoundaries;
257 void BitmapImage::extend(
const QPoint &p)
265 void BitmapImage::extend(
QRect rectangle)
284 mImage.reset(newImage);
285 mBounds = newBoundaries;
334 newBoundaries = mBounds;
343 newBoundaries = mBounds;
350 newBoundaries = mBounds.
united(sourceBounds);
351 mMinBound = mMinBound && isSourceMinBounds;
372 if (!mEnableAutoCrop)
return;
376 Q_ASSERT(mBounds.
size() == mImage->size());
379 if (mMinBound)
return;
382 const int width = mImage->width();
386 int relBottom = mBounds.
height()-1;
390 while (isEmpty && relTop <= relBottom)
393 const QRgb* cursor =
reinterpret_cast<const QRgb*
>(mImage->constScanLine(relTop));
394 for (
int col = 0; col < width; col++)
398 if (qAlpha(*cursor) != 0)
418 while (isEmpty && relBottom >= relTop)
421 const QRgb* cursor =
reinterpret_cast<const QRgb*
>(mImage->constScanLine(relBottom));
422 for (
int col = 0; col < width; col++)
426 if(qAlpha(*cursor) != 0)
446 int relRight = mBounds.
width()-1;
449 isEmpty = (relBottom >= relTop);
450 while (isEmpty && relBottom >= relTop && relLeft <= relRight)
453 const QRgb* cursor =
reinterpret_cast<const QRgb*
>(mImage->constScanLine(relTop)) + relLeft;
459 for (
int row = relTop; row <= relBottom; row++)
463 if(qAlpha(*cursor) != 0)
483 isEmpty = (relBottom >= relTop);
484 while (isEmpty && relRight >= relLeft)
487 const QRgb* cursor =
reinterpret_cast<const QRgb*
>(mImage->constScanLine(relTop)) + relRight;
493 for (
int row = relTop; row <= relBottom; row++)
497 if(qAlpha(*cursor) != 0)
526 QRgb BitmapImage::pixel(
int x,
int y)
528 return pixel(
QPoint(x, y));
531 QRgb BitmapImage::pixel(
QPoint p)
533 QRgb result = qRgba(0, 0, 0, 0);
539 void BitmapImage::setPixel(
int x,
int y, QRgb color)
541 setPixel(
QPoint(x, y), color);
544 void BitmapImage::setPixel(
QPoint p, QRgb color)
554 void BitmapImage::fillNonAlphaPixels(
const QRgb color)
556 if (mBounds.
isEmpty()) {
return; }
564 int width = 2 + pen.
width();
580 int width = pen.
width();
603 int width = pen.
width();
628 int width = pen.
width();
676 result.errorcode = Status::FAIL;
677 int left =
static_cast<int>(rect.
left());
678 int right =
static_cast<int>(rect.
right());
679 int top =
static_cast<int>(rect.
top());
680 int bottom =
static_cast<int>(rect.
bottom());
681 for (
int x = left; x <= right; x++)
683 for (
int y = top; y <= bottom; y++)
685 if (qAlpha(constScanLine(x,y)) == 255 && qGray(constScanLine(x,y)) < grayValue)
688 result.errorcode = Status::OK;
700 result.errorcode = Status::FAIL;
701 int left =
static_cast<int>(rect.
left());
702 int right =
static_cast<int>(rect.
right());
703 int top =
static_cast<int>(rect.
top());
704 int bottom =
static_cast<int>(rect.
bottom());
705 for (
int y = top; y <= bottom; y++)
707 for (
int x = left; x <= right; x++)
709 if (qAlpha(constScanLine(x,y)) == 255 && qGray(constScanLine(x,y)) < grayValue)
712 result.errorcode = Status::OK;
722 if (mImage && !mImage->isNull())
724 bool b = mImage->save(filename);
725 return (b) ? Status::OK : Status::FAIL;
728 if (bounds().isEmpty())
734 return (b) ? Status::OK : Status::FAIL;
741 void BitmapImage::clear()
744 mBounds =
QRect(0, 0, 0, 0);
749 QRgb BitmapImage::constScanLine(
int x,
int y)
const
751 QRgb result = qRgba(0, 0, 0, 0);
754 result = *(
reinterpret_cast<const QRgb*
>(mImage->constScanLine(y - mBounds.
top())) + x - mBounds.
left());
759 void BitmapImage::scanLine(
int x,
int y, QRgb color)
765 *(
reinterpret_cast<QRgb*
>(image()->
scanLine(y - mBounds.
top())) + x - mBounds.
left()) =
774 void BitmapImage::clear(
QRect rectangle)
806 if (newColor == oldColor)
return true;
808 if(cache && cache->
contains(newColor))
return cache->
value(newColor);
813 int diffRed =
static_cast<int>(qPow(qRed(oldColor) - qRed(newColor), 2));
814 int diffGreen =
static_cast<int>(qPow(qGreen(oldColor) - qGreen(newColor), 2));
815 int diffBlue =
static_cast<int>(qPow(qBlue(oldColor) - qBlue(newColor), 2));
818 int diffAlpha =
static_cast<int>(qPow(qAlpha(oldColor) - qAlpha(newColor), 2));
820 bool isSimilar = (diffRed + diffGreen + diffBlue + diffAlpha) <= tolerance;
824 Q_ASSERT(cache->
contains(isSimilar) ? isSimilar == (*cache)[newColor] :
true);
825 (*cache)[newColor] = isSimilar;
833 void BitmapImage::floodFill(
BitmapImage* targetImage,
840 if(!cameraRect.
united(targetImage->bounds()).contains(point))
846 tolerance =
static_cast<int>(qPow(tolerance, 2));
848 QRgb oldColor = targetImage->pixel(point);
849 oldColor = qRgba(qRed(oldColor), qGreen(oldColor), qBlue(oldColor), qAlpha(oldColor));
856 QRgb newPlacedColor = 0;
860 bool spanLeft =
false;
861 bool spanRight =
false;
864 targetImage->extend(cameraRect);
870 while (!queue.
empty())
874 point.
setX(tempPoint.
x());
875 point.
setY(tempPoint.
y());
879 newPlacedColor = replaceImage->constScanLine(xTemp, point.
y());
880 while (xTemp >= targetImage->mBounds.
left() &&
881 compareColor(targetImage->constScanLine(xTemp, point.
y()), oldColor, tolerance, cache.data())) xTemp--;
884 spanLeft = spanRight =
false;
885 while (xTemp <= targetImage->mBounds.
right() &&
886 compareColor(targetImage->constScanLine(xTemp, point.
y()), oldColor, tolerance, cache.data()) &&
887 newPlacedColor != newColor)
891 replaceImage->scanLine(xTemp, point.
y(), newColor);
893 if (!spanLeft && (point.
y() > targetImage->mBounds.
top()) &&
894 compareColor(targetImage->constScanLine(xTemp, point.
y() - 1), oldColor, tolerance, cache.data())) {
898 else if (spanLeft && (point.
y() > targetImage->mBounds.
top()) &&
899 !
compareColor(targetImage->constScanLine(xTemp, point.
y() - 1), oldColor, tolerance, cache.data())) {
903 if (!spanRight && point.
y() < targetImage->mBounds.
bottom() &&
904 compareColor(targetImage->constScanLine(xTemp, point.
y() + 1), oldColor, tolerance, cache.data())) {
909 else if (spanRight && point.
y() < targetImage->mBounds.
bottom() &&
910 !
compareColor(targetImage->constScanLine(xTemp, point.
y() + 1), oldColor, tolerance, cache.data())) {
914 Q_ASSERT(queue.
count() < (targetImage->mBounds.
width() * targetImage->mBounds.
height()));
919 targetImage->paste(replaceImage);
920 targetImage->modification();
QRect normalized() const const
QRect toRect() const const
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setCompositionMode(QPainter::CompositionMode mode)
void setRenderHint(QPainter::RenderHint hint, bool on)
Qt::BrushStyle style() const const
qreal length() const const
void setPixel(int x, int y, uint index_or_rgb)
QPointF center() const const
QPainterPath::Element elementAt(int index) const const
bool isNull() const const
void drawLine(const QLineF &line)
QImage copy(const QRect &rectangle) const const
void setFocalPoint(const QPointF &focalPoint)
void moveTopLeft(const QPoint &position)
void setCompositionModeBounds(BitmapImage *source, QPainter::CompositionMode cm)
Updates the bounds after a drawImage operation with the composition mode cm.
const QGradient * gradient() const const
qreal bottom() const const
void drawRect(const QRectF &rectangle)
QRgb pixel(int x, int y) const const
int count(const T &value) const const
void append(const T &value)
void drawPoint(const QPointF &position)
void fill(uint pixelValue)
void setPen(const QColor &color)
QRectF controlPointRect() const const
void drawEllipse(const QRectF &rectangle)
void setBrush(const QBrush &brush)
QRect translated(int dx, int dy) const const
QRect intersected(const QRect &rectangle) const const
void autoCrop()
Removes any transparent borders by reducing the boundaries.
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const const
const T value(const Key &key) const const
qreal right() const const
void setCenter(const QPointF ¢er)
bool isEmpty() const const
QPointF focalPoint() const const
bool contains(const QRect &rectangle, bool proper) const const
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags)
void drawPath(const QPainterPath &path)
QPoint toPoint() const const
QRectF translated(qreal dx, qreal dy) const const
void setHeight(int height)
void setWorldMatrixEnabled(bool enable)
QPoint topLeft() const const
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
bool contains(const Key &key) const const
void updateBounds(QRect rectangle)
Update image bounds.
void setSize(const QSize &size)
static bool compareColor(QRgb newColor, QRgb oldColor, int tolerance, QHash< QRgb, bool > *cache)
Compare colors for the purposes of flood filling.
QRect united(const QRect &rectangle) const const