Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Insectoid's Summer Programming Challenge
Index -> Contests
Goto page Previous  1, 2
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
DtY




PostPosted: Sat Apr 23, 2011 5:23 pm   Post subject: Re: RE:Insectoid\'s Summer Programming Challenge

ultimatebuster @ Sat Apr 23, 2011 1:17 pm wrote:
I'm not sure if Python can write non-text format via file.write

nm it can. though i think i has to be direct HEX code or via struct.

Following writes a text file in binary directly.
code:

with open("test.dat", "wb") as f: f.write('\x75\x6C\x74\x69\x6D\x61\x74\x65\x62\x75\x73\x74\x65\x72')
You can also use ord() to convert a single character to it's ordinal code (the character's numeric value) and chr() to go back.
Sponsor
Sponsor
Sponsor
sponsor
RandomLetters




PostPosted: Sat Apr 23, 2011 7:30 pm   Post subject: Re: Insectoid's Summer Programming Challenge

Well, finished the program to load a 24 bit bitmap, and apply a tunnel effect, like that terrible, terrible feature in ipad photobooth Razz
It's still extremely slow to something like MS paint however, which most of the time is taken because of loading the bitmap into an array.

code:
       
public void loadBmpPixelArray() throws IOException {
                FileInputStream in = new FileInputStream(file);
               
                bmpPixelArray = new byte[Math.abs(bmpInfoHeader.height)]
                                          [Math.abs(bmpInfoHeader.width)]
                                           [3];
               
                for(int i = 0; i < bmpHeader.offset; i++) {                             //reads in bytes from offset of bitmap
                        in.read();
                }
               
                byte[] buffer = new byte[(bmpInfoHeader.width % 4)];          //buffer at the end of each row to keep multiple of 4

                if(bmpInfoHeader.height >= 0) {                                          //check sign of "height" info, if it's positive, the image is "upside down"
                        for(int r = bmpPixelArray.length - 1; r >= 0; r--) {
                                for(byte[] bmpPixel : bmpPixelArray[r]) {
                                        in.read(bmpPixel);                                      //reads 3 bytes into the pixel array
                                }
                                in.read(buffer);
                        }
                } else {
                        for(int r = 0; r < bmpPixelArray.length; r++) {             //not upside down
                                for(byte[] bmpPixel : bmpPixelArray[r]) {
                                        in.read(bmpPixel);
                                }
                                in.read(buffer);
                        }
                }
                bmpOriginal = bmpPixelArray.clone();
        }

Is there any way to optimize this? Currently, I have a 2D array of pixels, which are themselves an array of 3 bytes.
DemonWasp




PostPosted: Sun Apr 24, 2011 10:28 am   Post subject: RE:Insectoid\'s Summer Programming Challenge

BufferedInputStream:

code:

InputStream in = new BufferedInputStream ( new FileInputStream ( file ) );

// Or, for extra fun:
DataInputStream in = new DataInputStream ( new BufferedInputStream ( new FileInputStream ( file ) ) );

// that last one allows you to read whole integers and so on easily


Also, don't forget to close your input streams when you're done with them.
DtY




PostPosted: Sun Apr 24, 2011 12:07 pm   Post subject: Re: Insectoid's Summer Programming Challenge

RandomLetters @ Sat Apr 23, 2011 7:30 pm wrote:
Well, finished the program to load a 24 bit bitmap, and apply a tunnel effect, like that terrible, terrible feature in ipad photobooth Razz
It's still extremely slow to something like MS paint however, which most of the time is taken because of loading the bitmap into an array.

code:
       
---snip

Is there any way to optimize this? Currently, I have a 2D array of pixels, which are themselves an array of 3 bytes.
There's a lot of overhead in using an array for each pixel. Instead, make each pixel a single integer, made up of red<<16+green<<8+blue. You'll have to use some weird bitmasking stuff to get the individual components, but it will be a lot more space efficient. It may seem odd at first that storing 24 bits in 32 bits is more space efficient, but to creating an array requires creating a pointer, which is itself 32 bits, and then 8 bits for each index in the array.
RandomLetters




PostPosted: Sat Apr 30, 2011 9:01 pm   Post subject: RE:Insectoid\'s Summer Programming Challenge

Thank's for the advice. It's almost instantaneous now.

Here's the mostly complete product. Bit operations are surprisingly useful.

Java:

import java.applet.*;
import java.awt.*;
import java.io.*;
import javax.swing.JFileChooser;

//by randomletters
public class BitmapEditor extends Applet {
        File file;
        BitmapHeader bmpHeader;
        BitmapInfoHeader bmpInfoHeader;
        int [][] bmpPixelArray;
        boolean isCleared = false;
        /**
         * @param args
         */
        public void init() {
                JFileChooser fileChooser = new JFileChooser();
                int fcValue = fileChooser.showOpenDialog(this);
                System.out.println();
                if(fcValue == JFileChooser.APPROVE_OPTION) {
                        file = fileChooser.getSelectedFile();
                        try {
                                System.out.println("opening");
                                loadBmpHeader();
                                System.out.println("loading");
                                loadBmpPixelArray();
                                System.out.println("applying effect");
                                applyTunnelEffect();
                                this.setSize(Math.abs(bmpInfoHeader.width), Math.abs(bmpInfoHeader.height));
                        } catch (Exception e) {
                                System.out.println(e.getMessage());
                                e.printStackTrace();
                        }
                }
        }
       
        //makes the circle tunnel effect on pictures by changing pixels
        public void applyTunnelEffect() {
                int r = bmpPixelArray.length/3;
                int xC = bmpPixelArray[0].length/2;
                int yC = bmpPixelArray.length/2;
                int dx, dy;
                int x1, y1;
                double angle;
               
                int[][] bmpOriginal = new int[bmpPixelArray.length][bmpPixelArray[0].length];
                for(int i = 0; i < bmpOriginal.length; i++) {
                        bmpOriginal[i] = bmpPixelArray[i].clone();
                }
               
                for(int y = 0; y < bmpPixelArray.length; y++) {
                        for(int x = 0; x < bmpPixelArray[y].length; x++) {
                                dx = x-xC;
                                dy = y-yC;
                                if(dx*dx + dy*dy > (r)*(r)) {
                                        angle = Math.atan(dy/(double)dx);
                                        if(dx < 0) {
                                                angle += Math.PI;
                                        }
                                        x1 = (int) (xC + r*Math.cos(angle));
                                        y1 = (int) (yC + r*Math.sin(angle));
                                        bmpPixelArray[y][x] = bmpOriginal[y1][x1];
                                }
                        }
                }
        }
        public void loadBmpPixelArray() throws IOException {
                BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
               
                bmpPixelArray = new int[Math.abs(bmpInfoHeader.height)]
                                          [Math.abs(bmpInfoHeader.width)];
                System.out.println(bmpPixelArray.length);
                System.out.println(bmpPixelArray[0].length);
               
                for(int i = 0; i < bmpHeader.offset; i++) {
                        in.read();
                }
               
                byte[] buffer = new byte[(bmpInfoHeader.width % 4)];
                System.out.println("Buffer length: " + buffer.length);
               
                if(bmpInfoHeader.height >= 0) { //upside down
                        for(int r = bmpPixelArray.length - 1; r >= 0; r--) {
                                for(int c = 0; c < bmpPixelArray[r].length; c++) {
                                        bmpPixelArray[r][c] = (in.read()<<16) | (in.read()<<8) | (in.read());
                                }
                                in.read(buffer);
                        }
                } else {
                        for(int r = 0; r < bmpPixelArray.length; r++) {
                                for(int c = 0; c < bmpPixelArray[r].length; c++) {
                                        bmpPixelArray[r][c] = (in.read()<<16) | (in.read()<<8) | (in.read());
                                }
                                in.read(buffer);
                        }
                }
                in.close();
        }

        public void paint(Graphics g) {
                if(isCleared) {
                        try {
                                for(int r = 0; r < bmpPixelArray.length; r++) {
                                        for(int c = 0; c < bmpPixelArray[r].length; c++) {
                                                g.setColor(new Color((bmpPixelArray[r][c] & 0xFF),
                                                                                                (bmpPixelArray[r][c] & 0xFF00) >>> 8,
                                                                                                (bmpPixelArray[r][c] & 0xFF0000) >>> 16));
                                                g.drawLine(c,r,c,r);
                                        }
                                }
                        } catch(NullPointerException e) {
                                System.out.println("Bitmap failed to load");
                        }
                } else {
                        isCleared = true;
                }
        }
       
        public void loadBmpHeader() throws Exception {
                BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
                BitmapHeader bmpHeader = new BitmapHeader();
                BitmapInfoHeader bmpInfoHeader = new BitmapInfoHeader();
               
                byte[] buffer2 = new byte[2];
                byte[] buffer4 = new byte[4];
               
                if(!(in.read() == 'B' && in.read() == 'M')) {
                        throw new Exception("Signature is not \"BM\"");
                }
                in.read(buffer4);
                bmpHeader.filesize = unsignedIntToLong(buffer4);
                in.read(buffer2);
                bmpHeader.reserved1 = unsignedShortToInt(buffer2);
                in.read(buffer2);
                bmpHeader.reserved2 = unsignedShortToInt(buffer2);
                in.read(buffer4);
                bmpHeader.offset = unsignedIntToLong(buffer4);
               
                in.read(buffer4);
                bmpInfoHeader.headersize = unsignedIntToLong(buffer4);
                in.read(buffer4);
                bmpInfoHeader.width = byteArrayToInt(buffer4);
                in.read(buffer4);
                bmpInfoHeader.height = byteArrayToInt(buffer4);
                in.read(buffer2);
                bmpInfoHeader.nplanes = unsignedShortToInt(buffer2);
                in.read(buffer2);
                bmpInfoHeader.bitspp = unsignedShortToInt(buffer2);
                in.read(buffer4);
                bmpInfoHeader.compresstype = unsignedIntToLong(buffer4);
                in.read(buffer4);
                bmpInfoHeader.imgsize = unsignedIntToLong(buffer4);
                in.read(buffer4);
                bmpInfoHeader.hres = byteArrayToInt(buffer4);
                in.read(buffer4);
                bmpInfoHeader.vres = byteArrayToInt(buffer4);
                in.read(buffer4);
                bmpInfoHeader.ncolors = unsignedIntToLong(buffer4);
                in.read(buffer4);
                bmpInfoHeader.nimpcolors = unsignedIntToLong(buffer4);
               
                this.bmpHeader = bmpHeader;
                this.bmpInfoHeader = bmpInfoHeader;
               
                System.out.println(this.bmpHeader.toString());
                System.out.println(this.bmpInfoHeader.toString());
                in.close();
        }
       
        public static final int byteArrayToInt(byte[] b) {
        return (b[3] << 24)
        + ((b[2] & 0xFF) << 16)
        + ((b[1] & 0xFF) << 8)
        + (b[0] & 0xFF);
        }
       
        public static final long unsignedIntToLong(byte[] b)
        {
            long l = 0;
            l |= b[3] & 0xFF;
            l <<= 8;
            l |= b[2] & 0xFF;
            l <<= 8;
            l |= b[1] & 0xFF;
            l <<= 8;
            l |= b[0] & 0xFF;
            return l;
        }
            
        public static final int unsignedShortToInt(byte[] b)
        {
            int i = 0;
            i |= b[1] & 0xFF;
            i <<= 8;
            i |= b[0] & 0xFF;
            return i;
        }
}

class BitmapHeader {
    public long filesize;       //size of file (unreliable?)
        public int reserved1;   //unused
        public int reserved2;
        public long offset;          //offset of start of pixel array
       
        @Override public String toString() {
                StringBuilder result = new StringBuilder();
                String NL = System.getProperty("line.separator");
               
                result.append(this.getClass().getName() + " Object {" + NL);
                result.append(" filesize: " + this.filesize + NL);
                result.append(" reserved1: " + this.reserved1 + NL);
                result.append(" reserved2: " + this.reserved2 + NL );
                result.append(" offset: " + this.offset + NL);
                result.append("}");
               
                return result.toString();
        }
}

class BitmapInfoHeader {
    public long headersize;     //size of this header in the file (must 40)
    public int width;      //width of bitmap (in pixels)
    public int height;    //height of bitmap (in pixels)
    public int nplanes; //number of color planes (must 1)
    public int bitspp;  //bits per pixel (color depth)
    public long compresstype;   //compression method (must 0 for this)
    public long imgsize;                //raw bitmap data size
    public int hres;        //horizontal res (pixels/meter)
    public int vres;        //vertical res (pixels/meter)
    public long ncolors;                //number of colors
    public long nimpcolors;     //number of important colors (unused)
   
        @Override public String toString() {
                StringBuilder result = new StringBuilder();
                String NL = System.getProperty("line.separator");
               
                result.append(this.getClass().getName() + " Object {" + NL);
                result.append(" headersize: " + this.headersize + NL);
                result.append(" width: " + this.width + NL);
                result.append(" height: " + this.height + NL );
                result.append(" nplanes: " + this.nplanes + NL);
                result.append(" bitspp: " + this.bitspp + NL);
                result.append(" compresstype: " + this.compresstype + NL);
                result.append(" imgsize: " + this.imgsize + NL);
                result.append(" hres: " + this.hres + NL);
                result.append(" vres: " + this.vres + NL);
                result.append(" ncolors: " + this.ncolors + NL);
                result.append(" nimpcolors: " + this.nimpcolors + NL);
                result.append("}");
               
                return result.toString();
        }
}
Brightguy




PostPosted: Mon May 02, 2011 2:47 am   Post subject: Re: RE:Insectoid\'s Summer Programming Challenge

DtY @ Sat Apr 23, 2011 5:23 pm wrote:
You can also use ord() to convert a single character to it's ordinal code (the character's numeric value) and chr() to go back.

In high school the first time I worked with a binary format I opened the file in text mode, translated the characters to their ordinal codes, made the requried modifications, translated the ordinal codes back to characters and outputted the file in text mode. Heh.
ultimatebuster




PostPosted: Mon May 02, 2011 9:40 am   Post subject: Re: RE:Insectoid\'s Summer Programming Challenge

Brightguy @ Mon May 02, 2011 2:47 am wrote:
DtY @ Sat Apr 23, 2011 5:23 pm wrote:
You can also use ord() to convert a single character to it's ordinal code (the character's numeric value) and chr() to go back.

In high school the first time I worked with a binary format I opened the file in text mode, translated the characters to their ordinal codes, made the requried modifications, translated the ordinal codes back to characters and outputted the file in text mode. Heh.


Now that's how you do it. Rebel.
Velocity




PostPosted: Thu Jan 12, 2012 12:29 am   Post subject: RE:Insectoid\'s Summer Programming Challenge

what is the difference between binary and trinary?
Insectoid




PostPosted: Thu Jan 12, 2012 7:48 am   Post subject: RE:Insectoid\'s Summer Programming Challenge

What's the difference between a bicycle and a tricycle?
mirhagk




PostPosted: Thu Jan 12, 2012 10:49 am   Post subject: RE:Insectoid\'s Summer Programming Challenge

1001010101

1210120120
Display posts from previous:   
   Index -> Contests
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 2 of 2  [ 25 Posts ]
Goto page Previous  1, 2
Jump to:   


Style:  
Search: