test

Dependencies:   BLE_API mbed-dev-bin nRF51822

Fork of microbit-dal by Lancaster University

Committer:
JKsoft_main
Date:
Tue Apr 17 12:10:30 2018 +0000
Revision:
75:6a5fcf1bf8e9
Parent:
69:b62f231e51ce
test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan Austin 1:8aa5cdb4ab67 1 /*
Jonathan Austin 1:8aa5cdb4ab67 2 The MIT License (MIT)
Jonathan Austin 1:8aa5cdb4ab67 3
Jonathan Austin 1:8aa5cdb4ab67 4 Copyright (c) 2016 British Broadcasting Corporation.
Jonathan Austin 1:8aa5cdb4ab67 5 This software is provided by Lancaster University by arrangement with the BBC.
Jonathan Austin 1:8aa5cdb4ab67 6
Jonathan Austin 1:8aa5cdb4ab67 7 Permission is hereby granted, free of charge, to any person obtaining a
Jonathan Austin 1:8aa5cdb4ab67 8 copy of this software and associated documentation files (the "Software"),
Jonathan Austin 1:8aa5cdb4ab67 9 to deal in the Software without restriction, including without limitation
Jonathan Austin 1:8aa5cdb4ab67 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
Jonathan Austin 1:8aa5cdb4ab67 11 and/or sell copies of the Software, and to permit persons to whom the
Jonathan Austin 1:8aa5cdb4ab67 12 Software is furnished to do so, subject to the following conditions:
Jonathan Austin 1:8aa5cdb4ab67 13
Jonathan Austin 1:8aa5cdb4ab67 14 The above copyright notice and this permission notice shall be included in
Jonathan Austin 1:8aa5cdb4ab67 15 all copies or substantial portions of the Software.
Jonathan Austin 1:8aa5cdb4ab67 16
Jonathan Austin 1:8aa5cdb4ab67 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jonathan Austin 1:8aa5cdb4ab67 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jonathan Austin 1:8aa5cdb4ab67 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Jonathan Austin 1:8aa5cdb4ab67 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Jonathan Austin 1:8aa5cdb4ab67 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 23 DEALINGS IN THE SOFTWARE.
Jonathan Austin 1:8aa5cdb4ab67 24 */
Jonathan Austin 1:8aa5cdb4ab67 25
Jonathan Austin 1:8aa5cdb4ab67 26 /**
Jonathan Austin 1:8aa5cdb4ab67 27 * Class definition for a MicroBitImage.
Jonathan Austin 1:8aa5cdb4ab67 28 *
Jonathan Austin 1:8aa5cdb4ab67 29 * An MicroBitImage is a simple bitmap representation of an image.
Jonathan Austin 1:8aa5cdb4ab67 30 * n.b. This is a mutable, managed type.
Jonathan Austin 1:8aa5cdb4ab67 31 */
Jonathan Austin 1:8aa5cdb4ab67 32
Jonathan Austin 1:8aa5cdb4ab67 33 #include "MicroBitConfig.h"
Jonathan Austin 1:8aa5cdb4ab67 34 #include "MicroBitImage.h"
Jonathan Austin 1:8aa5cdb4ab67 35 #include "MicroBitFont.h"
Jonathan Austin 1:8aa5cdb4ab67 36 #include "MicroBitCompat.h"
Jonathan Austin 1:8aa5cdb4ab67 37 #include "ManagedString.h"
Jonathan Austin 1:8aa5cdb4ab67 38 #include "ErrorNo.h"
Jonathan Austin 1:8aa5cdb4ab67 39
Jonathan Austin 1:8aa5cdb4ab67 40
Jonathan Austin 1:8aa5cdb4ab67 41 /**
Jonathan Austin 1:8aa5cdb4ab67 42 * The null image. We actally create a small one byte buffer here, just to keep NULL pointers out of the equation.
Jonathan Austin 1:8aa5cdb4ab67 43 */
Jonathan Austin 1:8aa5cdb4ab67 44 static const uint16_t empty[] __attribute__ ((aligned (4))) = { 0xffff, 1, 1, 0, };
Jonathan Austin 1:8aa5cdb4ab67 45 MicroBitImage MicroBitImage::EmptyImage((ImageData*)(void*)empty);
Jonathan Austin 1:8aa5cdb4ab67 46
Jonathan Austin 1:8aa5cdb4ab67 47 /**
Jonathan Austin 1:8aa5cdb4ab67 48 * Default Constructor.
Jonathan Austin 1:8aa5cdb4ab67 49 * Creates a new reference to the empty MicroBitImage bitmap
Jonathan Austin 1:8aa5cdb4ab67 50 *
Jonathan Austin 1:8aa5cdb4ab67 51 * @code
Jonathan Austin 1:8aa5cdb4ab67 52 * MicroBitImage i(); //an empty image instance
Jonathan Austin 1:8aa5cdb4ab67 53 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 54 */
Jonathan Austin 1:8aa5cdb4ab67 55 MicroBitImage::MicroBitImage()
Jonathan Austin 1:8aa5cdb4ab67 56 {
Jonathan Austin 1:8aa5cdb4ab67 57 // Create new reference to the EmptyImage and we're done.
Jonathan Austin 1:8aa5cdb4ab67 58 init_empty();
Jonathan Austin 1:8aa5cdb4ab67 59 }
Jonathan Austin 1:8aa5cdb4ab67 60
Jonathan Austin 1:8aa5cdb4ab67 61
Jonathan Austin 1:8aa5cdb4ab67 62 /**
Jonathan Austin 1:8aa5cdb4ab67 63 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 64 * Create a blank bitmap representation of a given size.
Jonathan Austin 1:8aa5cdb4ab67 65 *
Jonathan Austin 1:8aa5cdb4ab67 66 * @param x the width of the image.
Jonathan Austin 1:8aa5cdb4ab67 67 *
Jonathan Austin 1:8aa5cdb4ab67 68 * @param y the height of the image.
Jonathan Austin 1:8aa5cdb4ab67 69 *
Jonathan Austin 1:8aa5cdb4ab67 70 * Bitmap buffer is linear, with 8 bits per pixel, row by row,
Jonathan Austin 1:8aa5cdb4ab67 71 * top to bottom with no word alignment. Stride is therefore the image width in pixels.
Jonathan Austin 1:8aa5cdb4ab67 72 * in where w and h are width and height respectively, the layout is therefore:
Jonathan Austin 1:8aa5cdb4ab67 73 *
Jonathan Austin 1:8aa5cdb4ab67 74 * |[0,0]...[w,o][1,0]...[w,1] ... [[w,h]
Jonathan Austin 1:8aa5cdb4ab67 75 *
Jonathan Austin 1:8aa5cdb4ab67 76 * A copy of the image is made in RAM, as images are mutable.
Jonathan Austin 1:8aa5cdb4ab67 77 *
Jonathan Austin 1:8aa5cdb4ab67 78 * TODO: Consider an immutable flavour, which might save us RAM for animation spritesheets...
Jonathan Austin 1:8aa5cdb4ab67 79 * ...as these could be kept in FLASH.
Jonathan Austin 1:8aa5cdb4ab67 80 */
Jonathan Austin 1:8aa5cdb4ab67 81 MicroBitImage::MicroBitImage(const int16_t x, const int16_t y)
Jonathan Austin 1:8aa5cdb4ab67 82 {
Jonathan Austin 1:8aa5cdb4ab67 83 this->init(x,y,NULL);
Jonathan Austin 1:8aa5cdb4ab67 84 }
Jonathan Austin 1:8aa5cdb4ab67 85
Jonathan Austin 1:8aa5cdb4ab67 86 /**
Jonathan Austin 1:8aa5cdb4ab67 87 * Copy Constructor.
Jonathan Austin 1:8aa5cdb4ab67 88 * Add ourselves as a reference to an existing MicroBitImage.
Jonathan Austin 1:8aa5cdb4ab67 89 *
Jonathan Austin 1:8aa5cdb4ab67 90 * @param image The MicroBitImage to reference.
Jonathan Austin 1:8aa5cdb4ab67 91 *
Jonathan Austin 1:8aa5cdb4ab67 92 * @code
Jonathan Austin 1:8aa5cdb4ab67 93 * MicroBitImage i("0,1,0,1,0\n");
Jonathan Austin 1:8aa5cdb4ab67 94 * MicroBitImage i2(i); //points to i
Jonathan Austin 1:8aa5cdb4ab67 95 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 96 */
Jonathan Austin 1:8aa5cdb4ab67 97 MicroBitImage::MicroBitImage(const MicroBitImage &image)
Jonathan Austin 1:8aa5cdb4ab67 98 {
Jonathan Austin 1:8aa5cdb4ab67 99 ptr = image.ptr;
Jonathan Austin 1:8aa5cdb4ab67 100 ptr->incr();
Jonathan Austin 1:8aa5cdb4ab67 101 }
Jonathan Austin 1:8aa5cdb4ab67 102
Jonathan Austin 1:8aa5cdb4ab67 103 /**
Jonathan Austin 1:8aa5cdb4ab67 104 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 105 * Create a blank bitmap representation of a given size.
Jonathan Austin 1:8aa5cdb4ab67 106 *
Jonathan Austin 1:8aa5cdb4ab67 107 * @param s A text based representation of the image given whitespace delimited numeric values.
Jonathan Austin 1:8aa5cdb4ab67 108 *
Jonathan Austin 1:8aa5cdb4ab67 109 * @code
Jonathan Austin 1:8aa5cdb4ab67 110 * MicroBitImage i("0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n"); // 5x5 image
Jonathan Austin 1:8aa5cdb4ab67 111 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 112 */
Jonathan Austin 1:8aa5cdb4ab67 113 MicroBitImage::MicroBitImage(const char *s)
Jonathan Austin 1:8aa5cdb4ab67 114 {
Jonathan Austin 1:8aa5cdb4ab67 115 int width = 0;
Jonathan Austin 1:8aa5cdb4ab67 116 int height = 0;
Jonathan Austin 1:8aa5cdb4ab67 117 int count = 0;
Jonathan Austin 1:8aa5cdb4ab67 118 int digit = 0;
Jonathan Austin 1:8aa5cdb4ab67 119
Jonathan Austin 1:8aa5cdb4ab67 120 char parseBuf[10];
Jonathan Austin 1:8aa5cdb4ab67 121
Jonathan Austin 1:8aa5cdb4ab67 122 const char *parseReadPtr;
Jonathan Austin 1:8aa5cdb4ab67 123 char *parseWritePtr;
Jonathan Austin 1:8aa5cdb4ab67 124 uint8_t *bitmapPtr;
Jonathan Austin 1:8aa5cdb4ab67 125
Jonathan Austin 1:8aa5cdb4ab67 126 if (s == NULL)
Jonathan Austin 1:8aa5cdb4ab67 127 {
Jonathan Austin 1:8aa5cdb4ab67 128 init_empty();
Jonathan Austin 1:8aa5cdb4ab67 129 return;
Jonathan Austin 1:8aa5cdb4ab67 130 }
Jonathan Austin 1:8aa5cdb4ab67 131
Jonathan Austin 1:8aa5cdb4ab67 132 // First pass: Parse the string to determine the geometry of the image.
Jonathan Austin 1:8aa5cdb4ab67 133 // We do this from first principles to avoid unecessary load of the strtok() libs etc.
Jonathan Austin 1:8aa5cdb4ab67 134 parseReadPtr = s;
Jonathan Austin 1:8aa5cdb4ab67 135
Jonathan Austin 1:8aa5cdb4ab67 136 while (*parseReadPtr)
Jonathan Austin 1:8aa5cdb4ab67 137 {
Jonathan Austin 1:8aa5cdb4ab67 138 if (isdigit(*parseReadPtr))
Jonathan Austin 1:8aa5cdb4ab67 139 {
Jonathan Austin 1:8aa5cdb4ab67 140 // Ignore numbers.
Jonathan Austin 1:8aa5cdb4ab67 141 digit = 1;
Jonathan Austin 1:8aa5cdb4ab67 142 }
Jonathan Austin 1:8aa5cdb4ab67 143 else if (*parseReadPtr =='\n')
Jonathan Austin 1:8aa5cdb4ab67 144 {
Jonathan Austin 1:8aa5cdb4ab67 145 if (digit)
Jonathan Austin 1:8aa5cdb4ab67 146 {
Jonathan Austin 1:8aa5cdb4ab67 147 count++;
Jonathan Austin 1:8aa5cdb4ab67 148 digit = 0;
Jonathan Austin 1:8aa5cdb4ab67 149 }
Jonathan Austin 1:8aa5cdb4ab67 150
Jonathan Austin 1:8aa5cdb4ab67 151 height++;
Jonathan Austin 1:8aa5cdb4ab67 152
Jonathan Austin 1:8aa5cdb4ab67 153 width = count > width ? count : width;
Jonathan Austin 1:8aa5cdb4ab67 154 count = 0;
Jonathan Austin 1:8aa5cdb4ab67 155 }
Jonathan Austin 1:8aa5cdb4ab67 156 else
Jonathan Austin 1:8aa5cdb4ab67 157 {
Jonathan Austin 1:8aa5cdb4ab67 158 if (digit)
Jonathan Austin 1:8aa5cdb4ab67 159 {
Jonathan Austin 1:8aa5cdb4ab67 160 count++;
Jonathan Austin 1:8aa5cdb4ab67 161 digit = 0;
Jonathan Austin 1:8aa5cdb4ab67 162 }
Jonathan Austin 1:8aa5cdb4ab67 163 }
Jonathan Austin 1:8aa5cdb4ab67 164
Jonathan Austin 1:8aa5cdb4ab67 165 parseReadPtr++;
Jonathan Austin 1:8aa5cdb4ab67 166 }
Jonathan Austin 1:8aa5cdb4ab67 167
Jonathan Austin 1:8aa5cdb4ab67 168 this->init(width, height, NULL);
Jonathan Austin 1:8aa5cdb4ab67 169
Jonathan Austin 1:8aa5cdb4ab67 170 // Second pass: collect the data.
Jonathan Austin 1:8aa5cdb4ab67 171 parseReadPtr = s;
Jonathan Austin 1:8aa5cdb4ab67 172 parseWritePtr = parseBuf;
Jonathan Austin 1:8aa5cdb4ab67 173 bitmapPtr = this->getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 174
Jonathan Austin 1:8aa5cdb4ab67 175 while (*parseReadPtr)
Jonathan Austin 1:8aa5cdb4ab67 176 {
Jonathan Austin 1:8aa5cdb4ab67 177 if (isdigit(*parseReadPtr))
Jonathan Austin 1:8aa5cdb4ab67 178 {
Jonathan Austin 1:8aa5cdb4ab67 179 *parseWritePtr = *parseReadPtr;
Jonathan Austin 1:8aa5cdb4ab67 180 parseWritePtr++;
Jonathan Austin 1:8aa5cdb4ab67 181 }
Jonathan Austin 1:8aa5cdb4ab67 182 else
Jonathan Austin 1:8aa5cdb4ab67 183 {
Jonathan Austin 1:8aa5cdb4ab67 184 *parseWritePtr = 0;
Jonathan Austin 1:8aa5cdb4ab67 185 if (parseWritePtr > parseBuf)
Jonathan Austin 1:8aa5cdb4ab67 186 {
Jonathan Austin 1:8aa5cdb4ab67 187 *bitmapPtr = atoi(parseBuf);
Jonathan Austin 1:8aa5cdb4ab67 188 bitmapPtr++;
Jonathan Austin 1:8aa5cdb4ab67 189 parseWritePtr = parseBuf;
Jonathan Austin 1:8aa5cdb4ab67 190 }
Jonathan Austin 1:8aa5cdb4ab67 191 }
Jonathan Austin 1:8aa5cdb4ab67 192
Jonathan Austin 1:8aa5cdb4ab67 193 parseReadPtr++;
Jonathan Austin 1:8aa5cdb4ab67 194 }
Jonathan Austin 1:8aa5cdb4ab67 195 }
Jonathan Austin 1:8aa5cdb4ab67 196
Jonathan Austin 1:8aa5cdb4ab67 197 /**
Jonathan Austin 1:8aa5cdb4ab67 198 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 199 * Create an image from a specially prepared constant array, with no copying. Will call ptr->incr().
Jonathan Austin 1:8aa5cdb4ab67 200 *
Jonathan Austin 1:8aa5cdb4ab67 201 * @param ptr The literal - first two bytes should be 0xff, then width, 0, height, 0, and the bitmap. Width and height are 16 bit. The literal has to be 4-byte aligned.
Jonathan Austin 1:8aa5cdb4ab67 202 *
Jonathan Austin 1:8aa5cdb4ab67 203 * @code
Jonathan Austin 1:8aa5cdb4ab67 204 * static const uint8_t heart[] __attribute__ ((aligned (4))) = { 0xff, 0xff, 10, 0, 5, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 205 * MicroBitImage i((ImageData*)(void*)heart);
Jonathan Austin 1:8aa5cdb4ab67 206 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 207 */
Jonathan Austin 1:8aa5cdb4ab67 208 MicroBitImage::MicroBitImage(ImageData *p)
Jonathan Austin 1:8aa5cdb4ab67 209 {
Jonathan Austin 1:8aa5cdb4ab67 210 ptr = p;
Jonathan Austin 1:8aa5cdb4ab67 211 ptr->incr();
Jonathan Austin 1:8aa5cdb4ab67 212 }
Jonathan Austin 1:8aa5cdb4ab67 213
Jonathan Austin 1:8aa5cdb4ab67 214 /**
Jonathan Austin 1:8aa5cdb4ab67 215 * Get current ptr, do not decr() it, and set the current instance to empty image.
Jonathan Austin 1:8aa5cdb4ab67 216 *
Jonathan Austin 1:8aa5cdb4ab67 217 * This is to be used by specialized runtimes which pass ImageData around.
Jonathan Austin 1:8aa5cdb4ab67 218 */
Jonathan Austin 1:8aa5cdb4ab67 219 ImageData *MicroBitImage::leakData()
Jonathan Austin 1:8aa5cdb4ab67 220 {
Jonathan Austin 1:8aa5cdb4ab67 221 ImageData* res = ptr;
Jonathan Austin 1:8aa5cdb4ab67 222 init_empty();
Jonathan Austin 1:8aa5cdb4ab67 223 return res;
Jonathan Austin 1:8aa5cdb4ab67 224 }
Jonathan Austin 1:8aa5cdb4ab67 225
Jonathan Austin 1:8aa5cdb4ab67 226
Jonathan Austin 1:8aa5cdb4ab67 227 /**
Jonathan Austin 1:8aa5cdb4ab67 228 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 229 * Create a bitmap representation of a given size, based on a given buffer.
Jonathan Austin 1:8aa5cdb4ab67 230 *
Jonathan Austin 1:8aa5cdb4ab67 231 * @param x the width of the image.
Jonathan Austin 1:8aa5cdb4ab67 232 *
Jonathan Austin 1:8aa5cdb4ab67 233 * @param y the height of the image.
Jonathan Austin 1:8aa5cdb4ab67 234 *
Jonathan Austin 1:8aa5cdb4ab67 235 * @param bitmap a 2D array representing the image.
Jonathan Austin 1:8aa5cdb4ab67 236 *
Jonathan Austin 1:8aa5cdb4ab67 237 * @code
Jonathan Austin 1:8aa5cdb4ab67 238 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 239 * MicroBitImage i(10,5,heart);
Jonathan Austin 1:8aa5cdb4ab67 240 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 241 */
Jonathan Austin 1:8aa5cdb4ab67 242 MicroBitImage::MicroBitImage(const int16_t x, const int16_t y, const uint8_t *bitmap)
Jonathan Austin 1:8aa5cdb4ab67 243 {
Jonathan Austin 1:8aa5cdb4ab67 244 this->init(x,y,bitmap);
Jonathan Austin 1:8aa5cdb4ab67 245 }
Jonathan Austin 1:8aa5cdb4ab67 246
Jonathan Austin 1:8aa5cdb4ab67 247 /**
Jonathan Austin 1:8aa5cdb4ab67 248 * Destructor.
Jonathan Austin 1:8aa5cdb4ab67 249 *
Jonathan Austin 1:8aa5cdb4ab67 250 * Removes buffer resources held by the instance.
Jonathan Austin 1:8aa5cdb4ab67 251 */
Jonathan Austin 1:8aa5cdb4ab67 252 MicroBitImage::~MicroBitImage()
Jonathan Austin 1:8aa5cdb4ab67 253 {
Jonathan Austin 1:8aa5cdb4ab67 254 ptr->decr();
Jonathan Austin 1:8aa5cdb4ab67 255 }
Jonathan Austin 1:8aa5cdb4ab67 256
Jonathan Austin 1:8aa5cdb4ab67 257 /**
Jonathan Austin 1:8aa5cdb4ab67 258 * Internal constructor which defaults to the EmptyImage instance variable
Jonathan Austin 1:8aa5cdb4ab67 259 */
Jonathan Austin 1:8aa5cdb4ab67 260 void MicroBitImage::init_empty()
Jonathan Austin 1:8aa5cdb4ab67 261 {
Jonathan Austin 1:8aa5cdb4ab67 262 ptr = (ImageData*)(void*)empty;
Jonathan Austin 1:8aa5cdb4ab67 263 }
Jonathan Austin 1:8aa5cdb4ab67 264
Jonathan Austin 1:8aa5cdb4ab67 265 /**
Jonathan Austin 1:8aa5cdb4ab67 266 * Internal constructor which provides sanity checking and initialises class properties.
Jonathan Austin 1:8aa5cdb4ab67 267 *
Jonathan Austin 1:8aa5cdb4ab67 268 * @param x the width of the image
Jonathan Austin 1:8aa5cdb4ab67 269 *
Jonathan Austin 1:8aa5cdb4ab67 270 * @param y the height of the image
Jonathan Austin 1:8aa5cdb4ab67 271 *
Jonathan Austin 1:8aa5cdb4ab67 272 * @param bitmap an array of integers that make up an image.
Jonathan Austin 1:8aa5cdb4ab67 273 */
Jonathan Austin 1:8aa5cdb4ab67 274 void MicroBitImage::init(const int16_t x, const int16_t y, const uint8_t *bitmap)
Jonathan Austin 1:8aa5cdb4ab67 275 {
Jonathan Austin 1:8aa5cdb4ab67 276 //sanity check size of image - you cannot have a negative sizes
Jonathan Austin 1:8aa5cdb4ab67 277 if(x < 0 || y < 0)
Jonathan Austin 1:8aa5cdb4ab67 278 {
Jonathan Austin 1:8aa5cdb4ab67 279 init_empty();
Jonathan Austin 1:8aa5cdb4ab67 280 return;
Jonathan Austin 1:8aa5cdb4ab67 281 }
Jonathan Austin 1:8aa5cdb4ab67 282
Jonathan Austin 1:8aa5cdb4ab67 283
Jonathan Austin 1:8aa5cdb4ab67 284 // Create a copy of the array
Jonathan Austin 1:8aa5cdb4ab67 285 ptr = (ImageData*)malloc(sizeof(ImageData) + x * y);
Jonathan Austin 1:8aa5cdb4ab67 286 ptr->init();
Jonathan Austin 1:8aa5cdb4ab67 287 ptr->width = x;
Jonathan Austin 1:8aa5cdb4ab67 288 ptr->height = y;
Jonathan Austin 1:8aa5cdb4ab67 289
Jonathan Austin 1:8aa5cdb4ab67 290 // create a linear buffer to represent the image. We could use a jagged/2D array here, but experimentation
Jonathan Austin 1:8aa5cdb4ab67 291 // showed this had a negative effect on memory management (heap fragmentation etc).
Jonathan Austin 1:8aa5cdb4ab67 292
Jonathan Austin 1:8aa5cdb4ab67 293 if (bitmap)
Jonathan Austin 1:8aa5cdb4ab67 294 this->printImage(x,y,bitmap);
Jonathan Austin 1:8aa5cdb4ab67 295 else
Jonathan Austin 1:8aa5cdb4ab67 296 this->clear();
Jonathan Austin 1:8aa5cdb4ab67 297 }
Jonathan Austin 1:8aa5cdb4ab67 298
Jonathan Austin 1:8aa5cdb4ab67 299 /**
Jonathan Austin 1:8aa5cdb4ab67 300 * Copy assign operation.
Jonathan Austin 1:8aa5cdb4ab67 301 *
Jonathan Austin 1:8aa5cdb4ab67 302 * Called when one MicroBitImage is assigned the value of another using the '=' operator.
Jonathan Austin 1:8aa5cdb4ab67 303 *
Jonathan Austin 1:8aa5cdb4ab67 304 * Decrement our reference count and free up the buffer as necessary.
Jonathan Austin 1:8aa5cdb4ab67 305 *
Jonathan Austin 1:8aa5cdb4ab67 306 * Then, update our buffer to refer to that of the supplied MicroBitImage,
Jonathan Austin 1:8aa5cdb4ab67 307 * and increase its reference count.
Jonathan Austin 1:8aa5cdb4ab67 308 *
Jonathan Austin 1:8aa5cdb4ab67 309 * @param s The MicroBitImage to reference.
Jonathan Austin 1:8aa5cdb4ab67 310 *
Jonathan Austin 1:8aa5cdb4ab67 311 * @code
Jonathan Austin 1:8aa5cdb4ab67 312 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 313 * MicroBitImage i(10,5,heart);
Jonathan Austin 1:8aa5cdb4ab67 314 * MicroBitImage i1();
Jonathan Austin 1:8aa5cdb4ab67 315 * i1 = i; // i1 now references i
Jonathan Austin 1:8aa5cdb4ab67 316 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 317 */
Jonathan Austin 1:8aa5cdb4ab67 318 MicroBitImage& MicroBitImage::operator = (const MicroBitImage& i)
Jonathan Austin 1:8aa5cdb4ab67 319 {
Jonathan Austin 1:8aa5cdb4ab67 320 if(ptr == i.ptr)
Jonathan Austin 1:8aa5cdb4ab67 321 return *this;
Jonathan Austin 1:8aa5cdb4ab67 322
Jonathan Austin 1:8aa5cdb4ab67 323 ptr->decr();
Jonathan Austin 1:8aa5cdb4ab67 324 ptr = i.ptr;
Jonathan Austin 1:8aa5cdb4ab67 325 ptr->incr();
Jonathan Austin 1:8aa5cdb4ab67 326
Jonathan Austin 1:8aa5cdb4ab67 327 return *this;
Jonathan Austin 1:8aa5cdb4ab67 328 }
Jonathan Austin 1:8aa5cdb4ab67 329
Jonathan Austin 1:8aa5cdb4ab67 330 /**
Jonathan Austin 1:8aa5cdb4ab67 331 * Equality operation.
Jonathan Austin 1:8aa5cdb4ab67 332 *
Jonathan Austin 1:8aa5cdb4ab67 333 * Called when one MicroBitImage is tested to be equal to another using the '==' operator.
Jonathan Austin 1:8aa5cdb4ab67 334 *
Jonathan Austin 1:8aa5cdb4ab67 335 * @param i The MicroBitImage to test ourselves against.
Jonathan Austin 1:8aa5cdb4ab67 336 *
Jonathan Austin 1:8aa5cdb4ab67 337 * @return true if this MicroBitImage is identical to the one supplied, false otherwise.
Jonathan Austin 1:8aa5cdb4ab67 338 *
Jonathan Austin 1:8aa5cdb4ab67 339 * @code
Jonathan Austin 1:8aa5cdb4ab67 340 * MicroBitDisplay display;
Jonathan Austin 1:8aa5cdb4ab67 341 * MicroBitImage i();
Jonathan Austin 1:8aa5cdb4ab67 342 * MicroBitImage i1();
Jonathan Austin 1:8aa5cdb4ab67 343 *
Jonathan Austin 1:8aa5cdb4ab67 344 * if(i == i1) //will be true
Jonathan Austin 1:8aa5cdb4ab67 345 * display.scroll("true");
Jonathan Austin 1:8aa5cdb4ab67 346 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 347 */
Jonathan Austin 1:8aa5cdb4ab67 348 bool MicroBitImage::operator== (const MicroBitImage& i)
Jonathan Austin 1:8aa5cdb4ab67 349 {
Jonathan Austin 1:8aa5cdb4ab67 350 if (ptr == i.ptr)
Jonathan Austin 1:8aa5cdb4ab67 351 return true;
Jonathan Austin 1:8aa5cdb4ab67 352 else
Jonathan Austin 1:8aa5cdb4ab67 353 return (ptr->width == i.ptr->width && ptr->height == i.ptr->height && (memcmp(getBitmap(), i.ptr->data, getSize())==0));
Jonathan Austin 1:8aa5cdb4ab67 354 }
Jonathan Austin 1:8aa5cdb4ab67 355
Jonathan Austin 1:8aa5cdb4ab67 356
Jonathan Austin 1:8aa5cdb4ab67 357 /**
Jonathan Austin 1:8aa5cdb4ab67 358 * Resets all pixels in this image to 0.
Jonathan Austin 1:8aa5cdb4ab67 359 *
Jonathan Austin 1:8aa5cdb4ab67 360 * @code
Jonathan Austin 1:8aa5cdb4ab67 361 * MicroBitImage i("0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n"); // 5x5 image
Jonathan Austin 1:8aa5cdb4ab67 362 * i.clear();
Jonathan Austin 1:8aa5cdb4ab67 363 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 364 */
Jonathan Austin 1:8aa5cdb4ab67 365 void MicroBitImage::clear()
Jonathan Austin 1:8aa5cdb4ab67 366 {
Jonathan Austin 1:8aa5cdb4ab67 367 memclr(getBitmap(), getSize());
Jonathan Austin 1:8aa5cdb4ab67 368 }
Jonathan Austin 1:8aa5cdb4ab67 369
Jonathan Austin 1:8aa5cdb4ab67 370 /**
Jonathan Austin 1:8aa5cdb4ab67 371 * Sets the pixel at the given co-ordinates to a given value.
Jonathan Austin 1:8aa5cdb4ab67 372 *
Jonathan Austin 1:8aa5cdb4ab67 373 * @param x The co-ordinate of the pixel to change.
Jonathan Austin 1:8aa5cdb4ab67 374 *
Jonathan Austin 1:8aa5cdb4ab67 375 * @param y The co-ordinate of the pixel to change.
Jonathan Austin 1:8aa5cdb4ab67 376 *
Jonathan Austin 1:8aa5cdb4ab67 377 * @param value The new value of the pixel (the brightness level 0-255)
Jonathan Austin 1:8aa5cdb4ab67 378 *
Jonathan Austin 1:8aa5cdb4ab67 379 * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 380 *
Jonathan Austin 1:8aa5cdb4ab67 381 * @code
Jonathan Austin 1:8aa5cdb4ab67 382 * MicroBitImage i("0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n"); // 5x5 image
Jonathan Austin 1:8aa5cdb4ab67 383 * i.setPixelValue(0,0,255);
Jonathan Austin 1:8aa5cdb4ab67 384 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 385 *
Jonathan Austin 1:8aa5cdb4ab67 386 * @note all coordinates originate from the top left of an image.
Jonathan Austin 1:8aa5cdb4ab67 387 */
Jonathan Austin 1:8aa5cdb4ab67 388 int MicroBitImage::setPixelValue(int16_t x , int16_t y, uint8_t value)
Jonathan Austin 1:8aa5cdb4ab67 389 {
Jonathan Austin 1:8aa5cdb4ab67 390 //sanity check
Jonathan Austin 1:8aa5cdb4ab67 391 if(x >= getWidth() || y >= getHeight() || x < 0 || y < 0)
Jonathan Austin 1:8aa5cdb4ab67 392 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 393
Jonathan Austin 1:8aa5cdb4ab67 394 this->getBitmap()[y*getWidth()+x] = value;
Jonathan Austin 1:8aa5cdb4ab67 395 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 396 }
Jonathan Austin 1:8aa5cdb4ab67 397
Jonathan Austin 1:8aa5cdb4ab67 398 /**
LancasterUniversity 69:b62f231e51ce 399 * Retrieves the value of a given pixel.
Jonathan Austin 1:8aa5cdb4ab67 400 *
Jonathan Austin 1:8aa5cdb4ab67 401 * @param x The x co-ordinate of the pixel to read. Must be within the dimensions of the image.
Jonathan Austin 1:8aa5cdb4ab67 402 *
Jonathan Austin 1:8aa5cdb4ab67 403 * @param y The y co-ordinate of the pixel to read. Must be within the dimensions of the image.
Jonathan Austin 1:8aa5cdb4ab67 404 *
Jonathan Austin 1:8aa5cdb4ab67 405 * @return The value assigned to the given pixel location (the brightness level 0-255), or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 406 *
Jonathan Austin 1:8aa5cdb4ab67 407 * @code
Jonathan Austin 1:8aa5cdb4ab67 408 * MicroBitImage i("0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n1,0,1,0,1\n0,1,0,1,0\n"); // 5x5 image
Jonathan Austin 1:8aa5cdb4ab67 409 * i.getPixelValue(0,0); //should be 0;
Jonathan Austin 1:8aa5cdb4ab67 410 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 411 */
Jonathan Austin 1:8aa5cdb4ab67 412 int MicroBitImage::getPixelValue(int16_t x , int16_t y)
Jonathan Austin 1:8aa5cdb4ab67 413 {
Jonathan Austin 1:8aa5cdb4ab67 414 //sanity check
Jonathan Austin 1:8aa5cdb4ab67 415 if(x >= getWidth() || y >= getHeight() || x < 0 || y < 0)
Jonathan Austin 1:8aa5cdb4ab67 416 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 417
Jonathan Austin 1:8aa5cdb4ab67 418 return this->getBitmap()[y*getWidth()+x];
Jonathan Austin 1:8aa5cdb4ab67 419 }
Jonathan Austin 1:8aa5cdb4ab67 420
Jonathan Austin 1:8aa5cdb4ab67 421 /**
Jonathan Austin 1:8aa5cdb4ab67 422 * Replaces the content of this image with that of a given 2D array representing
Jonathan Austin 1:8aa5cdb4ab67 423 * the image.
Jonathan Austin 1:8aa5cdb4ab67 424 *
Jonathan Austin 1:8aa5cdb4ab67 425 * @param x the width of the image. Must be within the dimensions of the image.
Jonathan Austin 1:8aa5cdb4ab67 426 *
Jonathan Austin 1:8aa5cdb4ab67 427 * @param y the width of the image. Must be within the dimensions of the image.
Jonathan Austin 1:8aa5cdb4ab67 428 *
Jonathan Austin 1:8aa5cdb4ab67 429 * @param bitmap a 2D array representing the image.
Jonathan Austin 1:8aa5cdb4ab67 430 *
Jonathan Austin 1:8aa5cdb4ab67 431 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 432 *
Jonathan Austin 1:8aa5cdb4ab67 433 * @code
Jonathan Austin 1:8aa5cdb4ab67 434 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 435 * MicroBitImage i();
Jonathan Austin 1:8aa5cdb4ab67 436 * i.printImage(0,0,heart);
Jonathan Austin 1:8aa5cdb4ab67 437 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 438 *
Jonathan Austin 1:8aa5cdb4ab67 439 * @note all coordinates originate from the top left of an image.
Jonathan Austin 1:8aa5cdb4ab67 440 */
Jonathan Austin 1:8aa5cdb4ab67 441 int MicroBitImage::printImage(int16_t width, int16_t height, const uint8_t *bitmap)
Jonathan Austin 1:8aa5cdb4ab67 442 {
Jonathan Austin 1:8aa5cdb4ab67 443 const uint8_t *pIn;
Jonathan Austin 1:8aa5cdb4ab67 444 uint8_t *pOut;
Jonathan Austin 1:8aa5cdb4ab67 445 int pixelsToCopyX, pixelsToCopyY;
Jonathan Austin 1:8aa5cdb4ab67 446
Jonathan Austin 1:8aa5cdb4ab67 447 // Sanity check.
Jonathan Austin 1:8aa5cdb4ab67 448 if (width <= 0 || width <= 0 || bitmap == NULL)
Jonathan Austin 1:8aa5cdb4ab67 449 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 450
Jonathan Austin 1:8aa5cdb4ab67 451 // Calcualte sane start pointer.
Jonathan Austin 1:8aa5cdb4ab67 452 pixelsToCopyX = min(width,this->getWidth());
Jonathan Austin 1:8aa5cdb4ab67 453 pixelsToCopyY = min(height,this->getHeight());
Jonathan Austin 1:8aa5cdb4ab67 454
Jonathan Austin 1:8aa5cdb4ab67 455 pIn = bitmap;
Jonathan Austin 1:8aa5cdb4ab67 456 pOut = this->getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 457
Jonathan Austin 1:8aa5cdb4ab67 458 // Copy the image, stride by stride.
Jonathan Austin 1:8aa5cdb4ab67 459 for (int i=0; i<pixelsToCopyY; i++)
Jonathan Austin 1:8aa5cdb4ab67 460 {
Jonathan Austin 1:8aa5cdb4ab67 461 memcpy(pOut, pIn, pixelsToCopyX);
Jonathan Austin 1:8aa5cdb4ab67 462 pIn += width;
Jonathan Austin 1:8aa5cdb4ab67 463 pOut += this->getWidth();
Jonathan Austin 1:8aa5cdb4ab67 464 }
Jonathan Austin 1:8aa5cdb4ab67 465
Jonathan Austin 1:8aa5cdb4ab67 466 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 467 }
Jonathan Austin 1:8aa5cdb4ab67 468
Jonathan Austin 1:8aa5cdb4ab67 469 /**
Jonathan Austin 1:8aa5cdb4ab67 470 * Pastes a given bitmap at the given co-ordinates.
Jonathan Austin 1:8aa5cdb4ab67 471 *
LancasterUniversity 69:b62f231e51ce 472 * Any pixels in the relevant area of this image are replaced.
Jonathan Austin 1:8aa5cdb4ab67 473 *
Jonathan Austin 1:8aa5cdb4ab67 474 * @param image The MicroBitImage to paste.
Jonathan Austin 1:8aa5cdb4ab67 475 *
Jonathan Austin 1:8aa5cdb4ab67 476 * @param x The leftmost X co-ordinate in this image where the given image should be pasted. Defaults to 0.
Jonathan Austin 1:8aa5cdb4ab67 477 *
Jonathan Austin 1:8aa5cdb4ab67 478 * @param y The uppermost Y co-ordinate in this image where the given image should be pasted. Defaults to 0.
Jonathan Austin 1:8aa5cdb4ab67 479 *
Jonathan Austin 1:8aa5cdb4ab67 480 * @param alpha set to 1 if transparency clear pixels in given image should be treated as transparent. Set to 0 otherwise. Defaults to 0.
Jonathan Austin 1:8aa5cdb4ab67 481 *
Jonathan Austin 1:8aa5cdb4ab67 482 * @return The number of pixels written.
Jonathan Austin 1:8aa5cdb4ab67 483 *
Jonathan Austin 1:8aa5cdb4ab67 484 * @code
Jonathan Austin 1:8aa5cdb4ab67 485 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 486 * MicroBitImage i(10,5,heart); // a big heart
Jonathan Austin 1:8aa5cdb4ab67 487 * i.paste(i, -5, 0); // a small heart
Jonathan Austin 1:8aa5cdb4ab67 488 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 489 */
Jonathan Austin 1:8aa5cdb4ab67 490 int MicroBitImage::paste(const MicroBitImage &image, int16_t x, int16_t y, uint8_t alpha)
Jonathan Austin 1:8aa5cdb4ab67 491 {
Jonathan Austin 1:8aa5cdb4ab67 492 uint8_t *pIn, *pOut;
Jonathan Austin 1:8aa5cdb4ab67 493 int cx, cy;
Jonathan Austin 1:8aa5cdb4ab67 494 int pxWritten = 0;
Jonathan Austin 1:8aa5cdb4ab67 495
Jonathan Austin 1:8aa5cdb4ab67 496 // Sanity check.
Jonathan Austin 1:8aa5cdb4ab67 497 // We permit writes that overlap us, but ones that are clearly out of scope we can filter early.
Jonathan Austin 1:8aa5cdb4ab67 498 if (x >= getWidth() || y >= getHeight() || x+image.getWidth() <= 0 || y+image.getHeight() <= 0)
Jonathan Austin 1:8aa5cdb4ab67 499 return 0;
Jonathan Austin 1:8aa5cdb4ab67 500
Jonathan Austin 1:8aa5cdb4ab67 501 //Calculate the number of byte we need to copy in each dimension.
Jonathan Austin 1:8aa5cdb4ab67 502 cx = x < 0 ? min(image.getWidth() + x, getWidth()) : min(image.getWidth(), getWidth() - x);
Jonathan Austin 1:8aa5cdb4ab67 503 cy = y < 0 ? min(image.getHeight() + y, getHeight()) : min(image.getHeight(), getHeight() - y);
Jonathan Austin 1:8aa5cdb4ab67 504
Jonathan Austin 1:8aa5cdb4ab67 505 // Calculate sane start pointer.
Jonathan Austin 1:8aa5cdb4ab67 506 pIn = image.ptr->data;
Jonathan Austin 1:8aa5cdb4ab67 507 pIn += (x < 0) ? -x : 0;
Jonathan Austin 1:8aa5cdb4ab67 508 pIn += (y < 0) ? -image.getWidth()*y : 0;
Jonathan Austin 1:8aa5cdb4ab67 509
Jonathan Austin 1:8aa5cdb4ab67 510 pOut = getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 511 pOut += (x > 0) ? x : 0;
Jonathan Austin 1:8aa5cdb4ab67 512 pOut += (y > 0) ? getWidth()*y : 0;
Jonathan Austin 1:8aa5cdb4ab67 513
Jonathan Austin 1:8aa5cdb4ab67 514 // Copy the image, stride by stride
Jonathan Austin 1:8aa5cdb4ab67 515 // If we want primitive transparecy, we do this byte by byte.
Jonathan Austin 1:8aa5cdb4ab67 516 // If we don't, use a more efficient block memory copy instead. Every little helps!
Jonathan Austin 1:8aa5cdb4ab67 517
Jonathan Austin 1:8aa5cdb4ab67 518 if (alpha)
Jonathan Austin 1:8aa5cdb4ab67 519 {
Jonathan Austin 1:8aa5cdb4ab67 520 for (int i=0; i<cy; i++)
Jonathan Austin 1:8aa5cdb4ab67 521 {
Jonathan Austin 1:8aa5cdb4ab67 522 for (int j=0; j<cx; j++)
Jonathan Austin 1:8aa5cdb4ab67 523 {
Jonathan Austin 1:8aa5cdb4ab67 524 // Copy this byte if appropriate.
Jonathan Austin 1:8aa5cdb4ab67 525 if (*(pIn+j) != 0){
Jonathan Austin 1:8aa5cdb4ab67 526 *(pOut+j) = *(pIn+j);
Jonathan Austin 1:8aa5cdb4ab67 527 pxWritten++;
Jonathan Austin 1:8aa5cdb4ab67 528 }
Jonathan Austin 1:8aa5cdb4ab67 529 }
Jonathan Austin 1:8aa5cdb4ab67 530
Jonathan Austin 1:8aa5cdb4ab67 531 pIn += image.getWidth();
Jonathan Austin 1:8aa5cdb4ab67 532 pOut += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 533 }
Jonathan Austin 1:8aa5cdb4ab67 534 }
Jonathan Austin 1:8aa5cdb4ab67 535 else
Jonathan Austin 1:8aa5cdb4ab67 536 {
Jonathan Austin 1:8aa5cdb4ab67 537 for (int i=0; i<cy; i++)
Jonathan Austin 1:8aa5cdb4ab67 538 {
Jonathan Austin 1:8aa5cdb4ab67 539 memcpy(pOut, pIn, cx);
Jonathan Austin 1:8aa5cdb4ab67 540
Jonathan Austin 1:8aa5cdb4ab67 541 pxWritten += cx;
Jonathan Austin 1:8aa5cdb4ab67 542 pIn += image.getWidth();
Jonathan Austin 1:8aa5cdb4ab67 543 pOut += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 544 }
Jonathan Austin 1:8aa5cdb4ab67 545 }
Jonathan Austin 1:8aa5cdb4ab67 546
Jonathan Austin 1:8aa5cdb4ab67 547 return pxWritten;
Jonathan Austin 1:8aa5cdb4ab67 548 }
Jonathan Austin 1:8aa5cdb4ab67 549
Jonathan Austin 1:8aa5cdb4ab67 550 /**
Jonathan Austin 1:8aa5cdb4ab67 551 * Prints a character to the display at the given location
Jonathan Austin 1:8aa5cdb4ab67 552 *
Jonathan Austin 1:8aa5cdb4ab67 553 * @param c The character to display.
Jonathan Austin 1:8aa5cdb4ab67 554 *
Jonathan Austin 1:8aa5cdb4ab67 555 * @param x The x co-ordinate of on the image to place the top left of the character. Defaults to 0.
Jonathan Austin 1:8aa5cdb4ab67 556 *
Jonathan Austin 1:8aa5cdb4ab67 557 * @param y The y co-ordinate of on the image to place the top left of the character. Defaults to 0.
Jonathan Austin 1:8aa5cdb4ab67 558 *
Jonathan Austin 1:8aa5cdb4ab67 559 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 560 *
Jonathan Austin 1:8aa5cdb4ab67 561 * @code
Jonathan Austin 1:8aa5cdb4ab67 562 * MicroBitImage i(5,5);
Jonathan Austin 1:8aa5cdb4ab67 563 * i.print('a');
Jonathan Austin 1:8aa5cdb4ab67 564 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 565 */
Jonathan Austin 1:8aa5cdb4ab67 566 int MicroBitImage::print(char c, int16_t x, int16_t y)
Jonathan Austin 1:8aa5cdb4ab67 567 {
Jonathan Austin 1:8aa5cdb4ab67 568 unsigned char v;
Jonathan Austin 1:8aa5cdb4ab67 569 int x1, y1;
Jonathan Austin 1:8aa5cdb4ab67 570
Jonathan Austin 1:8aa5cdb4ab67 571 MicroBitFont font = MicroBitFont::getSystemFont();
Jonathan Austin 1:8aa5cdb4ab67 572
Jonathan Austin 1:8aa5cdb4ab67 573 // Sanity check. Silently ignore anything out of bounds.
Jonathan Austin 1:8aa5cdb4ab67 574 if (x >= getWidth() || y >= getHeight() || c < MICROBIT_FONT_ASCII_START || c > font.asciiEnd)
Jonathan Austin 1:8aa5cdb4ab67 575 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 576
Jonathan Austin 1:8aa5cdb4ab67 577 // Paste.
Jonathan Austin 1:8aa5cdb4ab67 578 int offset = (c-MICROBIT_FONT_ASCII_START) * 5;
Jonathan Austin 1:8aa5cdb4ab67 579
Jonathan Austin 1:8aa5cdb4ab67 580 for (int row=0; row<MICROBIT_FONT_HEIGHT; row++)
Jonathan Austin 1:8aa5cdb4ab67 581 {
Jonathan Austin 1:8aa5cdb4ab67 582 v = (char)*(font.characters + offset);
Jonathan Austin 1:8aa5cdb4ab67 583
Jonathan Austin 1:8aa5cdb4ab67 584 offset++;
Jonathan Austin 1:8aa5cdb4ab67 585
Jonathan Austin 1:8aa5cdb4ab67 586 // Update our Y co-ord write position
Jonathan Austin 1:8aa5cdb4ab67 587 y1 = y+row;
Jonathan Austin 1:8aa5cdb4ab67 588
Jonathan Austin 1:8aa5cdb4ab67 589 for (int col = 0; col < MICROBIT_FONT_WIDTH; col++)
Jonathan Austin 1:8aa5cdb4ab67 590 {
Jonathan Austin 1:8aa5cdb4ab67 591 // Update our X co-ord write position
Jonathan Austin 1:8aa5cdb4ab67 592 x1 = x+col;
Jonathan Austin 1:8aa5cdb4ab67 593
Jonathan Austin 1:8aa5cdb4ab67 594 if (x1 < getWidth() && y1 < getHeight())
Jonathan Austin 1:8aa5cdb4ab67 595 this->getBitmap()[y1*getWidth()+x1] = (v & (0x10 >> col)) ? 255 : 0;
Jonathan Austin 1:8aa5cdb4ab67 596 }
Jonathan Austin 1:8aa5cdb4ab67 597 }
Jonathan Austin 1:8aa5cdb4ab67 598
Jonathan Austin 1:8aa5cdb4ab67 599 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 600 }
Jonathan Austin 1:8aa5cdb4ab67 601
Jonathan Austin 1:8aa5cdb4ab67 602
Jonathan Austin 1:8aa5cdb4ab67 603 /**
Jonathan Austin 1:8aa5cdb4ab67 604 * Shifts the pixels in this Image a given number of pixels to the left.
Jonathan Austin 1:8aa5cdb4ab67 605 *
Jonathan Austin 1:8aa5cdb4ab67 606 * @param n The number of pixels to shift.
Jonathan Austin 1:8aa5cdb4ab67 607 *
Jonathan Austin 1:8aa5cdb4ab67 608 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 609 *
Jonathan Austin 1:8aa5cdb4ab67 610 * @code
Jonathan Austin 1:8aa5cdb4ab67 611 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 612 * MicroBitImage i(10,5,heart); // a big heart
Jonathan Austin 1:8aa5cdb4ab67 613 * i.shiftLeft(5); // a small heart
Jonathan Austin 1:8aa5cdb4ab67 614 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 615 */
Jonathan Austin 1:8aa5cdb4ab67 616 int MicroBitImage::shiftLeft(int16_t n)
Jonathan Austin 1:8aa5cdb4ab67 617 {
Jonathan Austin 1:8aa5cdb4ab67 618 uint8_t *p = getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 619 int pixels = getWidth()-n;
Jonathan Austin 1:8aa5cdb4ab67 620
Jonathan Austin 1:8aa5cdb4ab67 621 if (n <= 0 )
Jonathan Austin 1:8aa5cdb4ab67 622 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 623
Jonathan Austin 1:8aa5cdb4ab67 624 if(n >= getWidth())
Jonathan Austin 1:8aa5cdb4ab67 625 {
Jonathan Austin 1:8aa5cdb4ab67 626 clear();
Jonathan Austin 1:8aa5cdb4ab67 627 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 628 }
Jonathan Austin 1:8aa5cdb4ab67 629
Jonathan Austin 1:8aa5cdb4ab67 630 for (int y = 0; y < getHeight(); y++)
Jonathan Austin 1:8aa5cdb4ab67 631 {
Jonathan Austin 1:8aa5cdb4ab67 632 // Copy, and blank fill the rightmost column.
Jonathan Austin 1:8aa5cdb4ab67 633 memcpy(p, p+n, pixels);
Jonathan Austin 1:8aa5cdb4ab67 634 memclr(p+pixels, n);
Jonathan Austin 1:8aa5cdb4ab67 635 p += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 636 }
Jonathan Austin 1:8aa5cdb4ab67 637
Jonathan Austin 1:8aa5cdb4ab67 638 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 639 }
Jonathan Austin 1:8aa5cdb4ab67 640
Jonathan Austin 1:8aa5cdb4ab67 641 /**
Jonathan Austin 1:8aa5cdb4ab67 642 * Shifts the pixels in this Image a given number of pixels to the right.
Jonathan Austin 1:8aa5cdb4ab67 643 *
Jonathan Austin 1:8aa5cdb4ab67 644 * @param n The number of pixels to shift.
Jonathan Austin 1:8aa5cdb4ab67 645 *
Jonathan Austin 1:8aa5cdb4ab67 646 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 647 *
Jonathan Austin 1:8aa5cdb4ab67 648 * @code
Jonathan Austin 1:8aa5cdb4ab67 649 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 650 * MicroBitImage i(10,5,heart); // a big heart
Jonathan Austin 1:8aa5cdb4ab67 651 * i.shiftLeft(5); // a small heart
Jonathan Austin 1:8aa5cdb4ab67 652 * i.shiftRight(5); // a big heart
Jonathan Austin 1:8aa5cdb4ab67 653 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 654 */
Jonathan Austin 1:8aa5cdb4ab67 655 int MicroBitImage::shiftRight(int16_t n)
Jonathan Austin 1:8aa5cdb4ab67 656 {
Jonathan Austin 1:8aa5cdb4ab67 657 uint8_t *p = getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 658 int pixels = getWidth()-n;
Jonathan Austin 1:8aa5cdb4ab67 659
Jonathan Austin 1:8aa5cdb4ab67 660 if (n <= 0)
Jonathan Austin 1:8aa5cdb4ab67 661 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 662
Jonathan Austin 1:8aa5cdb4ab67 663 if(n >= getWidth())
Jonathan Austin 1:8aa5cdb4ab67 664 {
Jonathan Austin 1:8aa5cdb4ab67 665 clear();
Jonathan Austin 1:8aa5cdb4ab67 666 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 667 }
Jonathan Austin 1:8aa5cdb4ab67 668
Jonathan Austin 1:8aa5cdb4ab67 669 for (int y = 0; y < getHeight(); y++)
Jonathan Austin 1:8aa5cdb4ab67 670 {
Jonathan Austin 1:8aa5cdb4ab67 671 // Copy, and blank fill the leftmost column.
Jonathan Austin 1:8aa5cdb4ab67 672 memmove(p+n, p, pixels);
Jonathan Austin 1:8aa5cdb4ab67 673 memclr(p, n);
Jonathan Austin 1:8aa5cdb4ab67 674 p += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 675 }
Jonathan Austin 1:8aa5cdb4ab67 676
Jonathan Austin 1:8aa5cdb4ab67 677 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 678 }
Jonathan Austin 1:8aa5cdb4ab67 679
Jonathan Austin 1:8aa5cdb4ab67 680
Jonathan Austin 1:8aa5cdb4ab67 681 /**
Jonathan Austin 1:8aa5cdb4ab67 682 * Shifts the pixels in this Image a given number of pixels to upward.
Jonathan Austin 1:8aa5cdb4ab67 683 *
Jonathan Austin 1:8aa5cdb4ab67 684 * @param n The number of pixels to shift.
Jonathan Austin 1:8aa5cdb4ab67 685 *
Jonathan Austin 1:8aa5cdb4ab67 686 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 687 *
Jonathan Austin 1:8aa5cdb4ab67 688 * @code
Jonathan Austin 1:8aa5cdb4ab67 689 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 690 * MicroBitImage i(10,5,heart);
Jonathan Austin 1:8aa5cdb4ab67 691 * i.shiftUp(1);
Jonathan Austin 1:8aa5cdb4ab67 692 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 693 */
Jonathan Austin 1:8aa5cdb4ab67 694 int MicroBitImage::shiftUp(int16_t n)
Jonathan Austin 1:8aa5cdb4ab67 695 {
Jonathan Austin 1:8aa5cdb4ab67 696 uint8_t *pOut, *pIn;
Jonathan Austin 1:8aa5cdb4ab67 697
Jonathan Austin 1:8aa5cdb4ab67 698 if (n <= 0 )
Jonathan Austin 1:8aa5cdb4ab67 699 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 700
Jonathan Austin 1:8aa5cdb4ab67 701 if(n >= getHeight())
Jonathan Austin 1:8aa5cdb4ab67 702 {
Jonathan Austin 1:8aa5cdb4ab67 703 clear();
Jonathan Austin 1:8aa5cdb4ab67 704 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 705 }
Jonathan Austin 1:8aa5cdb4ab67 706
Jonathan Austin 1:8aa5cdb4ab67 707 pOut = getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 708 pIn = getBitmap()+getWidth()*n;
Jonathan Austin 1:8aa5cdb4ab67 709
Jonathan Austin 1:8aa5cdb4ab67 710 for (int y = 0; y < getHeight(); y++)
Jonathan Austin 1:8aa5cdb4ab67 711 {
Jonathan Austin 1:8aa5cdb4ab67 712 // Copy, and blank fill the leftmost column.
Jonathan Austin 1:8aa5cdb4ab67 713 if (y < getHeight()-n)
Jonathan Austin 1:8aa5cdb4ab67 714 memcpy(pOut, pIn, getWidth());
Jonathan Austin 1:8aa5cdb4ab67 715 else
Jonathan Austin 1:8aa5cdb4ab67 716 memclr(pOut, getWidth());
Jonathan Austin 1:8aa5cdb4ab67 717
Jonathan Austin 1:8aa5cdb4ab67 718 pIn += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 719 pOut += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 720 }
Jonathan Austin 1:8aa5cdb4ab67 721
Jonathan Austin 1:8aa5cdb4ab67 722 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 723 }
Jonathan Austin 1:8aa5cdb4ab67 724
Jonathan Austin 1:8aa5cdb4ab67 725
Jonathan Austin 1:8aa5cdb4ab67 726 /**
Jonathan Austin 1:8aa5cdb4ab67 727 * Shifts the pixels in this Image a given number of pixels to downward.
Jonathan Austin 1:8aa5cdb4ab67 728 *
Jonathan Austin 1:8aa5cdb4ab67 729 * @param n The number of pixels to shift.
Jonathan Austin 1:8aa5cdb4ab67 730 *
Jonathan Austin 1:8aa5cdb4ab67 731 * @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER.
Jonathan Austin 1:8aa5cdb4ab67 732 *
Jonathan Austin 1:8aa5cdb4ab67 733 * @code
Jonathan Austin 1:8aa5cdb4ab67 734 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 735 * MicroBitImage i(10,5,heart);
Jonathan Austin 1:8aa5cdb4ab67 736 * i.shiftDown(1);
Jonathan Austin 1:8aa5cdb4ab67 737 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 738 */
Jonathan Austin 1:8aa5cdb4ab67 739 int MicroBitImage::shiftDown(int16_t n)
Jonathan Austin 1:8aa5cdb4ab67 740 {
Jonathan Austin 1:8aa5cdb4ab67 741 uint8_t *pOut, *pIn;
Jonathan Austin 1:8aa5cdb4ab67 742
Jonathan Austin 1:8aa5cdb4ab67 743 if (n <= 0 )
Jonathan Austin 1:8aa5cdb4ab67 744 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 745
Jonathan Austin 1:8aa5cdb4ab67 746 if(n >= getHeight())
Jonathan Austin 1:8aa5cdb4ab67 747 {
Jonathan Austin 1:8aa5cdb4ab67 748 clear();
Jonathan Austin 1:8aa5cdb4ab67 749 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 750 }
Jonathan Austin 1:8aa5cdb4ab67 751
Jonathan Austin 1:8aa5cdb4ab67 752 pOut = getBitmap() + getWidth()*(getHeight()-1);
Jonathan Austin 1:8aa5cdb4ab67 753 pIn = pOut - getWidth()*n;
Jonathan Austin 1:8aa5cdb4ab67 754
Jonathan Austin 1:8aa5cdb4ab67 755 for (int y = 0; y < getHeight(); y++)
Jonathan Austin 1:8aa5cdb4ab67 756 {
Jonathan Austin 1:8aa5cdb4ab67 757 // Copy, and blank fill the leftmost column.
Jonathan Austin 1:8aa5cdb4ab67 758 if (y < getHeight()-n)
Jonathan Austin 1:8aa5cdb4ab67 759 memcpy(pOut, pIn, getWidth());
Jonathan Austin 1:8aa5cdb4ab67 760 else
Jonathan Austin 1:8aa5cdb4ab67 761 memclr(pOut, getWidth());
Jonathan Austin 1:8aa5cdb4ab67 762
Jonathan Austin 1:8aa5cdb4ab67 763 pIn -= getWidth();
Jonathan Austin 1:8aa5cdb4ab67 764 pOut -= getWidth();
Jonathan Austin 1:8aa5cdb4ab67 765 }
Jonathan Austin 1:8aa5cdb4ab67 766
Jonathan Austin 1:8aa5cdb4ab67 767 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 768 }
Jonathan Austin 1:8aa5cdb4ab67 769
Jonathan Austin 1:8aa5cdb4ab67 770
Jonathan Austin 1:8aa5cdb4ab67 771 /**
Jonathan Austin 1:8aa5cdb4ab67 772 * Converts the bitmap to a csv ManagedString.
Jonathan Austin 1:8aa5cdb4ab67 773 *
Jonathan Austin 1:8aa5cdb4ab67 774 * @code
Jonathan Austin 1:8aa5cdb4ab67 775 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 776 * MicroBitImage i(10,5,heart);
Jonathan Austin 1:8aa5cdb4ab67 777 * uBit.serial.printString(i.toString()); // "0,1,0,1,0,0,0,0,0,0\n..."
Jonathan Austin 1:8aa5cdb4ab67 778 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 779 */
Jonathan Austin 1:8aa5cdb4ab67 780 ManagedString MicroBitImage::toString()
Jonathan Austin 1:8aa5cdb4ab67 781 {
Jonathan Austin 1:8aa5cdb4ab67 782 //width including commans and \n * height
Jonathan Austin 1:8aa5cdb4ab67 783 int stringSize = getSize() * 2;
Jonathan Austin 1:8aa5cdb4ab67 784
Jonathan Austin 1:8aa5cdb4ab67 785 //plus one for string terminator
Jonathan Austin 1:8aa5cdb4ab67 786 char parseBuffer[stringSize + 1];
Jonathan Austin 1:8aa5cdb4ab67 787
Jonathan Austin 1:8aa5cdb4ab67 788 parseBuffer[stringSize] = '\0';
Jonathan Austin 1:8aa5cdb4ab67 789
Jonathan Austin 1:8aa5cdb4ab67 790 uint8_t *bitmapPtr = getBitmap();
Jonathan Austin 1:8aa5cdb4ab67 791
Jonathan Austin 1:8aa5cdb4ab67 792 int parseIndex = 0;
Jonathan Austin 1:8aa5cdb4ab67 793 int widthCount = 0;
Jonathan Austin 1:8aa5cdb4ab67 794
Jonathan Austin 1:8aa5cdb4ab67 795 while (parseIndex < stringSize)
Jonathan Austin 1:8aa5cdb4ab67 796 {
Jonathan Austin 1:8aa5cdb4ab67 797 if(*bitmapPtr)
Jonathan Austin 1:8aa5cdb4ab67 798 parseBuffer[parseIndex] = '1';
Jonathan Austin 1:8aa5cdb4ab67 799 else
Jonathan Austin 1:8aa5cdb4ab67 800 parseBuffer[parseIndex] = '0';
Jonathan Austin 1:8aa5cdb4ab67 801
Jonathan Austin 1:8aa5cdb4ab67 802 parseIndex++;
Jonathan Austin 1:8aa5cdb4ab67 803
Jonathan Austin 1:8aa5cdb4ab67 804 if(widthCount == getWidth()-1)
Jonathan Austin 1:8aa5cdb4ab67 805 {
Jonathan Austin 1:8aa5cdb4ab67 806 parseBuffer[parseIndex] = '\n';
Jonathan Austin 1:8aa5cdb4ab67 807 widthCount = 0;
Jonathan Austin 1:8aa5cdb4ab67 808 }
Jonathan Austin 1:8aa5cdb4ab67 809 else
Jonathan Austin 1:8aa5cdb4ab67 810 {
Jonathan Austin 1:8aa5cdb4ab67 811 parseBuffer[parseIndex] = ',';
Jonathan Austin 1:8aa5cdb4ab67 812 widthCount++;
Jonathan Austin 1:8aa5cdb4ab67 813 }
Jonathan Austin 1:8aa5cdb4ab67 814
Jonathan Austin 1:8aa5cdb4ab67 815 parseIndex++;
Jonathan Austin 1:8aa5cdb4ab67 816 bitmapPtr++;
Jonathan Austin 1:8aa5cdb4ab67 817 }
Jonathan Austin 1:8aa5cdb4ab67 818
Jonathan Austin 1:8aa5cdb4ab67 819 return ManagedString(parseBuffer);
Jonathan Austin 1:8aa5cdb4ab67 820 }
Jonathan Austin 1:8aa5cdb4ab67 821
Jonathan Austin 1:8aa5cdb4ab67 822 /**
Jonathan Austin 1:8aa5cdb4ab67 823 * Crops the image to the given dimensions.
Jonathan Austin 1:8aa5cdb4ab67 824 *
Jonathan Austin 1:8aa5cdb4ab67 825 * @param startx the location to start the crop in the x-axis
Jonathan Austin 1:8aa5cdb4ab67 826 *
Jonathan Austin 1:8aa5cdb4ab67 827 * @param starty the location to start the crop in the y-axis
Jonathan Austin 1:8aa5cdb4ab67 828 *
Jonathan Austin 1:8aa5cdb4ab67 829 * @param width the width of the desired cropped region
Jonathan Austin 1:8aa5cdb4ab67 830 *
Jonathan Austin 1:8aa5cdb4ab67 831 * @param height the height of the desired cropped region
Jonathan Austin 1:8aa5cdb4ab67 832 *
Jonathan Austin 1:8aa5cdb4ab67 833 * @code
Jonathan Austin 1:8aa5cdb4ab67 834 * const uint8_t heart[] = { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; // a cute heart
Jonathan Austin 1:8aa5cdb4ab67 835 * MicroBitImage i(10,5,heart);
Jonathan Austin 1:8aa5cdb4ab67 836 * i.crop(0,0,2,2).toString() // "0,1\n1,1\n"
Jonathan Austin 1:8aa5cdb4ab67 837 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 838 */
Jonathan Austin 1:8aa5cdb4ab67 839 MicroBitImage MicroBitImage::crop(int startx, int starty, int cropWidth, int cropHeight)
Jonathan Austin 1:8aa5cdb4ab67 840 {
Jonathan Austin 1:8aa5cdb4ab67 841 int newWidth = startx + cropWidth;
Jonathan Austin 1:8aa5cdb4ab67 842 int newHeight = starty + cropHeight;
Jonathan Austin 1:8aa5cdb4ab67 843
Jonathan Austin 1:8aa5cdb4ab67 844 if (newWidth >= getWidth() || newWidth <=0)
Jonathan Austin 1:8aa5cdb4ab67 845 newWidth = getWidth();
Jonathan Austin 1:8aa5cdb4ab67 846
Jonathan Austin 1:8aa5cdb4ab67 847 if (newHeight >= getHeight() || newHeight <= 0)
Jonathan Austin 1:8aa5cdb4ab67 848 newHeight = getHeight();
Jonathan Austin 1:8aa5cdb4ab67 849
Jonathan Austin 1:8aa5cdb4ab67 850 //allocate our storage.
Jonathan Austin 1:8aa5cdb4ab67 851 uint8_t cropped[newWidth * newHeight];
Jonathan Austin 1:8aa5cdb4ab67 852
Jonathan Austin 1:8aa5cdb4ab67 853 //calculate the pointer to where we want to begin cropping
Jonathan Austin 1:8aa5cdb4ab67 854 uint8_t *copyPointer = getBitmap() + (getWidth() * starty) + startx;
Jonathan Austin 1:8aa5cdb4ab67 855
Jonathan Austin 1:8aa5cdb4ab67 856 //get a reference to our storage
Jonathan Austin 1:8aa5cdb4ab67 857 uint8_t *pastePointer = cropped;
Jonathan Austin 1:8aa5cdb4ab67 858
Jonathan Austin 1:8aa5cdb4ab67 859 //go through row by row and select our image.
Jonathan Austin 1:8aa5cdb4ab67 860 for (int i = starty; i < newHeight; i++)
Jonathan Austin 1:8aa5cdb4ab67 861 {
Jonathan Austin 1:8aa5cdb4ab67 862 memcpy(pastePointer, copyPointer, newWidth);
Jonathan Austin 1:8aa5cdb4ab67 863
Jonathan Austin 1:8aa5cdb4ab67 864 copyPointer += getWidth();
Jonathan Austin 1:8aa5cdb4ab67 865 pastePointer += newHeight;
Jonathan Austin 1:8aa5cdb4ab67 866 }
Jonathan Austin 1:8aa5cdb4ab67 867
Jonathan Austin 1:8aa5cdb4ab67 868 return MicroBitImage(newWidth, newHeight, cropped);
Jonathan Austin 1:8aa5cdb4ab67 869 }
Jonathan Austin 1:8aa5cdb4ab67 870
Jonathan Austin 1:8aa5cdb4ab67 871 /**
Jonathan Austin 1:8aa5cdb4ab67 872 * Check if image is read-only (i.e., residing in flash).
Jonathan Austin 1:8aa5cdb4ab67 873 */
Jonathan Austin 1:8aa5cdb4ab67 874 bool MicroBitImage::isReadOnly()
Jonathan Austin 1:8aa5cdb4ab67 875 {
Jonathan Austin 1:8aa5cdb4ab67 876 return ptr->isReadOnly();
Jonathan Austin 1:8aa5cdb4ab67 877 }
Jonathan Austin 1:8aa5cdb4ab67 878
Jonathan Austin 1:8aa5cdb4ab67 879 /**
Jonathan Austin 1:8aa5cdb4ab67 880 * Create a copy of the image bitmap. Used particularly, when isReadOnly() is true.
Jonathan Austin 1:8aa5cdb4ab67 881 *
Jonathan Austin 1:8aa5cdb4ab67 882 * @return an instance of MicroBitImage which can be modified independently of the current instance
Jonathan Austin 1:8aa5cdb4ab67 883 */
Jonathan Austin 1:8aa5cdb4ab67 884 MicroBitImage MicroBitImage::clone()
Jonathan Austin 1:8aa5cdb4ab67 885 {
Jonathan Austin 1:8aa5cdb4ab67 886 return MicroBitImage(getWidth(), getHeight(), getBitmap());
LancasterUniversity 69:b62f231e51ce 887 }