Browse Source

Added method Image::getClippedImage(), which allows the use of images that refer to subsections of another image. This means that the the parameters to a couple of Graphics methods no longer need a clipping rectangle. Also dded a static Image::null object and another constructor for Image::BitmapData.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
9f0c91196f
39 changed files with 198 additions and 160 deletions
  1. +1
    -1
      extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h
  2. +1
    -1
      extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h
  3. +1
    -1
      extras/juce demo/Source/demos/OpenGLDemo.cpp
  4. +2
    -5
      extras/juce demo/Source/demos/RenderingTestComponent.cpp
  5. +1
    -1
      src/core/juce_PlatformDefs.h
  6. +1
    -1
      src/core/juce_StandardHeader.h
  7. +1
    -1
      src/gui/components/controls/juce_ToolbarItemComponent.cpp
  8. +1
    -1
      src/gui/components/filebrowser/juce_FileListComponent.cpp
  9. +1
    -1
      src/gui/components/filebrowser/juce_ImagePreviewComponent.cpp
  10. +2
    -2
      src/gui/components/juce_Component.cpp
  11. +2
    -2
      src/gui/components/menus/juce_PopupMenu.cpp
  12. +3
    -3
      src/gui/components/menus/juce_PopupMenu.h
  13. +1
    -1
      src/gui/components/mouse/juce_DragAndDropContainer.h
  14. +3
    -3
      src/gui/components/special/juce_ColourSelector.cpp
  15. +1
    -3
      src/gui/components/special/juce_MagnifierComponent.cpp
  16. +1
    -1
      src/gui/components/windows/juce_CallOutBox.cpp
  17. +2
    -2
      src/gui/graphics/contexts/juce_FillType.cpp
  18. +5
    -8
      src/gui/graphics/contexts/juce_Graphics.cpp
  19. +5
    -14
      src/gui/graphics/contexts/juce_Graphics.h
  20. +2
    -3
      src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h
  21. +5
    -7
      src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp
  22. +2
    -3
      src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h
  23. +21
    -25
      src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
  24. +2
    -3
      src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h
  25. +2
    -2
      src/gui/graphics/drawables/juce_DrawableImage.cpp
  26. +2
    -2
      src/gui/graphics/effects/juce_DropShadowEffect.cpp
  27. +7
    -11
      src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp
  28. +1
    -1
      src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h
  29. +2
    -2
      src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp
  30. +3
    -3
      src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp
  31. +63
    -0
      src/gui/graphics/imaging/juce_Image.cpp
  32. +26
    -2
      src/gui/graphics/imaging/juce_Image.h
  33. +2
    -2
      src/gui/graphics/imaging/juce_ImageCache.cpp
  34. +1
    -1
      src/gui/graphics/imaging/juce_ImageConvolutionKernel.cpp
  35. +3
    -3
      src/gui/graphics/imaging/juce_ImageFileFormat.cpp
  36. +3
    -3
      src/native/linux/juce_linux_Windowing.cpp
  37. +1
    -1
      src/native/mac/juce_iphone_UIViewComponentPeer.mm
  38. +12
    -31
      src/native/mac/juce_mac_CoreGraphicsContext.mm
  39. +3
    -3
      src/native/windows/juce_win32_Windowing.cpp

+ 1
- 1
extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h View File

@@ -296,7 +296,7 @@ protected:
dataBlock.writeInt (0); // clr used dataBlock.writeInt (0); // clr used
dataBlock.writeInt (0); // clr important dataBlock.writeInt (0); // clr important
const Image::BitmapData bitmap (image, 0, 0, w, h);
const Image::BitmapData bitmap (image, false);
const int alphaThreshold = 5; const int alphaThreshold = 5;
int y; int y;


+ 1
- 1
extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h View File

@@ -266,7 +266,7 @@ private:
data.write (type, 4); data.write (type, 4);
data.writeIntBigEndian (8 + 4 * w * h); data.writeIntBigEndian (8 + 4 * w * h);
const Image::BitmapData bitmap (image, 0, 0, w, h);
const Image::BitmapData bitmap (image, false);
int y; int y;
for (y = 0; y < h; ++y) for (y = 0; y < h; ++y)


+ 1
- 1
extras/juce demo/Source/demos/OpenGLDemo.cpp View File

@@ -132,7 +132,7 @@ public:
glPixelStorei (GL_UNPACK_ALIGNMENT, 4); glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
Image::BitmapData srcData (image, 0, 0, image.getWidth(), image.getHeight());
Image::BitmapData srcData (image, false);
glTexImage2D (GL_TEXTURE_2D, 0, 4, image.getWidth(), image.getHeight(), glTexImage2D (GL_TEXTURE_2D, 0, 4, image.getWidth(), image.getHeight(),
0, GL_RGB, 0, GL_RGB,


+ 2
- 5
extras/juce demo/Source/demos/RenderingTestComponent.cpp View File

@@ -192,9 +192,7 @@ private:
.rotated (bouncingNumber[3]) .rotated (bouncingNumber[3])
.scaled (bouncingNumber[2] + 4.0f, bouncingNumber[2] + 4.0f) .scaled (bouncingNumber[2] + 4.0f, bouncingNumber[2] + 4.0f)
.translated (bouncingPointX[2], bouncingPointY[2])); .translated (bouncingPointX[2], bouncingPointY[2]));
g.reduceClipRegion (argbImage,
Rectangle<int> (0, 0, argbImage.getWidth(), argbImage.getHeight()),
transform);
g.reduceClipRegion (argbImage, transform);
} }
void drawPaths (Graphics& g, bool /*solid*/, bool linearGradient, bool radialGradient) void drawPaths (Graphics& g, bool /*solid*/, bool linearGradient, bool radialGradient)
@@ -268,8 +266,7 @@ private:
.followedBy (getTransform())); .followedBy (getTransform()));
g.setOpacity ((float) owner.opacitySlider->getValue()); g.setOpacity ((float) owner.opacitySlider->getValue());
g.drawImageTransformed (image, image.getBounds(),
transform, false);
g.drawImageTransformed (image, transform, false);
} }
void drawTiling (Graphics& g, const Image& image) void drawTiling (Graphics& g, const Image& image)


+ 1
- 1
src/core/juce_PlatformDefs.h View File

@@ -68,7 +68,7 @@
@see Logger::outputDebugString @see Logger::outputDebugString
*/ */
#define DBG(dbgtext) Logger::outputDebugString (dbgtext);
#define DBG(dbgtext) JUCE_NAMESPACE::Logger::outputDebugString (dbgtext);
//============================================================================== //==============================================================================
// Assertions.. // Assertions..


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/ */
#define JUCE_MAJOR_VERSION 1 #define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52 #define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 39
#define JUCE_BUILDNUMBER 40
/** Current Juce version number. /** Current Juce version number.


+ 1
- 1
src/gui/components/controls/juce_ToolbarItemComponent.cpp View File

@@ -96,7 +96,7 @@ public:
if (dnd != 0) if (dnd != 0)
{ {
dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image(), true);
dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image::null, true);
ToolbarItemComponent* const tc = dynamic_cast <ToolbarItemComponent*> (getParentComponent()); ToolbarItemComponent* const tc = dynamic_cast <ToolbarItemComponent*> (getParentComponent());


+ 1
- 1
src/gui/components/filebrowser/juce_FileListComponent.cpp View File

@@ -199,7 +199,7 @@ private:
void clearIcon() void clearIcon()
{ {
icon = Image();
icon = Image::null;
} }
void updateIcon (const bool onlyUpdateIfCached) void updateIcon (const bool onlyUpdateIfCached)


+ 1
- 1
src/gui/components/filebrowser/juce_ImagePreviewComponent.cpp View File

@@ -68,7 +68,7 @@ void ImagePreviewComponent::timerCallback()
{ {
stopTimer(); stopTimer();
currentThumbnail = Image();
currentThumbnail = Image::null;
currentDetails = String::empty; currentDetails = String::empty;
repaint(); repaint();


+ 2
- 2
src/gui/components/juce_Component.cpp View File

@@ -502,7 +502,7 @@ void Component::setBufferedToImage (const bool shouldBeBuffered)
{ {
if (shouldBeBuffered != flags.bufferToImageFlag) if (shouldBeBuffered != flags.bufferToImageFlag)
{ {
bufferedImage_ = Image();
bufferedImage_ = Image::null;
flags.bufferToImageFlag = shouldBeBuffered; flags.bufferToImageFlag = shouldBeBuffered;
} }
} }
@@ -1478,7 +1478,7 @@ void Component::repaint()
void Component::repaint (const int x, const int y, void Component::repaint (const int x, const int y,
const int w, const int h) const int w, const int h)
{ {
bufferedImage_ = Image();
bufferedImage_ = Image::null;
if (flags.visibleFlag) if (flags.visibleFlag)
internalRepaint (x, y, w, h); internalRepaint (x, y, w, h);


+ 2
- 2
src/gui/components/menus/juce_PopupMenu.cpp View File

@@ -1334,7 +1334,7 @@ void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager,
: info.shortName, : info.shortName,
target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0, target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0,
(info.flags & ApplicationCommandInfo::isTicked) != 0, (info.flags & ApplicationCommandInfo::isTicked) != 0,
Image(),
Image::null,
Colours::black, Colours::black,
false, false,
0, 0, 0, 0,
@@ -1369,7 +1369,7 @@ void PopupMenu::addCustomItem (const int itemResultId,
addSeparatorIfPending(); addSeparatorIfPending();
items.add (new Item (itemResultId, String::empty, true, false, Image(),
items.add (new Item (itemResultId, String::empty, true, false, Image::null,
Colours::black, false, customComponent, 0, 0)); Colours::black, false, customComponent, 0, 0));
} }


+ 3
- 3
src/gui/components/menus/juce_PopupMenu.h View File

@@ -119,7 +119,7 @@ public:
const String& itemText, const String& itemText,
bool isActive = true, bool isActive = true,
bool isTicked = false, bool isTicked = false,
const Image& iconToUse = Image());
const Image& iconToUse = Image::null);
/** Adds an item that represents one of the commands in a command manager object. /** Adds an item that represents one of the commands in a command manager object.
@@ -145,7 +145,7 @@ public:
const Colour& itemTextColour, const Colour& itemTextColour,
bool isActive = true, bool isActive = true,
bool isTicked = false, bool isTicked = false,
const Image& iconToUse = Image());
const Image& iconToUse = Image::null);
/** Appends a custom menu item. /** Appends a custom menu item.
@@ -183,7 +183,7 @@ public:
void addSubMenu (const String& subMenuName, void addSubMenu (const String& subMenuName,
const PopupMenu& subMenu, const PopupMenu& subMenu,
bool isActive = true, bool isActive = true,
const Image& iconToUse = Image(),
const Image& iconToUse = Image::null,
bool isTicked = false); bool isTicked = false);
/** Appends a separator to the menu, to help break it up into sections. /** Appends a separator to the menu, to help break it up into sections.


+ 1
- 1
src/gui/components/mouse/juce_DragAndDropContainer.h View File

@@ -90,7 +90,7 @@ public:
*/ */
void startDragging (const String& sourceDescription, void startDragging (const String& sourceDescription,
Component* sourceComponent, Component* sourceComponent,
const Image& dragImage = Image(),
const Image& dragImage = Image::null,
bool allowDraggingToOtherJuceWindows = false, bool allowDraggingToOtherJuceWindows = false,
const Point<int>* imageOffsetFromMouse = 0); const Point<int>* imageOffsetFromMouse = 0);


+ 3
- 3
src/gui/components/special/juce_ColourSelector.cpp View File

@@ -117,7 +117,7 @@ public:
const int height = getHeight() / 2; const int height = getHeight() / 2;
colours = Image (Image::RGB, width, height, false); colours = Image (Image::RGB, width, height, false);
Image::BitmapData pixels (colours, 0, 0, width, height, true);
Image::BitmapData pixels (colours, true);
for (int y = 0; y < height; ++y) for (int y = 0; y < height; ++y)
{ {
@@ -155,7 +155,7 @@ public:
if (lastHue != h) if (lastHue != h)
{ {
lastHue = h; lastHue = h;
colours = Image();
colours = Image::null;
repaint(); repaint();
} }
@@ -164,7 +164,7 @@ public:
void resized() void resized()
{ {
colours = Image();
colours = Image::null;
updateMarker(); updateMarker();
} }


+ 1
- 3
src/gui/components/special/juce_MagnifierComponent.cpp View File

@@ -275,9 +275,7 @@ void MagnifierComponent::paint (Graphics& g)
} }
g.setImageResamplingQuality (quality); g.setImageResamplingQuality (quality);
g.drawImageTransformed (temp, temp.getBounds(),
AffineTransform::scale ((float) scaleFactor, (float) scaleFactor),
false);
g.drawImageTransformed (temp, AffineTransform::scale ((float) scaleFactor, (float) scaleFactor), false);
} }
void MagnifierComponent::childBoundsChanged (Component* c) void MagnifierComponent::childBoundsChanged (Component* c)


+ 1
- 1
src/gui/components/windows/juce_CallOutBox.cpp View File

@@ -201,7 +201,7 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R
void CallOutBox::refreshPath() void CallOutBox::refreshPath()
{ {
repaint(); repaint();
background = Image();
background = Image::null;
outline.clear(); outline.clear();
const float gap = 4.5f; const float gap = 4.5f;


+ 2
- 2
src/gui/graphics/contexts/juce_FillType.cpp View File

@@ -92,7 +92,7 @@ bool FillType::operator!= (const FillType& other) const
void FillType::setColour (const Colour& newColour) throw() void FillType::setColour (const Colour& newColour) throw()
{ {
gradient = 0; gradient = 0;
image = Image();
image = Image::null;
colour = newColour; colour = newColour;
} }
@@ -104,7 +104,7 @@ void FillType::setGradient (const ColourGradient& newGradient)
} }
else else
{ {
image = Image();
image = Image::null;
gradient = new ColourGradient (newGradient); gradient = new ColourGradient (newGradient);
colour = Colours::black; colour = Colours::black;
} }


+ 5
- 8
src/gui/graphics/contexts/juce_Graphics.cpp View File

@@ -105,10 +105,10 @@ bool Graphics::reduceClipRegion (const Path& path, const AffineTransform& transf
return ! context->isClipEmpty(); return ! context->isClipEmpty();
} }
bool Graphics::reduceClipRegion (const Image& image, const Rectangle<int>& sourceClipRegion, const AffineTransform& transform)
bool Graphics::reduceClipRegion (const Image& image, const AffineTransform& transform)
{ {
saveStateIfPending(); saveStateIfPending();
context->clipToImageAlpha (image, sourceClipRegion, transform);
context->clipToImageAlpha (image, transform);
return ! context->isClipEmpty(); return ! context->isClipEmpty();
} }
@@ -667,7 +667,7 @@ void Graphics::drawImage (const Image& imageToDraw,
if (imageToDraw.isValid() && context->clipRegionIntersects (Rectangle<int> (dx, dy, dw, dh))) if (imageToDraw.isValid() && context->clipRegionIntersects (Rectangle<int> (dx, dy, dw, dh)))
{ {
drawImageTransformed (imageToDraw, Rectangle<int> (sx, sy, sw, sh),
drawImageTransformed (imageToDraw.getClippedImage (Rectangle<int> (sx, sy, sw, sh)),
AffineTransform::scale (dw / (float) sw, dh / (float) sh) AffineTransform::scale (dw / (float) sw, dh / (float) sh)
.translated ((float) dx, (float) dy), .translated ((float) dx, (float) dy),
fillAlphaChannelWithCurrentBrush); fillAlphaChannelWithCurrentBrush);
@@ -675,24 +675,21 @@ void Graphics::drawImage (const Image& imageToDraw,
} }
void Graphics::drawImageTransformed (const Image& imageToDraw, void Graphics::drawImageTransformed (const Image& imageToDraw,
const Rectangle<int>& imageSubRegion,
const AffineTransform& transform, const AffineTransform& transform,
const bool fillAlphaChannelWithCurrentBrush) const const bool fillAlphaChannelWithCurrentBrush) const
{ {
if (imageToDraw.isValid() && ! context->isClipEmpty()) if (imageToDraw.isValid() && ! context->isClipEmpty())
{ {
const Rectangle<int> srcClip (imageSubRegion.getIntersection (imageToDraw.getBounds()));
if (fillAlphaChannelWithCurrentBrush) if (fillAlphaChannelWithCurrentBrush)
{ {
context->saveState(); context->saveState();
context->clipToImageAlpha (imageToDraw, srcClip, transform);
context->clipToImageAlpha (imageToDraw, transform);
fillAll(); fillAll();
context->restoreState(); context->restoreState();
} }
else else
{ {
context->drawImage (imageToDraw, srcClip, transform, false);
context->drawImage (imageToDraw, transform, false);
} }
} }
} }


+ 5
- 14
src/gui/graphics/contexts/juce_Graphics.h View File

@@ -492,18 +492,11 @@ public:
int sourceX, int sourceY, int sourceWidth, int sourceHeight, int sourceX, int sourceY, int sourceWidth, int sourceHeight,
bool fillAlphaChannelWithCurrentBrush = false) const; bool fillAlphaChannelWithCurrentBrush = false) const;
/** Draws part of an image, having applied an affine transform to it.
/** Draws an image, having applied an affine transform to it.
This lets you throw the image around in some wacky ways, rotate it, shear, This lets you throw the image around in some wacky ways, rotate it, shear,
scale it, etc. scale it, etc.
A subregion is specified within the source image, and all transformations
will be treated as relative to the origin of this sub-region. So, for example if
your subregion is (50, 50, 100, 100), and your transform is a translation of (20, 20),
the resulting pixel drawn at (20, 20) in the destination context is from (50, 50) in
your image. If you want to use the whole image, then Image::getBounds() returns a
suitable rectangle to use as the imageSubRegion parameter.
Images are composited using the context's current opacity, so if you Images are composited using the context's current opacity, so if you
don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f) don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f)
(or setColour() with an opaque colour) before drawing images. (or setColour() with an opaque colour) before drawing images.
@@ -511,10 +504,12 @@ public:
If fillAlphaChannelWithCurrentBrush is set to true, then the image's RGB channels If fillAlphaChannelWithCurrentBrush is set to true, then the image's RGB channels
are ignored and it is filled with the current brush, masked by its alpha channel. are ignored and it is filled with the current brush, masked by its alpha channel.
If you want to render only a subsection of an image, use Image::getClippedImage() to
create the section that you need.
@see setImageResamplingQuality, drawImage @see setImageResamplingQuality, drawImage
*/ */
void drawImageTransformed (const Image& imageToDraw, void drawImageTransformed (const Image& imageToDraw,
const Rectangle<int>& imageSubRegion,
const AffineTransform& transform, const AffineTransform& transform,
bool fillAlphaChannelWithCurrentBrush = false) const; bool fillAlphaChannelWithCurrentBrush = false) const;
@@ -588,15 +583,11 @@ public:
@param image the image whose alpha-channel should be used. If the image doesn't @param image the image whose alpha-channel should be used. If the image doesn't
have an alpha-channel, it is treated as entirely opaque. have an alpha-channel, it is treated as entirely opaque.
@param sourceClipRegion a subsection of the image that should be used. To use the
entire image, just pass a rectangle of bounds
(0, 0, image.getWidth(), image.getHeight()).
@param transform a matrix to apply to the image @param transform a matrix to apply to the image
@returns true if the resulting clipping region is non-zero in size @returns true if the resulting clipping region is non-zero in size
@see reduceClipRegion @see reduceClipRegion
*/ */
bool reduceClipRegion (const Image& image, const Rectangle<int>& sourceClipRegion,
const AffineTransform& transform);
bool reduceClipRegion (const Image& image, const AffineTransform& transform);
/** Excludes a rectangle to stop it being drawn into. */ /** Excludes a rectangle to stop it being drawn into. */
void excludeClipRegion (const Rectangle<int>& rectangleToExclude); void excludeClipRegion (const Rectangle<int>& rectangleToExclude);


+ 2
- 3
src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h View File

@@ -71,7 +71,7 @@ public:
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0; virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0;
virtual void excludeClipRectangle (const Rectangle<int>& r) = 0; virtual void excludeClipRectangle (const Rectangle<int>& r) = 0;
virtual void clipToPath (const Path& path, const AffineTransform& transform) = 0; virtual void clipToPath (const Path& path, const AffineTransform& transform) = 0;
virtual void clipToImageAlpha (const Image& sourceImage, const Rectangle<int>& srcClip, const AffineTransform& transform) = 0;
virtual void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) = 0;
virtual bool clipRegionIntersects (const Rectangle<int>& r) = 0; virtual bool clipRegionIntersects (const Rectangle<int>& r) = 0;
virtual const Rectangle<int> getClipBounds() const = 0; virtual const Rectangle<int> getClipBounds() const = 0;
@@ -89,8 +89,7 @@ public:
virtual void fillRect (const Rectangle<int>& r, bool replaceExistingContents) = 0; virtual void fillRect (const Rectangle<int>& r, bool replaceExistingContents) = 0;
virtual void fillPath (const Path& path, const AffineTransform& transform) = 0; virtual void fillPath (const Path& path, const AffineTransform& transform) = 0;
virtual void drawImage (const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& transform, bool fillEntireClipAsTiles) = 0;
virtual void drawImage (const Image& sourceImage, const AffineTransform& transform, bool fillEntireClipAsTiles) = 0;
virtual void drawLine (const Line <float>& line) = 0; virtual void drawLine (const Line <float>& line) = 0;
virtual void drawVerticalLine (int x, float top, float bottom) = 0; virtual void drawVerticalLine (int x, float top, float bottom) = 0;


+ 5
- 7
src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp View File

@@ -140,7 +140,7 @@ void LowLevelGraphicsPostScriptRenderer::clipToPath (const Path& path, const Aff
out << "clip\n"; out << "clip\n";
} }
void LowLevelGraphicsPostScriptRenderer::clipToImageAlpha (const Image& /*sourceImage*/, const Rectangle<int>& /*srcClip*/, const AffineTransform& /*transform*/)
void LowLevelGraphicsPostScriptRenderer::clipToImageAlpha (const Image& /*sourceImage*/, const AffineTransform& /*transform*/)
{ {
needToClip = true; needToClip = true;
jassertfalse; // xxx jassertfalse; // xxx
@@ -454,11 +454,10 @@ void LowLevelGraphicsPostScriptRenderer::writeImage (const Image& im,
out << "\n>}\n"; out << "\n>}\n";
} }
void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& transform, const bool /*fillEntireClipAsTiles*/)
void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, const AffineTransform& transform, const bool /*fillEntireClipAsTiles*/)
{ {
const int w = jmin (sourceImage.getWidth(), srcClip.getRight());
const int h = jmin (sourceImage.getHeight(), srcClip.getBottom());
const int w = sourceImage.getWidth();
const int h = sourceImage.getHeight();
writeClip(); writeClip();
@@ -468,7 +467,6 @@ void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, co
RectangleList imageClip; RectangleList imageClip;
sourceImage.createSolidAreaMask (imageClip, 0.5f); sourceImage.createSolidAreaMask (imageClip, 0.5f);
imageClip.clipTo (srcClip);
out << "newpath "; out << "newpath ";
int itemsOnLine = 0; int itemsOnLine = 0;
@@ -491,7 +489,7 @@ void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, co
out << w << ' ' << h << " scale\n"; out << w << ' ' << h << " scale\n";
out << w << ' ' << h << " 8 [" << w << " 0 0 -" << h << ' ' << (int) 0 << ' ' << h << " ]\n"; out << w << ' ' << h << " 8 [" << w << " 0 0 -" << h << ' ' << (int) 0 << ' ' << h << " ]\n";
writeImage (sourceImage, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight());
writeImage (sourceImage, 0, 0, w, h);
out << "false 3 colorimage grestore\n"; out << "false 3 colorimage grestore\n";
needToClip = true; needToClip = true;


+ 2
- 3
src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h View File

@@ -54,7 +54,7 @@ public:
bool clipToRectangleList (const RectangleList& clipRegion); bool clipToRectangleList (const RectangleList& clipRegion);
void excludeClipRectangle (const Rectangle<int>& r); void excludeClipRectangle (const Rectangle<int>& r);
void clipToPath (const Path& path, const AffineTransform& transform); void clipToPath (const Path& path, const AffineTransform& transform);
void clipToImageAlpha (const Image& sourceImage, const Rectangle<int>& srcClip, const AffineTransform& transform);
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform);
void saveState(); void saveState();
void restoreState(); void restoreState();
@@ -72,8 +72,7 @@ public:
void fillRect (const Rectangle<int>& r, bool replaceExistingContents); void fillRect (const Rectangle<int>& r, bool replaceExistingContents);
void fillPath (const Path& path, const AffineTransform& transform); void fillPath (const Path& path, const AffineTransform& transform);
void drawImage (const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& transform, bool fillEntireClipAsTiles);
void drawImage (const Image& sourceImage, const AffineTransform& transform, bool fillEntireClipAsTiles);
void drawLine (const Line <float>& line); void drawLine (const Line <float>& line);


+ 21
- 25
src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp View File

@@ -986,7 +986,7 @@ public:
virtual const Ptr excludeClipRectangle (const Rectangle<int>& r) = 0; virtual const Ptr excludeClipRectangle (const Rectangle<int>& r) = 0;
virtual const Ptr clipToPath (const Path& p, const AffineTransform& transform) = 0; virtual const Ptr clipToPath (const Path& p, const AffineTransform& transform) = 0;
virtual const Ptr clipToEdgeTable (const EdgeTable& et) = 0; virtual const Ptr clipToEdgeTable (const EdgeTable& et) = 0;
virtual const Ptr clipToImageAlpha (const Image& image, const Rectangle<int>& srcClip, const AffineTransform& t, const bool betterQuality) = 0;
virtual const Ptr clipToImageAlpha (const Image& image, const AffineTransform& t, const bool betterQuality) = 0;
virtual bool clipRegionIntersects (const Rectangle<int>& r) const = 0; virtual bool clipRegionIntersects (const Rectangle<int>& r) const = 0;
virtual const Rectangle<int> getClipBounds() const = 0; virtual const Rectangle<int> getClipBounds() const = 0;
@@ -1224,9 +1224,9 @@ public:
return edgeTable.isEmpty() ? 0 : this; return edgeTable.isEmpty() ? 0 : this;
} }
const Ptr clipToImageAlpha (const Image& image, const Rectangle<int>& srcClip, const AffineTransform& transform, const bool betterQuality)
const Ptr clipToImageAlpha (const Image& image, const AffineTransform& transform, const bool betterQuality)
{ {
const Image::BitmapData srcData (image, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight());
const Image::BitmapData srcData (image, false);
if (transform.isOnlyTranslation()) if (transform.isOnlyTranslation())
{ {
@@ -1416,9 +1416,9 @@ public:
return Ptr (new ClipRegion_EdgeTable (clip))->clipToEdgeTable (et); return Ptr (new ClipRegion_EdgeTable (clip))->clipToEdgeTable (et);
} }
const Ptr clipToImageAlpha (const Image& image, const Rectangle<int>& srcClip, const AffineTransform& transform, const bool betterQuality)
const Ptr clipToImageAlpha (const Image& image, const AffineTransform& transform, const bool betterQuality)
{ {
return Ptr (new ClipRegion_EdgeTable (clip))->clipToImageAlpha (image, srcClip, transform, betterQuality);
return Ptr (new ClipRegion_EdgeTable (clip))->clipToImageAlpha (image, transform, betterQuality);
} }
bool clipRegionIntersects (const Rectangle<int>& r) const bool clipRegionIntersects (const Rectangle<int>& r) const
@@ -1803,20 +1803,20 @@ public:
} }
} }
void clipToImageAlpha (const Image& image, const Rectangle<int>& srcClip, const AffineTransform& t)
void clipToImageAlpha (const Image& image, const AffineTransform& t)
{ {
if (clip != 0) if (clip != 0)
{ {
if (image.hasAlphaChannel()) if (image.hasAlphaChannel())
{ {
cloneClipIfMultiplyReferenced(); cloneClipIfMultiplyReferenced();
clip = clip->clipToImageAlpha (image, srcClip, t.translated ((float) xOffset, (float) yOffset),
clip = clip->clipToImageAlpha (image, t.translated ((float) xOffset, (float) yOffset),
interpolationQuality != Graphics::lowResamplingQuality); interpolationQuality != Graphics::lowResamplingQuality);
} }
else else
{ {
Path p; Path p;
p.addRectangle (srcClip);
p.addRectangle (image.getBounds());
clipToPath (p, t); clipToPath (p, t);
} }
} }
@@ -1839,7 +1839,7 @@ public:
{ {
if (fillType.isColour()) if (fillType.isColour())
{ {
Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true);
Image::BitmapData destData (image, true);
clip->fillRectWithColour (destData, r.translated (xOffset, yOffset), fillType.colour.getPixelARGB(), replaceContents); clip->fillRectWithColour (destData, r.translated (xOffset, yOffset), fillType.colour.getPixelARGB(), replaceContents);
} }
else else
@@ -1859,7 +1859,7 @@ public:
{ {
if (fillType.isColour()) if (fillType.isColour())
{ {
Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true);
Image::BitmapData destData (image, true);
clip->fillRectWithColour (destData, r.translated ((float) xOffset, (float) yOffset), fillType.colour.getPixelARGB()); clip->fillRectWithColour (destData, r.translated ((float) xOffset, (float) yOffset), fillType.colour.getPixelARGB());
} }
else else
@@ -1898,7 +1898,7 @@ public:
if (shapeToFill != 0) if (shapeToFill != 0)
{ {
Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true);
Image::BitmapData destData (image, true);
if (fillType.isGradient()) if (fillType.isGradient())
{ {
@@ -1923,7 +1923,7 @@ public:
} }
else if (fillType.isTiledImage()) else if (fillType.isTiledImage())
{ {
renderImage (image, fillType.image, fillType.image.getBounds(), fillType.transform, shapeToFill);
renderImage (image, fillType.image, fillType.transform, shapeToFill);
} }
else else
{ {
@@ -1933,13 +1933,12 @@ public:
} }
//============================================================================== //==============================================================================
void renderImage (Image& destImage, const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& t, const SoftwareRendererClasses::ClipRegionBase* const tiledFillClipRegion)
void renderImage (Image& destImage, const Image& sourceImage, const AffineTransform& t, const SoftwareRendererClasses::ClipRegionBase* const tiledFillClipRegion)
{ {
const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset));
const Image::BitmapData destData (destImage, 0, 0, destImage.getWidth(), destImage.getHeight(), true);
const Image::BitmapData srcData (sourceImage, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight());
const Image::BitmapData destData (destImage, true);
const Image::BitmapData srcData (sourceImage, false);
const int alpha = fillType.colour.getAlpha(); const int alpha = fillType.colour.getAlpha();
const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality); const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality);
@@ -1960,7 +1959,7 @@ public:
} }
else else
{ {
SoftwareRendererClasses::ClipRegionBase::Ptr c (new SoftwareRendererClasses::ClipRegion_EdgeTable (Rectangle<int> (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds())));
SoftwareRendererClasses::ClipRegionBase::Ptr c (new SoftwareRendererClasses::ClipRegion_EdgeTable (Rectangle<int> (tx, ty, sourceImage.getWidth(), sourceImage.getHeight()).getIntersection (destImage.getBounds())));
c = clip->applyClipTo (c); c = clip->applyClipTo (c);
if (c != 0) if (c != 0)
@@ -1981,7 +1980,7 @@ public:
else else
{ {
Path p; Path p;
p.addRectangle (srcClip);
p.addRectangle (sourceImage.getBounds());
SoftwareRendererClasses::ClipRegionBase::Ptr c (clip->clone()); SoftwareRendererClasses::ClipRegionBase::Ptr c (clip->clone());
c = c->clipToPath (p, transform); c = c->clipToPath (p, transform);
@@ -2058,9 +2057,9 @@ void LowLevelGraphicsSoftwareRenderer::clipToPath (const Path& path, const Affin
currentState->clipToPath (path, transform); currentState->clipToPath (path, transform);
} }
void LowLevelGraphicsSoftwareRenderer::clipToImageAlpha (const Image& sourceImage, const Rectangle<int>& srcClip, const AffineTransform& transform)
void LowLevelGraphicsSoftwareRenderer::clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform)
{ {
currentState->clipToImageAlpha (sourceImage, srcClip, transform);
currentState->clipToImageAlpha (sourceImage, transform);
} }
bool LowLevelGraphicsSoftwareRenderer::clipRegionIntersects (const Rectangle<int>& r) bool LowLevelGraphicsSoftwareRenderer::clipRegionIntersects (const Rectangle<int>& r)
@@ -2126,12 +2125,9 @@ void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineT
currentState->fillPath (image, path, transform); currentState->fillPath (image, path, transform);
} }
void LowLevelGraphicsSoftwareRenderer::drawImage (const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& transform, const bool fillEntireClipAsTiles)
void LowLevelGraphicsSoftwareRenderer::drawImage (const Image& sourceImage, const AffineTransform& transform, const bool fillEntireClipAsTiles)
{ {
jassert (sourceImage.getBounds().contains (srcClip));
currentState->renderImage (image, sourceImage, srcClip, transform,
currentState->renderImage (image, sourceImage, transform,
fillEntireClipAsTiles ? currentState->clip : 0); fillEntireClipAsTiles ? currentState->clip : 0);
} }


+ 2
- 3
src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h View File

@@ -54,7 +54,7 @@ public:
bool clipToRectangleList (const RectangleList& clipRegion); bool clipToRectangleList (const RectangleList& clipRegion);
void excludeClipRectangle (const Rectangle<int>& r); void excludeClipRectangle (const Rectangle<int>& r);
void clipToPath (const Path& path, const AffineTransform& transform); void clipToPath (const Path& path, const AffineTransform& transform);
void clipToImageAlpha (const Image& sourceImage, const Rectangle<int>& srcClip, const AffineTransform& transform);
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform);
bool clipRegionIntersects (const Rectangle<int>& r); bool clipRegionIntersects (const Rectangle<int>& r);
const Rectangle<int> getClipBounds() const; const Rectangle<int> getClipBounds() const;
@@ -72,8 +72,7 @@ public:
void fillRect (const Rectangle<int>& r, bool replaceExistingContents); void fillRect (const Rectangle<int>& r, bool replaceExistingContents);
void fillPath (const Path& path, const AffineTransform& transform); void fillPath (const Path& path, const AffineTransform& transform);
void drawImage (const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& transform, bool fillEntireClipAsTiles);
void drawImage (const Image& sourceImage, const AffineTransform& transform, bool fillEntireClipAsTiles);
void drawLine (const Line <float>& line); void drawLine (const Line <float>& line);


+ 2
- 2
src/gui/graphics/drawables/juce_DrawableImage.cpp View File

@@ -108,13 +108,13 @@ void DrawableImage::render (const Drawable::RenderingContext& context) const
if (opacity > 0.0f && ! overlayColour.isOpaque()) if (opacity > 0.0f && ! overlayColour.isOpaque())
{ {
context.g.setOpacity (context.opacity * opacity); context.g.setOpacity (context.opacity * opacity);
context.g.drawImageTransformed (image, image.getBounds(), t, false);
context.g.drawImageTransformed (image, t, false);
} }
if (! overlayColour.isTransparent()) if (! overlayColour.isTransparent())
{ {
context.g.setColour (overlayColour.withMultipliedAlpha (context.opacity)); context.g.setColour (overlayColour.withMultipliedAlpha (context.opacity));
context.g.drawImageTransformed (image, image.getBounds(), t, true);
context.g.drawImageTransformed (image, t, true);
} }
} }
} }


+ 2
- 2
src/gui/graphics/effects/juce_DropShadowEffect.cpp View File

@@ -66,8 +66,8 @@ void DropShadowEffect::applyEffect (Image& image, Graphics& g)
Image shadowImage (Image::SingleChannel, w, h, false); Image shadowImage (Image::SingleChannel, w, h, false);
const Image::BitmapData srcData (image, 0, 0, w, h);
const Image::BitmapData destData (shadowImage, 0, 0, w, h, true);
const Image::BitmapData srcData (image, false);
const Image::BitmapData destData (shadowImage, true);
const int filter = roundToInt (63.0f / radius); const int filter = roundToInt (63.0f / radius);
const int radiusMinus1 = roundToInt ((radius - 1.0f) * 63.0f); const int radiusMinus1 = roundToInt ((radius - 1.0f) * 63.0f);


+ 7
- 11
src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp View File

@@ -33,8 +33,7 @@ BEGIN_JUCE_NAMESPACE
//============================================================================== //==============================================================================
GIFLoader::GIFLoader (InputStream& in) GIFLoader::GIFLoader (InputStream& in)
: image (0),
input (in),
: input (in),
dataBlockIsZero (false), dataBlockIsZero (false),
fresh (false), fresh (false),
finished (false) finished (false)
@@ -99,9 +98,7 @@ GIFLoader::GIFLoader (InputStream& in)
image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB,
imageWidth, imageHeight, (transparent >= 0)); imageWidth, imageHeight, (transparent >= 0));
readImage (imageWidth, imageHeight,
(buf[8] & 0x40) != 0,
transparent);
readImage ((buf[8] & 0x40) != 0, transparent);
break; break;
} }
@@ -361,8 +358,7 @@ int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize)
return code; return code;
} }
bool GIFLoader::readImage (const int width, const int height,
const int interlace, const int transparent)
bool GIFLoader::readImage (const int interlace, const int transparent)
{ {
unsigned char c; unsigned char c;
@@ -381,7 +377,7 @@ bool GIFLoader::readImage (const int width, const int height,
int index; int index;
int xpos = 0, ypos = 0, pass = 0; int xpos = 0, ypos = 0, pass = 0;
const Image::BitmapData destData (image, 0, 0, width, height, true);
const Image::BitmapData destData (image, true);
uint8* p = destData.data; uint8* p = destData.data;
const bool hasAlpha = image.hasAlphaChannel(); const bool hasAlpha = image.hasAlphaChannel();
@@ -409,7 +405,7 @@ bool GIFLoader::readImage (const int width, const int height,
p += destData.pixelStride; p += destData.pixelStride;
++xpos; ++xpos;
if (xpos == width)
if (xpos == destData.width)
{ {
xpos = 0; xpos = 0;
@@ -423,7 +419,7 @@ bool GIFLoader::readImage (const int width, const int height,
case 3: ypos += 2; break; case 3: ypos += 2; break;
} }
while (ypos >= height)
while (ypos >= destData.height)
{ {
++pass; ++pass;
@@ -444,7 +440,7 @@ bool GIFLoader::readImage (const int width, const int height,
p = destData.getPixelPointer (xpos, ypos); p = destData.getPixelPointer (xpos, ypos);
} }
if (ypos >= height)
if (ypos >= destData.height)
break; break;
} }


+ 1
- 1
src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h View File

@@ -69,7 +69,7 @@ private:
int processExtension (int type, int& transparent); int processExtension (int type, int& transparent);
int readLZWByte (bool initialise, int input_code_size); int readLZWByte (bool initialise, int input_code_size);
int getCode (int code_size, bool initialise); int getCode (int code_size, bool initialise);
bool readImage (int width, int height, int interlace, int transparent);
bool readImage (int interlace, int transparent);
static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; }
GIFLoader (const GIFLoader&); GIFLoader (const GIFLoader&);


+ 2
- 2
src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp View File

@@ -302,7 +302,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in)
image = Image (Image::RGB, width, height, false); image = Image (Image::RGB, width, height, false);
const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect)
const Image::BitmapData destData (image, 0, 0, width, height, true);
const Image::BitmapData destData (image, true);
for (int y = 0; y < height; ++y) for (int y = 0; y < height; ++y)
{ {
@@ -405,7 +405,7 @@ bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct, JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct,
JPOOL_IMAGE, strideBytes, 1); JPOOL_IMAGE, strideBytes, 1);
const Image::BitmapData srcData (image, 0, 0, jpegCompStruct.image_width, jpegCompStruct.image_height);
const Image::BitmapData srcData (image, false);
while (jpegCompStruct.next_scanline < jpegCompStruct.image_height) while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
{ {


+ 3
- 3
src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp View File

@@ -168,7 +168,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in)
if (pngInfoStruct == 0) if (pngInfoStruct == 0)
{ {
png_destroy_read_struct (&pngReadStruct, 0, 0); png_destroy_read_struct (&pngReadStruct, 0, 0);
return Image();
return Image::null;
} }
png_set_error_fn (pngReadStruct, 0, PNGHelpers::errorCallback, PNGHelpers::errorCallback ); png_set_error_fn (pngReadStruct, 0, PNGHelpers::errorCallback, PNGHelpers::errorCallback );
@@ -226,7 +226,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in)
hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect)
const Image::BitmapData destData (image, 0, 0, (int) width, (int) height, true);
const Image::BitmapData destData (image, true);
uint8* srcRow = tempBuffer; uint8* srcRow = tempBuffer;
uint8* destRow = destData.data; uint8* destRow = destData.data;
@@ -304,7 +304,7 @@ bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
png_set_shift (pngWriteStruct, &sig_bit); png_set_shift (pngWriteStruct, &sig_bit);
png_set_packing (pngWriteStruct); png_set_packing (pngWriteStruct);
const Image::BitmapData srcData (image, 0, 0, width, height);
const Image::BitmapData srcData (image, false);
for (int y = 0; y < height; ++y) for (int y = 0; y < height; ++y)
{ {


+ 63
- 0
src/gui/graphics/imaging/juce_Image.cpp View File

@@ -95,6 +95,57 @@ Image::SharedImage* Image::SharedImage::createSoftwareImage (Image::PixelFormat
return new SoftwareSharedImage (format, width, height, clearImage); return new SoftwareSharedImage (format, width, height, clearImage);
} }
//==============================================================================
class SubsectionSharedImage : public Image::SharedImage
{
public:
SubsectionSharedImage (Image::SharedImage* const image_, const Rectangle<int>& area_)
: Image::SharedImage (image_->getPixelFormat(), area_.getWidth(), area_.getHeight()),
image (image_), area (area_)
{
pixelStride = image_->getPixelStride();
lineStride = image_->getLineStride();
imageData = image_->getPixelData (area_.getX(), area_.getY());
}
~SubsectionSharedImage() {}
Image::ImageType getType() const
{
return Image::SoftwareImage;
}
LowLevelGraphicsContext* createLowLevelContext()
{
LowLevelGraphicsContext* g = image->createLowLevelContext();
g->clipToRectangle (area);
g->setOrigin (area.getX(), area.getY());
return g;
}
SharedImage* clone()
{
return new SubsectionSharedImage (image->clone(), area);
}
private:
const ReferenceCountedObjectPtr<Image::SharedImage> image;
const Rectangle<int> area;
};
const Image Image::getClippedImage (const Rectangle<int>& area) const
{
if (area.contains (getBounds()))
return *this;
const Rectangle<int> validArea (area.getIntersection (getBounds()));
if (validArea.isEmpty())
return Image::null;
return Image (new SubsectionSharedImage (image, validArea));
}
//============================================================================== //==============================================================================
Image::Image() Image::Image()
{ {
@@ -128,6 +179,8 @@ Image::~Image()
{ {
} }
const Image Image::null;
LowLevelGraphicsContext* Image::createLowLevelContext() const LowLevelGraphicsContext* Image::createLowLevelContext() const
{ {
return image == 0 ? 0 : image->createLowLevelContext(); return image == 0 ? 0 : image->createLowLevelContext();
@@ -231,6 +284,16 @@ Image::BitmapData::BitmapData (const Image& image, const int x, const int y, con
jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight());
} }
Image::BitmapData::BitmapData (const Image& image, bool /*needsToBeWritable*/)
: data (image.image == 0 ? 0 : image.image->imageData),
pixelFormat (image.getFormat()),
lineStride (image.image == 0 ? 0 : image.image->lineStride),
pixelStride (image.image == 0 ? 0 : image.image->pixelStride),
width (image.getWidth()),
height (image.getHeight())
{
}
Image::BitmapData::~BitmapData() Image::BitmapData::~BitmapData()
{ {
} }


+ 26
- 2
src/gui/graphics/imaging/juce_Image.h View File

@@ -139,6 +139,11 @@ public:
*/ */
inline bool isNull() const throw() { return image == 0; } inline bool isNull() const throw() { return image == 0; }
/** A null Image object that can be used when you need to return an invalid image.
This object is the equivalient to an Image created with the default constructor.
*/
static const Image null;
//============================================================================== //==============================================================================
/** Returns the image's width (in pixels). */ /** Returns the image's width (in pixels). */
int getWidth() const throw() { return image == 0 ? 0 : image->width; } int getWidth() const throw() { return image == 0 ? 0 : image->width; }
@@ -206,6 +211,19 @@ public:
*/ */
void duplicateIfShared(); void duplicateIfShared();
/** Returns an image which refers to a subsection of this image.
This will not make a copy of the original - the new image will keep a reference to it, so that
if the original image is changed, the contents of the subsection will also change. Likewise if you
draw into the subimage, you'll also be drawing onto that area of the original image. Note that if
you use operator= to make the original Image object refer to something else, the subsection image
won't pick up this change, it'll remain pointing at the original.
The area passed-in will be clipped to the bounds of this image, so this may return a smaller
image than the area you asked for, or even a null image if the area was out-of-bounds.
*/
const Image getClippedImage (const Rectangle<int>& area) const;
//============================================================================== //==============================================================================
/** Returns the colour of one of the pixels in the image. /** Returns the colour of one of the pixels in the image.
@@ -276,6 +294,7 @@ public:
public: public:
BitmapData (Image& image, int x, int y, int w, int h, bool needsToBeWritable); BitmapData (Image& image, int x, int y, int w, int h, bool needsToBeWritable);
BitmapData (const Image& image, int x, int y, int w, int h); BitmapData (const Image& image, int x, int y, int w, int h);
BitmapData (const Image& image, bool needsToBeWritable);
~BitmapData(); ~BitmapData();
/** Returns a pointer to the start of a line in the image. /** Returns a pointer to the start of a line in the image.
@@ -382,6 +401,13 @@ public:
static SharedImage* createNativeImage (PixelFormat format, int width, int height, bool clearImage); static SharedImage* createNativeImage (PixelFormat format, int width, int height, bool clearImage);
static SharedImage* createSoftwareImage (PixelFormat format, int width, int height, bool clearImage); static SharedImage* createSoftwareImage (PixelFormat format, int width, int height, bool clearImage);
const PixelFormat getPixelFormat() const throw() { return format; }
int getWidth() const throw() { return width; }
int getHeight() const throw() { return height; }
int getPixelStride() const throw() { return pixelStride; }
int getLineStride() const throw() { return lineStride; }
uint8* getPixelData (int x, int y) const throw();
protected: protected:
friend class Image; friend class Image;
friend class Image::BitmapData; friend class Image::BitmapData;
@@ -391,8 +417,6 @@ public:
uint8* imageData; uint8* imageData;
var userTag; var userTag;
uint8* getPixelData (int x, int y) const throw();
SharedImage (const SharedImage&); SharedImage (const SharedImage&);
SharedImage& operator= (const SharedImage&); SharedImage& operator= (const SharedImage&);
}; };


+ 2
- 2
src/gui/graphics/imaging/juce_ImageCache.cpp View File

@@ -63,7 +63,7 @@ public:
return item->image; return item->image;
} }
return Image();
return Image::null;
} }
void addImageToCache (const Image& image, const int64 hashCode) void addImageToCache (const Image& image, const int64 hashCode)
@@ -136,7 +136,7 @@ const Image ImageCache::getFromHashCode (const int64 hashCode)
if (Pimpl::getInstanceWithoutCreating() != 0) if (Pimpl::getInstanceWithoutCreating() != 0)
return Pimpl::getInstanceWithoutCreating()->getFromHashCode (hashCode); return Pimpl::getInstanceWithoutCreating()->getFromHashCode (hashCode);
return Image();
return Image::null;
} }
void ImageCache::addImageToCache (const Image& image, const int64 hashCode) void ImageCache::addImageToCache (const Image& image, const int64 hashCode)


+ 1
- 1
src/gui/graphics/imaging/juce_ImageConvolutionKernel.cpp View File

@@ -143,7 +143,7 @@ void ImageConvolutionKernel::applyToImage (Image& destImage,
const Image::BitmapData destData (destImage, area.getX(), area.getY(), area.getWidth(), area.getHeight(), true); const Image::BitmapData destData (destImage, area.getX(), area.getY(), area.getWidth(), area.getHeight(), true);
uint8* line = destData.data; uint8* line = destData.data;
const Image::BitmapData srcData (sourceImage, 0, 0, sourceImage.getWidth(), sourceImage.getHeight());
const Image::BitmapData srcData (sourceImage, false);
if (destData.pixelStride == 4) if (destData.pixelStride == 4)
{ {


+ 3
- 3
src/gui/graphics/imaging/juce_ImageFileFormat.cpp View File

@@ -106,7 +106,7 @@ const Image ImageFileFormat::loadFrom (InputStream& input)
if (format != 0) if (format != 0)
return format->decodeImage (input); return format->decodeImage (input);
return Image();
return Image::null;
} }
const Image ImageFileFormat::loadFrom (const File& file) const Image ImageFileFormat::loadFrom (const File& file)
@@ -119,7 +119,7 @@ const Image ImageFileFormat::loadFrom (const File& file)
return loadFrom (b); return loadFrom (b);
} }
return Image();
return Image::null;
} }
const Image ImageFileFormat::loadFrom (const void* rawData, const int numBytes) const Image ImageFileFormat::loadFrom (const void* rawData, const int numBytes)
@@ -130,7 +130,7 @@ const Image ImageFileFormat::loadFrom (const void* rawData, const int numBytes)
return loadFrom (stream); return loadFrom (stream);
} }
return Image();
return Image::null;
} }
END_JUCE_NAMESPACE END_JUCE_NAMESPACE

+ 3
- 3
src/native/linux/juce_linux_Windowing.cpp View File

@@ -622,7 +622,7 @@ public:
const uint32 bShiftL = jmax (0, getShiftNeeded (bMask)); const uint32 bShiftL = jmax (0, getShiftNeeded (bMask));
const uint32 bShiftR = jmax (0, -getShiftNeeded (bMask)); const uint32 bShiftR = jmax (0, -getShiftNeeded (bMask));
const Image::BitmapData srcData (Image (this), 0, 0, width, height);
const Image::BitmapData srcData (Image (this), false);
for (int y = sy; y < sy + dh; ++y) for (int y = sy; y < sy + dh; ++y)
{ {
@@ -1819,7 +1819,7 @@ private:
else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000) else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000)
{ {
stopTimer(); stopTimer();
image = Image();
image = Image::null;
} }
} }
@@ -3137,7 +3137,7 @@ void MouseCursor::showInAllWindows() const
//============================================================================== //==============================================================================
const Image juce_createIconForFile (const File& file) const Image juce_createIconForFile (const File& file)
{ {
return Image();
return Image::null;
} }
Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage)


+ 1
- 1
src/native/mac/juce_iphone_UIViewComponentPeer.mm View File

@@ -878,7 +878,7 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo)
//============================================================================== //==============================================================================
const Image juce_createIconForFile (const File& file) const Image juce_createIconForFile (const File& file)
{ {
return Image();
return Image::null;
} }
//============================================================================== //==============================================================================


+ 12
- 31
src/native/mac/juce_mac_CoreGraphicsContext.mm View File

@@ -76,7 +76,7 @@ public:
} }
else else
{ {
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());
const Image::BitmapData srcData (juceImage, false);
CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.height, 0); CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.height, 0);
@@ -234,7 +234,7 @@ public:
lastClipRectIsValid = false; lastClipRectIsValid = false;
} }
void clipToImageAlpha (const Image& sourceImage, const Rectangle<int>& srcClip, const AffineTransform& transform)
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform)
{ {
if (! transform.isSingularity()) if (! transform.isSingularity())
{ {
@@ -245,19 +245,11 @@ public:
CGImageRef image = CoreGraphicsImage::createImage (singleChannelImage, true, greyColourSpace); CGImageRef image = CoreGraphicsImage::createImage (singleChannelImage, true, greyColourSpace);
if (srcClip != sourceImage.getBounds())
{
CGImageRef fullImage = image;
image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), srcClip.getY(),
srcClip.getWidth(), srcClip.getHeight()));
CGImageRelease (fullImage);
}
flip(); flip();
AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, srcClip.getHeight()).followedBy (transform));
AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform));
applyTransform (t); applyTransform (t);
CGRect r = CGRectMake (0, 0, srcClip.getWidth(), srcClip.getHeight());
CGRect r = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight());
CGContextClipToMask (context, r, image); CGContextClipToMask (context, r, image);
applyTransform (t.inverted()); applyTransform (t.inverted());
@@ -383,7 +375,7 @@ public:
{ {
CGContextSaveGState (context); CGContextSaveGState (context);
CGContextClipToRect (context, cgRect); CGContextClipToRect (context, cgRect);
drawImage (state->fillType.image, state->fillType.image.getBounds(), state->fillType.transform, true);
drawImage (state->fillType.image, state->fillType.transform, true);
CGContextRestoreGState (context); CGContextRestoreGState (context);
} }
} }
@@ -416,33 +408,24 @@ public:
if (state->fillType.isGradient()) if (state->fillType.isGradient())
drawGradient(); drawGradient();
else else
drawImage (state->fillType.image, state->fillType.image.getBounds(), state->fillType.transform, true);
drawImage (state->fillType.image, state->fillType.transform, true);
} }
CGContextRestoreGState (context); CGContextRestoreGState (context);
} }
void drawImage (const Image& sourceImage, const Rectangle<int>& srcClip,
const AffineTransform& transform, const bool fillEntireClipAsTiles)
void drawImage (const Image& sourceImage, const AffineTransform& transform, const bool fillEntireClipAsTiles)
{ {
jassert (sourceImage.getBounds().contains (srcClip));
CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace);
CGImageRef image = fullImage;
if (srcClip != sourceImage.getBounds())
{
image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), srcClip.getY(),
srcClip.getWidth(), srcClip.getHeight()));
CGImageRelease (fullImage);
}
const int iw = sourceImage.getWidth();
const int ih = sourceImage.getHeight();
CGImageRef image = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace);
CGContextSaveGState (context); CGContextSaveGState (context);
CGContextSetAlpha (context, state->fillType.getOpacity()); CGContextSetAlpha (context, state->fillType.getOpacity());
flip(); flip();
applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, srcClip.getHeight()).followedBy (transform));
CGRect imageRect = CGRectMake (0, 0, srcClip.getWidth(), srcClip.getHeight());
applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, ih).followedBy (transform));
CGRect imageRect = CGRectMake (0, 0, iw, ih);
if (fillEntireClipAsTiles) if (fillEntireClipAsTiles)
{ {
@@ -459,8 +442,6 @@ public:
{ {
// Fallback to manually doing a tiled fill on 10.4 // Fallback to manually doing a tiled fill on 10.4
CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context));
const int iw = srcClip.getWidth();
const int ih = srcClip.getHeight();
int x = 0, y = 0; int x = 0, y = 0;
while (x > clip.origin.x) x -= iw; while (x > clip.origin.x) x -= iw;


+ 3
- 3
src/native/windows/juce_win32_Windowing.cpp View File

@@ -877,7 +877,7 @@ private:
void timerCallback() void timerCallback()
{ {
stopTimer(); stopTimer();
image = Image();
image = Image::null;
} }
private: private:
@@ -2356,7 +2356,7 @@ static const Image createImageFromHBITMAP (HBITMAP bitmap)
SelectObject (dc, bitmap); SelectObject (dc, bitmap);
im = Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true); im = Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true);
Image::BitmapData imageData (im, 0, 0, bm.bmWidth, bm.bmHeight, true);
Image::BitmapData imageData (im, true);
for (int y = bm.bmHeight; --y >= 0;) for (int y = bm.bmHeight; --y >= 0;)
{ {
@@ -2403,7 +2403,7 @@ static const Image createImageFromHICON (HICON icon)
} }
} }
return Image();
return Image::null;
} }
static HICON createHICONFromImage (const Image& image, const BOOL isIcon, int hotspotX, int hotspotY) static HICON createHICONFromImage (const Image& image, const BOOL isIcon, int hotspotX, int hotspotY)


Loading…
Cancel
Save