The MASM Forum

General => The Workshop => Windows Graphics Programming => Topic started by: zedd151 on April 11, 2025, 08:15:16 AM

Title: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 08:15:16 AM
I was wondering if anyone here has any experience with changing the hue of an image using gdiplus.

My idea is instead of using several different colored .pngs, I was thinking, "why not use only one .png image and just change the hue to any color the user chooses?"  The user then can change the color of all of the graphic elements, if I can figure out a way to implement it.

Any ideas where to start? What exactly should I research?
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 08:39:25 AM
Welll, if you can somehow get the image as just a raw bitmap (NOT a .BMP), and you know
then you could cruise through the bitmap and change colors.
Somehow. That might not be easy. But you could probably figure out how to change red (or reddish) pixels to blue or blueish.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 08:43:08 AM
Quote from: NoCforMe on April 11, 2025, 08:39:25 AMWelll, if you can somehow get the image as just a raw bitmap (NOT a .BMP), and you know
  • the image width & height
  • the image bitness (# bits/pixel)
then you could cruise through the bitmap and change colors.
Somehow. That might not be easy. But you could probably figure out how to change red (or reddish) pixels to blue or blueish.
It's not that easy. The images are not single color, plus they have an alpha channel. Hence the need for gdiplus. Otherwise I'd just plunk a new color on the colormap in pace of the old color. (For 1, 4, 16, or 256 color bitmaps that is.) That's easy.

If you can demonstrate your idea, I'll try it.  :smiley:  I guess you could swap the R G and B? Or somehow perform voodoo on them.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 08:58:09 AM
Quote from: zedd151 on April 11, 2025, 08:43:08 AMIt's not that easy. The images are not single color
I would assume not.
Quoteplus they have an alpha channel. Hence the need for gdiplus.
Not necessarily; the alpha channel is just the 4th byte, otherwise unused, of the RGB color.
You can simply leave that data alone to preserve the transparency of those pixels.
QuoteOtherwise I'd just plunk a new color on the colormap in pace of the old color. (For 1, 4, 16, or 256 color bitmaps that is.) That's easy.
Yes; I've done that in my BMP toolbar creator, where I created a new palette (what you called the "colormap") to combine several images into one with a common palette.
But that wouldn't be the way to do it, I don't think. What I was doing was preserving the colors of the component images (more or less) and combining them into a single image with a single palette.
QuoteIf you can demonstrate your idea, I'll try it.  :smiley:  I guess you could swap the R G and B? Or somehow perform voodoo on them.
Not swap; that would give really weird results.
More the second choice: voodoo.

Let's say you have an image that's predominantly one color, say red: not a single color, but the image is mainly red or reddish.
You could identify those pixels (say by selecting those with a minimum R value) and change them to blue or blue-ish, by increasing B and decreasing R.
Still not easy, but probably do-able.

What I don't know how to do is getting the raw bitmap pixels from a GDI+-loaded image.
Anyone know the magic incantation to do that? If so, I could experiment a bit.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 09:01:59 AM
Sounds like a neat coding exercise, but I'm not up for that kind of challenge.
Probably would be time consuming.

Let me take a look at my png's in Gimp, to see exactly how many colors there are.... brb. I don't think they are 24 bit color...
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 09:07:45 AM
Quote from: zedd151 on April 11, 2025, 09:01:59 AMI don't think they are 24 bit color...
They are 32 bit RGBA. I thought I had reduced the colors. I guess not.

red.png

PostImage screwed with the image I posted originally. Made it 180x180 and 43 kb.
The one above is original size 80x80 and ~9kb. You can right click it and "Save image as..." if you want to experiment with it.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 09:16:11 AM
I found a way to get access to the pixels:
GdipBitmapGetPixel()
Not the best way (probly slow), but all you need is the (x,y) coords. of the pixel.
And of course there's a GdipBitmapSetPixel() as well.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 09:19:42 AM
Quote from: zedd151 on April 11, 2025, 09:01:59 AMSounds like a neat coding exercise, but I'm not up for that kind of challenge.
Don't give up so easily. It could boil down to something like this:
loop through all pixels (x,y)
for each pixel
    get R
    if R > (some threshold)
          set R low
          set B high
When I get done with (part of) my other 85,792 projects I might play around with this.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 09:24:10 AM
Quote from: NoCforMe on April 11, 2025, 09:16:11 AMI found a way to get access to the pixels:
GdipBitmapGetPixel()
Not the best way (probly slow), but all you need is the (x,y) coords. of the pixel.
And of course there's a GdipBitmapSetPixel() as well.
I don't know about that - it might be a fun experiment, but surely there has to be a better way.

In any case, I don't mind having multiple images, but it would be nice to be able to change the hue 'on-the-fly' without too much acrobatics.

Quote from: NoCforMe on April 11, 2025, 09:19:42 AMWhen I get done with (part of) my other 85,792 projects I might play around with this.
:biggrin:
Yes, always too many things to do. But so little time. Same here.
Title: Re: Has anyone used gdiplus to change hue?
Post by: sinsi on April 11, 2025, 09:31:50 AM
Found this on reddit but it might be a bit too involved :biggrin: (and it's .net :dazzled: )
Quote from: Replacing all pixels of a certain colour with another colour in a bitmapYou can use GDI+ for this, using a DrawAttributes and a ColorMap. basically load the image then create a new blank canvas and use ImageAttributes to draw the loaded image into that new canvas using a ColorMap table.

Load existing image.

Create new Bitmap the same size as the original image.

use Graphics.FromImage() to create a new canvas from the second, new, image.

Create a new ImageAttributes instance, create a array of ColorMap, one for each mapping of old to new colours, presumably from your dictionary. Assign to the ImageAttributes class via .SetRemapTable().

use DrawImage on your second canvas and draw the first image loaded from the file to the canvas using the Image Attributes parameter.

If desired you can now save the replaced bitmap by saving the second bitmap you created.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 09:36:37 AM
I'm sure that would work, but just think how complex that would be:
You'd have to create that "dictionary", which sounds quite non-trivial.
(Unless you could maybe grab someone's already-made dictionary?)
My proposal is to change the image in situ, without having to create a new image from scratch like they do.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 10:15:11 AM
btw, I asked ChatGPT for code for this...
Too many errors in that code.  :tongue:
Like two arguments short on a very important invoke...

it's not totally useless. But usually for the most interesting stuff, it is about as useless as it can get.  :joking:
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 10:28:34 AM
Quote from: zedd151 on April 11, 2025, 10:15:11 AMbtw, I asked ChatGPT for code for this...
Too many errors in that code.  :tongue:

it's not totally useless. But usually for the most interesting stuff, it is about as useless as it can get.  :joking:
"Hallucinations 'Я' Us"
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 10:30:57 AM
Quote from: NoCforMe on April 11, 2025, 10:28:34 AM"Hallucinations 'Я' Us"
I keep telling you, you gotta lay off of them 'shrooms.  :biggrin:

Like it or not, AI is sometimes useful. No like, no use.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 10:34:38 AM
Me no like, no use.
"Artificial Ignorance"
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 11, 2025, 10:35:37 AM
Quote from: NoCforMe on April 11, 2025, 10:34:38 AMMe no like, no use.
"Artificial Ignorance"
Ok.
Title: Re: Has anyone used gdiplus to change hue?
Post by: sinsi on April 11, 2025, 11:20:19 AM
This seems to let you get a copy of the bitmap pixels.
I know it's .net but it seems pretty straightforward to convert.

private void LockUnlockBitsExample(PaintEventArgs e)
    {

        // Create a new bitmap.
        Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");

        // Lock the bitmap's bits. 
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        System.Drawing.Imaging.BitmapData bmpData =
            bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
            bmp.PixelFormat);

        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;

        // Declare an array to hold the bytes of the bitmap.
        int bytes  = Math.Abs(bmpData.Stride) * bmp.Height;
        byte[] rgbValues = new byte[bytes];

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

        // Set every third value to 255. A 24bpp bitmap will look red. 
        for (int counter = 2; counter < rgbValues.Length; counter += 3)
            rgbValues[counter] = 255;

        // Copy the RGB values back to the bitmap
        System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

        // Unlock the bits.
        bmp.UnlockBits(bmpData);

        // Draw the modified image.
        e.Graphics.DrawImage(bmp, 0, 150);
    }
Where it says Set every third value to 255 is where you would put your code for colour manipulation.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 11, 2025, 11:25:52 AM
Thanks, nice.
So far as the .net-ness of it goes, should be easy enough to convert to the GDI+ "flat" model:

This
            bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
            bmp.PixelFormat);

becomes
            INVOKE GdipBitmapLockBits, ADDR rect, <flags>, <format>, ADDR <bits>
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 12, 2025, 10:53:14 PM
During my research, I find that these are needed (or something similar - regarding the matrix)...
The matrix needed will be determined by the degree of hue rotation (the matrix here is for +90 degree rotation).


.data
; For example (90-degree hue rotation matrix)  flat 5x5 matrix
HueMatrix REAL4 \
    0.213, 0.715, 0.072, 0.0, 0.0, \
    0.213, 0.715, 0.072, 0.0, 0.0, \
    0.213, 0.715, 0.072, 0.0, 0.0, \
    0.0,   0.0,   0.0,   1.0, 0.0, \
    0.0,   0.0,   0.0,   0.0, 1.0

.code
; Create ImageAttributes object
    invoke GdipCreateImageAttributes, offset imageAttr

; Set color matrix for hue rotation
    invoke GdipSetImageAttributesColorMatrix, imageAttr, ColorAdjustTypeDefault, TRUE, offset HueMatrix, 0, ColorMatrixFlagsDefault
Then draw the image with new hue.
This is a brief summary so far, and obviously does not include gdiplus initialization, image loading, hgraphics setup etc., etc.

I am continuing my research... :smiley:
And will be experimenting with the information that I find from various sources ...

I will be looking for code necessary for setting the matrix needed for a given rotation...

In Photoshop adjusting hue from red to blue for instance requires around -128 degree rotation (depending on how red the source image is, and how much blue the destination image should be) if that makes any sense.

Plus I do not know why a 5x5 matrix is needed or how those values are determined. Will look into that, too.
Title: Re: Has anyone used gdiplus to change hue?
Post by: sinsi on April 12, 2025, 11:06:07 PM
Quote from: zedd151 on April 12, 2025, 10:53:14 PMPlus I do not know why a 5x5 matrix is needed. Will look into that, too.

Maybe this will help?
ImageAttributes::SetColorMatrix (https://learn.microsoft.com/en-us/windows/win32/api/gdiplusimageattributes/nf-gdiplusimageattributes-imageattributes-setcolormatrix)
QuoteAn ImageAttributes object maintains color and grayscale settings for five adjustment categories: default, bitmap, brush, pen, and text. For example, you can specify a color-adjustment matrix for the default category, a different color-adjustment matrix for the bitmap category, and still a different color-adjustment matrix for the pen category.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 12, 2025, 11:14:02 PM
Quote from: sinsi on April 12, 2025, 11:06:07 PMMaybe this will help?
ImageAttributes::SetColorMatrix (https://learn.microsoft.com/en-us/windows/win32/api/gdiplusimageattributes/nf-gdiplusimageattributes-imageattributes-setcolormatrix)

QuoteAn ImageAttributes object maintains color and grayscale settings for five adjustment categories: default, bitmap, brush, pen, and text. For example, you can specify a color-adjustment matrix for the default category, a different color-adjustment matrix for the bitmap category, and still a different color-adjustment matrix for the pen category.

Thanks sinsi, I would have gotten there eventually.
Btw, I ran that code (in your gdip startup test) and both of those calls returned zero. So I must be on the right track...  :biggrin:

I will play with this a bit (in actual code, with an image) and post the results.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 12, 2025, 11:19:48 PM
Quote from: zedd151 on April 12, 2025, 11:14:02 PMI will play with this a bit (in actual code, with an image) and post the results.
I inserted that code into a working example, no changes noticed in the image.
I must be missing something.  :undecided:

Back to the drawing board.  :biggrin:
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 12, 2025, 11:40:36 PM
Success!! Well, partially...

I had to use GdipDrawImageRectRectI, to get the attributes actually set in the image.
The first time around I used GdipDrawImageRectI - thus no attributes set,  :mrgreen:

DrawImage proc hDC:dword, Image:dword, x:dword, y:dword
local wid:dword, hgt:dword, pGraphics:dword
    invoke GdipCreateFromHDC, hDC, addr pGraphics
    invoke GdipGetImageWidth, Image, addr wid
    invoke GdipGetImageHeight, Image, addr hgt

    ; draw original image
    invoke GdipDrawImageRectI, pGraphics, Image, x, y, wid, hgt
   
    ; Create ImageAttributes object
    invoke GdipCreateImageAttributes, offset imageAttr

    ; Set color matrix for hue rotation
    invoke GdipSetImageAttributesColorMatrix, imageAttr, ColorAdjustTypeDefault, 1, offset HueMatrix, 0, ColorMatrixFlagsDefault

    ; Draw the image with new attributes
    add x, 90
    invoke GdipDrawImageRectRectI, pGraphics, Image, x, y, wid, hgt, 0, 0, wid, hgt, UnitPixel, imageAttr, 0, 0
   
    invoke GdipDisposeImageAttributes, imageAttr
    invoke GdipDeleteGraphics, pGraphics
    ret
DrawImage endp

The result using that matrix from post #18:
The image on the left is the original'
The image on the right has the hue adjusted.

(https://i.postimg.cc/c1m368VK/untitled.png)

The image (on the right) is highly saturated (or contrast is blown out), will need to look into remedying that.

I will post a proper example shortly. I reused a previous project for this demonstration that uses Vortex' method of loading the image as an object file - look Ma, no (discreet) resources :biggrin:
Executable for this demo is attached below
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 12:06:34 AM
After blindly tweaking the matrix:
HueMatrix REAL4 \
    0.213, 0.615, 0.072, 0.0, 0.0, \
    0.213, 0.615, 0.072, 0.0, 0.0, \
    0.213, 0.615, 0.072, 0.0, 0.0, \
    0.0,  0.0,  0.0,  0.7, 0.0, \
    0.0,  0.0,  0.0,  0.0, 0.7

(https://i.postimg.cc/qvf65XK5/untitled.png)
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 12:27:49 AM
I might make a dialog box with 2 images.
One for before adjustment and one for after.
It will have 25 controls corresponding to each matrix cell. Sliders? Up down? Or simply text boxes?
Text boxes maybe the easiest to implement.
And a button to update the matrix and process the image.

It will be a test fixture of sorts to see what effect each of the 25 floats has on the output image. I have to find out the range for those. I think it should probably be from -1.0 to +1.0, or maybe from 0 to 1.0? I will have to look into that first.

It seems that I have gone down the rabbit hole with this gdiplus stuff. So many new things for me.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 01:50:20 AM
Better use your own algorithm to change the Hue. Also, not sure what you plan to do, is it only to work with your game test or is it for general usage ?

If it is for other usages (Image or video processing), HSL is not the proper or best way to change colors. Better is you use CieLCH colorspace in order to achieve a precise color correspondence of the human vision. The only downside using CieLCH is that you needs to use cos functions, but, this also can be worked if you do your own algorithm (using tables as well, works fine) to retrieve the proper cosine angles. Siekmanski has nice algorithms to calculate fast and precise those trigonometric functions.

Keep in mind that, for Colorspaces like CieLCH or even Cielab (i don´t recommend this , btw) the Luma is, in fact, just a representation of greys. So, you can use an integer as input and output for those particular colorspaces. of course, you won´t find any of those grey correspondencies with luma on "normal" papers, but i can tell you by my own experience while trying to build such algorithms that Luma is nothing more, nothing less than a table of greys.

So, each table acts like a range (or bands if you prefer this name) for Hue and Chroma values. Plus, Hue and Chroma are also correlated to each other. So, for example, say that you are working with Luma whose intensity is around 155, this particular value has a defined and limited amount of variations of Hue/Chroma that are used in all of those refined colorspaces. Therefore, each luma, in fact, also corresponds to a particular range of Hue (that also has his own range of chroma). Ex:
Luma (Grey) = 155
Hue Range: 65.6897º to 77.5454º
Chroma: 221.45 to 321.69

You can normalize chroma and hue as well, as long you know which "band" they belongs to. So, at the end, you just create your own algo with the following inputs and outputs
Luma (Integer): from 0 to 255
Chroma (Percentage from 0 to 100% on each band of 255 grey values) = Or also you can normalize by integers as well, from 0 to 255
Hue (Percentage from 0 to 100% on each band of 255 grey values) = Or also you can normalize by integers as well, from 0 to 255

As long you save a table predefined those ranges for you retrieve the proper values, you are good to use.

The main confusion is when you change the band, and migrate from Luma 155 to another value, say...30. You have 2 options for your algorithm


of course, you can enhance a bit more depending on the profile you are using, on a way to distinguish a colorspace made for NTSC-RGB, ECT RGB, Ekta, Adobe etc etc
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 02:48:50 AM
To be honest guga, I only understand maybe 5% of all of that - well maybe a little bit more. Will this work for images with an alpha channel? I used the gdiplus functions since I knew that they did support 32 color ARGB (or is it RGBA) meaning 24 bit color plus alpha channel, plus I am learning how to use gdiplus in general these past couple of weeks.

I had known that Siekmanski had some tables, but honestly I thought those were for his direct draw or direct 3D stuff. I wasn't doing any graphics work back then so I didn't pay it much attention. I'll have to ring him up.  :tongue:

Thanks for the tips, more new things for me.

I was only experimenting with the posted code, just to see what the hue adjustment would look like. It is definitely not ready to go into any production code just yet. Just for my experimentation.  :smiley:

Oh strictly for use with images, no video. I already have too much to learn with just learning gdiplus.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 03:54:33 AM
Quote from: zedd151 on April 13, 2025, 02:48:50 AMTo be honest guga, I only understand maybe 5% of all of that - well maybe a little bit more. Will this work for images with an alpha channel? I used the gdiplus functions since I knew that they did support 32 color ARGB (or is it RGBA) meaning 24 bit color plus alpha channel, plus I am learning how to use gdiplus in general these past couple of weeks.

I had known that Siekmanski had some tables, but honestly I thought those were for his direct draw or direct 3D stuff. I wasn't doing any graphics work back then so I didn't pay it much attention. I'll have to ring him up.  :tongue:

Thanks for the tips, more new things for me.

I was only experimenting with the posted code, just to see what the hue adjustment would look like. It is definitely not ready to go into any production code just yet. Just for my experimentation.  :smiley:

Oh strictly for use with images, no video. I already have too much to learn with just learning gdiplus.

Hi Zedd

For alpha channels ? Yes, those works as well. Faster way is converting from RGBA to RGB and vice-versa, before passing the values onto those color spaces.On this way you will have the actual mix of colors (background + foreground used as a layer for the alpha channel) to use those spaces.

GDiPlus is really fun. I gave a try sometime ago. A bit hard at the beginning, but once you know what it is doing, you can make helpers to work with that easier. I made some functions like: GdipCreateBitmapFromBmpNfo, GdipSaveColorIndexedImage, GetPixelDataFromGdiImage etc. Some of them adapted from Siekmanski algorithms. For instance, to take the pixel from a gdi you can use:

;;
    GetPixelDataFromGdiImage
        This function copies a GDI+ bitmap image to memory, ensuring it is converted to a 32-bit ARGB format.

    Parameters:

        pGdiPlusImage(In): Pointer to the GDI+ image object.
        pImageMemory(Out): Pointer to a pImageMemory structure that will receive the bitmap data in memory.

    Return Values

        Returns &S_OK if the image is loaded successfully.
        Returns 0-1 if any error occurs.

    Remarks:
        The function converts the GDI+ image to a 32-bit ARGB format before copying the pixel data.
        It handles memory allocation and ensures the memory is freed if previously allocated.
        The function uses GdipBitmapLockBits and GdipBitmapUnlockBits for accessing the pixel data safely.
        In the context of this function, the PixelFormat and BitsPerPixel members of the returned pImageMemory structure will always
        return PIXELFORMAT_32BPPARGB and 32 bpps, respectivelly.
       
        The pImageMemory structure holds information about the bitmap in memory, including its dimensions, pixel format, and pixel data.
       
        It is defined as follows:

        [pImageMemory:
         pImageMemory.dwWidth: D$ 0
         pImageMemory.dwHeight: D$ 0
         pImageMemory.lpvBits: D$ 0
         pImageMemory.lpvBitsSize: D$ 0
         pImageMemory.PixelFormat: D$ 0
         pImageMemory.BitsPerPixel: D$ 0
         pImageMemory.Pitch: D$ 0]

        And the equates displacement are:
       
        [pImageMemory.dwWidthDis 0
         pImageMemory.dwHeightDis 4
         pImageMemory.lpvBitsDis 8
         pImageMemory.lpvBitsSizeDis 12
         pImageMemory.PixelFormatDis 16
         pImageMemory.BitsPerPixelDis 20
         pImageMemory.PitchDis 24]
       
        [Size_Of_pImageMemory 28]
         
         Members:
            dwWidth: The width of the bitmap in pixels.
            dwHeight: The height of the bitmap in pixels.
            lpvBits: Pointer to the pixel data of the bitmap. The pixel data is displacaed on ARGB format
            lpvBitsSize: The total size of the pixel data in bytes.
            PixelFormat: The pixel format of the bitmap, typically PIXELFORMAT_32BPPARGB . But it can be any of the following equates:
                            PIXELFORMAT_UNDEFINED 0
                            PIXELFORMAT_1BPPINDEXED 030101
                            PIXELFORMAT_4BPPINDEXED 030402
                            PIXELFORMAT_8BPPINDEXED 030803
                            PIXELFORMAT_16BPPGRAYSCALE 0101004
                            PIXELFORMAT_16BPPRGB555 021005
                            PIXELFORMAT_16BPPRGB565 021006
                            PIXELFORMAT_16BPPARGB1555 061007
                            PIXELFORMAT_24BPPRGB 021808
                            PIXELFORMAT_32BPPRGB 022009
                            PIXELFORMAT_32BPPARGB 026200A
                            PIXELFORMAT_32BPPPARGB 0E200B
                            PIXELFORMAT_48BPPRGB 010300C
                            PIXELFORMAT_64BPPARGB 034400D
                            PIXELFORMAT_64BPPPARGB 01A400E
            BitsPerPixel: The number of bits per pixel, usually 32 for ARGB format.
            Pitch: The number of bytes per scan line, also known as stride.

    See Also:
        SetGdiImageFromPixelData

References:
    https://museum2020.it-berater.org/index.php?topic=1866.0
    https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_ImageGetPixelFormat.htm
    https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/gdiplus/-gdiplus-constant-image-pixel-format-constants.md
    see GetPixelDataFromGdiImage from DBScanTest10a.exe
;;


[pImageMemory.dwWidthDis 0
 pImageMemory.dwHeightDis 4
 pImageMemory.lpvBitsDis 8
 pImageMemory.lpvBitsSizeDis 12
 pImageMemory.PixelFormatDis 16
 pImageMemory.BitsPerPixelDis 20
 pImageMemory.PitchDis 24]

[Size_Of_pImageMemory 28]

Proc GetPixelDataFromGdiImage::
    Arguments @pGdiPlusImage, @pImageMemory
    Local @TmpMem, @ImagePixelFormat, @ImgSize, @ReturnValue
    Structure @GDIPLUSBITMAPDATA 24, @GDIPLUSBITMAPDATA.dwWidthDis 0, @GDIPLUSBITMAPDATA.dwHeightDis 4, @GDIPLUSBITMAPDATA.StrideDis 8,
                                     @GDIPLUSBITMAPDATA.PixelFormatDis 12, @GDIPLUSBITMAPDATA.Scan0Dis 16, @GDIPLUSBITMAPDATA.ReservedDis 20
    Uses edi, ecx, edx

    mov D@ReturnValue 0-1

    call 'RosMem.ZeroMemory' D@GDIPLUSBITMAPDATA, Size_Of_GDIPLUSBITMAPDATA
    ; Always to be converted to 32 bit ARGB format!
    call 'gdiplus.GdipBitmapLockBits' D@pGdiPlusImage, &NULL, IMAGELOCK_MODE_READ, PIXELFORMAT_32BPPARGB, D@GDIPLUSBITMAPDATA;GDIplusBitmapData
    .If eax = &S_OK
        ; Gather some BitMap info from the original bitmap image
        mov edi D@pImageMemory
        mov D$edi+pImageMemory.BitsPerPixelDis 32
        mov D$edi+pImageMemory.PixelFormatDis PIXELFORMAT_32BPPARGB
        mov eax D@GDIPLUSBITMAPDATA.dwWidthDis | mov D$edi+pImageMemory.dwWidthDis eax
        mov eax D@GDIPLUSBITMAPDATA.dwHeightDis | mov D$edi+pImageMemory.dwHeightDis eax

        ; get the lenght of the bitmap data in bytes
        imul eax D@GDIPLUSBITMAPDATA.StrideDis | mov D$edi+pImageMemory.lpvBitsSizeDis eax | mov D@ImgSize eax
        mov eax D@GDIPLUSBITMAPDATA.StrideDis | mov D$edi+pImageMemory.PitchDis eax

        If D$edi+pImageMemory.lpvBitsDis <> 0
            call 'RosMem.VMemFree' D$edi+pImageMemory.lpvBitsDis
            mov D$edi+pImageMemory.lpvBitsDis 0
        End_If

        lea eax D@TmpMem
        call 'RosMem.VMemAlloc' eax, D@ImgSize
        If eax <> 0
            mov D$edi+pImageMemory.lpvBitsDis eax
            call 'RosMem.FastMemcpy' eax, D@GDIPLUSBITMAPDATA.Scan0Dis, D@ImgSize
        End_If
        call 'gdiplus.GdipBitmapUnlockBits' D@pGdiPlusImage, D@GDIPLUSBITMAPDATA
        call 'gdiplus.GdipDisposeImage' D@pGdiPlusImage
        mov D@ReturnValue &S_OK
    .End_If

    mov eax D@ReturnValue

EndP

If you need to load the images from the resource section of a PE you can use:


;;
    GdipLoadImageFromResource
        Load an image from the resource section of a file. It can load cursors, icons, gif, bitmap, png, jpg, webp, tiff.

    Parameters

    [in, optional] hModule: A handle to the module whose portable executable file or an accompanying MUI file contains the resource.
                            If this parameter is NULL, the function searches the module used to create the current process.
    [in] lpName: The name of the resource. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID
                 is the integer identifier of the resource. For more information, see the Remarks section below.
    [in] lpType: The resource type. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is
                 the integer identifier of the given resource type.
                 For standard resource types, the following equates are allowed:
                    RT_CURSOR           Hardware-dependent cursor resource.
                    RT_BITMAP           Bitmap resource.
                    RT_ICON             Hardware-dependent icon resource.
                    RT_RCDATA           Application-defined resource (raw data).
                    RT_NEWBITMAP        Another Bitmap Resource (older version)

    [out] pGdiPlusImage: A pointer to a variable that will hold the GdiImage plus object

    Return value
        If the function succeeds, it returns &S_OK
        If the function fails, it returns 0-1.
       
        To get extended error information, call GetLastError.

    Remarks:
            The RT_RCDATA windows type can be used to load gif, png, webp and any other image format needed.
    References:
        https://developers.google.com/speed/webp/docs/api
        https://github.com/webmproject/webp-wic-codec/tree/main
        https://chromium.googlesource.com/webm/webp-wic-codec/+/cc19e37b6ca673e750610785707261ebc8e2a0a3/src/libwebp/webp/decode.h
        https://stackoverflow.com/questions/72687289/getting-actual-frame-from-animated-webp-using-cwebp-libwebp
        https://cpp.hotexamples.com/examples/-/-/WebPDecodeBGRA/cpp-webpdecodebgra-function-examples.html
        https://www.google.com/search?client=firefox-b-d&q=animated+webp#ip=1
        https://ezgif.com/webp-maker
        https://groups.google.com/a/webmproject.org/g/webp-discuss/c/39WSf2zRxz0
        https://colinbendell.github.io/webperf/animated-gif-decode/webp.html
        https://www.reddit.com/r/photoshop/comments/17cat1l/saving_out_animated_webp_files/?rdt=40758
        https://resource.dopus.com/t/animated-webp-image-format-support/35777
        https://groups.google.com/a/webmproject.org/g/webp-discuss/c/x1KhpfpMk0M
        https://developers.google.com/speed/webp/docs/webpmux
        https://stackoverflow.com/questions/45190469/how-to-identify-whether-webp-image-is-static-or-animated
        https://developers.google.com/speed/webp/docs/riff_container
       
        license of webp
        https://www.webmproject.org/license/software/
;;

Proc GdipLoadImageFromResource::
    Arguments @hModule, @lpName, @lpType, @pGdiPlusImage
    Local @hRsrc, @ImageSize, @ImagePointer, @hLibwebp, @hWebPDecodeBGRA, @pImgWidth, @pImgHeight
    Uses esi, ecx, edx

    .If_And D@lpType >= &RT_MENU, D@lpType <= &RT_MANIFEST
        If_Or D@lpType = &RT_RCDATA, D@lpType = 13, D@lpType = 15, D@lpType = 18, D@lpType = &RT_NEWBITMAP
        ELse
            mov eax 0-1 | ExitP
        End_If
    .Else_if_Or D@lpType = &RT_DLGINIT, D@lpType = &RT_TOOLBAR, D@lpType = &RT_NEWRESOURCE, D@lpType = &RT_NEWMENU, D@lpType = &RT_NEWDIALOG, D@lpType = &RT_ERROR
        mov eax 0-1 | ExitP
    .End_If

    call 'kernel32.FindResourceA' D@hModule, D@lpName, D@lpType
    .If eax <> 0
        ; Found a possible valid resource. Let´ check if it is a webp file. before we try to stream it
        ; Get the data pointer and the data size from the resource Image data
        mov D@hRsrc eax
        call 'kernel32.SizeofResource' &NULL, eax
        mov D@ImageSize eax
        call 'kernel32.LoadResource' &NULL, D@hRsrc
        call 'kernel32.LockResource' eax
        mov D@ImagePointer eax
        If_And D$eax+RIFFCHUNK_WEBP_FORMAT.chunkIDDis = 'RIFF', D$eax+RIFFCHUNK_WEBP_FORMAT.FormatDis = 'WEBP'
            call GdipDecodeWebp D@ImagePointer, D@ImageSize, D@pGdiPlusImage
        Else
            call GdipStreamImageFromMemory D@ImagePointer, D@ImageSize, D@pGdiPlusImage
        End_If
    .Else
        mov eax 0-1
    .End_If

EndP


;;
    GdipDecodeWebp decodes a WebP image from memory and creates a GDI+ Bitmap object from the decoded pixel data.
   
    Parameters:
        ImagePointer(in): A pointer to the memory buffer containing the WebP image data.
        ImageSize(in): The size of the WebP image data in bytes.
        pGdiPlusImage(out): A pointer to the GDI+ Bitmap object created from the decoded WebP image.

    Return Value:
        Success: Returns 0 (&S_OK) if the WebP image was successfully decoded and the GDI+ Bitmap object was created.
        Failure: Returns -1 if there was an error loading the libwebp library, retrieving the WebPDecodeBGRA function, or decoding the WebP image.

    Remarks:
        Dependency: This function depends on libwebp.dll to decode the WebP image. So, make sure you have the proper dll on your system
                    or in the working directory of your app.
        Memory Management: The decoded pixel data from the WebP image is managed by the GDI+ Bitmap object created by GdipCreateScanImageFromMemory.
                           Do not free the pixel data manually; it will be handled by GDI+.
        Error Handling: Ensure proper error handling in case the libwebp library fails to load, the WebPDecodeBGRA function
                        is not found, or the WebP image fails to decode.
        Thread Safety: Ensure that the function is called in a thread-safe manner if used in a multi-threaded environment.   
   
    Function Internals: The function performs the following steps:
                        Loads the libwebp.dll library.
                        Retrieves the WebPDecodeBGRA function from the libwebp library.
                        Decodes the WebP image data using WebPDecodeBGRA.
                        Creates a GDI+ Bitmap object from the decoded pixel data using GdipCreateScanImageFromMemory.
                        Frees the libwebp library.
                        Returns the status of the operation.

    Example of usage:
        1 - Ensure the libwebp.dll is available in your application's directory or in a location that can be found by the application.
        2 - Prepare the WebP image data in memory.
        3 - Call GdipDecodeWebp with appropriate parameters.
       
        RosAsm Syntax:
       
        [pGdiPlusImage: D$ 0]
       
            lea ecx D@FileSize
            lea eax D@pFileData
            call 'FastCRT.ReadOpenedFile' &NULL, D@pFilename, eax, ecx, 0
            .If eax = &TRUE
                call 'FastCRT.GdipDecodeWebp' D@pFileData, D@FileSize, pGdiPlusImage
                If eax <> &S_OK
                    mov D@ReturnValue 0-1
                End_If
                call 'RosMem.VMemFree' D@pFileData ; we ca now safely release the allocated data
                mov eax D@ReturnValue

;;

Proc GdipDecodeWebp::
    Arguments @ImagePointer, @ImageSize, @pGdiPlusImage
    Local @hLibwebp, @hWebPDecodeBGRA, @pImgWidth, @pImgHeight, @ReturnValue
    Uses ecx, edx

    call 'KERNEL32.LoadLibraryA' {B$ "libwebp.dll", 0}
    If eax = 0
        mov eax 0-1 | ExitP
    End_If
    mov D@hLibwebp eax
    call 'KERNEL32.GetProcAddress' eax, {B$ 'WebPDecodeBGRA', 0} | mov D@hWebPDecodeBGRA eax
    If eax = 0
        call 'KERNEL32.FreeLibrary' D@hLibwebp
        mov eax 0-1
        ExitP
    End_If
    lea eax D@pImgWidth | mov D$eax 0
    lea ecx D@pImgHeight | mov D$ecx 0
    C_call D@hWebPDecodeBGRA D@ImagePointer, D@ImageSize, eax, ecx
    If eax <> 0
        ; The format of he pixels in webp are in RGBQUAD (same as BGRA)
        ; The data pixels at eax from webp image will be attached to the pixels object thereforem can´t be freed
        call GdipCreateScanImageFromMemory eax, D@pImgWidth, D@pImgHeight, D@pGdiPlusImage, PIXELFORMAT_32BPPARGB
        mov D@ReturnValue eax
    Else
        mov D@ReturnValue 0-1
    End_If
    call 'KERNEL32.FreeLibrary' D@hLibwebp
    mov eax D@ReturnValue

EndP



Proc GdipStreamImageFromMemory::
    Arguments @ImagePointer, @ImageSize, @pGdiPlusImage
    Local @ReturnMessage, @TmpMem, @ImageBuffer, @pStream
    Uses ecx, edx

    ; Default to failure and validate input parameters
    mov eax 0-1
    If_Or D@ImagePointer = 0, D@ImageSize = 0, D@pGdiPlusImage = 0
        ExitP
    End_If

    mov D@ReturnMessage eax

    ; Try allocating memory using VMemAlloc
    lea eax D@TmpMem
    call 'RosMem.VMemAlloc' eax, D@ImageSize
    ...If eax <> &NULL
        mov D@ImageBuffer eax
        call 'RosMem.FastMemcpy' D@ImageBuffer, D@ImagePointer, D@ImageSize
        call 'shlwapi.SHCreateMemStream' D@ImageBuffer, D@ImageSize
        .If eax <> &NULL
            mov D@pStream eax
            call 'gdiplus.GdipCreateBitmapFromStream' D@pStream, D@pGdiPlusImage
            mov D@ReturnMessage eax
            ; Release the stream
            If D@pStream <> 0
                call IStream_Release D@pStream
            End_If
        .End_If
        ; Free the allocated memory
        call 'RosMem.VMemFree' D@ImageBuffer
    ...Else
        ; cannot allocate memory, try with GloballAlloc Method. Fallback to GlobalAlloc if VMemAlloc fails
        call 'kernel32.GlobalAlloc' &GMEM_FIXED__&GMEM_ZEROINIT, D@ImageSize ; allocate memory for the stream
        ..If eax <> &NULL
            mov D@ImageBuffer eax
            call 'RosMem.FastMemcpy' D@ImageBuffer, D@ImagePointer, D@ImageSize
            lea eax D@pStream | mov D@pStream &NULL ; must be zero before creating a new stream
            call 'ole32.CreateStreamOnHGlobal' D@ImageBuffer, &TRUE, eax ; TRUE -> hGlobal will be released by IStream_Release
            .If eax = &S_OK
                call 'gdiplus.GdipCreateBitmapFromStream' D@pStream, D@pGdiPlusImage
                mov D@ReturnMessage eax
            .Else
                call 'kernel32.GlobalFree' D@ImageBuffer
            .End_If
            ; Release the stream
            If D@pStream <> 0
                call IStream_Release D@pStream
            End_If
        ..End_If
    ...End_If
    mov eax D@ReturnMessage

EndP



Personally, i think that creating a predefined set of functions is way easier than having to hard code all over again. You can create some personalized set of functions to work with GDI+ on your projects.

Btw...about the Hue, i presume you are using HSL to RGB and vice-versa, right ? For buttons, or simple images, it works fine.

About Siekmanski tables, well, it works for a wide range of things, not only for Dx. His algorithms are fantastic btw.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 04:01:29 AM
Wow guga, thanks for all of the study/research material.  :thumbsup:
Yes, customized functions would be preferable by me as well, coding the same code line by line all the time gets tedious.

Thank you for your gdiplus code. That will come in handy pretty quickly I would imagine.

Thanks for the info regarding Siekmanskis tables as well. That will take a little more time to research and understand how and where they could be used.

I agree, gdiplus is hard to learn, but the rewards are substantial. A big improvement over only using gdi32 and others, especially when real partially transparent images are needed and not the phony transparency that TransparentBlt*  (yeah, I know that's not in gdi32, but you know what I mean) offers.

Later:Oh yeah msimg32* (I couldn't think of it earlier (for TransparentBlt)...
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 04:40:30 AM
If you want, i can send u the set of customized functions i created for working with Gdi+. On the forum, i guess i also posted examples a long time ago. Cannot post now other examples, because i lost one of my HDs 2 years ago, and some of the code and apps i used as backup was there. But, some of the sources are here yet. Also some that works with text effects (Really fun to learn working with text on gdi+). Let me know, and i´ll attach them here if needed
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 05:00:09 AM
Quote from: guga on April 13, 2025, 04:40:30 AMLet me know, and i´ll attach them here if needed
If you can , it would be greatly appreciated. :azn:  Other members will probably appreciate it too.(Many members are most likely interested in gdiplus, that don't already use it).  :thumbsup:  Or even links to the posts where some it was used in the past.  :smiley:

Is it RosAsm code, or masm?
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 05:02:00 AM
OK, Zedd, this is just for you:
I just finished a li'l GDI+ testbed that lets you play with color changes, plus it shows us some basic things about using GDI+ in general. Package attached here.

You can load any image file and do one of 3 color transformations:
Play around with it and see what happens.

I learned a lot about GDI+ coding this.
One thing I already knew, of course, was how piss-poor the available documentation for this API is. (I'm talking specifically about the GDI+ flat model here, which is what we assembler programmers use.)
There is a lot of documentation available; one particularly good resource is Jose Roca's GDI+ flat API reference (http://www.jose.it-berater.org/gdiplus/iframe/index.htm). He's basically assembled the info from the Microsoft help app and made it accessible.
Problem is, that app has wrong information, and he hasn't bothered to correct it.
I'll go into those details later.
Also, our MASM32 package has some support for this API. Most importantly we have (I think) all of the PROTOs and library entries for the hundreds of functions. Plus we have some (but not all) of the needed structures.

In this app here's what I've done:
o Open and display the original image file with GDI+ (we already know how to do this)
o For the new, modified image:
  o Get the "pixel format" of the original image which we'll need later:
    INVOKE    GdipGetImagePixelFormat, OriginalBitmapHandle, ADDR pixelFormat
  o Make a copy of the original image:
    INVOKE    GdipCloneImage, OriginalBitmapHandle, ADDR newBitmapPtr
  o ; Lock the new image bits so we can play with them:
    INVOKE    GdipBitmapLockBits, NewBitmapHandle, ADDR gdiRect, ImageLockModeRead or ImageLockModeWrite,
            pixelFormat, ADDR gdiBmpData
  o Allocate a buffer for the bitmap bits, using the size of the image
  o Copy the bits from the bitmap to our buffer, using data from the GDI+ Bitmap structure, which gives us a pointer to those bits
  o Manipulate the bits to change the color (see below)
  o Copy the bits back to the bitmap from the buffer
  o Unlock the new bitmap:
    INVOKE    GdipBitmapUnlockBits, NewBitmapHandle, ADDR gdiBmpData
  o Display the new, modified image (we already know how to do that)

Phew.
One important thing I learned about GDI+:
"Images" and "bitmaps" can be treated as if they're the same.
Except when they aren't.


But I didn't find any cases yet where this wasn't true. You'll notice that I mixed and matched Image and Bitmap functions here.

I'll have much more to say on this subject in the coming days.

Regarding the color manipulation I did, here's the code for all three of the cases (swapping colors in a pixel):
;====================================
; Modify the buffer bits by swapping
; colors:
;====================================
    PUSH    EBX
    MOV    ECX, bitmapSize
    SHR    ECX, 2                ;/4 for DWORDS.
    MOV    EBX, bitmapHeap

modify:    PUSH    ECX
    MOV    EAX, [EBX]            ;Get next pixel.
    MOV    ECX, EAX            ;Make a copy of it.
    MOV    EDX, EAX            ;Make another copy.

    CMP    swap, $BGswap
    JE    doBG
    CMP    swap, $RGswap
    JE    doRG

; R<-->B swap:
doRB:    AND    ECX, 0FF0000h            ;Get R value.
    SHR    ECX, 16                ;Get it into low byte.
    MOV    AL, CL                ;Put R into B.
    AND    EDX, 0FFh            ;Isolate B.
    SHL    EDX, 16
    AND    EAX, 0FF00FFFFh            ;Zero out B in pixel.
    OR    EAX, EDX            ;Put B into R.
    JMP    SHORT putpix

; R<-->G swap:
doRG:    AND    ECX, 0FF00h            ;Get G value.
    SHL    ECX, 8                ;Get it into where R goes.
    MOV    EDX, EAX            ;Make another copy.
    AND    EDX, 0FF0000h            ;Get R.
    SHR    EDX, 8                ;Get it into where G goes.
    AND    EAX, 0FF0000FFh            ;Zero out R & G.
    OR    EAX, ECX            ;Put G into R.
    OR    EAX, EDX            ;Put R into G.
    JMP    SHORT putpix

; B<-->G swap:
doBG:    AND    ECX, 0FFh            ;Get B.
    SHL    ECX, 8                ;Put B where G goes.
    AND    EDX, 0FF00h            ;Get G.
    SHR    EDX, 8                ;Put G where B goes.
    AND    EAX, 0FFFF0000h            ;Zero out B & G.
    OR    EAX, ECX            ;Put B into G.
    OR    EAX, EDX            ;Put G into B.

putpix:    MOV    [EBX], EAX            ;Put modified pixel back in buffer.
skip:    ADD    EBX, SIZEOF DWORD
    POP    ECX
    LOOP    modify
    POP    EBX
Pretty basic stuff.
Of course, there are a lot more things you can do here.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 05:05:43 AM
Hi Zedd

Here goes :) Attached my predefined set of GDI+ functions, also some others for bitmap manipulation and some image effects. Added as well, the SSE2 macros set used for better understanding.

There are still needing some other helper/customized functions for gdi+ and image manipulation, but i didn´t finished those yet.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 05:08:27 AM
@Guga: That's nice, and thanks.
But one thing: could you please, please post stuff in MASM, not that kinda strange dialect of your assembler? Takes quite a bit of translation to use it otherwise.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 05:11:35 AM
Well gee, David. Now I am starting to get overwelmed.  :tongue:

Quote from: NoCforMe on April 13, 2025, 05:02:00 AMOne thing I already knew, of course, was how piss-poor the available documentation for this API is. (I'm talking specifically about the GDI+ flat model here, which is what we assembler programmers use.)
Isn't that the truth...

Quote from: NoCforMeOne important thing I learned about GDI+:
"Images" and "bitmaps" can be treated as if they're the same.
Except when they aren't.

But I didn't find any cases yet where this wasn't true. You'll notice that I mixed and matched Image and Bitmap functions here
I am used to that. Usually when dealing with gdiplus, I stay away from functions that have "Bitmap" in their name. Its fine if a .png has only 24 bit color and no alpha channel (a lot of code here on the forum is like that, only using .png because the filesize is smaller than 24 bit .bmp's), but not so for 32 bit images with alpha channel from the few instances I have seen.

And thanks for your contribution to the body of gdiplus code on the forum.  :thumbsup:
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 05:17:14 AM
Btw about the links on the forum, here are some:

Demuxing Webp (https://masm32.com/board/index.php?topic=12105.msg132521#msg132521)
BlendPixels (https://masm32.com/board/index.php?topic=12097.msg132426#msg132426)
Gdi+ Examples (https://masm32.com/board/index.php?topic=12084.msg132230#msg132230)
DBScan and image homogeneity - I really needs to finish those eventually (https://masm32.com/board/index.php?topic=11919.0)
FAst median algorithms discussions (https://masm32.com/board/index.php?topic=8671.150)
libwebpdemux (https://masm32.com/board/index.php?topic=12105.msg132521#msg132521)
Gdi+ Gif Animation Test  (https://masm32.com/board/index.php?topic=8917.msg97377#msg97377)
Icons and GDIPlus  (https://masm32.com/board/index.php?topic=8849.msg96583#msg96583)
Rainbow text with GdipDrawString issue (https://masm32.com/board/index.php?topic=8963.0)
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 05:21:30 AM
@ guga, It will take me some time to 'masm32ize' your code.

@ NoCforMe, attach an image where your proggy actually worked on. I am having some issues with it here, with various images/bitmaps.

Better yet, what format and bitness is the program expecting? That might help clarify...
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 05:23:31 AM
Quote from: NoCforMe on April 13, 2025, 05:08:27 AM@Guga: That's nice, and thanks.
But one thing: could you please, please post stuff in MASM, not that kinda strange dialect of your assembler? Takes quite a bit of translation to use it otherwise.

Hi David. You´re welcome  :thumbsup:

About masm, i´m sorry, i don´t code for masm in years, it's hard for me to remember the syntax on a way i could create or port the RosAsm syntax to masm a bit faster. But, i´ll try later to create a kind of translator from RosAsm code to Masm. The syntax is not that hard, at all, really. The problem is time for me to try to create some basic translator and force my memory to remember the proper masm syntax to be ported/converted.

Btw, if i remember, JJ started some simple translator from RosAsm (when using RosAsm macros set) to Masm sometime ago.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 05:28:25 AM
Nice, @Guga; we need a lot more stuff like that here.
I started a new thread about all this. (https://masm32.com/board/index.php?topic=12696.0)
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 05:36:06 AM
Quote from: zedd151 on April 13, 2025, 05:21:30 AM@ NoCforMe, attach an image where your proggy actually worked on. I am having some issues with it here, with various images/bitmaps.

Better yet, what format and bitness is the program expecting? That might help clarify...
original 24 bit bitmap (zipped)  color red = 00FF0000h
redd bitmap.zip

result convert red to blue
untitled.PNG

Similar results on 16 bit bitmaps
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 05:39:19 AM
Quote from: zedd151 on April 13, 2025, 05:21:30 AM@ NoCforMe, attach an image where your proggy actually worked on. I am having some issues with it here, with various images/bitmaps.

screenshot.jpg

QuoteBetter yet, what format and bitness is the program expecting? That might help clarify...

That might be a problem: I guess I'm ASS-U-Ming the image is 24 or 32 bits/pixel, so might not work with other bitnesses.

Something else I learned: when I got the Bitmap structure for my image, one of the elements is the PixelFormat.
Running in the debugger, I saw that this value was 26200A hex, or 2498570 decimal. WTF???
Turned out that this was the correct value. From the GDI+ enumeration
PixelFormat1bppIndexed EQU 196865
PixelFormat4bppIndexed EQU 197634
PixelFormat8bppIndexed EQU 198659
PixelFormat16bppGrayScale EQU 1052676
PixelFormat16bppRGB555 EQU 135173
PixelFormat16bppRGB565 EQU 135174
PixelFormat16bppARGB1555 EQU 397319
PixelFormat24bppRGB EQU 137224
PixelFormat32bppRGB EQU 139273
PixelFormat32bppARGB EQU 2498570
PixelFormat32bppPARGB EQU 925707
PixelFormat48bppRGB EQU 1060876
PixelFormat64bppARGB EQU 3424269
PixelFormat64bppPARGB EQU 29622286
PixelFormatMax EQU 15

It turns out that the format was 32 bpp ARGB, which is what your red pill image is.

So you can use this value to determine the bitness of your image, something you'd obviously need to do to correctly process it.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 05:44:57 AM
Quote from: NoCforMe on April 13, 2025, 05:39:19 AMIt turns out that the format was 32 bpp ARGB, which is what your red pill image is.
:thumbsup:

I only tested it with bitmaps. :rolleyes:
Works a charm with 32 bit .pngs
(https://i.postimg.cc/65Z2ZW5Z/untitled.png)

I am definitely going to look at this code. A lot better/easier than dealing with the floating point matrix.

Is it ARGB or RGBA? I have seen both used, and that is confusing. I have been saying RGBA in several places lately.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 06:00:34 AM
Quote from: NoCforMe on April 13, 2025, 05:39:19 AM
Quote from: zedd151 on April 13, 2025, 05:21:30 AM@ NoCforMe, attach an image where your proggy actually worked on. I am having some issues with it here, with various images/bitmaps.

screenshot.jpg

QuoteBetter yet, what format and bitness is the program expecting? That might help clarify...

That might be a problem: I guess I'm ASS-U-Ming the image is 24 or 32 bits/pixel, so might not work with other bitnesses.

Something else I learned: when I got the Bitmap structure for my image, one of the elements is the PixelFormat.
Running in the debugger, I saw that this value was 26200A hex, or 2498570 decimal. WTF???
Turned out that this was the correct value. From the GDI+ enumeration
PixelFormat1bppIndexed EQU 196865
PixelFormat4bppIndexed EQU 197634
PixelFormat8bppIndexed EQU 198659
PixelFormat16bppGrayScale EQU 1052676
PixelFormat16bppRGB555 EQU 135173
PixelFormat16bppRGB565 EQU 135174
PixelFormat16bppARGB1555 EQU 397319
PixelFormat24bppRGB EQU 137224
PixelFormat32bppRGB EQU 139273
PixelFormat32bppARGB EQU 2498570
PixelFormat32bppPARGB EQU 925707
PixelFormat48bppRGB EQU 1060876
PixelFormat64bppARGB EQU 3424269
PixelFormat64bppPARGB EQU 29622286
PixelFormatMax EQU 15

It turns out that the format was 32 bpp ARGB, which is what your red pill image is.

So you can use this value to determine the bitness of your image, something you'd obviously need to do to correctly process it.

Yep, those are the correct values (in decimal). I posted those in one of the sources (In hex, however inside a multiline comment i did while i was creating the functions).


; --- In binary representation

       PIXELFORMAT_INDEXED                    00__0000_0001__0000_0000__0000_0000
        PIXELFORMAT_GDI                        00__0000_0010__0000_0000__0000_0000
        PIXELFORMAT_ALPHA                      00__0000_0100__0000_0000__0000_0000
        PIXELFORMAT_PALPHA                     00__0000_1000__0000_0000__0000_0000
        PIXELFORMAT_EXTENDED                   00__0001_0000__0000_0000__0000_0000
        PIXELFORMAT_CANONICAL                  00__0010_0000__0000_0000__0000_0000

; ------ Hex + Binary representation

        PIXELFORMAT_1BPPINDEXED 030101         00__0000_0011__0000_0001__0000_0001 ; PIXELFORMAT_INDEXED+PIXELFORMAT_GDI
        PIXELFORMAT_4BPPINDEXED 030402         00__0000_0011__0000_0100__0000_0010 ; PIXELFORMAT_INDEXED+PIXELFORMAT_GDI
        PIXELFORMAT_8BPPINDEXED 030803         00__0000_0011__0000_1000__0000_0011 ; PIXELFORMAT_INDEXED+PIXELFORMAT_GDI
        PIXELFORMAT_16BPPGRAYSCALE 0101004     00__0001_0000__0001_0000__0000_0100 ; PIXELFORMAT_EXTENDED
        PIXELFORMAT_16BPPRGB555 021005         00__0000_0010__0001_0000__0000_0101 ; PIXELFORMAT_GDI
        PIXELFORMAT_16BPPRGB565 021006         00__0000_0010__0001_0000__0000_0110 ; PIXELFORMAT_GDI
        PIXELFORMAT_16BPPARGB1555 061007       00__0000_0110__0001_0000__0000_0111 ; PIXELFORMAT_GDI+PIXELFORMAT_ALPHA
        PIXELFORMAT_24BPPRGB 021808            00__0000_0010__0001_1000__0000_1000 ; PIXELFORMAT_GDI
        PIXELFORMAT_32BPPRGB 022009            00__0000_0010__0010_0000__0000_1001 ; PIXELFORMAT_GDI
        PIXELFORMAT_32BPPARGB 026200A          00__0010_0110__0010_0000__0000_1010 ; PIXELFORMAT_GDI+PIXELFORMAT_ALPHA+PIXELFORMAT_CANONICAL
        PIXELFORMAT_32BPPPARGB 0E200B          00__0000_1110__0010_0000__0000_1011 ; PIXELFORMAT_GDI+PIXELFORMAT_ALPHA+PIXELFORMAT_PALPHA
        PIXELFORMAT_48BPPRGB 010300C           00__0001_0000__0011_0000__0000_1100 ; PIXELFORMAT_EXTENDED
        PIXELFORMAT_64BPPARGB 034400D          00__0011_0100__0100_0000__0000_1101 ; PIXELFORMAT_ALPHA+PIXELFORMAT_EXTENDED+PIXELFORMAT_CANONICAL
        PIXELFORMAT_64BPPPARGB 01A400E         00__0001_1010__0100_0000__0000_1110 ; PIXELFORMAT_GDI+PIXELFORMAT_PALPHA+PIXELFORMAT_EXTENDED

        The equates are created like this (Decimal shifts and OR):

        PixelFormat1bppIndexed = (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI),
        PixelFormat4bppIndexed = (2 | ( 4 << 8) | PixelFormatIndexed | PixelFormatGDI),
        PixelFormat8bppIndexed = (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI),
        PixelFormat16bppRGB555 = (5 | (16 << 8) | PixelFormatGDI),   
        PixelFormat16bppRGB565 = (6 | (16 << 8) | PixelFormatGDI),   
        PixelFormat16bppARGB1555 = (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI), 
        PixelFormat24bppRGB = (8 | (24 << 8) | PixelFormatGDI),   
        PixelFormat32bppRGB = (9 | (32 << 8) | PixelFormatGDI),   
        PixelFormat32bppARGB = (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical),
        PixelFormat32bppPARGB = (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI),
        PixelFormat48bppRGB = (12 | (48 << 8) | PixelFormatExtended),   
        PixelFormat64bppARGB = (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended),
        PixelFormat64bppPARGB = (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended),
        PixelFormatMax = 15         
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 06:02:01 AM
Quote from: zedd151 on April 13, 2025, 05:44:57 AMI only tested it with bitmaps. :rolleyes:
Works a charm with 32 bit .pngs
A .png is a bitmap.
It'll work correctly with any 32 BPP image format.
QuoteIs it ARGB or RGBA? I have seen both used, and that is confusing.
I'd say ARGB, based on the memory layout of a pixel (I had to draw this for myself to keep things straight):

ARGB.gif
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 06:06:32 AM
Quote from: guga on April 13, 2025, 06:00:34 AM; ------ Hex + Binary representation

        PIXELFORMAT_1BPPINDEXED 030101        00__0000_0011__0000_0001__0000_0001 ; PIXELFORMAT_INDEXED+PIXELFORMAT_GDI
        PIXELFORMAT_4BPPINDEXED 030402        00__0000_0011__0000_0100__0000_0010 ; PIXELFORMAT_INDEXED+PIXELFORMAT_GDI
        PIXELFORMAT_8BPPINDEXED 030803        00__0000_0011__0000_1000__0000_0011 ; PIXELFORMAT_INDEXED+PIXELFORMAT_GDI
        PIXELFORMAT_16BPPGRAYSCALE 0101004    00__0001_0000__0001_0000__0000_0100 ; PIXELFORMAT_EXTENDED
        PIXELFORMAT_16BPPRGB555 021005        00__0000_0010__0001_0000__0000_0101 ; PIXELFORMAT_GDI
        PIXELFORMAT_16BPPRGB565 021006        00__0000_0010__0001_0000__0000_0110 ;
Guga, sorry to be kind of a pain in the ass about this, but those representations are just not useful for the majority of use who don't use RosAsm. Those numeric representations are just too weird. They may make sense to you, but are pretty useless to the rest of us.

Kind of like how JJ persistently posts code in MasmBasic which not all of us use ...
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 06:11:21 AM
@Zedd: Try the color swapper on any regular JPG picture; it works, but the change is usually very subtle, even hard to see.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 06:15:10 AM
Quote from: NoCforMe on April 13, 2025, 06:02:01 AM
Quote from: zedd151 on April 13, 2025, 05:44:57 AMI only tested it with bitmaps. :rolleyes:
Works a charm with 32 bit .pngs
A .png is a bitmap.
It'll work correctly with any 32 BPP image format.
QuoteIs it ARGB or RGBA? I have seen both used, and that is confusing.
I'd say ARGB, based on the memory layout of a pixel (I had to draw this for myself to keep things straight):

ARGB.gif
Fair enough. But during my research I kept seeing RGBA all over the place, so naturally that's what I thought was most proper.  :rolleyes:

In retrospect ARGB sounds more likely upon thinking about it.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 06:15:59 AM
Quote from: NoCforMe on April 13, 2025, 06:11:21 AM@Zedd: Try the color swapper on any regular JPG picture; it works, but the change is usually very subtle, even hard to see.
Okay, gimme about an hour. It's time to feed, then walk, the doggies.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 06:37:57 AM
Hi David

these are the ones inside the comments.

Hexadecimal in RosAsm can use the ending "h" or not. Hexadecimals are represented by 1 leading 0 ate the beginning. It also can contains separators "_" for better reading if needed. But, "x" is not allowed, since it is used for mathematical expressions.
Ex:
0123FA25D
can also written as:
0123FA25Dh - similar to masm syntax, i presume
0123F_A25Dh - similar to masm syntax, i presume (except for the separator)
0123F_A25D
0_123F_A25D
0_123F_A25Dh - similar to masm syntax, i presume (except for the separator)


Separators do nothing at all, unless make the numbers (or labels, variables names etc) better to read.

Decimals always starts from 0 to 9. So, not changes here for masm syntax

Binary always starts with 2 leading 0. Also may contains optional identification "b" and optional separator "_"

Ex:
The number 196865 (in decimal), can be represented in binary as:
00__0000_0011__0000_0001__0000_0001
00__0000_0011__0000_0001__0000_0001b
00000000110000000100000001b (less readable) - similar to masm syntax, i presume
00110000000100000001b (less readable) - similar to masm syntax, i presume
00000000110000000100000001 (less readable)
00110000000100000001 (less readable)

Personally, i prefer without the ending identificators and using separators "_" when is better to read.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 07:13:46 AM
Quote from: NoCforMe on April 13, 2025, 06:11:21 AM@Zedd: Try the color swapper on any regular JPG picture; it works, but the change is usually very subtle, even hard to see.

(https://i.postimg.cc/vZY4Npd2/untitled.png)
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 07:23:24 AM
OK, those artifacts are because I'm ASS-U-Ming a 32bpp image where it's actually 24bpp.
Smarter manipulation code would take care of this.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 07:25:27 AM
Quote from: guga on April 13, 2025, 06:37:57 AMHexadecimal in RosAsm can use the ending "h" or not. Hexadecimals are represented by 1 leading 0 ate the beginning. It also can contains separators "_" for better reading if needed. But, "x" is not allowed, since it is used for mathematical expressions.
Ex:
0123FA25D
can also written as:
0123FA25Dh - similar to masm syntax, i presume
0123F_A25Dh - similar to masm syntax, i presume (except for the separator)
0123F_A25D
0_123F_A25D
0_123F_A25Dh - similar to masm syntax, i presume (except for the separator)
Sorry, too weird for most of us here.
"Except for the separator": that's the problem.
I won't bother even trying to decipher or convert such representations.
Life's too short.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 07:27:41 AM
Quote from: NoCforMe on April 13, 2025, 07:23:24 AMOK, those artifacts are because I'm ASS-U-Ming a 32bpp image where it's actually 24bpp.
Ah, okay. So the present code only works for 32bpp... got it.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 07:35:55 AM
Quote from: zedd151 on April 13, 2025, 07:27:41 AM
Quote from: NoCforMe on April 13, 2025, 07:23:24 AMOK, those artifacts are because I'm ASS-U-Ming a 32bpp image where it's actually 24bpp.
Ah, okay. So the present code only works for 32bpp... got it.
Yes. Take a look at the pixel-changing code I posted.
It would take a lot more checking (on the bitmap format) and branching in that code to handle all those other formats.
Could be done, of course; I just wanted to throw together a small demo to show how it might work.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 07:38:40 AM
Quote from: NoCforMe on April 13, 2025, 07:35:55 AMIt would take a lot more checking (on the bitmap format) and branching in that code to handle all those other formats.
Could be done, of course; I just wanted to throw together a small demo to show how it might work.
No thats fine. I might even play with the code a bit,  at least to cover 24bpp even if it is a seperate program from the 32bpp version.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 07:56:10 AM
If you wanted to extend my program, you could look for the pixel format value of PixelFormat24bppRGB in the color-swapping code, and branch to a new section where you work on 24-bit pixels.

A little more complicated, as you'll need to read 3 bytes at a time, but still do-able. (You could use the same swapping code, just change the loop to read 3 bytes instead of a DWORD per pixel.)
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 07:58:54 AM
Quote from: NoCforMe on April 13, 2025, 07:56:10 AMIf you wanted to extend my program, you could look for the pixel format value of PixelFormat24bppRGB in the color-swapping code, and branch to a new section where you work on 24-bit pixels.

A little more complicated, as you'll need to read 3 bytes at a time, but still do-able. (You could use the same swapping code, just change the loop to read 3 bytes instead of a DWORD per pixel.)
That's what I had in mind. At least something similar.  :thumbsup:

Now if I can put all of this aside long enough to finish my frigging game (Connect 4), I'll be as happy as a clam.  :joking:

All of these different ways to work with graphics is kind of addicting, always wanting more tools for the toolbox.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 08:03:48 AM
Quote from: NoCforMe on April 13, 2025, 07:25:27 AM
Quote from: guga on April 13, 2025, 06:37:57 AMHexadecimal in RosAsm can use the ending "h" or not. Hexadecimals are represented by 1 leading 0 ate the beginning. It also can contains separators "_" for better reading if needed. But, "x" is not allowed, since it is used for mathematical expressions.
Ex:
0123FA25D
can also written as:
0123FA25Dh - similar to masm syntax, i presume
0123F_A25Dh - similar to masm syntax, i presume (except for the separator)
0123F_A25D
0_123F_A25D
0_123F_A25Dh - similar to masm syntax, i presume (except for the separator)
Sorry, too weird for most of us here.
"Except for the separator": that's the problem.
I won't bother even trying to decipher or convert such representations.
Life's too short.

I´ll try to write some basics translator in time. What´s the proper syntax for masm, then ? Only 0123FA25Dh, right ? Or there are other fixed tokens/syntax ?
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 08:21:01 AM
You only need the leading 0, if the first hex digit is A,B,C,D,E or F.
In your 0123FA25Dh
While it doesn't hurt to leave it there, normally it's not done like that.
Ought to be
123FA25Dh

Conversely:
ABCDEF01h would need the leading zero: 0ABCDEF01h else the assembler will assume it's a variable name even with the trailing h.




Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 08:43:40 AM
Quote from: guga on April 13, 2025, 08:03:48 AMWhat´s the proper syntax for masm, then ? Only 0123FA25Dh, right ?
Decimal: just like anywhere else. (No "d" required.)
Hex: XXXXXh (must put in a leading zero if the first digit is A-F)
Binary: XXXXXb

Symbolic constants:
name EQU value

Data declarations:
name, optional  DB/DW/DD/DQ value(s)

Structure definition:
name    STRUCT
data declaration
data declaration
data declaration
   . . .
name    ENDS

Structure declaration:

name, optional  struct name <value(s), optional>
(angle brackets at end required)

That's it.
MASM keywords are case-insensitive; names aren't, unless an option is set to make them so.

(hopefully my nomenclature is clear)
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 09:28:23 AM
@Zedd: try the attached new version. Handles 24bpp images correctly (like almost all JPGs). Code's a little more complicated, but not too much.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 09:34:25 AM
Tks guys. Good to know these diferences.

NoCForme, about
QuoteSymbolic constants:
name EQU value

Data declarations:
name, optional  DB/DW/DD/DQ value(s)

Yeah, i remember simlar of those in RosAsm when activating the Preparse Alternates. I never used, though.

Is these syntax more similar to Masm ? Those are the ones the current version of rosAsm can assemble:


mov  ecx  D[Counter]
mov  ecx  dWord [Counter]
mov  ecx  dWord Ptr [Counter]

mov  ecx  [Counter]
mov  ax  [Counter]
mov  [Counter]  bl

; Seems the same as your examples.
[TRUE  =  1,    FALSE  =  0]
[TRUE  EQU  1,    FALSE  EQU  0]

Also syntax with things like
Byte Ptr[Value]
Dword Ptr[Value]
Qword Ptr[Value]
etc are also allowed

What i never saw was the Struct token, but this can be implemented if needed. On this way, it would also be easier to create a sort of translator later.

I never used the alternates preparser so far. I personally don´t like it, but it may be needed by someone in the future, so once i succeed to finish the major updates i´ll try to focus on those alternatives syntaxes. Of course, i don´t plan to make RosAsm assemble all masm syntax (i.e.: all of the fixed tokens), specially because we don´t use things like directives, assume, .data, .code etc, but i guess it won´t hurt adding additional alternatives syntaxes a bit more compatible to masm. I´ll put those information you and Zedd did on the development area on the source, so i won´t forget about it on the future.

Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 09:54:29 AM
Quote from: guga on April 13, 2025, 09:34:25 AMIs these syntax more similar to Masm ?

mov  ecx  D[Counter]
mov  ecx  dWord [Counter]
mov  ecx  dWord Ptr [Counter]
You need a comma there:
mov  ecx, CounterNo "D[  ]" weirdness, either.
Quote; Seems the same as your examples.
[TRUE  =  1,    FALSE  =  0]
[TRUE  EQU  1,    FALSE  EQU  0]
Again, lose the square brackets, but yes:
you can use either the equal sign or EQU, although they have slightly different meanings (an EQU cannot be changed later)
QuoteAlso syntax with things like
Byte Ptr[Value]
Dword Ptr[Value]
Qword Ptr[Value]
etc are also allowed
Yes; those are modifiers, like
  MOV  ByteSizeVar, BYTE PTR [EDX]
  MOV  AL, BYTE PTR DwordSizeVar
Note no square brackets around that last one.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 09:59:31 AM
Quote from: NoCforMe on April 13, 2025, 09:28:23 AM@Zedd: try the attached new version. Handles 24bpp images correctly (like almost all JPGs). Code's a little more complicated, but not too much.
result
(https://i.postimg.cc/QM3CLw5W/untitled.png)

source jpg image
untitledb.JPG

It works fine for 24 bit bitmaps though.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 10:06:02 AM
Ack.
Could you post that image file so I can check it out?
I think I might know what the problem is. Was just thinking about it.
When processing bitmap images, you have to take into account this thing called stride, which is the distance between scan lines.
That's because some bitmaps have padding, since a scan line must begin on a DWORD boundary.
So depending on the bitmap size, lines may have padding.
I'm just going through the bitmap as if it's just a big linear array.
Wrong. The correct way to process a bitmap is line by line, treating it as a 2D array.
Just means you need an inner and an outer loop, where you move [stride] bytes from one line to the next.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 13, 2025, 10:07:19 AM
Quote from: NoCforMe on April 13, 2025, 10:06:02 AMAck.
Could you post that image file so I can check it out?
it is in above post. That file was saved with photoshop. right click and save image as...
For jpgs saved with mspaint, it works fine.  :thumbsup:
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 10:08:41 AM
Quote from: NoCforMe on April 13, 2025, 09:54:29 AM
Quote from: guga on April 13, 2025, 09:34:25 AMIs these syntax more similar to Masm ?

mov  ecx  D[Counter]
mov  ecx  dWord [Counter]
mov  ecx  dWord Ptr [Counter]
You need a comma there:
mov  ecx, CounterNo "D[  ]" weirdness, either.
Quote; Seems the same as your examples.
[TRUE  =  1,    FALSE  =  0]
[TRUE  EQU  1,    FALSE  EQU  0]
Again, lose the square brackets, but yes:
you can use either the equal sign or EQU, although they have slightly different meanings (an EQU cannot be changed later)
QuoteAlso syntax with things like
Byte Ptr[Value]
Dword Ptr[Value]
Qword Ptr[Value]
etc are also allowed
Yes; those are modifiers, like
  MOV  ByteSizeVar, BYTE PTR [EDX]


Oh, the commas are mandatory in masm then. Ok, the current version of RosAsm can also handle those commas (but they are not fixed, is optional to use - the internal parsers will simply skip those). But, currently, those can also be assembled as:

MOV  ByteSizeVar, BYTE PTR [EDX].

About removing the squared brackets, i´ll need a way to implement this. Or simply leave this to the translator. Currently, the brackets are made to distinguish the several different statements (Variables, equates, macros)

[TRUE  =  1,    FALSE  =  0]
[TRUE  EQU  1,    FALSE  EQU  0]

Can be written one on each bracket

[TRUE  =  1]
[FALSE  =  0]
[TRUE  EQU  1]
[FALSE  EQU  0]


But, on masm then we should use no brackets at all ? Just this ?

TRUE  =  1
FALSE  =  0
TRUE  EQU  1
FALSE  EQU  0

But., how the assembler will distinguish if they are data, equates, variables or code ? Or the absence of brackets in masm only works for equates ?
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 13, 2025, 10:20:22 AM
Quote from: guga on April 13, 2025, 10:08:41 AMBut, on masm then we should use no brackets at all ? Just this ?

TRUE  =  1
FALSE  =  0
TRUE  EQU  1
FALSE  EQU  0

Yep, that's it.

QuoteBut., how the assembler will distinguish if they are data, equates, variables or code ? Or the absence of brackets in masm only works for equates ?
They're neither code nor data, just symbolic constants, meaning they evaluate to a numeric value and can be used in place of numbers in statements.

The EQU operator does, however, have other uses: for example,
$CRLF            EQU <13, 10>

results in a sequence of two bytes if used in a DB statement, like so:

Message  DB "Halt! Who goes there?", $CRLF, 0

Then there are text macros. Let's don't even go there yet ...

I guess you could say that EQU and friends are all part of the preprocessor, like in C.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 13, 2025, 01:03:53 PM
Ok, tks, David :thumbsup:  :thumbsup:  :thumbsup:

I inserted the information you guys provided to the development part of the source.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 15, 2025, 02:44:28 AM
Hi guga, could you start a new topic for your rosasm to masm translation issues? When you were posting about it here, it kind of interrupted the flow of the conversation underway between NoCforMe and myself.

I am not asking that any posts be removed from here or deleted, but if you want to continue with your rosasm to masm syntax discussions I am asking very politley to please start a new topic and do not continue here, please.  :smiley:
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 15, 2025, 03:22:38 AM
Quote from: NoCforMe on April 13, 2025, 09:28:23 AM@Zedd: try the attached new version. Handles 24bpp images correctly (like almost all JPGs). Code's a little more complicated, but not too much.
Now back to the topic.

NoCforMe...

Why do you only have 3 choices to change hue. I think there should be six.

Red to Blue
Blue to Red

Red to Green
Green to Red

Blue to Green
Green to Blue

Also:
What I would (and might) do is use the same static to display the results and the source image.
Any changes the would be applied to the already processed image, after initially processing the source image.

If your methods are sound, changing from red to blue and back again, the result should match the source image or have the perception of being the same.

Anyway, these were some things I was thinking about. I don't have a lot of time for coding the next few days (6 acre property, only half finished with yard work), but when I do, I will explore doing what I had mentioned above.
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 15, 2025, 03:38:44 AM
Quote from: zedd151 on April 15, 2025, 03:22:38 AM
Quote from: NoCforMe on April 13, 2025, 09:28:23 AM@Zedd: try the attached new version. Handles 24bpp images correctly (like almost all JPGs). Code's a little more complicated, but not too much.
Now back to the topic.

NoCforMe...

Why do you only have 3 choices to change hue. I think there should be six.

Red to Blue
Blue to Red
No.
They're swaps; red<-->blue interchanges the two, so only 1 choice needed there.

There are, of course, lots of other ways you could mess with a bitmap.

If you do play with that testbed program, be sure to implement those inner and outer loops I mentioned earlier so you're processing the bitmap line-by-line. Otherwise, knock yourself out.
Just be sure to post any interesting results here.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 15, 2025, 03:47:46 AM
Quote from: NoCforMe on April 15, 2025, 03:38:44 AMJust be sure to post any interesting results here.

Absolutely! Even if they are not very interesting.

Quote from: NoCforMe on April 15, 2025, 03:38:44 AMThey're swaps; red<-->blue interchanges the two, so only 1 choice needed there.
I did not realize that, clicking the button again did nothing so I figured it was only a one way color shift. I have mainly been testing with images/bitmaps with only a few colors. I will look at it in more detail with many more colors in the same image to see for myself.
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 15, 2025, 10:35:34 AM
I did a quick test by using a blue image and clicking red<--->blue. Indeed it turned red.  :rolleyes:  I missed that "<--->" meant bidirectional.  :toothy:
Title: Re: Has anyone used gdiplus to change hue?
Post by: NoCforMe on April 15, 2025, 11:22:56 AM
Well, now maybe you can come up with your own wicked way of changing bitmap pixels around ...
I'm all out of ideas ATM.
Title: Re: Has anyone used gdiplus to change hue?
Post by: guga on April 15, 2025, 12:12:26 PM
Quote from: zedd151 on April 15, 2025, 02:44:28 AMHi guga, could you start a new topic for your rosasm to masm translation issues? When you were posting about it here, it kind of interrupted the flow of the conversation underway between NoCforMe and myself.

I am not asking that any posts be removed from here or deleted, but if you want to continue with your rosasm to masm syntax discussions I am asking very politley to please start a new topic and do not continue here, please.  :smiley:

Hi zedd

It wasn´t suppose to be a new topic, it was just a conversation on how to help since the code i sent was not easy to follow. But, another topic of a future translator, is not a bad idea. When i have time to start coding it, i´ll open a new topic asking for all major differences of masm tokens to be able to create the necessary translator. :thumbsup:
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 15, 2025, 03:08:19 PM
Quote from: guga on April 15, 2025, 12:12:26 PMBut, another topic of a future translator, is not a bad idea. When i have time to start coding it, i´ll open a new topic asking for all major differences of masm tokens to be able to create the necessary translator. :thumbsup:
I wish you the best of luck in your endeavors in creating that translator. If I can be of any assistance, let me know.  :thumbsup:
Title: Re: Has anyone used gdiplus to change hue?
Post by: zedd151 on April 15, 2025, 03:25:54 PM
Quote from: NoCforMe on April 15, 2025, 11:22:56 AMWell, now maybe you can come up with your own wicked way of changing bitmap pixels around ...
I'm all out of ideas ATM.
As soon as I get ample free time to experiment (which itself may take a considerable amount of time) with it, I have a few ideas to possibly make it even better than it is already. It really is a great little program as is, imo. It just needs some finishing touches,

And as always I myself have a few yet unfinished programs that I want to finish. So I really don't know when I will be able to get to really working on this. So many things need to get done, and so little time as usual.