Display secondary underlying image on a Imagelist? - delphi

I have a Image list assigned to a listview to display transparent images.
There is a slight issue with this regarding some transparent images that are added, and that is they are sometimes hard to see/find in the listview.
See this example image:
You will notice that the images (noticeably the mouse) is barely viewable, infact if a empty image was added you would not even see it, the number captions come to the rescue here to show there is something actually there.
But I would like to make the images visually easier to see. I thought maybe having another image underneath the transparent images would work - of course though it could not affect the actual image.
So with that in mind, I made a bitmap of a chessboard grid:
I feel this would be the most suitable way of representing transparent areas of the images just like Paint.NET etc does.
To further illustrate this example I have modified the original image to show how it would look, if we had the chessboard bitmap as the underlay image:
Having the chessboard there would indicate there is a list item there in the first place, and the bitmap of the chessboard grid could be darker or an altogether different kind of image. As I said earlier if there was no image you would see nothing at all, so better to show an empty chess grid or other bitmap than nothing.
So, how can I display a second image underneath the original images using a imagelist to give a result similar to the example above? The underneath image could be anything - just another loaded bitmap for example.

If you store the chessboard as the first image (with index 0) and make the overlay image from the current image in the OnGetImageIndex event handler, it will do what you want to. However I'm not sure how efficient is to make the overlay image every time the event is fired.
procedure TForm1.ListView1GetImageIndex(Sender: TObject; Item: TListItem);
begin
// make the overlay (with overlay index 1) from the
// image with index Item.Index + 1
ImageList1.Overlay(Item.Index + 1, 1);
// use the first image from the list as a background
Item.ImageIndex := 0;
// and assign just created overlay index for overlay
Item.OverlayIndex := 1;
end;

I seems that what you need is a TImageList with extra capabilities.
As a starting point, I suggests you to consider TImageListEx described in the book Inside Delphi 2006
Excerpt:
The TImageListEx component is a TImageList descendant that can use the
images from another image list to generate disabled images, which can
be used on toolbars and other user interface elements.
The TImageListEx component is a TImageList descendant that can use the
images from another image list to generate disabled images, which can
be used on toolbars and other user interface elements.
There are several benefits of the TImageListEx component:
It eliminates the need for creating disabled glyphs.
It eliminates the need for adding the disabled glyphs to an additional TImageList component at design time.
It can drastically reduce the size of the .dfm file and of the entire application, especially in large applications that use a lot of
glyphs.
It's extremely fast, taking only milliseconds to disable all images in an image list, even when there are number of images.
It's extremely lightweight. (If you add it to an application that already uses the standard TImageList component, it won't increase the
size of the executable at all, and if you add it to an application
that doesn't use the standard TImageList component, the overhead is
only 2 KB.)
It's far from your requirements but yet detailed enough to show how to extend TImageList.

Related

How to get a control that is underneath another control?

I am trying to create a basic map editor for fun which consists of a scrollbox and paintbox (to draw the grid).
In the OnMouseDown event for the paintbox I create images at runtime and add them inside the scrollbox, the grid paintbox is painted above the images ( because if the grid was at the back it just would not look good ).
Here is a sample screen:
My question would solve two of my problems in one.
I need to be able to drag and drop (to move) the images around at runtime.
I also need to be able to get the X and Y position of the image to display as information.
Here is where my problem lies, to solve the problems above I first need to get the Image under the mouse cursor. But because I paint my grid (paintbox) above the images, the cursor will only ever 'see' the paintbox grid, and not the underlying images.
I did experiment with copying the paintbox grid to a TImage but it came out all wrong and I was getting out of memory errors. The size of the maps could be quite large and so putting the grid onto a bitmap is not ideal due the memory and limitations etc.
The grid must go on the top, otherwise it would look something like this:
Which hides the grid, and I don't want that to happen.
So, how can I see past the paintbox and get to the images underneath, using FindVCLWindow or something similar?
Set the Enabled property of the PaintBox to False. That will let the mouse messages go through.
Further:
In the OnMouseDown event for the PaintBox I create images at runtime and add them inside the scrollbox
Change that to the OnMouseDown event on the ScrollBox. Adjust the coordinates by ScrollBox.[Horz/Vert]Scrollbar.Position.

Fill background by tiling with bitmap

In my FMX Application I have to fill the entire background area of my form using a Bitmap pattern.
The reason why I'm thinking to use this pattern is because the form is freely resizable by the user and whether I set a fixed image the stretch causes the loss of quality of the background.
Is there a way to use a small Bitmap pattern I can repeat (X and Y) to fill the whole form area according to the resizing?
The effect you are looking for is a Tile.
See TTilerEffect and FireMonkey_Image_Effects for documentation.
The properties HorizontalTileCount and VerticalTileCount controls how many times a bitmap will be replicated. Since these values are floats, you need to adapt their values when the form is rescaled.
Add a TImage to the form
Make all the other controls children of it (so they appear on top).
Set the image's Align to alClient.
Load the Bitmap.
Set the WrapMode to imTile.

Bulk creation + edit images

I currently use photoshop + datasets to automatically create CTA buttons for testing on a clients website. The dataset often contains text and other changes like underline or background colour, as well as alignment and font formatting.
Typically these can run into the thousands, which photoshop handles very well but the task is technical and not graphical. For me photoshop is overkill for the task.
Is anyone aware of a solution that is more code-friendly? I am currently playing around with canvas on HTML and fabric.js. This allows me to manipulate a template image, and I hoping I can pipe in code to create a number of .png output images.
Canvas would be well suited to your automation
First, create a base .png and then programmatically alter it in thousands of ways.
Save the results to appropriately named .png files.
You could even create an on-screen viewer that dynamically creates thousands of variations. The client(s) could browse the dynamically created images and select the variations that interest them. That would eliminate the need for thousands of saved files.
Here are just a start of canvas commands you can use to automate:
Apply text:
context.font("italic 14pt Verdana");
context.textAlign = textAlign; // left|right|center
context.fillText("anyText", x,y);
Underlines are just a bit trickier:
// use measureText to get the text width
var textWidth =context.measureText(text).width;
// 1-time only, pre-calculate all the “Y” underline offsets for each font you use
var ULOffset=lookupULOffset(font,fontSize);
context.moveTo(x,y+ULOffset);
context.lineTo(textWidth,y+ULOffset);
context.stroke();
Change background color or anything else that you've created a sub-layer for!
Like Photoshop Canvas has an excellent set of compositing operations.
Source-over
Source-in
Source-out
Source-atop
Lighter
Xor
Destination-over
Destination-in
Destination-out
Destination-atop
Darker (this has been deprecated for some reason??)
You also can apply an alpha when drawing a layer as well as an alpha while drawing any canvas shapes.
In addition, check online for many image filters that have been created for canvas.
And that's just be beginning...
Happy Automating!

How do I create nodes with transparent backgrounds in a TVirtualDrawTree?

I am deriving a custom control from TVirtualDrawTree and I am overriding the DoPaintBackground event to draw a background gradient effect for the tree view.
I am also overriding the DoBeforeItemPaint function so I can custom draw the tree view items. However, I can't quite manage to get the items to paint with a transparent background.
Looking into the source for TVirtualDrawTree, it looks as though the item is copied to a TBitmap image and then copied onto the canvas, however, I have tried editing the source and setting the transparency options on the bitmap itself and it still doesn't seem to be working.
I have also tried clearing the canvas before drawing e.g. Canvas.Brush.Style := bsClear and filling the item rect but no joy.
Don't do transparency, cheat!
Drawing the gradient sounds like a lot of work: draw it to a temporary bitmap so you don't need to re-generate it every time DoPaintBackgrdound() is called. Once you have the background in a bitmap you can BitBlt the relevant portion into the Canvas when you handle DoBeforeItemPaint, and you can BitBlt the bitmap to the whole virtual tree when you need the whole background.
This way you don't need to deal with expensive transparency yet for the end user it looks like your items had been painted using transparency. It's a win:win situation.

overlaying images when displaying in OpenCV

I have two images that I want to display on top of each other. one image a single channel image and the second image is a RGB image but with most of the area being transparent.
How these two images are generated in different functions. I know to just display these on top of each other, i can use the same window name when calling cvShowImage() but this doesn't work when they are drawn from different functions. When trying this, I used cvCvtcolor() to convert he binary image from single channel to RGB and then displaying the second image from another function. But this didn't work. Both images are same dimension, depth and number of channels (after conversion).
I want to avoid passing in one image into the second function and then draw them. So I'm looking for a quick dirty trick to display these two images overlapped.
Thank you
EDIT:
I don't think that's possible. You'll have to create a new image or modify an existing one. Here's an article that shows how to do this: Transparent image overlays in OpenCV
There is no way to "overlay" images. cvShowImage() displays a single image from memory. You'll need to blend/combine them together. There are several ways to do this.
You can copy one into 1 or 2 channels of the other, you can use logical operations like AND, OR or XOR, you can use arithmetic operations like Add, Multiply and MultiplyScale (these operations will saturate values larger than 255). All these can also be done with an optional mask image like your blob image.
Naturally, you may want to do this into a third buffer so as not to overwrite your originals.
Apparently now it can be done using OpenCV 2.1 version
http://opencv.willowgarage.com/documentation/cpp/highgui_qt_new_functions.html#cv-displayoverlay

Resources