Thread overview
adamdruppe: Drawing scaled image
Jun 02, 2016
Pie?
Jun 02, 2016
Adam D. Ruppe
Jun 02, 2016
Pie?
Jun 03, 2016
Adam D. Ruppe
Jun 03, 2016
Pie?
Jun 04, 2016
Adam D. Ruppe
Jun 04, 2016
Pie?
June 02, 2016
I found your git hub and tried simpledisplay and png. I had virtually no problems getting them working from the get go! Thanks for your hard work!!! You deserve a cookie, or a million bucks!

I'm curious about how to draw a scaled image. I would like to have a "global" scale for my image drawing. Is there a way to apply a global transform efficiently?(not all image drawing though, just some).

Also, png.d doesn't seem to work with alpha channel? I did a quick "alpha" search and simpledisplay.d says it doesn't work with alpha yet, except for openGL.

How hard would this be to add? Obviously it requires composting the underlying bits. I will be working on a buffer for all window drawing, one large non-alpha bitmap that I draw everything to, hence it should be somewhat fast to compose.

Which also leads me to, how to draw one image on to another?

Basically I want to setup a sort of triple buffer(if necessary, or just single) sprite rendering engine(well, not really but it's equivalent to it).

Is simple display and png capable of doing this without too much trouble?



June 02, 2016
On Thursday, 2 June 2016 at 03:19:20 UTC, Pie? wrote:
> I'm curious about how to draw a scaled image.

There's a few general options:

1) Scale it yourself in-memory then draw. This is a pain, I don't think my public libraries have a scale method....

2) If on MS Windows, you can resize the window as a user and it will stretch for you automatically. X on Linux doesn't support this though.

3) Again, on MS Windows, you could call StretchBlt yourself to scale and draw to it.

4) You can make an OpenGL texture and draw that at any scale/rotation. This is fairly involved and uses a totally different drawing system, but you can do it all with simpledisplay.d too.

> Also, png.d doesn't seem to work with alpha channel?

png does, but simpledisplay doesn't (except for the OpenGL stuff, of course).

Both the MemoryImage implementations (TrueColorImage and IndexedImage) have a rgba thing internally.... so you could blend yourself before drawing (color.d has an alphaBlend function, undocumented though), but if you want it done automatically or in hardware, gotta use the opengl stuff.

> Which also leads me to, how to draw one image on to another?

Gotta DIY there, I haven't written a function for that yet.

It's not hard to do though, at least with MemoryImages. The simpledisplay Image is different - it is optimized for the platform so the bits change around (it doesn't have an alpha channel in all cases either).

My terminal emulator does this.. here's the function:

https://github.com/adamdruppe/terminal-emulator/blob/master/main.d#L296

so basically you copy the bits yourself, using the offset members to handle the platform-specific stuff. I didn't do alpha blending there though... but the blend function from color.d could do it.



Doing alpha blending as we draw on the window needs new functions used... AlphaBlend on Windows and XRender on Linux IIRC. But since I tend to use OpenGL when I want to do lots of the blending I haven't been in a big rush to do it.
June 02, 2016
On Thursday, 2 June 2016 at 03:37:01 UTC, Adam D. Ruppe wrote:
> On Thursday, 2 June 2016 at 03:19:20 UTC, Pie? wrote:
>> I'm curious about how to draw a scaled image.
>
> There's a few general options:
>
> 1) Scale it yourself in-memory then draw. This is a pain, I don't think my public libraries have a scale method....
>
> 2) If on MS Windows, you can resize the window as a user and it will stretch for you automatically. X on Linux doesn't support this though.
>
> 3) Again, on MS Windows, you could call StretchBlt yourself to scale and draw to it.
>
> 4) You can make an OpenGL texture and draw that at any scale/rotation. This is fairly involved and uses a totally different drawing system, but you can do it all with simpledisplay.d too.
>
>> Also, png.d doesn't seem to work with alpha channel?
>
> png does, but simpledisplay doesn't (except for the OpenGL stuff, of course).
>
> Both the MemoryImage implementations (TrueColorImage and IndexedImage) have a rgba thing internally.... so you could blend yourself before drawing (color.d has an alphaBlend function, undocumented though), but if you want it done automatically or in hardware, gotta use the opengl stuff.
>
>> Which also leads me to, how to draw one image on to another?
>
> Gotta DIY there, I haven't written a function for that yet.
>
> It's not hard to do though, at least with MemoryImages. The simpledisplay Image is different - it is optimized for the platform so the bits change around (it doesn't have an alpha channel in all cases either).
>
> My terminal emulator does this.. here's the function:
>
> https://github.com/adamdruppe/terminal-emulator/blob/master/main.d#L296
>
> so basically you copy the bits yourself, using the offset members to handle the platform-specific stuff. I didn't do alpha blending there though... but the blend function from color.d could do it.
>
>
>
> Doing alpha blending as we draw on the window needs new functions used... AlphaBlend on Windows and XRender on Linux IIRC. But since I tend to use OpenGL when I want to do lots of the blending I haven't been in a big rush to do it.

Thanks, I'll look into it. I have tried OpenGL with simpledisplay but I cannot draw to the window. I assume other drawing methods are required?

	auto window = new SimpleWindow(600, 400, "Pong game!", OpenGlOptions.yes);
	
	window.setAsCurrentOpenGlContext();
	//auto img = imageFromPng(readPng(cast(ubyte[]) read(args[1])));
	// newer api, simpler but less control
	auto img = readPng(`x.png`);
	auto img2 = readPng(`y.png`);
	window.redrawOpenGlScene = delegate() {
			auto painter = window.draw();
			painter.clear();
			painter.drawImage(Point(10, 10), Image.fromMemoryImage(img2));
			painter.drawImage(Point(10, 10), Image.fromMemoryImage(img));
	};

	//displayImage(Image.fromMemoryImage(img), window);
	window.eventLoop(50, // set a 50 ms timer pulls
		// This runs once per timer pulse
		delegate () {
			//auto painter = window.draw();
			//painter.clear();
			//painter.drawImage(Point(10, 10), Image.fromMemoryImage(img2));
			//painter.drawImage(Point(10, 10), Image.fromMemoryImage(img));
			window.redrawOpenGlSceneNow();

		},
		delegate (KeyEvent event) {
		},
		delegate (MouseEvent event) {
		}
	);


If so, I can use gamehelpers.d to do the drawing of the images?

Thanks.

June 03, 2016
On Thursday, 2 June 2016 at 04:01:03 UTC, Pie? wrote:
> Thanks, I'll look into it. I have tried OpenGL with simpledisplay but I cannot draw to the window. I assume other drawing methods are required?

Yeah, you have to use the OpenGL functions instead of my painter functions.

> If so, I can use gamehelpers.d to do the drawing of the images?

Yeah, the OpenGlTexture class can help with it. You can construct it with a TrueColorImage (readPng gives MemoryImage which you can call .getAsTrueColorImage on to get one)

Then the OpenGlTexture has a draw method which you can call from inside the redrawOpenGlScene method. OpenGL coordinates are different than desktop, but the `create2dWindow` method in gamehelpers.d will create one with a matrix that matches out.

So the function might look like:

SimpleWindow window = create2dWindow("your title", width, height);

auto image = new OpenGlTexture(readPng(your_png_file).getAsTrueColorImage));

window.redrawOpenGlScene = {
   image.draw(x, y);
};

window.eventLoop(....);



Use window.redrawOpenGlSceneNow(); in the event loop to make it redraw.
June 03, 2016
On Friday, 3 June 2016 at 15:47:16 UTC, Adam D. Ruppe wrote:
> On Thursday, 2 June 2016 at 04:01:03 UTC, Pie? wrote:
>> Thanks, I'll look into it. I have tried OpenGL with simpledisplay but I cannot draw to the window. I assume other drawing methods are required?
>
> Yeah, you have to use the OpenGL functions instead of my painter functions.
>
>> If so, I can use gamehelpers.d to do the drawing of the images?
>
> Yeah, the OpenGlTexture class can help with it. You can construct it with a TrueColorImage (readPng gives MemoryImage which you can call .getAsTrueColorImage on to get one)
>
> Then the OpenGlTexture has a draw method which you can call from inside the redrawOpenGlScene method. OpenGL coordinates are different than desktop, but the `create2dWindow` method in gamehelpers.d will create one with a matrix that matches out.
>
> So the function might look like:
>
> SimpleWindow window = create2dWindow("your title", width, height);
>
> auto image = new OpenGlTexture(readPng(your_png_file).getAsTrueColorImage));
>
> window.redrawOpenGlScene = {
>    image.draw(x, y);
> };
>
> window.eventLoop(....);
>
>
>
> Use window.redrawOpenGlSceneNow(); in the event loop to make it redraw.

Thanks! It is working. A few issues with my images being clipped and not throwing when file doesn't exist... but transparency and such does exist.

Is the display double buffered or will I need to deal with that myself?

Also, when the window is resized it goes white. Any ideas how to fix that?

Thanks again! Your code has been the easiest to work with! Normally have all kinds of problems.

June 04, 2016
On Friday, 3 June 2016 at 20:06:50 UTC, Pie? wrote:
> Thanks! It is working. A few issues with my images being clipped and not throwing when file doesn't exist...

That's weird.. I don't know what's going on there.

BTW have you seen my documentation site too? http://dpldocs.info/experimental-docs/arsd.gamehelpers.OpenGlTexture.draw.1.html

It has a lot of my modules as well as my fork of the official Phobos docs.

But the clipping and throwing shouldn't be a problem.

> Is the display double buffered or will I need to deal with that myself?

That's automatic.

> Also, when the window is resized it goes white. Any ideas how to fix that?

It might help to set a window.windowResized handler

window.windowResized = (int width, int height) {
   window.redrawOpenGlSceneNow();
};

though I thought I did that automatically, I might have messed it up (I don't often resize windows when using opengl mode...)

> Thanks again! Your code has been the easiest to work with! Normally have all kinds of problems.

yea, I try to keep it simple - I like minimal dependencies so things just work without a complicated build process, but sometimes I drop balls. If you ever want to do patches btw, I also try to keep the code fairly simple so hacking on it shouldn't be too hard.
June 04, 2016
On Saturday, 4 June 2016 at 02:22:37 UTC, Adam D. Ruppe wrote:
> On Friday, 3 June 2016 at 20:06:50 UTC, Pie? wrote:
>> Thanks! It is working. A few issues with my images being clipped and not throwing when file doesn't exist...
>
> That's weird.. I don't know what's going on there.
>
> BTW have you seen my documentation site too? http://dpldocs.info/experimental-docs/arsd.gamehelpers.OpenGlTexture.draw.1.html
>
> It has a lot of my modules as well as my fork of the official Phobos docs.
>
> But the clipping and throwing shouldn't be a problem.
>
>> Is the display double buffered or will I need to deal with that myself?
>
> That's automatic.
>
>> Also, when the window is resized it goes white. Any ideas how to fix that?
>
> It might help to set a window.windowResized handler
>
> window.windowResized = (int width, int height) {
>    window.redrawOpenGlSceneNow();
> };
>
> though I thought I did that automatically, I might have messed it up (I don't often resize windows when using opengl mode...)
>
>> Thanks again! Your code has been the easiest to work with! Normally have all kinds of problems.
>
> yea, I try to keep it simple - I like minimal dependencies so things just work without a complicated build process, but sometimes I drop balls. If you ever want to do patches btw, I also try to keep the code fairly simple so hacking on it shouldn't be too hard.


Thanks. I will work on improving it the best I can when I actually improve upon it ;)

In the simple display code, windowResized happens at the end of a resize. You explicitly mention that WM_SIZING was not handled because of performance issues in your code.

I tried to add a windowResizing but, of course, the delegate signature conflicts with windowResized. I was thinking about about to accomplish this.

Would it be better for events to have "Features"? e.g., to deal with identical signatures?

e.g.,

delegate (int w, int h, Feature f)

and when the delegate is called we can use f to disambiguate the call? (same call for WM_SIZE and WM_SIZING)

Of course, we could create more separation by somehow allowing for separate assignment.... but not sure of any cool way to do this?

Right now you add delegates to the event handling using an array.

...,delegate (int w, int h) { },...

It would be cool if we could add "specifiers" or possibly attributes to them.

..., (delegate (int w, int h) { }).Resized, (delegate (int w, int h) { }).Resizing,...

Any ideas on that?