void Image::desaturate() { if (isARGB() || isRGB()) { const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite); if (isARGB()) { for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); for (int x = 0; x < destData.width; ++x) { ((PixelARGB*) p)->desaturate(); p += destData.pixelStride; } } } else { for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); for (int x = 0; x < destData.width; ++x) { ((PixelRGB*) p)->desaturate(); p += destData.pixelStride; } } } } }
Image Image::convertedToFormat (PixelFormat newFormat) const { if (image == nullptr || newFormat == image->pixelFormat) return *this; const int w = image->width, h = image->height; const ScopedPointer<ImageType> type (image->createType()); Image newImage (type->create (newFormat, w, h, false)); if (newFormat == SingleChannel) { if (! hasAlphaChannel()) { newImage.clear (getBounds(), Colours::black); } else { const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); const BitmapData srcData (*this, 0, 0, w, h); for (int y = 0; y < h; ++y) { const PixelARGB* const src = (const PixelARGB*) srcData.getLinePointer (y); uint8* const dst = destData.getLinePointer (y); for (int x = 0; x < w; ++x) dst[x] = src[x].getAlpha(); } } } else if (image->pixelFormat == SingleChannel && newFormat == Image::ARGB) { const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); const BitmapData srcData (*this, 0, 0, w, h); for (int y = 0; y < h; ++y) { const PixelAlpha* const src = (const PixelAlpha*) srcData.getLinePointer (y); PixelARGB* const dst = (PixelARGB*) destData.getLinePointer (y); for (int x = 0; x < w; ++x) dst[x].set (src[x]); } } else { if (hasAlphaChannel()) newImage.clear (getBounds()); Graphics g (newImage); g.drawImageAt (*this, 0, 0); } return newImage; }
Image Image::convertedToFormat (PixelFormat newFormat) const { if (image == nullptr || newFormat == image->format) return *this; const int w = image->width, h = image->height; Image newImage (newFormat, w, h, false, image->getType()); if (newFormat == SingleChannel) { if (! hasAlphaChannel()) { newImage.clear (getBounds(), Colours::black); } else { const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); const BitmapData srcData (*this, 0, 0, w, h); for (int y = 0; y < h; ++y) { const PixelARGB* src = (const PixelARGB*) srcData.getLinePointer(y); uint8* dst = destData.getLinePointer (y); for (int x = w; --x >= 0;) { *dst++ = src->getAlpha(); ++src; } } } } else { if (hasAlphaChannel()) newImage.clear (getBounds()); Graphics g (newImage); g.drawImageAt (*this, 0, 0); } return newImage; }
void Image::multiplyAllAlphas (const float amountToMultiplyBy) { if (hasAlphaChannel()) { const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite); if (isARGB()) { for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); for (int x = 0; x < destData.width; ++x) { ((PixelARGB*) p)->multiplyAlpha (amountToMultiplyBy); p += destData.pixelStride; } } } else { for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); for (int x = 0; x < destData.width; ++x) { *p = (uint8) (*p * amountToMultiplyBy); p += destData.pixelStride; } } } } else { jassertfalse; // can't do this without an alpha-channel! } }
void Image::createSolidAreaMask (RectangleList& result, const float alphaThreshold) const { if (hasAlphaChannel()) { const uint8 threshold = (uint8) jlimit (0, 255, roundToInt (alphaThreshold * 255.0f)); SparseSet<int> pixelsOnRow; const BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); for (int y = 0; y < srcData.height; ++y) { pixelsOnRow.clear(); const uint8* lineData = srcData.getLinePointer (y); if (isARGB()) { for (int x = 0; x < srcData.width; ++x) { if (((const PixelARGB*) lineData)->getAlpha() >= threshold) pixelsOnRow.addRange (Range<int> (x, x + 1)); lineData += srcData.pixelStride; } } else { for (int x = 0; x < srcData.width; ++x) { if (*lineData >= threshold) pixelsOnRow.addRange (Range<int> (x, x + 1)); lineData += srcData.pixelStride; } } for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i) { const Range<int> range (pixelsOnRow.getRange (i)); result.add (Rectangle<int> (range.getStart(), y, range.getLength(), 1)); } result.consolidate(); } } else { result.add (0, 0, getWidth(), getHeight()); } }
void Image::setPixelData (int x, int y, int w, int h, const uint8* const sourcePixelData, const int sourceLineStride) { jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= getWidth() && y + h <= getHeight()); if (Rectangle<int>::intersectRectangles (x, y, w, h, 0, 0, getWidth(), getHeight())) { const BitmapData dest (*this, x, y, w, h, BitmapData::writeOnly); for (int i = 0; i < h; ++i) { memcpy (dest.getLinePointer(i), sourcePixelData + sourceLineStride * i, w * dest.pixelStride); } } }