Python-pptx - How to insert a slide number for all slides - python

I am trying to automatically insert slide numbers to all my slides in PPT that is messy and strictly formatted. When we do manually,we are not able to do it for all the PPTs due to manual work involved. Is there anyway to do this for all 35 plus slides in 20 plus PPT files? When we do using python inbuilt option menus ,it is not working and qe are unable to figure out why. Could be because of our messy format. So, want to use python pptx, insert text box and number them
I referred the SO post and tried the below
i=0
for slide in slides
i = i + 1
txBox = slide.shapes.add_textbox(0,0,10,12)
tf = txBox.text_frame
tf.text = i
tf.font.size = (11)
But not sure whether am doing it right. How can I make the slide numbers appear at the bottom of slide?
update based on Luke answer
for slide in presentation.slides:
i = i + 1
txBox = slide.shapes.add_textbox(0,0,5,6)
txBox.height = Inches(0.5)
txBox.width = Inches(0.5)
txBox.top = SH - txBox.height
#if (i % 2) != 0:
# txBox.left = SW - Inches(OutsideMargin) - txBox.width
#else:
#
txBox.right = Inches(float(OutsideMargin)) #updated here
tf = txBox.text_frame
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.RIGHT #updated here
run = p.add_run()
run.text = "Page" + str(i)
run.font.size = Pt(11)

UPDATE
If you want the textbox to always be on the right side just do this
txBox.left = presentation.slide_width - txBox.width
You just need to reposition the textbox. maybe something like this...
from pptx import *
from pptx.util import Inches, Pt
from pptx.enum.text import MSO_ANCHOR, MSO_AUTO_SIZE, PP_ALIGN
presentation = Presentation("input.pptx")
SH = presentation.slide_height
SW = presentation.slide_width
OutsideMargin = 0.5
i=0
for slide in presentation.slides:
i = i + 1
txBox = slide.shapes.add_textbox(0,0,10,12)
txBox.height = Inches(1)
txBox.width = Inches(2)
txBox.top = SH - txBox.height
if (i % 2) != 0:
txBox.left = SW - Inches(OutsideMargin) - txBox.width
else:
txBox.left = Inches(float(OutsideMargin))
tf = txBox.text_frame
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.CENTER
run = p.add_run()
run.text = "Page " + str(i)
run.font.size = Pt(11)
presentation.save("output.pptx")

Related

How do you save the images that are embedded in the placeholders of a pptx file using python?

I can extract all the images from the shapes of a slide, as shown in the code below. The problem comes when an image is embedded in a placeholder. I have no idea how to get the images from those placeholders, and the documentation to me isn't clear.
Note also that I have a minimum width limit for the kind of images I want, hence I have "shape.width > 250000" in the code
import os
import pptx
from pptx.enum.shapes import MSO_SHAPE_TYPE
ppFileName = "Test.pptx"
directory = os.path.dirname(__file__)
imageDirectory = directory + "\\Images " + ppFileName.replace(".pptx","")
if not os.path.exists(imageDirectory):
os.makedirs(imageDirectory)
def saveImage(shape,slideNumber,imageNumber):
image = shape.image
imageBytes = image.blob
imageFileName = f"Slide {slideNumber} Image {imageNumber}.{image.ext}"
imagePath = imageDirectory + "\\" + imageFileName
with open(imagePath, 'wb') as file:
file.write(imageBytes)
imageNumber += 1
prs = pptx.Presentation(directory + "\\" + ppFileName)
slides = prs.slides
slideNumber = 0
for slide in slides:
imageNumber = 0
for shape in slide.shapes:
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE and shape.width > 250000:
saveImage(shape,slideNumber,imageNumber)
elif shape.shape_type == MSO_SHAPE_TYPE.GROUP and shape.width > 250000:
for s in shape.shapes:
saveImage(s,slideNumber,imageNumber)
slideNumber += 1
Alright, I figured it out.
Just added these three lines of code:
for shape in slide.placeholders:
if hasattr(shape, "image") and shape.width > 250000:
saveImage(shape,slideNumber,imageNumber)

Get the coordinates of detected words using pytesseract

Am making a digital assistant as final year project and I want to automate the browser tab by getting title of tab including the location of the detected words and use the coordinates to click the tab. I tried this answers I found here but not what I needed.
from pytesseract import *
from PIL import ImageGrab
pytesseract.tesseract_cmd = 'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'
while True:
cap = ImageGrab.grab(bbox=(0, 0, 1182, 34)) # bounding box of the browser tab bar
text = pytesseract.image_to_data(cap, output_type=Output.DICT)
print(text)
data = {}
for i in range(len(text['line_num'])):
txt = text['text'][i]
block_num = text['block_num'][i]
line_num = text['line_num'][i]
top, left = text['top'][i], text['left'][i]
width, height = text['width'][i], text['height'][i]
if not txt == '' or txt.isspace():
tup = (txt, left, top, width, height)
if block_num in data:
if line_num in data[block_num]:
data[block_num][line_num].append(tup)
else:
data[block_num][line_num] = [tup]
else:
data[block_num] = {}
data[block_num][line_num] = [tup]
linedata = {}
idx = 0
for _, b in data.items():
for _, i in b.items():
linedata[idx] = i
idx += 1
line_idx = 1
for _, line in linedata.items():
xmin, ymin = line[0][1], line[0][2]
xmax, ymax = (line[-1][1] + line[-1][3]), (line[-1][2] + line[-1][4])
print(f'line{line_idx}, {xmin}, {ymin}, {xmax}, {ymax}, {txt}')
line_idx += 1
I need the title of each tab and their coordinates. Am pretty confident that pytesseract.image_to_data() is what I need but don't know how to extract the information that need

Python find function selects one match per line

I am trying to make a simple text editor using python. I am now trying to make a find function. This is what I've got:
def Find():
text = textArea.get('1.0', END+'-1c').lower()
input = simpledialog.askstring("Find", "Enter text to find...").lower()
startindex = []
endindex = []
lines = 0
if input in text:
text = textArea.get('1.0', END+'-1c').lower().splitlines()
for var in text:
character = text[lines].index(input)
start = str(lines + 1) + '.' + str(character)
startindex.append(start)
end = str(lines + 1) + '.' + str(character + int(len(input)))
endindex.append(end)
textArea.tag_add('select', startindex[lines], endindex[lines])
lines += 1
textArea.tag_config('select', background = 'green')
This will succesfully highlight words that match the users input with a green background. But the problem is, that it only highlights the first match every line, as you can see here.
I want it to highlight all matches.
Full code here: https://pastebin.com/BkuXN5pk
Recommend using the text widget's built-in search capability. Shown using python3.
from tkinter import *
root = Tk()
textArea = Text(root)
textArea.grid()
textArea.tag_config('select', background = 'green')
f = open('mouse.py', 'r')
content = f.read()
f.close()
textArea.insert(END, content)
def Find(input):
start = 1.0
length = len(input)
while 1:
pos = textArea.search(input, start, END)
if not pos:
break
end_tag = pos + '+' + str(length) + 'c'
textArea.tag_add('select', pos, end_tag)
start = pos + '+1c'
Find('display')
root.mainloop()

need guidance my vignette code in Jython/Python

i'm having trouble with having my CGI picture and vignette profile image going together to make a vignette picture where the picture is slightly darker around the edges of the picture without compromising the image anywhere else, i am getting everything so far that i think is right but my picture is showing up dark in the middle instead of showing the image normal but with slightly darker colored edges.
this is what i have currently:
def main():
inputPic = makePicture(pickAFile())
vignette = makePicture(pickAFile())
addVignette(inputPic, vignette)
def addVignette(inputPic, vignette):
if getWidth(inputPic) == getWidth(vignette) and getHeight(inputPic) == getHeight(vignette):
explore(inputPic)
explore(vignette)
px1 = getPixels(inputPic)
px2 = getPixels(vignette)
for px in getPixels(inputPic):
x = getX(px)
y = getY(px)
px2 = getPixelAt(vignette, x, y)
x2 = getX(px2)
y2 = getY(px2)
r1 = getRed(px)
r2 = getRed(px2)
g1 = getGreen(px)
g2 = getGreen(px2)
b1 = getBlue(px)
b2 = getBlue(px2)
newR = (r1-r2+104)
newG = (g1-g2+88)
newB = (b1-b2+48)
newC = makeColor(newR, newG, newB)
setColor(px, newC)
explore(inputPic)
folder = pickAFolder()
filename = requestString("enter file name: ")
path = folder+filename+".jpg"
writePictureTo(inputPic, path)
http://i.stack.imgur.com/PqW7K.jpg
picture 1 is what the image needs to be
http://i.stack.imgur.com/PtS4U.jpg
picture 2 is my image i get at the end of my coding
Any help to get me in the right direction would be very much appreciated
After absolutely getting this wrong the first 3 times I worked it out with the help of my little friend the modules operator.
def addVignette(inputPic, vignette):
# Create empty canvas
canvas = makeEmptyPicture(getWidth(inputPic), getHeight(inputPic))
for x in range(0, getWidth(inputPic)):
for y in range(0, getHeight(inputPic)):
px = getPixel(canvas, x, y)
inputPixel = getPixel(inputPic, x, y)
vignettePixel = getPixel(vignette, x, y)
# Make a new color from those values
newColor = getNewColorValues(inputPixel, vignettePixel)
# Assign this new color to the current pixel of the input image
setColor(px, newColor)
explore(canvas)
def getNewColorValues(inputPixel, vignettePixel):
inputRed = getRed(inputPixel)
vignetteRed = getRed(vignettePixel)
inputGreen = getGreen(inputPixel)
vignetteGreen = getGreen(vignettePixel)
inputBlue = getBlue(inputPixel)
vignetteBlue = getBlue(vignettePixel)
newR = inputRed - (255 % vignetteRed) / 3
newG = inputGreen - (255 % vignetteGreen) / 3
newB = inputBlue - (255 % vignetteBlue) / 3
newC = makeColor(newR, newG, newB)
return newC

Creating a tiled map with blender

I'm looking at creating map tiles based on a 3D model made in blender,
The map is 16 x 16 in blender.
I've got 4 different zoom levels and each tile is 100 x 100 pixels. The entire map at the most zoomed out level is 4 x 4 tiles constructing an image of 400 x 400.
The most zoomed in level is 256 x 256 obviously constructing an image of 25600 x 25600
What I need is a script for blender that can create the tiles from the model.
I've never written in python before so I've been trying to adapt a couple of the scripts which are already there.
So far I've come up with a script, but it doesn't work very well. I'm having real difficulties getting the tiles to line up seamlessly. I'm not too concerned about changing the height of the camera as I can always create the same zoomed out tiles at 6400 x 6400 images and split the resulting images into the correct tiles.
Here is what I've got so far...
#!BPY
"""
Name: 'Export Map Tiles'
Blender: '242'
Group: 'Export'
Tip: 'Export to Map'
"""
import Blender
from Blender import Scene,sys
from Blender.Scene import Render
def init():
thumbsize = 200
CameraHeight = 4.4
YStart = -8
YMove = 4
XStart = -8
XMove = 4
ZoomLevel = 1
Path = "/Images/Map/"
Blender.drawmap = [thumbsize,CameraHeight,YStart,YMove,XStart,XMove,ZoomLevel,Path]
def show_prefs():
buttonthumbsize = Blender.Draw.Create(Blender.drawmap[0]);
buttonCameraHeight = Blender.Draw.Create(Blender.drawmap[1])
buttonYStart = Blender.Draw.Create(Blender.drawmap[2])
buttonYMove = Blender.Draw.Create(Blender.drawmap[3])
buttonXStart = Blender.Draw.Create(Blender.drawmap[4])
buttonXMove = Blender.Draw.Create(Blender.drawmap[5])
buttonZoomLevel = Blender.Draw.Create(Blender.drawmap[6])
buttonPath = Blender.Draw.Create(Blender.drawmap[7])
block = []
block.append(("Image Size", buttonthumbsize, 0, 500))
block.append(("Camera Height", buttonCameraHeight, -0, 10))
block.append(("Y Start", buttonYStart, -10, 10))
block.append(("Y Move", buttonYMove, 0, 5))
block.append(("X Start", buttonXStart,-10, 10))
block.append(("X Move", buttonXMove, 0, 5))
block.append(("Zoom Level", buttonZoomLevel, 1, 10))
block.append(("Export Path", buttonPath,0,200,"The Path to save the tiles"))
retval = Blender.Draw.PupBlock("Draw Map: Preferences" , block)
if retval:
Blender.drawmap[0] = buttonthumbsize.val
Blender.drawmap[1] = buttonCameraHeight.val
Blender.drawmap[2] = buttonYStart.val
Blender.drawmap[3] = buttonYMove.val
Blender.drawmap[4] = buttonXStart.val
Blender.drawmap[5] = buttonXMove.val
Blender.drawmap[6] = buttonZoomLevel.val
Blender.drawmap[7] = buttonPath.val
Export()
def Export():
scn = Scene.GetCurrent()
context = scn.getRenderingContext()
def cutStr(str): #cut off path leaving name
c = str.find("\\")
while c != -1:
c = c + 1
str = str[c:]
c = str.find("\\")
str = str[:-6]
return str
#variables from gui:
thumbsize,CameraHeight,YStart,YMove,XStart,XMove,ZoomLevel,Path = Blender.drawmap
XMove = XMove / ZoomLevel
YMove = YMove / ZoomLevel
Camera = Scene.GetCurrent().getCurrentCamera()
Camera.LocZ = CameraHeight / ZoomLevel
YStart = YStart + (YMove / 2)
XStart = XStart + (XMove / 2)
#Point it straight down
Camera.RotX = 0
Camera.RotY = 0
Camera.RotZ = 0
TileCount = 4**ZoomLevel
#Because the first thing we do is move the camera, start it off the map
Camera.LocY = YStart - YMove
for i in range(0,TileCount):
Camera.LocY = Camera.LocY + YMove
Camera.LocX = XStart - XMove
for j in range(0,TileCount):
Camera.LocX = Camera.LocX + XMove
Render.EnableDispWin()
context.extensions = True
context.renderPath = Path
#setting thumbsize
context.imageSizeX(thumbsize)
context.imageSizeY(thumbsize)
#could be put into a gui.
context.imageType = Render.PNG
context.enableOversampling(0)
#render
context.render()
#save image
ZasString = '%s' %(int(ZoomLevel))
XasString = '%s' %(int(j+1))
YasString = '%s' %(int((3-i)+1))
context.saveRenderedImage("Z" + ZasString + "X" + XasString + "Y" + YasString)
#close the windows
Render.CloseRenderWindow()
try:
type(Blender.drawmap)
except:
#print 'initialize extern variables'
init()
show_prefs()
This was relatively simple in the end.
I scaled up the model so that 1 tile on the map was 1 grid in blender.
Set the camera to be orthographic.
Set the scale on the camera to 1 for the highest zoom, 4 for the next one, 16 for the next one and so on.
Updated the start coordinates and move values accordingly.

Categories

Resources