3

我有一张 SD 卡、SD 卡扩展板和 Arduino Uno R3。我需要将图像写入 SD 卡。我更喜欢从原始数组转换为 JPEG/PNG/BMP/等,而不是使用易于编写但不能真正打开的格式(PPM、PGM 等)。

Arduino标准库中是否包含图像写入功能?如果没有,我应该使用什么库?我看过lodePNG,但遇到了奇怪的错误(vector is not a member of std)。

4

1 回答 1

2

当我从 Arduino 论坛 ( http://forum.arduino.cc/index.php?topic=112733.0 ) 上的一个线程中提取此代码时,我对这段代码的评价为零。它将 .bmp 文件写入 SD 卡。

另一项讨论表明,由于与 JPG 和 PNG 文件相关的压缩算法,使这些工作的代码量更难以适应 Arduino,这在我的脑海中是有道理的(http://forum.arduino.cc /index.php?topic=76376.0)。

希望这可以帮助。绝对不是 Arduino 的专家——只是稍微修改了一下。

#include <SdFat.h>
#include <SdFatUtil.h>

/*
 WRITE BMP TO SD CARD
 Jeff Thompson
 Summer 2012

 TO USE MEGA:
 The SdFat library must be edited slightly to use a Mega - in line 87
 of SdFatConfig.h, change to:

   #define MEGA_SOFT_SPI 1

 (this uses pins 10-13 for writing to the card)

 Writes pixel data to an SD card, saved as a BMP file.  Lots of code
 via the following...

 BMP header and pixel format:
   http://stackoverflow.com/a/2654860

 SD save:
   http://arduino.cc/forum/index.php?topic=112733 (lots of thanks!)
 ... and the SdFat example files too

 www.jeffreythompson.org
 */

char name[] = "9px_0000.bmp";       // filename convention (will auto-increment)
const int w = 16;                   // image width in pixels
const int h = 9;                    // " height
const boolean debugPrint = true;    // print details of process over serial?

const int imgSize = w*h;
int px[w*h];                        // actual pixel data (grayscale - added programatically below)

SdFat sd;
SdFile file;
const uint8_t cardPin = 8;          // pin that the SD is connected to (d8 for SparkFun MicroSD shield)

void setup() {

  // iteratively create pixel data
  int increment = 256/(w*h);        // divide color range (0-255) by total # of px
  for (int i=0; i<imgSize; i++) {
    px[i] = i * increment;          // creates a gradient across pixels for testing
  }

  // SD setup
  Serial.begin(9600);
  if (!sd.init(SPI_FULL_SPEED, cardPin)) {
    sd.initErrorHalt();
    Serial.println("---");
  }

  // if name exists, create new filename
  for (int i=0; i<10000; i++) {
    name[4] = (i/1000)%10 + '0';    // thousands place
    name[5] = (i/100)%10 + '0';     // hundreds
    name[6] = (i/10)%10 + '0';      // tens
    name[7] = i%10 + '0';           // ones
    if (file.open(name, O_CREAT | O_EXCL | O_WRITE)) {
      break;
    }
  }

  // set fileSize (used in bmp header)
  int rowSize = 4 * ((3*w + 3)/4);      // how many bytes in the row (used to create padding)
  int fileSize = 54 + h*rowSize;        // headers (54 bytes) + pixel data

  // create image data; heavily modified version via:
  // http://stackoverflow.com/a/2654860
  unsigned char *img = NULL;            // image data
  if (img) {                            // if there's already data in the array, clear it
    free(img);
  }
  img = (unsigned char *)malloc(3*imgSize);

  for (int y=0; y<h; y++) {
    for (int x=0; x<w; x++) {
      int colorVal = px[y*w + x];                        // classic formula for px listed in line
      img[(y*w + x)*3+0] = (unsigned char)(colorVal);    // R
      img[(y*w + x)*3+1] = (unsigned char)(colorVal);    // G
      img[(y*w + x)*3+2] = (unsigned char)(colorVal);    // B
      // padding (the 4th byte) will be added later as needed...
    }
  }

  // print px and img data for debugging
  if (debugPrint) {
    Serial.print("\nWriting \"");
    Serial.print(name);
    Serial.print("\" to file...\n");
    for (int i=0; i<imgSize; i++) {
      Serial.print(px[i]);
      Serial.print("  ");
    }
  }

  // create padding (based on the number of pixels in a row
  unsigned char bmpPad[rowSize - 3*w];
  for (int i=0; i<sizeof(bmpPad); i++) {         // fill with 0s
    bmpPad[i] = 0;
  }

  // create file headers (also taken from StackOverflow example)
  unsigned char bmpFileHeader[14] = {            // file header (always starts with BM!)
    'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0   };
  unsigned char bmpInfoHeader[40] = {            // info about the file (size, etc)
    40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0   };

  bmpFileHeader[ 2] = (unsigned char)(fileSize      );
  bmpFileHeader[ 3] = (unsigned char)(fileSize >>  8);
  bmpFileHeader[ 4] = (unsigned char)(fileSize >> 16);
  bmpFileHeader[ 5] = (unsigned char)(fileSize >> 24);

  bmpInfoHeader[ 4] = (unsigned char)(       w      );
  bmpInfoHeader[ 5] = (unsigned char)(       w >>  8);
  bmpInfoHeader[ 6] = (unsigned char)(       w >> 16);
  bmpInfoHeader[ 7] = (unsigned char)(       w >> 24);
  bmpInfoHeader[ 8] = (unsigned char)(       h      );
  bmpInfoHeader[ 9] = (unsigned char)(       h >>  8);
  bmpInfoHeader[10] = (unsigned char)(       h >> 16);
  bmpInfoHeader[11] = (unsigned char)(       h >> 24);

  // write the file (thanks forum!)
  file.write(bmpFileHeader, sizeof(bmpFileHeader));    // write file header
  file.write(bmpInfoHeader, sizeof(bmpInfoHeader));    // " info header

  for (int i=0; i<h; i++) {                            // iterate image array
    file.write(img+(w*(h-i-1)*3), 3*w);                // write px data
    file.write(bmpPad, (4-(w*3)%4)%4);                 // and padding as needed
  }
  file.close();                                        // close file when done writing

  if (debugPrint) {
    Serial.print("\n\n---\n");
  }
}

void loop() { }
于 2013-05-23T22:38:01.530 回答