400 likes | 482 Views
Object-oriented programming object-oriented approach classes & objects user-defined classes example: Die class HW 7: OOP approach DeckOfCards, RowOfCards, skip3 Image class grayscale, b&w, negative, tint, reflect, randomize, … steganography: file splitting, embedding text.
E N D
Object-oriented programming object-oriented approach classes & objects user-defined classes example: Die class HW 7: OOP approach DeckOfCards, RowOfCards, skip3 Image class grayscale, b&w, negative, tint, reflect, randomize, … steganography: file splitting, embedding text CSC 221: Introduction to ProgrammingFall 2013
Object-oriented programming • the dominant approach to (large-scale) software development today is object-oriented programming (OOP) • in order to solve a problem, you identify the objects involved in the real-world solution and model them in software • e.g., if designing a banking system, model clients, accounts, deposits, … • a program is a collection of interacting objects • in software, objects are created from classes • the class describes the kind of object (its properties and behaviors) • the objects represent individual instantiations of the class • classes & objects in Scratch: • class: cat, baseball, die, … (collections of sprite templates) • object: sprite1, rollButton, … (can create or stamp out instances) • properties/fields: size, coords, costume, … (can view on stage and above scripts) • behaviors/methods: turn, move, think, … (can execute by clicking script or flag)
Class & object examples REAL WORLD CLASS: automobiles REAL WORLD OBJECTS: my 2011 Subaru Outback, the batmobile, … • the class encompasses all automobiles they all have common properties: wheels, engine, brakes, … they all have common behaviors: can sit in them, start them, accelerate, steer, … • each car object has its own specific characteristics and ways of producing behaviors my car is white & seats 5; the batmobile is black & seats 2 accelerating with V-4 is different than accelerating with jet engine class or object? • student • Creighton University • Morrison Stadium • shoe
OO in Python • Python fully supports the object-oriented approach • useful classes are built-in, e.g., string, list • the programmer can define new classes to extend the language • str class: properties/fields: the sequence of characters behaviors/methods: upper, lower, toupper, tolower, capitalize, strip, split, … • >>> str1 = "foo" shorthand for str1 = str("foo") • >>> str1.upper() • 'FOO' • list class: properties/fields: the sequence of items behaviors/methods: sort, reverse, index, count,… • >>> list1 = [2, 6, 4] shorthand for list1 = list([2, 6, 4]) • >>> list1.sort() • >>> list1 • [2, 4, 6]
Python class definition • each method has an implicit parameter self, which refers to the object that the method is being applied to • __init__ is a special method for initializing an object; it is automatically called when an object is created: • obj = CLASSNAME() • the fields (i.e., properties) of the object are variables with the prefix self., which implies that they belong to this object • fields can be accessed by all the methods; they exist as long as the object does • general form: class CLASSNAME: def __init__(self): self.FIELD1 = INITIAL_VALUE … self.FIELDn = INITIAL_VALUE def METHOD1(self): STATEMENTS … def METHODn(self): STATEMENTS
Example: 6-sided die • simple example: modeling a 6-sided die • properties/fields: number of rolls • behaviors/methods: rolls, numberOfRolls convention: class names will start with uppercase; variables & functions with lowercase
Example: N-sided die • can easily generalize the class to allow for different sided dice • properties/fields: number of sides, number of rolls • behaviors/methods: rolls, numberOfSides, numberOfRolls if a method has explicit parameters, place after self note: each Die object has its own copies of the fields
OO view of Skip-3 • can identify the objects involved in a Skip-3 game • Card properties/fields: rank & suit • DeckOfCards properties/fields: a sequence of cards (w/ top & bottom) behaviors/methods: shuffle, dealCard, numCards, … • RowOfCards properties/fields: a sequence of cards (w/ left & right) behaviors/methods: addAtEnd, moveCard, numCards, … • using these objects, • can build an • interactive game
cards.py ranks & suits are local variables (belong to the function); self.cards is a field (belongs to the object) addCard has an explicit parameter: the card to add __str__ is a special-purpose method, converts the object to a string (used by print)
HW 7: RowOfCards class • similarly, we could define a class that represents a row of cards • you will complete the class definition for the first part of HW 7
HW 7: skip3 game • you are given skip3w/ basic functionality • you will modify: • display # of cards left in deck at user prompt • display # of cards in the row at "quit" • add features for EXTRA CREDIT
Another OOP example: digital images representing images • images are stored using a variety of formats and compression techniques • the simplest representation is a bitmap • bitmaps partition an image into a grid of picture elements, called pixels, and then convert each pixel into a bit pattern resolution refers to the sharpness or clarity of an image • bitmaps that are divided into smaller pixels will yield higher resolution images • the left image is stored using 72pixels per square inch, and the right image is stored using 36pixels per square inch • the left image appears sharp, but has twice the storage requirements
Color formats • when creating a bitmap of a color image, more than one bit is required to represent each pixel • the most common system is to translate each pixel into a 24 bit code, known as its RGB value: 8 bits to represent the intensity of each red/green/blue component common image formats implement various compression techniques to reduce storage size • GIF (Graphics Interchange Format) • a lossless format, meaning no information is lost in the compression • commonly used for precise pictures, such as line drawings • PNG(Portable Network Graphics) • more modern alternative to GIF - more colors, 10-50% more compact • JPEG (Joint Photographic Experts Group) • a lossy format, so the compression is not fully reversible (but more efficient) • commonly used for photographs
Image class • images.py contains the definition of a class for manipulating GIFs • developed by Ken Lambert at Washington & Lee University Image(filename) Loads an image from the file named fileName and returns an Image object that represents this image. The file must exist in the current working directory. Image(width, height) Returns an Image object of the specified width and height with a single default color. getWidth() Returns the width of the image in pixels. getHeight() Returns the width of the image in pixels. getPixel(x, y) Returns the pixel at the specified coordinates. A pixel is of the form (r, g, b), where the letters are integers representing the red, green, and blue values of a color in the RGB system. setPixel(x, y, (r, g, b)) Resets the pixel at position (x, y) to the color value represented by (r, g, b). The coordinates must be in the range of the image's coordinates and the RGB values must range from 0 through 255. draw() Pops up a window and displays the image. The user must close the window to continue the program. clone() Returns an Image object that is an exact copy of the original object. save() Saves the image to its current file, if it has one. Otherwise, does nothing. save(filename) Saves the image to the given file and makes it the current file. This is similar to the Save As option in most File menus.
Image example • to use, import the Image class from the images.py module • stored in the class Code folder as images.pytxt • you must download a copy and rename as images.py • note: the Image class is meant to be simple, not Photoshop quality • the draw method opens a viewer window • can only view one image at a time • must close the viewer window in order to continue
Image = grid of pixels • recall that an image is made up of a 2-dimensional grid of pixels • top-left corner is (0, 0) • top-right corner is (img.getWidth()-1, 0) • bottom-left corner is (0, img.getHeight()-1) • bottom-right corner is (img.getWidth()-1, img.getHeight()-1) (0,0) (123,0) (0,249) (123,249)
Traversing the pixels • can go through each pixel in an image using nested loops: e.g., can obtain a photo negative by inverting each RGB number
Image tinting • similar task, adjust the tint of the image • want to be able to change the RGB values uniformly for every pixel PROBLEM?
Image tinting (cont.) • problem: the RGB values must be in range 0..255 • if attempt to set a pixel with values outside this range ERROR • need to make sure that adding maxes out at 255 & subtracting mins out at 0
Converting to grayscale (v. 1) • to store a grayscale image, really only need one value per pixel 0 is black … 64 is dark gray … 128 is gray … 192 is light gray … 255 is white • can simulate this in a color image by having equal RGB values (0,0,0) … (64,64,64) … (128,128,128) … (192,192,192) … (255,255,255) • to convert a color image to grayscale, simple approach: • for each pixel, replace RGB value with the average of the color RGB values
Converting to grayscale (v. 2) • it turns out that the human eye is more sensitive to green, then red, then blue • the relative sensitivities have been determined experimentally • a better grayscale conversion uses a weighted average based on these
Exercise: converting to B&W • to convert from color to black & white, for each pixel: • if the average RGB value < 128, then replace with black pixel: (0,0,0) • if the average RGB value ≥ 128, then replace with white pixel: (255,255,255)
Making static • the following function replaces each pixel with a random B&W value EXERCISE: implement a color version
Horizontal reflection • suppose we want to add a mirror effect to the image • take the top half of the image, reflect it below • for each pixel (x,y) in the top half: • copy its value to the corresponding (x, img.getHeight()-y) pixel in the bottom half EXERCISE: implement reflectVertical
Pixel smoothing • low resolution images can look bad due to pixilation • pixel smoothing can be used to blur the edges of an image, make it look "softer" • for each pixel, replace its RGB value with the average RGB value of that pixel and its 8 neighboring pixels
Smooth (v. 1) • brute force solution
Smooth (v. 2) • can be simplified using list comprehensions
GIF limitations • the Image class imports a GIF file and stores internally as a pixelmap (i.e., a 2-D grid of pixels) • the draw method displays the internal pixelmap • limitation of GIF files: can only store 256 unique color values • no problem for negative, makeGray1, makeGray2, , makeBW, randomBW, reflectHorizontal & reflectVertical • these functions will not introduce more than 256 colors • potential problem for tint, randomColor, smooth • these introduce new pixels, could exceed 256 different colors • most image manipulation programs will save a > 256-color GIF by combining colors to get below the 256-color limit • the Image class will allow you to continue transforming the internal image, but will cause an error when you try to save an image with > 256 colors
Images & steganography • steganography is the art & science of hiding messages in plain sight • messages written in invisible ink or lemon juice • microdots hidden in the period on a page (WWII) • tattooing a message on a scalp, then growing hair to cover (ancient Greece) • SECRET MESSAGE: • Caleb and Natalie yanked our underwear rather egregiously. • Arnie didn't think his intelligence sufficed. • steganography can be applied to digital images as well as text • we can hide the contents of an image by splitting it into two (seemingly) random files of static • we can hide text (or even other images) inside the pixels of an image • to avoid the 256-color limit of our Image class, we will limit ourselves to grayscale (but these techniques generalize to color JPGs as well)
Static files • consider the following grayscale images • both are (seemingly) random static • if you found one on a hard drive or attached to an email – no information!
Joining images • while these files are random, they are not independent • if you add the pixels, you get a real image • image(x,y) = (mystery1(x,y) + mystery2(x,y)) % 256 • note the use of modulo arithmetic (using %) • if the sum of any RGB values exceeds 255, wrap around to 0 • e.g., (128, 128, 128) + (200, 200, 200) (72, 72, 72) +
Join code • note: the images should have the same dimensions • could we handle different sized images? how?
Split code • splitting an image into two static files involves two steps • generating a completely random file of grayscale pixels • subtracting each of those random pixels from the image pixels (using %)
Exercise • take your favorite GIF file • make it grayscale using makeGray, then save it • split it into two static images using splitGrayImage • join them back together using joinGrayImages • note: when you split an image • the first split is completely chosen at random • when you subtract a random amount from a pixel, also get a random amount • both files are completely random when taken in isolation – they only have meaning when taken together • now, discover the secret to acing the final exam (ace1.gif & ace2.gif)
Embedding text in an image • are these squares the same color? • no: • top-left is (100,100,100) • bottom-right is (101,101,101) • human eye can barely distinguish the difference • so, last digit in the grayscale number is not very significant • can use that digit to hide a message
Repurposing bits • suppose we wanted to hide the message "Howdy" in an image • we can convert the message into bits using the ASCII code for each character • ord("H") 72 01001000 • ord("o") 111 01101111 • … • "Howdy" 0100100001101111011101110110010001111001 • idea: take the first 40 pixels in the image • replace the least significant bit in the pixel color with the corresponding bit in the message img(0,0) = (128, 128, 128) 1st message bit is 0, so change last bit in 128 to 0 • since 128 is even, already ends in 0 so OK img(0,1) = (128, 128, 128) 2nd message bit is 1, so change last bit in 128 to 1 since 128 is even, need to add 1 (129,129,129) img(0,2) = (255, 255, 255) 3rd message bit is 0, so change last bit in 255 to 0 since 255 is odd, need to subtract 1 (254,254,254)
Embedding code • before embedding the message, • must add a marker at end (#END#) so the extraction process knows when to stop
Extracting code • when extracting the message • convert the bits to text, then strip off the letters up to the marker (#END#) now, find the doubly secret message hidden in (ace1.gif & ace2.gif)