Avatar

Please consider registering
Guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed sp_TopicIcon
Shrinking bitmaps in VSTGUI 4
No permission to create posts
May 24, 2016
5:03 am
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

Hi everyone,

Does anyone have experience with shrinking bitmaps using VSTGUI 4? Setting a rect size larger than the bitmap will scale it up, but setting a rect smaller than the bitmap just clips it. (e.g. buttons, knobs) BTW, there seems to be a bug with CAnimKnob where it scales the width but not the height correctly (up-scaling).

In designing my plugin, I've had the artist create everything 4x in size with the intent that the user can resize the plugin and the graphics will always scale down (to hopefully maintain better scaling as opposed to up-scaling).

Just thought I'd check before diving into Windows and Mac specific code.

Thanks!

May 28, 2016
5:08 am
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

Alrighty,

I dove into the GdiplusBitmap class (VST3 SDK/vstgui4/vstgui/lib/platform/win32/ folder) a bit and made the follow changes:
NOTE:: This is assuming you are using "Make VST" to export the project from RackAFX.

1) modified GdiplusBitmap::load to accept a float scale parameter (you could pass in a CRect or CPoint instead). Here's the whole function. Don't forget to update the header file, I set a default scale of 1.0.

(in gdiplusbitmap.h)
bool load (const CResourceDescription& desc, float scale = 1.0) VSTGUI_OVERRIDE_VMETHOD;

(in gdiplusbitmap.cpp)
bool GdiplusBitmap::load (const CResourceDescription& desc, float scale)
{
if (bitmap == 0)
{
ResourceStream* resourceStream = new ResourceStream;
if (resourceStream->open (desc, "PNG"))
loadFromStream (resourceStream);
resourceStream->Release ();
if (!bitmap)
bitmap = Gdiplus::Bitmap::FromResource (GetInstance (), desc.type == CResourceDescription::kIntegerType ? (WCHAR*)MAKEINTRESOURCE(desc.u.id) : (WCHAR*)desc.u.name);
if (bitmap)
{
// Start of resize
if (scale != 1.0)
{
int newWidth = (int)(bitmap->GetWidth() * scale);
int newHeight = (int)(bitmap->GetHeight() * scale);
Gdiplus::Bitmap *newBmp = new Gdiplus::Bitmap(newWidth, newHeight, PixelFormat32bppPARGB);
Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(newBmp);

Gdiplus::Rect sizeR(0, 0, newWidth, newHeight);

pGraphics->DrawImage(bitmap, sizeR, 0, 0, (int)bitmap->GetWidth(), (int)bitmap->GetHeight(), Gdiplus::UnitPixel);

delete pGraphics;
delete bitmap;

bitmap = newBmp;
}
// end of resize

size.x = (CCoord)bitmap->GetWidth();
size.y = (CCoord)bitmap->GetHeight();
return true;
}
}
return false;
}

2) Update IPlatformBitmap::load to match

(in iplatformbitmap.h)
virtual bool load(const CResourceDescription& desc, float scale = 1.0) = 0;

3) Extend CBitmap and have a constructor that accepts the scale value along with the desc.

(in MyBitmap.cpp extended from CBitmap)

MyBitmap::MyBitmap(const CResourceDescription &desc, float scale) : CBitmap(desc)
{
#if defined WINDOWS || defined _WINDOWS || defined _WINDLL
// windows crap
platformBitmap = IPlatformBitmap::create();
if (platformBitmap && !platformBitmap->load(desc, scale))
{
platformBitmap->forget();
platformBitmap = 0;
}
#elif defined AUPLUGIN
// mac au crap
#else
// mac VST

#endif
}

Anyway, this will let you shrink bitmaps in GDI+.

Still have D2D to do for Windows and CGBitmaps for Mac.

May 29, 2016
9:13 pm
Avatar
W Pirkle
Admin
Forum Posts: 143
Member Since:
January 28, 2017
sp_UserOfflineSmall Offline

I've moved to VSTGUI4.3 with D2D when developing the current v6.7 Beta; I found that the bitmaps will automatically stretch/shrink to fit the container which I believe is D2D behavior only.

- Will

June 3, 2016
8:05 pm
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

I've changed the float scale parameter to an x & y value (scaleX & scaleY)

Here's the D2D code:

from d2dbitmap.cpp, I modified loadFromStream. the m_scaleX & m_scaleY are saved passed in and saved off in the load function. i.e.
bool D2DBitmap::load (const CResourceDescription& resourceDesc, int scaleX, int scaleY);

bool D2DBitmap::loadFromStream (IStream* iStream)
{
bool result = false;
IWICBitmapDecoder* decoder = 0;
IWICStream* stream = 0;
if (SUCCEEDED (WICGlobal::getFactory ()->CreateStream (&stream)))
{
if (SUCCEEDED (stream->InitializeFromIStream (iStream)))
{
WICGlobal::getFactory ()->CreateDecoderFromStream (stream, NULL, WICDecodeMetadataCacheOnLoad, &decoder);
}
stream->Release ();
}
if (decoder)
{
IWICBitmapFrameDecode* frame;
if (SUCCEEDED (decoder->GetFrame (0, &frame)))
{
UINT w = 0;
UINT h = 0;
frame->GetSize (&w, &h);
size.x = w;
size.y = h;

IWICBitmapScaler* scaler = 0;
WICGlobal::getFactory()->CreateBitmapScaler(&scaler);
if (scaler)
{
scaler->Initialize(frame, (m_scaleX > 0)?m_scaleX:w, (m_scaleY > 0)?m_scaleY:h, WICBitmapInterpolationModeFant);
source = scaler;
if (m_scaleX > 0)
{
size.x = m_scaleX;
size.y = m_scaleY;
}
}
IWICFormatConverter* converter = 0;
WICGlobal::getFactory()->CreateFormatConverter(&converter);
if (converter)
{
if (!SUCCEEDED(converter->Initialize(scaler, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut)))
{
converter->Release();
converter = 0;
}
else
source = converter;
}
frame->Release ();
}
decoder->Release ();
}
return source != 0;
}

June 3, 2016
8:08 pm
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

And here's the CGBitmap code. (cgbitmap.cpp) Again save off m_scaleX & m_scaleY in the load function i.e.
bool CGBitmap::load (const CResourceDescription& desc, int scaleX, int scaleY)

Then update getCGImage() as follows

CGImageRef CGBitmap::getCGImage ()
{
if (image == 0 && imageSource)
{
const void* keys[] = {kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32};
const void* values[] = {kCFBooleanTrue, kCFBooleanTrue};
CFDictionaryRef options = CFDictionaryCreate (NULL, keys, values, 2, NULL, NULL);
image = CGImageSourceCreateImageAtIndex (imageSource, 0, options);
CFRelease (imageSource);
CFRelease (options);
imageSource = 0;
if (m_scaleX > 0)
{
CGSize newSize = CGSizeMake(m_scaleX, m_scaleY);
CGRect newRect = CGRectMake(0, 0, newSize.width, newSize.height);
uint32_t info = CGImageGetBitmapInfo(image);
CGContextRef newImage = CGBitmapContextCreate(NULL,
newRect.size.width,
newRect.size.height,
CGImageGetBitsPerComponent(image),
0,
CGImageGetColorSpace(image),
kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(newImage, newRect, image);
CGImageRelease(image);
image = CGBitmapContextCreateImage(newImage);
CFRelease(newImage);

size.x = newSize.width;
size.y = newSize.height;
}
}
if ((dirty || image == 0) && bits)
{
freeCGImage ();

size_t rowBytes = getBytesPerRow ();
size_t byteCount = rowBytes * size.y;
size_t bitDepth = 32;

CGDataProviderRef provider = CGDataProviderCreateWithData (NULL, bits, byteCount, NULL);
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big;
image = CGImageCreate (size.x, size.y, 8, bitDepth, rowBytes, GetCGColorSpace (), bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault);
CGDataProviderRelease (provider);
dirty = false;
}
return image;
}

June 3, 2016
8:14 pm
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

Will said

I've moved to VSTGUI4.3 with D2D when developing the current v6.7 Beta; I found that the bitmaps will automatically stretch/shrink to fit the container which I believe is D2D behavior only.

- Will

Thanks Will, I've got the beta but ran into some problems and haven't had enough time to fully get everything working.

Quick question, on the VST export (for RAFX 6.6) you disable D2D support in the preprocessor definitions. Is that for increased compatibility? Any issues with turning that on when releasing a plugin?

June 3, 2016
9:10 pm
Avatar
W Pirkle
Admin
Forum Posts: 143
Member Since:
January 28, 2017
sp_UserOfflineSmall Offline

No, there is no issue with turning that on in the preprocessor defs. It is currently disabled because it requires extra work on the user's part to know where the D2D libs are located on their particular SDKs (Win SDK vs DirectX SDK, etc...) as well as modifying the Visual Studio project to find the d2d.lib file. I was actually going to do some kind of app-note about enabling D2D for the Make VST projects. If you'd like to contribute that then that would be cool.

- Will

June 4, 2016
5:16 am
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

Will said

No, there is no issue with turning that on in the preprocessor defs. It is currently disabled because it requires extra work on the user's part to know where the D2D libs are located on their particular SDKs (Win SDK vs DirectX SDK, etc...) as well as modifying the Visual Studio project to find the d2d.lib file. I was actually going to do some kind of app-note about enabling D2D for the Make VST projects. If you'd like to contribute that then that would be cool.

- Will

Interesting. I'm on Windows 7 running visual studio 2015 community, I can enable the VSTGUI D2D support on my VST exports and everything builds fine. Didn't do any special setup. I've been toggling back and forth between D2D and GDI+ to get the above code working.

I'll try it out on my laptop that has Windows 10.
I'd be happy to write up something if it's different.

June 5, 2016
11:37 am
Avatar
Derek
Member
Members
Forum Posts: 41
Member Since:
November 19, 2015
sp_UserOfflineSmall Offline

Hey Will,

I just did some VST exporting under Windows 10, VS 2105 community and was able to set the VSTGUI_D2D flag and compile just fine. No extra steps required. That's the same for me under windows 7 and 10.

June 13, 2016
10:11 pm
Avatar
W Pirkle
Admin
Forum Posts: 143
Member Since:
January 28, 2017
sp_UserOfflineSmall Offline

After doing a bunch of snooping, I found that all Visual Studio compilers will link with their own versions of d2d1.h without the need to make additional settings. The issue with D2D is for Visual Studio 2008 only, where you will need to add a #include search path for your particular d2d1.h. This should be found in:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include

unless you are on XP, in which case you will need to download the DirectX SDK and locate the directory that contains it.

- Will

Forum Timezone: America/New_York

Most Users Ever Online: 36

Currently Online:
2 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Skyler: 47

Peter: 41

Derek: 41

clau_ste: 39

Frodson: 38

Gwen: 32

EZB: 24

lppier: 23

Msaldaña: 18

Jorge: 17

Member Stats:

Guest Posters: 1

Members: 476

Moderators: 1

Admins: 4

Forum Stats:

Groups: 11

Forums: 30

Topics: 482

Posts: 1876

Newest Members:

sam, annaharris, Marie Weaver, kev, Steven, Mr Anderson, mguy, omelc

Moderators: W Pirkle: 143

Administrators: Tom: 65, JD Young: 80, Will Pirkle: 0, W Pirkle: 143