mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
CoreGraphics: Fix bug where subsection images were rendered incorrectly
This commit is contained in:
parent
a381fdf81d
commit
56ea531298
3 changed files with 92 additions and 21 deletions
|
|
@ -871,4 +871,68 @@ Graphics::ScopedSaveState::~ScopedSaveState()
|
|||
context.restoreState();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
class GraphicsTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
GraphicsTests() : UnitTest ("Graphics", UnitTestCategories::graphics) {}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
beginTest ("Render image subsection");
|
||||
{
|
||||
renderImageSubsection (NativeImageType{}, NativeImageType{});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void renderImageSubsection (const ImageType& sourceType, const ImageType& targetType)
|
||||
{
|
||||
const auto sourceColour = Colours::cyan;
|
||||
const auto sourceOffset = 49;
|
||||
|
||||
const Image source { Image::ARGB, 50, 50, true, sourceType };
|
||||
const Image target { Image::ARGB, 50, 50, true, targetType };
|
||||
|
||||
const auto subsection = source.getClippedImage (Rectangle { sourceOffset, sourceOffset, 1, 1 });
|
||||
|
||||
Image::BitmapData { subsection, Image::BitmapData::writeOnly }.setPixelColour (0, 0, sourceColour);
|
||||
|
||||
{
|
||||
// Render the subsection image so that it fills 'target'
|
||||
Graphics g { target };
|
||||
g.drawImage (subsection,
|
||||
0, 0, target.getWidth(), target.getHeight(),
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
|
||||
{
|
||||
// Check that all pixels in 'target' match the bottom right pixel of 'source'
|
||||
const Image::BitmapData bitmap { target, Image::BitmapData::readOnly };
|
||||
|
||||
int numFailures = 0;
|
||||
|
||||
for (auto y = 0; y < bitmap.height; ++y)
|
||||
{
|
||||
for (auto x = 0; x < bitmap.width; ++x)
|
||||
{
|
||||
const auto targetColour = bitmap.getPixelColour (x, y);
|
||||
|
||||
if (targetColour != sourceColour)
|
||||
++numFailures;
|
||||
}
|
||||
}
|
||||
|
||||
expect (numFailures == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static GraphicsTests graphicsTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ public:
|
|||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
CGContextRef getCGContext() const { return impl->getCGContext(); }
|
||||
CGImageRef getCGImage (CGColorSpaceRef x) const { return impl->getCGImage (x); }
|
||||
CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef x) const { return impl->getCGImage (x); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
@ -297,7 +297,7 @@ private:
|
|||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
virtual CGContextRef getCGContext() const = 0;
|
||||
virtual CGImageRef getCGImage (CGColorSpaceRef x) const = 0;
|
||||
virtual CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef x) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ private:
|
|||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
CGContextRef getCGContext() const override { return impl.getCGContext(); }
|
||||
CGImageRef getCGImage (CGColorSpaceRef x) const override { return impl.getCGImage (x); }
|
||||
CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef x) const override { return impl.getCGImage (x); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
@ -417,9 +417,12 @@ public:
|
|||
return self->sourceImage->getNativeExtensions().getCGContext();
|
||||
}
|
||||
|
||||
CGImageRef getCGImage (CGColorSpaceRef colourSpace) const
|
||||
CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef colourSpace) const
|
||||
{
|
||||
return self->sourceImage->getNativeExtensions().getCGImage (colourSpace);
|
||||
const auto& parentNative = self->sourceImage->getNativeExtensions();
|
||||
const auto parentImage = parentNative.getCGImage (colourSpace);
|
||||
return CFUniquePtr<CGImageRef> { CGImageCreateWithImageInRect (parentImage.get(),
|
||||
makeCGRect (self->area + parentNative.getTopLeft())) };
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -518,7 +521,7 @@ auto ImagePixelData::getNativeExtensions() -> NativeExtensions
|
|||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
CGContextRef getCGContext() const { return {}; }
|
||||
CGImageRef getCGImage (CGColorSpaceRef) const { return {}; }
|
||||
CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef) const { return {}; }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static CGImageRef getCachedImageRef (const Image& juceImage, CGColorSpaceRef colourSpace)
|
||||
static CFUniquePtr<CGImageRef> getCachedImageRef (const Image& juceImage, CGColorSpaceRef colourSpace)
|
||||
{
|
||||
auto* cgim = std::invoke ([&]() -> CGImageRef
|
||||
auto cgim = std::invoke ([&]() -> CFUniquePtr<CGImageRef>
|
||||
{
|
||||
if (auto ptr = juceImage.getPixelData())
|
||||
return ptr->getNativeExtensions().getCGImage (colourSpace);
|
||||
|
|
@ -155,7 +155,7 @@ public:
|
|||
});
|
||||
|
||||
if (cgim != nullptr)
|
||||
return CGImageRetain (cgim);
|
||||
return cgim;
|
||||
|
||||
const Image::BitmapData srcData (juceImage, Image::BitmapData::readOnly);
|
||||
|
||||
|
|
@ -163,13 +163,17 @@ public:
|
|||
CFUniquePtr<CFDataRef> data (CFDataCreate (nullptr, (const UInt8*) srcData.data, (CFIndex) usableSize));
|
||||
detail::DataProviderPtr provider { CGDataProviderCreateWithCFData (data.get()) };
|
||||
|
||||
return CGImageCreate ((size_t) srcData.width,
|
||||
return CFUniquePtr<CGImageRef> { CGImageCreate ((size_t) srcData.width,
|
||||
(size_t) srcData.height,
|
||||
8,
|
||||
(size_t) srcData.pixelStride * 8,
|
||||
(size_t) srcData.lineStride,
|
||||
colourSpace, getCGImageFlags (juceImage.getFormat()), provider.get(),
|
||||
nullptr, true, kCGRenderingIntentDefault);
|
||||
colourSpace,
|
||||
getCGImageFlags (juceImage.getFormat()),
|
||||
provider.get(),
|
||||
nullptr,
|
||||
true,
|
||||
kCGRenderingIntentDefault) };
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -185,10 +189,10 @@ public:
|
|||
HeapBlock<uint8> data;
|
||||
};
|
||||
|
||||
CGImageRef getCGImage (CGColorSpaceRef colourSpace)
|
||||
CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef colourSpace)
|
||||
{
|
||||
if (cachedImageRef != nullptr)
|
||||
return cachedImageRef.get();
|
||||
return CFUniquePtr<CGImageRef> { CGImageRetain (cachedImageRef.get()) };
|
||||
|
||||
const Image::BitmapData srcData { Image { this }, Image::BitmapData::readOnly };
|
||||
|
||||
|
|
@ -205,7 +209,7 @@ public:
|
|||
colourSpace, getCGImageFlags (pixelFormat), provider.get(),
|
||||
nullptr, true, kCGRenderingIntentDefault));
|
||||
|
||||
return cachedImageRef.get();
|
||||
return CFUniquePtr<CGImageRef> { CGImageRetain (cachedImageRef.get()) };
|
||||
}
|
||||
|
||||
ImageDataContainer::Ptr imageData = new ImageDataContainer();
|
||||
|
|
@ -222,7 +226,7 @@ public:
|
|||
return self->context.get();
|
||||
}
|
||||
|
||||
CGImageRef getCGImage (CGColorSpaceRef x) const
|
||||
CFUniquePtr<CGImageRef> getCGImage (CGColorSpaceRef x) const
|
||||
{
|
||||
return self->getCGImage (x);
|
||||
}
|
||||
|
|
@ -1200,7 +1204,7 @@ Image juce_createImageFromCIImage (CIImage* im, int w, int h)
|
|||
|
||||
CGImageRef juce_createCoreGraphicsImage (const Image& juceImage, CGColorSpaceRef colourSpace)
|
||||
{
|
||||
return CoreGraphicsPixelData::getCachedImageRef (juceImage, colourSpace);
|
||||
return CoreGraphicsPixelData::getCachedImageRef (juceImage, colourSpace).release();
|
||||
}
|
||||
|
||||
CGContextRef juce_getImageContext (const Image& image)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue