Essai d'application Lycée Malraux NSI
Dependencies: BLE_API nRF51822 mbed-dev-bin
source/types/MicroBitImage.cpp@1:8aa5cdb4ab67, 2016-04-07 (annotated)
- Committer:
- Jonathan Austin
- Date:
- Thu Apr 07 01:33:22 2016 +0100
- Revision:
- 1:8aa5cdb4ab67
- Child:
- 69:b62f231e51ce
Synchronized with git rev 55cb9199
Who changed what in which revision?
User | Revision | Line number | New 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 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 399 | * Retreives 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 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 472 | * Any pixels in the relvant 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()); |
Jonathan Austin |
1:8aa5cdb4ab67 | 887 | } |