Capture color from picturebox - vb.net

I'm attempting to capture the color of the color(s) primarily used in an icon within a picturebox. An example of this effect is how the windows taskbar (windows 7 and onwards) designates the background color of the application's icon square. I'm just not sure how to go about achieving this effect.

If you can get that into a System.Drawing.Bitmap you can loop over all of the pixels and then count them (group by color). With a lot of colors there could be pixels that are just slightly different that it will count as unique. Linq can also help group those things.
Here is a rough example of how to do it. This uses a WinForms PictureBox that already has an image loaded into it.
' Get a Bitmap from the PictureBox
Dim bm As Bitmap = PictureBox1.Image
Dim colorList As New List(Of System.Drawing.Color)
' One entry for every pixel (so this could get large with a large image)
For x As Integer = 0 To bm.Width - 1
For y As Integer = 0 To bm.Height - 1
colorList.Add(bm.GetPixel(x, y))
Next
Next
' Get the groups of colors with the count of each color that exists and sort them in
' decending order so you know the first one is the most used color
Dim groups = colorList.GroupBy(Function(value) value).OrderByDescending(Function(g) g.Count)
' You can loop over the groups and get their counts this way grp(0) is a color
For Each grp In groups
MsgBox(grp(0).Name & " - " & grp.Count)
Next
I just put them in order, you can pick out the first from the list because you know it will be the most, etc. The linq syntax is a little hard to read but is very useful.

Related

Why do rows in my list box have different different heights on different machines?

I am setting up a database and I have set up some VBA code to resize a list box within a report based on the number of records in the list box so that the list box will always be just the right size when printing. The problem I am having is that the resizing works perfectly on my machine, however when I ran the code on another machine the last record was cut off by the list box.
In an attempt to see if either machine was behaving oddly I ran the code on a 3rd machine to see what would happen and the last record was not cut off but was in a slightly different position to on the original machine, so I had 3 different heights for the list box required. I checked the values of the variables in the VBA code on both of the first 2 machines and the calculations are identical. I have checked that the font is the same and the font size is the same and the padding is the same.
Dim RecordCount as Integer
Dim FontSize as Integer
Dim Padding as Integer
Dim RowHeight as Integer
Dim lstIssues as Listbox
Dim Issues as Report
Set Issues = [Reports]![Issues]
Set lstIssues = Issues.lstIssues
RecordCount = lstIssues.ListCount
FontSize = lstIssues.FontSize
Padding = lstIssues.TopPadding + lstIssues.BottomPadding
RowHeight = 20 * FontSize + Padding
lstIssues.Height = RowHeight * RecordCount
On Error Resume Next
DoCmd.RunCommand acCmdPrint
On Error GoTo 0
Font size in my database is 11 and top and bottom padding are both 0.053cm or 30 twips each. RowHeight should thus be 280. Record count in my table is 24 so total listbox height should be 6720.

Dynamically Resize forms and controls inspite of change in Display size (Small/Medium/Large) in VB.net

We have developed windows application which is including many forms and controls with default small display size and it is working fine.
but in client systems,displays are not consistent. so when the same code runs with medium/large screen size, the controls are overlapping
It would be great help if anyone gives solution for dynamic re-size/fit the form & controls for any display (small-100%, medium-125%, large-150%)
and also Is there any way to find the Display size (small-100%, medium-125%, large-150%) in vb.net
You can change display size in control-Panel.
You can use the Anchor property to automatically adjust the control size according to its form size. You can anchor any side of the control to that side of the form. For example, if I anchor all four sides of a picturebox to the form, the picturebox will mimic the shape of the form when the form is resized. If you anchor only the top and the bottom of the picturebox, for example, it will change height with the form, but the width and horizontal position will remain constant.
Finally found a solution by doing R&D
call the below function in the Form_Load like ScaleForm(me)
Public Sub ScaleForm(WindowsForm As System.Windows.Forms.Form)
Using g As System.Drawing.Graphics = WindowsForm.CreateGraphics
Dim sngScaleFactor As Single
Dim sngFontFactor As Single = 1
If g.DpiX > 96 Then
sngScaleFactor = g.DpiX / 96
'sngFontFactor = 96 / g.DpiY
End If
If WindowsForm.AutoScaleDimensions = WindowsForm.CurrentAutoScaleDimensions Then
'ucWindowsFormHost.ScaleControl(WindowsForm, sngFontFactor)
WindowsForm.Scale(sngScaleFactor)
End If
End Using
End Sub

Finding coordinates of subform within form, in specific area

I'm using the Adobe Reader control AxAcroPdf in VB to show a pdf file within a form. In this form, there is an option to popup a subform, which shows a barcode. The user should be able to drag the subform where they want on the PDF, and upon hitting Enter, the barcode is stamped on that location where the subform was located.
So I've got the stamping down and the barcode design, but I can't seem to pinpoint the exact location this thing should go. I've tried a number of variations of this, and I can't seem to get anything to work.
'coordinates of barcodeform relative to the pdf control
Dim pt3 As Point = rdrAdobePdf.PointToClient(barCodeForm.Location)
'This comes close but is always 10-50 pixels off
Dim clientBarCode As Point = New Point(0.5 * (PointToClient(barCodeForm.Location).X - 5), (CInt(pdfReader.GetPageSize(1).Height) - PointToClient(barCodeForm.Location).Y - 80))
'Dim clientBCTry1 As Point = Point.op_Subtraction(PointToClient(screenBarCode), topLeftCorner)
'Dim clientBCtry2 As Point = rdrAdobePdf.PointToClient(screenBarCode)
I understand the basics about PointToClient and PointToScreen and I also understand the concepts of (X,Y) coordinates. Yet after days of trying things nothing works. Any help is appreciated.
This almost seems like a hardcoded solution, but this code somewhat helps. It does position the barcode accurately if stamped at the top of the PDF page. However, if stamped toward the bottom, it becomes less and less accurate... even though the dimensions of the page don't change. If anyone has any other solutions feel free to post them.
Dim x As Integer = CInt(0.5 * (PointToClient(screenBarCode).X))
Dim y As Integer = (CInt(pdfReader.GetPageSize(1).Height) - PointToClient(screenBarCode).Y)
If x < 0 Then x = 0
If y < 0 Then y = 0
Dim clientBarCode As Point = New Point(x, y)

Programmatically determine background of image (logos, etc) and make transparent?

I'm attempting to write a solution so that my user's can "watermark" their Images with their Company Logo. I've got the actual watermarking part done and working so now I'm creating the "upload logo" feature so that they can provide me with the Logo they wish to appear watermarked onto their Images.
I'm using VB.NET and this will probably end up in a Web Service that accepts the Logo JPG file, and returns the "altered" Logo. What I need to happen in this Web Service is:
1) Gray-scale the image. Which I have working as well, thanks to this article.
2) Make the background transparent (so the logo looks clean when watermarked onto an image). This is where I'm stuck.
I think for the most part, any logos that are uploaded will have a generic white background but I can't assume that. Is there a way to somehow detect the background of an image or the background colors, so that I may make those colors transparent?
I've downloaded and ran this project from code.google.com, called Transpoint, which is pretty much what I need except I won't be able to have this as a stand-alone app. Also, I think this is written in Python which is foreign to me.
So basically what I need is just a way to determine the background on an Image (if that's even possible?) or even just the background colors so that I may make them transparent. Any help/advice/suggestions would be greatly appreciated!
Thanks,
Lloyd
You could do something like reading the upper-left pixel and assuming that that pixel is representative of the background color, and then iterating through the image and setting the alpha value of each matching pixel (matching by color) to 0.
I can pretty much guarantee you, however, that the result will be awful. For transparency to work properly and look good, the image needs to support partial transparency, such that some pixels are completely transparent whereas some are only partially transparent. Any algorithm that takes a non-transparent image and sets only one color in the image to fully transparent is going to end up with jagged edges.
Most companies I've ever dealt with have versions of their logos done by professional artists, with smooth, partial transparency. You'd be much better off just requiring customers to submit a logo with transparency than trying to make a non-transparent image into a transparent one with code. Sorry, but this just doesn't work.
I think this would actually work (sorry it's just a description):
Assuming the upper-left corner pixel is the image's background color, you could iterate through each pixel in the image and set the alpha to 0 if the pixel color matches the background color (either exactly or within some threshold color distance). This would then leave you with an image with a transparent background but jagged edges when you re-draw it on a different-color background. Also, if the background color is present anywhere inside the image itself, it will be turned transparent, which you don't want.
To fix the latter problem, your algorithm should start scanning each row of the image from left to right, and stop when it reaches a non-background color pixel; at this point it should start on the same row and scan right to left until reaching a non-bg pixel.
To fix the edges, you can just blur the alpha values of the bitmap. Basically, you re-calculate the alpha value of each pixel as the average of 9 pixels (itself and the 8 pixels surrounding it, and just the alpha values - not the rgb values). To prevent sequencing artifacts, you would have a temporary array to store the averaged pixel values, which you would then copy back into the image's alpha values at the end of the process.
Also, there's probably one or more third-party tools that do this (is LEAD Tools still around?).
#MusiGenesis (and anyone else who may be interested) here is what I did to (kind of) solve my problem. I basically followed the first half of your idea. I've created a function that will accept a bitmap, check each pixel against the first pixel at (0,0) - using a threshold of 10 for each RGB color. For each color within that threshold, the pixel is made transparent. Here is my code, which seems to work alright for the few images I've tried it with:
Private Function TransparifyBackground(ByVal bmp As Bitmap) As Bitmap
Dim temp As Color
Dim background As Color = bmp.GetPixel(0, 0) 'top left will be assumed background color
For y As Integer = 0 To bmp.Height - 1
For x As Integer = 0 To bmp.Width - 1
'get the pixel for this position:
temp = bmp.GetPixel(x, y)
If ColorsMatch(background, temp) Then
'Make the Alpha value 50 for each pixel, leaving the other colors
Dim newColor As New Color
newColor = Color.Transparent
bmp.SetPixel(x, y, newColor)
End If
Next
Next
Return bmp
End Function
Private Function ColorsMatch(ByVal background As Color, ByVal temp As Color) As Boolean
Dim nThreshold As Integer = 10
Dim temp_R As Integer = CInt(temp.R)
Dim temp_G As Integer = CInt(temp.G)
Dim temp_B As Integer = CInt(temp.B)
Dim R As Integer = CInt(background.R)
Dim G As Integer = CInt(background.G)
Dim B As Integer = CInt(background.B)
'check the difference of each value against our threshold:
If ((temp_R - R) < nThreshold) AndAlso ((temp_G - G) < nThreshold) AndAlso ((temp_B < B) < nThreshold) Then
Return True
Else
Return False
End If
End Function

Branching Slides in PowerPoint (VBA)

I am trying to create a back button but using hyperlinks it simply just takes me to the previous page and ends up in a loop... e.g. if I have slide 1 which has links to slide 3, 4 & 5 then slide 3 links to 6 & 7. If I'm currently on slide 7 and click back it successfully takes me back to slide 3 but then I want to click back and end up at slide 1 rather than back to slide 7 (hopefully I'm making some sense!).
I presume the only way for me to do this is with VBA can anyone give me some advice on best way to create a back button? (I'm using PowerPoint 2007)
I was struggling with a similar problem today and made a little "breadcrumb"- generator for powerpoint. There is no link feature yet, but you can implement it if you like:
Github Project
Essential parts of the code
Public Sub breadcrumbs(ByVal count As Integer, ByRef titles() As String)
Dim cntr As Integer
Dim content() As String
Dim margin As Integer
Dim width As Integer
'----------------------------
' Set Titles
content = titles
cntr = 0
' Set width
width = ((Application.ActivePresentation.PageSetup.SlideWidth - (margin * count * 2) - 20) / count) - 50
' Loop through all slides
For Each sld In Application.ActivePresentation.Slides
' generate breadcrumb for each title
For Each con In content
sld.Shapes.AddShape(1, (50 + (width * cntr)), 15, width, 50).TextFrame.TextRange.Text = con
cntr = cntr + 1
Next con
cntr = 0
Next sld
End Sub
It sounds like you want a 'breadcrumb trail' of visited slides, instead of a simple back button. Thus you need a way to preserve the trail.
This could be addressed with a dynamic array. New browsing would add records to the array. Your "Next" and "Previous" locations would be found by moving up or down the array. You'll have some mild logic puzzles. I hate to refer you a generic resource, but I'm out of specifics and an overview may be helpful.
UPDATE: I've wanted this in the past for MS Access, and thought I'd readily find a snippet solution. But now I go to search (thinking it will convert over for you easily as well), and I don't find anything. This is surprising because I imagine it would be fun to built. Or ... it's harder to build than I anticipate.
There is a really cumbersome way to do this in PPT directly with no programming. You'll need "forward-facing slides" and 2 sets of "backward-facing slides". Backwards ones are two types - direct-back and home-back. They can all be identical, but make the backward ones hidden (e.g. instead of "Slide 3" you'll need "Slide 3a" and "Slide 3b" and "Slide 3c".). They are hidden so that when you progress through normally, you won't see them, but when you link to them, they will appear. Your link list on the "a" slides should always point to the "b" slides and your "b" slides will point to the "c" slides. Your hyperlinks on "back button" on "a" slides should be "previous slide" and on the "c" slides should be "last slide viewed" and on "h" slides should be "first slide" (use 'action' to set this instead of 'hyperlink').
It takes a while to work through, but it can be done.