ben winstone
/
ucam
As of Monday morning, so this is the code we showed at Uncraftivism.
Embed:
(wiki syntax)
Show/hide line numbers
Frame.cpp
00001 #include "stdafx.h" 00002 00003 #include "mbed.h" 00004 #include "ucam.h" 00005 #include "Frame.h" 00006 00007 extern Logger pcSerial; 00008 00009 Frame* Frame::m_frames[MAX_FRAMES]; // array of reusable frames 00010 00011 Frame::Frame() // don't construct Frame yourself - call allocFrame instead 00012 { 00013 m_pixels = NULL; 00014 m_width = 0; 00015 m_height = 0; 00016 m_pixelFormat = 0; 00017 m_deleted = true; 00018 m_numPixels = 0; 00019 m_bad = false; 00020 } 00021 00022 00023 Frame::~Frame() 00024 { 00025 if( m_pixels != NULL ) 00026 free( m_pixels ); 00027 00028 } 00029 00030 // static - initialise the array of frames - call once at app start time 00031 void Frame::initFrames() 00032 { 00033 for( int f = 0; f < MAX_FRAMES; f ++ ) 00034 m_frames[f] = NULL; 00035 } 00036 00037 //static - reuse an existing frame, or make a new one 00038 void Frame::allocFrame( Frame **frame, uint8_t pixelFormat, uint16_t width, uint16_t height, uint16_t frameSize ) 00039 { 00040 for( int f = 0; f < MAX_FRAMES; f ++ ) 00041 if( m_frames[f] == NULL ) 00042 { 00043 m_frames[f] = new Frame(); 00044 m_frames[f]->init( pixelFormat, width, height, frameSize ); 00045 *frame = m_frames[f]; 00046 00047 return; 00048 } 00049 else 00050 { 00051 if( m_frames[f]->m_deleted ) 00052 { 00053 m_frames[f]->init( pixelFormat, width, height, frameSize ); 00054 *frame = m_frames[f]; 00055 return; 00056 } 00057 00058 } 00059 00060 pcSerial.printf("No free frames!\r\n"); 00061 *frame = NULL; 00062 00063 } 00064 00065 //static - make an existing frame available for reuse 00066 void Frame::releaseFrame( Frame **frame ) 00067 { 00068 for( int f = 0; f < MAX_FRAMES; f ++ ) 00069 if( m_frames[f] == *frame ) 00070 { 00071 m_frames[f]->m_deleted = true; 00072 *frame = NULL; 00073 return; 00074 } 00075 } 00076 00077 //static - make a new frame with the same parameters as an existing one, alloc a pixel buffer, but do not initialise the pixels 00078 void Frame::cloneFrame( Frame **clone, Frame* original ) 00079 { 00080 allocFrame( clone, original->m_pixelFormat, original->m_width, original->m_height, original->m_frameSize ); 00081 00082 } 00083 00084 00085 void Frame::init( uint8_t pixelFormat, uint16_t width, uint16_t height, uint32_t frameSize ) 00086 { 00087 00088 if( m_frameSize != frameSize ) // keep the same pixel buffer if we can, to avoid fragmentation 00089 { 00090 free( m_pixels ); 00091 m_pixels = (uint8_t *) malloc( frameSize ); 00092 } 00093 00094 m_pixelFormat = pixelFormat; 00095 m_width = width; 00096 m_height = height; 00097 m_frameSize = frameSize; 00098 m_deleted = false; 00099 m_bad = false; 00100 00101 switch( m_pixelFormat ) 00102 { 00103 case UCAM_COLOUR_2_BIT_GREY: 00104 m_bitsPerPixel = 2; 00105 break; 00106 case UCAM_COLOUR_4_BIT_GREY: 00107 m_bitsPerPixel = 4; 00108 break; 00109 case UCAM_COLOUR_8_BIT_GREY: 00110 m_bitsPerPixel = 8; 00111 break; 00112 case UCAM_COLOUR_8_BIT_COLOUR: 00113 m_bitsPerPixel = 8; 00114 break; 00115 case UCAM_COLOUR_12_BIT_COLOR: 00116 m_bitsPerPixel = 16; 00117 break; 00118 case UCAM_COLOUR_16_BIT_COLOR: 00119 m_bitsPerPixel = 16; 00120 break; 00121 case UCAM_COLOUR_JPEG: 00122 default: 00123 m_bitsPerPixel = 16; // ?? not at all sure, but we are not using frames to handle jpegs right now 00124 break; 00125 } 00126 00127 m_numPixels = (8 * m_frameSize) / m_bitsPerPixel; 00128 } 00129 00130 uint16_t Frame::getPixel( uint32_t p ) 00131 { 00132 switch( m_bitsPerPixel ) 00133 { 00134 case 4: 00135 if( p & 1 ) 00136 return m_pixels[ p >> 1 ] & 0x0f; 00137 else 00138 return m_pixels[ p >> 1 ] >> 4; 00139 00140 00141 case 8: 00142 return m_pixels[ p ]; 00143 00144 case 16: 00145 default: 00146 return ((m_pixels[p<<1]) << 8) + m_pixels[1 + (p<<1) ]; // todo - check bytes order 00147 } 00148 } 00149 00150 void Frame::setPixel( uint32_t p, uint16_t val ) 00151 { 00152 switch( m_bitsPerPixel ) 00153 { 00154 case 4: 00155 if( p & 1 ) 00156 m_pixels[ p >> 1 ] = ( m_pixels[ p >> 1 ] & 0xf0) | (val & 0x0f); 00157 else 00158 m_pixels[ p >> 1 ] = ( m_pixels[ p >> 1 ] & 0x0f) | ((val & 0x0f) << 4 ); 00159 break; 00160 00161 case 8: 00162 m_pixels[ p ] = (uint8_t) val; 00163 break; 00164 case 16: 00165 default: 00166 m_pixels[p<<1] = val>>8; 00167 m_pixels[1 + (p<<1) ] = val & 0xff; 00168 break; 00169 } 00170 00171 00172 } 00173 00174 void Frame::writeToFile( char *filename ) 00175 { 00176 pcSerial.printf("writeToFile - %s\r\n", filename); 00177 00178 FILE *rawFile = fopen(filename, FILE_WRITE_STRING); // "w" or "wb" for Windows 00179 00180 fwrite( &m_pixelFormat, 1, 1, rawFile ); 00181 fwrite( &m_width, 1, 2, rawFile ); 00182 fwrite( &m_height, 1, 2, rawFile ); 00183 fwrite( &m_frameSize, 1, 4, rawFile ); 00184 00185 fwrite( m_pixels, 1, m_frameSize, rawFile ); 00186 00187 fclose( rawFile ); 00188 00189 } 00190 00191 // static 00192 void Frame::readFromFile( char *filename, Frame **frame ) 00193 { 00194 *frame = NULL; 00195 00196 pcSerial.printf("readFromFile - %s\r\n", filename); 00197 00198 FILE *rawFile = fopen(filename, FILE_READ_STRING); 00199 if( rawFile == NULL ) 00200 { 00201 pcSerial.printf("readFromFile - failed to open %s\r\n", filename); 00202 return; 00203 } 00204 00205 uint8_t pixelFormat; 00206 uint16_t width; 00207 uint16_t height; 00208 uint32_t frameSize; 00209 00210 if( 1 == fread( &pixelFormat, 1, 1, rawFile )) 00211 if( 2 == fread( &width, 1, 2, rawFile )) 00212 if( 2 == fread( &height, 1, 2, rawFile )) 00213 if( 4 == fread( &frameSize, 1, 4, rawFile )) 00214 { 00215 00216 allocFrame( frame, pixelFormat, width, height, frameSize ); 00217 00218 if( frameSize != fread( (*frame)->m_pixels, 1, frameSize, rawFile )) 00219 { 00220 releaseFrame( frame ); 00221 pcSerial.printf("readFromFile - bad size"); 00222 } 00223 } 00224 00225 fclose( rawFile ); 00226 00227 }
Generated on Wed Jul 27 2022 03:18:56 by 1.7.2