How to quickly texture a block of color - MBS?

Imagine I have a picture which is a plain Red color.
I also have a texture image which is greyscale.
Some parts are near white, some are near black.

such as this:

What is the fastest way to apply that texture to the red image, so that where the dark parts are less than a value of 0.5, the red pixels get darker, and where the texture is brighter than a value of 0.5, the red pixels get brighter?
(An early attempt of applying the texture with transparency , only seems to make things darker and duller)

I have tried looped through x,y
and calculating new RGB values for each pixel in turn by

  • getting the value of the texture,
  • working out how far from the mid point it is,
  • then adding to the RGB components of the target. (eg for dark, I add a negative amount, for light, I add a positive)

eg: if the texture pixel has a value of 0.4, then 0.4 -0.5 = -0.1
I multiply the -0.1 by some factor (say 20)
I add that to the RED, GREEN and BLUE values of the target image, making them a lower number
I cap them at 0 or 255
Then I get a new RGB color from those numbers, and redraw the pixel on the target.

I do that because you cannot amend the .value directly.

Using .graphics.pixel that is slow. In Windows, it is excruciatingly slow
using .rgbsurface.pixel fails on MacOS in 64bit builds (Xojo 2015… known bug)

What I really need is a way to apply the whole texture at once, so that it either lightens or darkens the original pixels
How is that best done?

Have you had a look at the Einhugur plugins? For the Windows side I have no idea what the MBS plugin supports. For macOS there are core graphics filters.

// --- void CGContextSetBlendMode(CGContextRef c, CGBlendMode mode); declare sub CGContextSetBlendMode lib "Cocoa" ( context as integer, blendmode as integer ) CGContextSetBlendMode( g.handle( graphics.handleTypeCGContext ), 3 ) )

const 3 = overlay
const 14 = color
const 15 = luminosity

Not tested, just typed, insert this in inbetween the two draw operations. Then set it back to zero at the end.

Thanks for the input guys.
I haven’t (and to be honest probably wont) considered the Einhurger plugins.
Theres almost certainly something in the MBS plugins (if only the documentation had something useful in it)

Sam: that looks promising but obviously its a Mac only solution.
I’ll keep it on a back shelf in case we find an equivalent windows only solution and I can #if around them

The Einhugur plugins are great for x-plat image editing; Björn is really helpful also. Back in '06 when we started working on Funtastic Photos I went with the Einhugur plugs as they were the best option, only thing was at that time we did well enough from selling Mac only that we never shipped Windows.

Once I have my latest project up and running on the Mac (and making money) I have every intention to go back to Einhugur so we can port it to Windows also.

Friad so; you wanted the quickest solution :wink:

btw: This works on 64-Bit macOS with 2017r3, but I’ve not tested it on any other platform. While it’s the fastest pure Xojo solution, it can be painfully slow with largish images.

If you still want to do it via pure Xojo, I’d recommend getting both images, accessing both their RGBSurfaces, and basically blending the hue & Saturation from one image, with the value from t’other. Look at the HSV function.

But all of those are read-only values, aren’t they?
I’ll go look at HSV now, and see if it suggests anything

Ah, I see.
OK, will experiment

This does speed up a bit, but still bound by the x/y looping.
What Im really looking for is a merge process. (a cross platform solution like the cocoa thing Sam proposed)

Im guessing that this is a composite
Im guessing it needs a ‘multiply’ or a ‘luminescence’ style.
I think these exist in the ImageMagick plugins.
But I cannot find a word of explanation

Why don‘t you simply set the mask? (You might have to use a darker red and play around with the mask a bit)

Setting a mask seems to only ever make things darker than the original.?
Am I misunderstanding the use of the mask?

I want to lighten some pixels , and darken other pixels, based on the texture.
In theory, that could make a lightened pixel get ‘capped’ at 255 or 0, causing an increase in contrast
Pixels need to be ‘nudged’ towards black and white

This is the fastest and most accurate way to to this

they will never be lighter that “white” (white areas of the mask), or darker than “RED” (the full black parts of the mask)
IF the mask is not truly only shades of gray (where RGB(x,x,x)), then convert it using a photo tool and you will be in good shape

so, yes :slight_smile:

EDIT : I examined the image, and it is in fact 234 shades of true gray

Thanks for the input

[quote]they will never be lighter than “white” (white areas of the mask), [/quote] agreed

[quote]
or darker than “RED” (the full black parts of the mask) -[/quote]
but it needs to be…

Essentially what I am after, starting with RED
is an image where some remains red,
some parts are pink approaching white,
while other parts are dark red approaching black.

well thats not how the mask works.
the mask ranges from 0x00 to 0xFF in shades of “gray” (ie. black to white)
therefore the output is then those same shades of the original color (ie. range of white to red with pink in between)

From you above image… what would you expect to show as “black”… since there is very little actual black in the image

I know.
Its not me that is suggesting a mask is the answer.
I have tried masks, it didnt do what I needed, and Im looking for something different.

Nothing from that one.
Thats purely an example greyscale image. There will be a variety of greyscale textures.

Imagine the starter position is a yellow circle.
Applying the texture I might want some parts to go dark, and some parts to go light, imparting a texture

So that it ends up like this:

ok… turning your yellow volleybal to a grayscale image and using it as mask, I was able to create any color volleyball I wanted…

Have you tried

Picture.CombineMBS(Mode as Integer, SecondPicture As Picture, X as Integer = 0, Y as Integer = 0, Width as Integer = 0, Height as Integer = 0) as picture ?
I guess this should do the trick (and fast too).

CombineMBS is fast, but I cannot work out what the heck it is doing.
The Mode option has 9 possible values and what I get is … interesting colors, but nothing like the effect above

Oh, you‘re right. There’s no multiplication which I think is what you are looking for.
There surely is a method in MBS plugins for picture multiplication, but I have not found it so far.

I shouldn’t need to ask, but since (when I try this), it looks rubbish, what does your code look like, Dave?