QR Code manipulation using Python (jython) - Scaling and removing Quiet Zone - python

Having trouble with this particular task (using JES 4.3). The task is to scale down a QR code image using Python to a 25 x 25 image, and to remove the white border (quiet zone) from the image. I have no trouble scaling it down, but the removal of the quiet zone is troubling. I believe it must be done before the scaling itself, and the quiet zone width can vary. Thus it appears that I need to remove each outer layer of pixels one by one until the program detects that its no longer the quiet zone. Quite sure a while loop is required, but have no clue how to implement that effectively. My code so far:
def reduce(qrPicture):
file = makePicture(qrPicture)
myPicture = duplicatePicture(file)
width = getWidth(myPicture)
height = getHeight(myPicture)
newPicture = makeEmptyPicture(25, 25)
newWidth = getWidth(newPicture)
newHeight = getHeight(newPicture)
basePixel = getPixelAt(myPicture, 0, 0)
startX = 0
startY = 0
xWidth = width/float(newWidth)
yHeight = height/float(newHeight)
for x in range(startX, newWidth):
for y in range(startY, newHeight):
smallPix = getPixel(newPicture, x, y)
pixelX = x*xWidth;
pixelY = y*yHeight;
oPixel = getPixel(myPicture, int(pixelX), int(pixelY))
setColor(smallPix, getColor(oPixel))
As mentioned, this simply scales the image to 25 x 25 but does not remove the quiet zone. Can someone tell me how to implement this removal of the quiet zone? Thanks.

def findQuietZone(pic):
width = getWidth(pic)
height = getHeight(pic)
for x in range(0, width):
for y in range(0, height):
px = getPixel(pic, x, y)
color = getColor(px)
if (colour != white):
value = getX(px)
quietZone = width - value

Related

How to have an auto page break for pyfpdf when the image exceeds the page dimensions?

I looked at a similar question here but there doesn't seem to be a solution except to switch to a different library.
I have created some code to automatically space my images vertically and horizontally, but I am having a problem with auto page breaks when the image inserted is larger than the page (since the image will get cut off).
def generate_pdf_report(start_height):
name = "PDF"
page_width = 210
page_height = 297
object_margins = 10
objects_per_row = 1
objects_in_path = 6 ##SAMPLE VARIABLE
total_margins = object_margins * (objects_per_row + 1)
object_width = (page_width - total_margins)/objects_per_row
pdf = FPDF()
pdf.add_page()
pdf.set_font('Arial', 'B', 16)
object_counter = 0
height_position = start_height
for item in range(objects_in_path):
object_counter += 1
position = object_counter % objects_per_row
if position == 0:
start_position = object_width * (objects_per_row - 1) + object_margins * objects_per_row
pdf.image("test_image.jpg", x=start_position, y=height_position, w=object_width)
height_position += start_height + object_margins
else:
start_position = object_width * (position - 1) + object_margins * position
pdf.image("test_image.jpg", x=start_position, y=height_position, w=object_width)
pdf.output('test_pdf.pdf')
Is there some kind of way to return the dimensions of each image inserted using pdf.image()? Since I set the width of the image, the height is automatically scaled by default. So currently I have to actually manually set the start_height parameter of the function depending on the resulting height of the image--else it can overlap or have too large a gap. Since I don't have the image height to adequately space the images or skip to the next page
There is one solution I can think of which is to measure the image outside the pyfpdf package and determine the width-height ratio of the image so I can determine the height of the final image. But I think there should be a better and easier way?

Cutting the codes in the program and making it neater

I'm having a hard time cutting the code and making it into a loop so that it would make the code of the program, neater.
Although my code works as it suppose to be, I think there is a right way of creating it, adding a for loop rather than writing all of these codes, I know there is an easy way to do this, I just couldn't figure how to do it properly. I know I'm suppose to create a for loop.
squares
from graphics import *
def main():
win = GraphWin("Squares", 500, 500)
rect = Rectangle(Point(0,500), Point(500,0))
rect.setFill("Red")
rect.draw(win)
rect2 = Rectangle(Point(20,480), Point(480,20))
rect2.setFill("white")
rect2.draw(win)
rect3 = Rectangle(Point(40,460), Point(460,40))
rect3.setFill("red")
rect3.draw(win)
rect4 = Rectangle(Point(60,440), Point(440,60))
rect4.setFill("white")
rect4.draw(win)
rect5 = Rectangle(Point(80,420), Point(420,80))
rect5.setFill("red")
rect5.draw(win)
rect6 = Rectangle(Point(100,400), Point(400,100))
rect6.setFill("white")
rect6.draw(win)
rect7 = Rectangle(Point(120,380), Point(380,120))
rect7.setFill("red")
rect7.draw(win)
rect8 = Rectangle(Point(140,360), Point(360,140))
rect8.setFill("white")
rect8.draw(win)
rect9 = Rectangle(Point(160,340), Point(340,160))
rect9.setFill("red")
rect9.draw(win)
rect10 = Rectangle(Point(180,320), Point(320,180))
rect10.setFill("white")
rect10.draw(win)
rect11 = Rectangle(Point(200,300), Point(300,200))
rect11.setFill("red")
rect11.draw(win)
rect12 = Rectangle(Point(220,280), Point(280,220))
rect12.setFill("white")
rect12.draw(win)
The results shows squares into some sort of a patchwork
Try the following:
from graphics import *
def main():
win = GraphWin("Squares", 500, 500)
# create all rects
rects = [Rectangle(Point(0 + 20*i,500 - 20*i), Point(500 - 20*i, 0 + 20*i)) for i in range(12)]
# draw all rects
for idx, rect in enumerate(rects):
rect.fill("red" if idx % 2 == 0 else "white")
rect.draw(win)
If the patchwork is just a background and you don't plan on modifying it you could use this:
from graphics import *
def main():
win = GraphWin("Squares", 500, 500)
i = 1
for x in range(0, 221, 20):
rect = Rectangle(Point(x, 500 - x), Point(500 - x,x))
rect.setFill("red" if i % 2 else "white")
rect.draw(win)
i += 1
An alternate approach that only needs to draw half as many rectangles due to using the rectangle's outline as the other color:
SQUARE, WIDTH = 500, 20
def main():
win = GraphWin("Squares", SQUARE, SQUARE)
save_config = dict(DEFAULT_CONFIG)
DEFAULT_CONFIG.update(dict(outline='red', fill='white', width=WIDTH))
for xy in range(WIDTH//2, SQUARE//2, WIDTH*2):
Rectangle(Point(xy, SQUARE - xy), Point(SQUARE - xy, xy)).draw(win)
DEFAULT_CONFIG.update(save_config)
It's fully parameterized so you can fit it to a different size square or have different width stripes by adjusting the SQUARE and WIDTH parameters. Rather than draw 12 rectangles in alternating colors, with the parameters as currently set, it draws 6 white rectangles with red outlines:

A box within a box

I am attempting to solve a problem where I have a region of size = width * height and then have to find a sub-region within the region at a location x, y and of size width_1 * height_1.
The values are:
Region_width = 71680
Region_height = 39680
Sub_location_x=272
Sub_location_y=130
Sub_width=372
Sub_height=519
The code I am attempting to implement I think should be like this.
#Width height of box
region_width = 71680
region_height = 39680
x = 272
y = 130
sub_width = 372
sub_height = 519
#Create numpy array of width and height (This I am unsure of)
Region_array = np.array(width, height)
#Pull out sub box (This I am also unsure of)
Sub_box = Region_array[x: x + sub_width, y: y + sub_height]
Would really appreciate any help or insight has to how I solve the problem.

Increasing image width by one pixel

I am trying to implement a program, that will increase the width of an image by one pixel. I then want to take the new maximum x ordinate and put this with a random y ordinate (that is within the range of the image) to create a new pixel.
for x in range (0,getWidth(pic)):
for y in range (0,getHeight(pic)):
X=getWidth(pic)
newX = (X+1)
colr=(255,0,0)
newPixel = getPixel (pic, newX, y)//line 25
setColor(newPixel, colr)
Y=getHeight(pic)
newY= (Y+1)
newPixel = getPixel( pic,x, newY)
setColor(newPixel, colr)
I get this error:
getPixel(picture,x,y): x (= 226) is less than 0 or bigger than the width (= 224)
The error was:
Inappropriate argument value (of correct type).
An error occurred attempting to pass an argument to a function.
Please check line 25 of D:\bla bla
I understand it is out of the range. What am I doing wrong?
Here is generalized approach to increase the size of an image keeping its current content:
Feel free to adapt.
# Increase a picture given an offset, a color and the anciant
# content must be centered or not.
# Offsets must be positive.
def increaseAndCopy(pic, offsetX, offsetY, bg_color=black, center=True):
# Offsets must be positive
if (offsetX < 0.0) or (offsetY < 0.0):
printNow("Error: Offsets must be positive !")
return None
new_w = pic.getWidth() + int(2*offsetX)
new_h = pic.getHeight() + int(2*offsetY)
startX = 0
startY = 0
if (center) and (offsetX > 1.0):
startX = int(offsetX)
if (center) and (offsetY > 1.0):
startY = int(offsetY)
new_pic = makeEmptyPicture(new_w, new_h)
# Fill with background color
setAllPixelsToAColor(new_pic, bg_color)
# Process copy
for x in xrange(pic.getWidth()):
for y in xrange(pic.getHeight()):
px = getPixel(pic, x, y)
new_px = getPixel(new_pic, x + startX, y + startY)
setColor(new_px, getColor(px))
return new_pic
file = pickAFile()
picture = makePicture(file)
# Pass an offset of 0.5 to increase by 1 pixel
#new_picture = increaseAndCopy(picture, 0.5, 0, blue)
new_picture = increaseAndCopy(picture, 10, 20, gray, True)
if (new_picture):
writePictureTo(new_picture, "/home/biggerPic.png")
show(new_picture)
Output (Painting by Jean-Michel Basquiat):
...........................................................
How can you get something that an object does not have?
newPixel = getPixel (pic, newX, y)//line 25
The original image remains sized at getWidth(pic) but you are asking for a pixel at getWidth(pic) + 1 which does not exist.
You can enlarge the image by copying it to a new picture similar to this answer.
...
newPic=makeEmptyPicture(newX,newY)
xstart=0
ystart=0
for y in range(ystart,newY):
for x in range(xstart, newX):
if x == newX or y == newY:
colour=(255,0,0)
else:
oldPixel=getPixel(oldPic,x,y)
colour=getColor(oldPixel)
newPixel=getPixel(newPic,x,y)
setColor(newPixel,colour)
explore(newPic)

Loop patchwork in python3

I need to create a patchwork in Python 3. All I have left to do is create a loop which makes the design border the graphics window. I know I need a for loop however I am not sure how to do this.
This is what I have so far:
from graphics import *
def main():
height = eval(input("What is the height of the window"))
width = eval(input("What is the width of the window"))
colour = input("enter the colour of the patch")
win = GraphWin("Patch", 100*width, 100*height)
boat_x = 0
boat_y = 0
for x in range (4):
boat(win, boat_x, boat_y, colour)
boat_x = boat_x + 23
for i in range(height * 5):
boat(win, boat_x, boat_y, colour)
boat_x = boat_x + 24
for j in range(height * 5):
boat(win, boat_x, boat_y, colour)
boat_y = boat_y + 100
win.getMouse()
win.close()
def boat(win, x, y, colour):
body1 = Polygon(Point(1+x,95+y), Point(5+x,100+y),
Point(20+x,100+y), Point(24+x,95+y))
body1.draw(win)
line1 = Line(Point(13+x,95+y), Point(13+x,90+y))
line1.draw(win)
sail1 = Polygon(Point(1+x,90+y), Point(24+x,90+y), Point(13+x, 73+y))
sail1.setFill(colour)
sail1.draw(win)
body2 = Polygon(Point(1+x, 63), Point(5+x, 68),
Point(20+x,68), Point(24+x,63))
body2.draw(win)
line2 = Line(Point(13+x,63), Point(13+x,58))
line2.draw(win)
sail2 = Polygon(Point(1+x,58), Point(24+x, 58), Point(13+x,40))
sail2.setFill(colour)
sail2.draw(win)
body3 = Polygon(Point(1+x,28), Point(5+x,33),
Point(20+x,33), Point(24+x, 28))
body3.draw(win)
line3 = Polygon(Point(13+x,28), Point(13+x,23))
line3.draw(win)
sail3 = Polygon(Point(1+x,23), Point(24+x, 23), Point(13+x, 5))
sail3.setFill(colour)
sail3.draw(win)
main()
So far this creates the top border but nothing else.
I am also aware that the boat function isn't the most efficient way of drawing
When you say that you need to "make the design border the graphics window" I assume you want your boat design to be repeated several times along each edge of the window (that is, the top, bottom, left and right).
This should be doable in two loops. One will draw the top and bottom edges, the other two will draw the left and right edges. I'm not too sure how your drawing code works, so I'm guessing at some offsets here:
top = 0
bottom = (height-1) * 100
for x in range(0, width*100, 25):
boat(x, top, colour)
boat(x, bottom, colour)
left = 0
right = width * 100 - 25
for y in range(100, (height-1)*100, 100):
boat(left, y, colour)
boat(right, y, colour)
This should call your boat subroutine every 25 pixels across the top and bottom, and every 100 pixels along the left and right edges. Adjust the top, bottom, left and right values and the parameters in the range calls in the loops to make the spacing suit your needs (I just made it up). This code avoids drawing the corner items twice, though depending on how the drawing routine works that might not be necessary.

Categories