Using ABCPDF draw another doc as an image with rounded corners - abcpdf

I find ABCPDF is very capable. However, so far I had not managed to find a way to draw one PDF into another with rounded corners - until now. But, the approach I discovered depends on getting the correct PDF object id for the inserted PDF stream, and herein lies the reason for this question.
Anyone who knows ABCPDF will ask why that is an issue ? Does not the addImageDoc() function which embeds one PDF inside another return the PDF object ID ? No - it returns something else - most likely the inserted PDF goes into the document catalogue as an isolated object and what you get in the returned ID is an object that refers to it. Unpacking the document streams seems to bear this out.
Long story short, in my experimenting I found that I needed to insert into the stream a 'Do' call, with the target of that derived as:
imgObjId = addImageDoc(some pdf object) // inserted off-page
insert into stream "/Iabc<imgObjId + 1> Do"
For example, if the returned imgObjId value is 5 then I need it to be 6 to make
/Iabc6 Do
Question: Whilst this works OK, I am relying on adding one to the returned value and I wonder how robust that is going to be. Or is there a correct way to achieve this ?
More info: I have kept the question short but readers may be wondering why the above matters? Because to achieve rounded corners you need to construct a stream of PDF commands which has a clipping region defined. Think of a path for a rectangle with Bezier curves for the corners. Having got that, you need to draw an image, or in my case another PDF, into the same context so as to get the clipping effect. After that you can close and reset the graphics state and be a good PDF stack citizen. However, there is no means, other than my approach above, that I can find in ABCPDF to get a handle on the inserted PDF doc stream in the catalogue so as to be able to ask for it to be drawn somewhere else.
Inserting an image seems to be a similar process, except the getinfo() function can discover the pixmap. There appears to be no like approach for an embedded PDF.

I don't know if you can change the target abcpdf rectangle prior to do a "AddImageDoc".
Maybe you can do a trick, getting a Bitmap from the source, editing it by changing borders, and adding to a new doc. Something like this:
Dim oDoc As New WebSupergoo.ABCpdf10.Doc
Dim oImg As System.Drawing.Bitmap
oDoc.Read("D:\source.pdf")
oImg = oDoc.Rendering.GetBitmap()
' image quality can be improved with .Rendering properties as 'AntiAliasImages', etc.
oDoc.Dispose()
oDoc = Nothing
Dim oGraph As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(oImg)
Dim gPath As New System.Drawing.Drawing2D.GraphicsPath
Dim oBrush As New System.Drawing.SolidBrush(System.Drawing.Color.Red) ' only to see the rectangle... white when be ready
gPath.AddRectangle(New System.Drawing.Rectangle(0, 0, oImg.Width, oImg.Height))
' 2 / 100 it's the percent factor for borders
Dim iLeftBorder As Integer = CInt(2 / 100 * (oImg.Width / 2))
Dim iTopBorder As Integer = CInt(2 / 100 * (oImg.Height / 2))
gPath.AddEllipse(New System.Drawing.Rectangle(iLeftBorder, iTopBorder, oImg.Width - (iLeftBorder * 2) - 1, oImg.Height - (iTopBorder * 2) - 1))
oGraph.FillPath(oBrush, gPath)
oBrush.Dispose()
oGraph.Dispose()
oDoc = New WebSupergoo.ABCpdf10.Doc
oDoc.AddImageBitmap(oImg, False)
oDoc.Save("D:\finalpath.pdf")
oDoc.Dispose()
oDoc = Nothing
But it's only a "trick".

Related

Programatically Removing and Replacing Watermarks in Word

I'm trying to do some standardized document manipulation specifically in a Windows environment on Word documents. For frustratingly silly reasons, I'd also like to do this in VBscript or at least language tools available in Vanilla Windows 10 + Office.
As it stands, the documents coming in all have a standardized text Watermark on them, and I'd like to replace that watermark with a new text watermark. From what I've been able to gather, the watermark is some sort of generalized shape object. I've had some fiddly success finding and deleting all shapes, but it's not clear to me if there is a way to inspect each shape and determine if it is the correct shape in VBscript, or to replace the text hiding somewhere within the shape structure to produce a new watermark.
My deletion looks something like the following, where lDoc is a document object of document I'm manipulating.
sub UpdateWatermark(lDoc)
Dim section
Dim hdr, hdr_rng, sp, str
dim cnv
dim rng
for each section in lDoc.Sections
for each hdr in section.Headers
For each sp in hdr.Shapes
if InStr(sp.Name, "PowerPlusWaterMarkObject") > 0 Then
sp.Delete
End if
next
next
next
end sub
The strange thing with this brute force deletion approach is I'm seeing many PowerPlusWaterMarkObjects in the header, but only one is the "for real" watermark. I also am not sure how to create a new object and insert it with the same properties as the one I'm deleting. My preference would be to simply find the watermark object and manipulate it directly. Any Guru's out there who could lend me a hand?

Access 2016 restrict picture size to 600x800

I am building a database and came across an issue that I need help in resolving. This database the customer wants to be able to link pictures to specific records. I have it so the pics are not OLE objects but links to a picture folder that will be on their network drive...So essentially the picture will be a hyperlink to the file path....
My question is does anyone know I way I can have the database reformat the picture automatically to 600 x 800 size, to help save space? We all know if I don't force the DB to do it for them it will not happen and potentially eat up valuable space, as this DB is expected to get quite large. So I would like to keep the picture folder as small as possible, giving the database more room.
You can use the WIA libary as shown in VBA – Resize Image like this:
Function ResizeImageTo600x800(ByVal PathToImage As String, ByVal PathToResizedImage As String) As Boolean
Dim WiaImgFile As Object 'WIA.ImageFile
Set WiaImgFile = CreateObject("WIA.ImageFile")
With CreateObject("WIA.ImageProcess") 'WIA.ImageProcess
.Filters.Add .FilterInfos("Scale").FilterID 'Add Scale Filter to ImageProcess
.Filters(1).Properties("MaximumWidth") = 600 ' Set Width to 600px
.Filters(1).Properties("MaximumHeight") = 800 'Set Height to 800px
'.Filters(1).Properties("PreserveAspectRatio") = False ' uncomment if AspectRatio should not be preseved
WiaImgFile.LoadFile PathToImage ' Load Image
.Apply(WiaImgFile).SaveFile PathToResizedImage ' Apply Filter and save resized Image
ResizeImageTo600x800 = True
Set WiaImgFile = Nothing
End With
End Function
Usage:
If ResizeImageTo600x800("\\path\to\image", "\\path\to\resized\image") then
Msgbox "ResizeImageTo600x800 successful!"
End If
Or:
ResizeImageTo600x800 "\\path\to\image", "\\path\to\resized\image"
Depending on your image types, you may also increase the compression of your image to save space. WIA should support this too (with the Convert Filter and its Quality Property).

Variable Increase in MS PowerPoint

I've very limited knowledge of PowerPoint but have been asked to create a presentation slide where I would have to click areas on a map and that would change color and increment a number (population). I am able to change the color of the map on click and I'm able to display a bubble but I am not able to increment the population number based on the areas of the map that are clicked.
I've looked at some solutions around here and did some research online but couldn't find anything that would point me in the right direction.
Is there a way to create a variable and pass a number when you click a specific area of the map, which is a Freeform.
Thank you in advance for the help.
You can set each shape's Action Setting to Run Macro: (macro name)
That will run the VBA subroutine called (macro name) when you click on the shape during a slide show.
Mac PowerPoint has a few bugs that keep this from working as smoothly as it does in Windows PowerPoint but the code below works around these issues and works in either version.
Sub IncrementNumber(oSh as Shape)
Dim oSl as Slide
Dim oShTemp as Shape
' oSh.Parent returns a valid reference to the shape's host slide:
Set oSl = ActivePresentation.Slides(oSh.Parent.SlideIndex)
' and oSh.Name works as well
' So we use those two bits to get a reference
' to the clicked shape like so
Set oShTemp = oSl.Shapes(oSh.Name)
With oShTemp
.TextFrame.TextRange.Text = _
Cstr(CLng(oShTemp.TextRange.Text) + 1)
End With
End Sub
About this bit:
Cstr(CLng(oShTemp.TextRange.Text) + 1)
This gets the current text in the shape, converts it from text (string) to a number so we can do arithmetic on it, adds 1 to it, then converts it back to text so we can plug it back into the shape's text.
If you don't know what to do with VBA code examples, there's a tutorial on the PowerPoint FAQ site that I maintain:
How do I use VBA code in PowerPoint
http://www.pptfaq.com/FAQ00033_How_do_I_use_VBA_code_in_PowerPoint.htm

Scale / Resize StdPicture in VB6

I have looked far and wide and reached the end of my wits trying to figure out how to do this. I have looked on XtremeVBTalk.com and the rest of the internet on how to resize a damn StdPicture!
Does anyone know how to do this? Is this even possible?
Thank you so much in advance. I desire not to use any type libraries etc. so if that is offered in a solution I don't think I will be able to use it.
I'm not using A picturebox control at all.
Say I have the following function header, and an StdPicture is passed in:
Private Function EncodeImageToBase64(ByRef Image As StdPicture) As String
I then have the following declarations where I intend on encoding the StdPicture to base64:
Dim xmlDoc As DOMDocument60
Dim xmlNode As MSXML2.IXMLDOMElement
Dim bColor() As Byte
Dim bMask() As Byte
Dim bImage() As Byte
Dim lCrcTable() As Long
Dim lWidth As Long
Dim lHeight As Long
EncodeImageToBase64 = vbNullString
If Image Is Nothing Then
Exit Function
End If
Call CRCTable(lCrcTable)
Call Icon2Arrays(Image, bColor, bMask, lWidth, lHeight)
If Not CreatePngByteArray(bImage, lWidth, lHeight, bColor, bMask, lCrcTable) Then
Debug.Assert False
Exit Function
End If
However, before calling that, I want to cut the image's width and height in half. How can I do so? CreatePngByteArray only supports 16x16 PNGs and I am using 32x32, so I'd like to cut them down in order to pass the asserts they have.
OK, I spent quite some time that I didn't really have on this one, because I didn't know the answer to begin with, but I was still interested in finding out what the potential solution was.
The following answer is my understanding of what you are trying to do, but may not be the answer to the question itself, so it could very well be considered wrong.
So, here's what I came up with. You will need to use an IPictureDisp object instead of an StdPicture object. You will also need to use a PictureBox control, even if you don't really want to.
Create a new project. Add a form, or open an existing one if one is provided. Set the ScaleMode of the form to pixels. Add a PictureBox control on the form. Set the AutoRedraw property of the PictureBox control to 'True', the BorderStyle property of the control to 'None', and the Height and Width properties of the control to 16 pixels each. Add the following code to the form, and modify the location and type of the image that you want to resize, and then the location to save it to:
Private Sub Form_Load()
Dim TestPic As IPictureDisp
Set TestPic = LoadPicture("C:\Users\Your Name\Desktop\image.gif")
With TestPic
.Render Picture1.hDC, 0, 16, 16, -17, 0, 0, .width, .height, 0
End With
SavePicture Picture1.Image, "C:\Users\Your Name\Desktop\image2.bmp"
End Sub
The image can start with any of the types that Visual Basic 6 supports (.bmp, .cur, .gif, .ico, .jpeg or .jpg, and .wmf), but must always be saved in bitmap format. Please note that Visual Basic 6 does not support PNG file formats at all, so you will not be able to use any VB6 functions to open PNG files or create them.
I would be interested in other solutions that other people come up with.
Edit: Fixed dimensions.
Do you mean inside the PICTUREBOX control or inside an IMAGE CONTROL? Because If I remember correctly it has a STRETCH property which autofits the image to the container
#Zaf Khan beat me to it. I have something similar where I have a PictureBox. Under behaviour I have SizeMode set to StretchImage then when I load an image like so
LoadWebImageToPictureBox(ImagePreview, SelectedFile)
it auto fits.

Using VBA to insert and keep images in file - Excel 2013

I'm working on a macro for a friend of mine who needs to import a set of images in an excel document and later use this document on other computers. The problem I encountered is that when opening this document on a different computer, all the images are gone and instead you get these little error signs, indicating that the image path could not be found.
I have developed the macro on my own computer where I have Excel 2007 and for me, the code works perfectly fine. My friend uses Excel 2013 and apparently, there seems to be a major difference on how those 2 versions deal with the image importing and saving.
Overall, I found 2 different ways how to insert images. The first one I tried was something similar to this:
Set pic = ActiveSheet.Pictures.Insert("C:\documents\somepicture.jpg")
The second way of doing this looked like this:
Set pic = Application.ActiveSheet.Shapes.AddPicture("C:\documents\somepicture.jpg", False, True, 1, 1, 1, 1)
In the documentation for this 2nd approach it is said that the 3rd paramenter (which is True here) is responsible for saving the picture with the document.
However, both these approaches look more or less the same in the end result: They work fine for me but won't work if they are executed on my friends pc with Excel 2013. So what I need is a work-around for the newer Excel versions (I read somewhere that from Excel 2010 upwards, there is a bug or something like that with these image import methods).
In all my uses, Adding a picture with Insert makes a reference to a file on your harddrive, for whatever reason if you want the image to be embedded in the file you have to add a shape and then put the image on the shape using the AddPicture (like you use), I have never had any issues with this.
Also you are giving the picture a height and width of 1 pixel, You will almost never be able to see that true setting that higher as below:
Application.ActiveSheet.Shapes.AddPicture "C:\documents\somepicture.jpg", False, True, 1, 1, 100, 100
I have a feeling it was working all along and you just never saw the picture cause it was too small.
The first snippet works just fine, but it does not allow picture positioning (i.e. if you need a pic placed at some certain range), so I made something that works nicely with positioning available, based on the second solution, such as it is shown below.
Dim r As Range
Dim pic As Shape
Set r = ActiveSheet.Range("A34:Q58")
Set pic = ActiveSheet.Shapes.AddPicture(ThisWorkbook.Path & "\FracAnalysis.png", _
linktofile:=msoFalse, savewithdocument:=msoCTrue, Left:=0, Top:=0, Width:=-1, Height:=-1)
With pic
.LockAspectRatio = msoFalse
.Top = r.Top
.Left = r.Left
.Width = r.Width
.Height = r.Height
End with
Previous answer has been really useful! I just wanted to add the reference to the method parameters (I thought the width and height were in pixels, turns out they're in points):
https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.shapes.addpicture.ASPX
I usually run a macro that downloads images from a server into files that are then forwarded to clients who do not have access to that server. My coding is quite basic so I'll just copy the particular line I use to insert the picture:
Set pic = ActiveSheet.Shapes.AddPicture(Filename:="C:\documents\somepicture.jpg", _
linktofile:=msoFalse, savewithdocument:=msoCTrue, Left:=0, Top:=0, Width:=-1, Height:=-1)
I know its technically the same code as the one you proposed, but try using msoCTrue and msoFalse. I seem to recall that being part of the issues. Let me know if it works and maybe we can try something else. It works for me, so we should be able to get it to work for you.

Resources