Image.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
  2. #include "Image.h"
  3. #include "bmp/BMPParser.h"
  4. #include "Canvas.h"
  5. #include <cerrno>
  6. #include <cstdlib>
  7. #include <cstring>
  8. #include <node_buffer.h>
  9. /* Cairo limit:
  10. * https://lists.cairographics.org/archives/cairo/2010-December/021422.html
  11. */
  12. static constexpr int canvas_max_side = (1 << 15) - 1;
  13. #ifdef HAVE_GIF
  14. typedef struct {
  15. uint8_t *buf;
  16. unsigned len;
  17. unsigned pos;
  18. } gif_data_t;
  19. #endif
  20. #ifdef HAVE_JPEG
  21. #include <csetjmp>
  22. struct canvas_jpeg_error_mgr: jpeg_error_mgr {
  23. Image* image;
  24. jmp_buf setjmp_buffer;
  25. };
  26. #endif
  27. /*
  28. * Read closure used by loadFromBuffer.
  29. */
  30. typedef struct {
  31. unsigned len;
  32. uint8_t *buf;
  33. } read_closure_t;
  34. using namespace v8;
  35. Nan::Persistent<FunctionTemplate> Image::constructor;
  36. /*
  37. * Initialize Image.
  38. */
  39. void
  40. Image::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
  41. Nan::HandleScope scope;
  42. Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(Image::New);
  43. constructor.Reset(ctor);
  44. ctor->InstanceTemplate()->SetInternalFieldCount(1);
  45. ctor->SetClassName(Nan::New("Image").ToLocalChecked());
  46. // Prototype
  47. Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
  48. Nan::SetAccessor(proto, Nan::New("complete").ToLocalChecked(), GetComplete);
  49. Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth);
  50. Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight);
  51. Nan::SetAccessor(proto, Nan::New("naturalWidth").ToLocalChecked(), GetNaturalWidth);
  52. Nan::SetAccessor(proto, Nan::New("naturalHeight").ToLocalChecked(), GetNaturalHeight);
  53. Nan::SetAccessor(proto, Nan::New("dataMode").ToLocalChecked(), GetDataMode, SetDataMode);
  54. ctor->Set(Nan::New("MODE_IMAGE").ToLocalChecked(), Nan::New<Number>(DATA_IMAGE));
  55. ctor->Set(Nan::New("MODE_MIME").ToLocalChecked(), Nan::New<Number>(DATA_MIME));
  56. Local<Context> ctx = Nan::GetCurrentContext();
  57. Nan::Set(target, Nan::New("Image").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked());
  58. // Used internally in lib/image.js
  59. NAN_EXPORT(target, GetSource);
  60. NAN_EXPORT(target, SetSource);
  61. }
  62. /*
  63. * Initialize a new Image.
  64. */
  65. NAN_METHOD(Image::New) {
  66. if (!info.IsConstructCall()) {
  67. return Nan::ThrowTypeError("Class constructors cannot be invoked without 'new'");
  68. }
  69. Image *img = new Image;
  70. img->data_mode = DATA_IMAGE;
  71. img->Wrap(info.This());
  72. Nan::Set(info.This(), Nan::New("onload").ToLocalChecked(), Nan::Null()).Check();
  73. Nan::Set(info.This(), Nan::New("onerror").ToLocalChecked(), Nan::Null()).Check();
  74. info.GetReturnValue().Set(info.This());
  75. }
  76. /*
  77. * Get complete boolean.
  78. */
  79. NAN_GETTER(Image::GetComplete) {
  80. info.GetReturnValue().Set(Nan::New<Boolean>(true));
  81. }
  82. /*
  83. * Get dataMode.
  84. */
  85. NAN_GETTER(Image::GetDataMode) {
  86. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  87. Nan::ThrowTypeError("Method Image.GetDataMode called on incompatible receiver");
  88. return;
  89. }
  90. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  91. info.GetReturnValue().Set(Nan::New<Number>(img->data_mode));
  92. }
  93. /*
  94. * Set dataMode.
  95. */
  96. NAN_SETTER(Image::SetDataMode) {
  97. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  98. Nan::ThrowTypeError("Method Image.SetDataMode called on incompatible receiver");
  99. return;
  100. }
  101. if (value->IsNumber()) {
  102. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  103. int mode = Nan::To<uint32_t>(value).FromMaybe(0);
  104. img->data_mode = (data_mode_t) mode;
  105. }
  106. }
  107. /*
  108. * Get natural width
  109. */
  110. NAN_GETTER(Image::GetNaturalWidth) {
  111. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  112. Nan::ThrowTypeError("Method Image.GetNaturalWidth called on incompatible receiver");
  113. return;
  114. }
  115. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  116. info.GetReturnValue().Set(Nan::New<Number>(img->naturalWidth));
  117. }
  118. /*
  119. * Get width.
  120. */
  121. NAN_GETTER(Image::GetWidth) {
  122. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  123. Nan::ThrowTypeError("Method Image.GetWidth called on incompatible receiver");
  124. return;
  125. }
  126. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  127. info.GetReturnValue().Set(Nan::New<Number>(img->width));
  128. }
  129. /*
  130. * Set width.
  131. */
  132. NAN_SETTER(Image::SetWidth) {
  133. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  134. Nan::ThrowTypeError("Method Image.SetWidth called on incompatible receiver");
  135. return;
  136. }
  137. if (value->IsNumber()) {
  138. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  139. img->width = Nan::To<uint32_t>(value).FromMaybe(0);
  140. }
  141. }
  142. /*
  143. * Get natural height
  144. */
  145. NAN_GETTER(Image::GetNaturalHeight) {
  146. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  147. Nan::ThrowTypeError("Method Image.GetNaturalHeight called on incompatible receiver");
  148. return;
  149. }
  150. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  151. info.GetReturnValue().Set(Nan::New<Number>(img->naturalHeight));
  152. }
  153. /*
  154. * Get height.
  155. */
  156. NAN_GETTER(Image::GetHeight) {
  157. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  158. Nan::ThrowTypeError("Method Image.GetHeight called on incompatible receiver");
  159. return;
  160. }
  161. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  162. info.GetReturnValue().Set(Nan::New<Number>(img->height));
  163. }
  164. /*
  165. * Set height.
  166. */
  167. NAN_SETTER(Image::SetHeight) {
  168. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  169. // #1534
  170. Nan::ThrowTypeError("Method Image.SetHeight called on incompatible receiver");
  171. return;
  172. }
  173. if (value->IsNumber()) {
  174. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  175. img->height = Nan::To<uint32_t>(value).FromMaybe(0);
  176. }
  177. }
  178. /*
  179. * Get src path.
  180. */
  181. NAN_METHOD(Image::GetSource){
  182. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  183. // #1534
  184. Nan::ThrowTypeError("Method Image.GetSource called on incompatible receiver");
  185. return;
  186. }
  187. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  188. info.GetReturnValue().Set(Nan::New<String>(img->filename ? img->filename : "").ToLocalChecked());
  189. }
  190. /*
  191. * Clean up assets and variables.
  192. */
  193. void
  194. Image::clearData() {
  195. if (_surface) {
  196. cairo_surface_destroy(_surface);
  197. Nan::AdjustExternalMemory(-_data_len);
  198. _data_len = 0;
  199. _surface = NULL;
  200. }
  201. delete[] _data;
  202. _data = nullptr;
  203. free(filename);
  204. filename = NULL;
  205. #ifdef HAVE_RSVG
  206. if (_rsvg != NULL) {
  207. g_object_unref(_rsvg);
  208. _rsvg = NULL;
  209. }
  210. #endif
  211. width = height = 0;
  212. naturalWidth = naturalHeight = 0;
  213. state = DEFAULT;
  214. }
  215. /*
  216. * Set src path.
  217. */
  218. NAN_METHOD(Image::SetSource){
  219. if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
  220. // #1534
  221. Nan::ThrowTypeError("Method Image.SetSource called on incompatible receiver");
  222. return;
  223. }
  224. Image *img = Nan::ObjectWrap::Unwrap<Image>(info.This());
  225. cairo_status_t status = CAIRO_STATUS_READ_ERROR;
  226. Local<Value> value = info[0];
  227. img->clearData();
  228. // Clear errno in case some unrelated previous syscall failed
  229. errno = 0;
  230. // url string
  231. if (value->IsString()) {
  232. Nan::Utf8String src(value);
  233. if (img->filename) free(img->filename);
  234. img->filename = strdup(*src);
  235. status = img->load();
  236. // Buffer
  237. } else if (node::Buffer::HasInstance(value)) {
  238. uint8_t *buf = (uint8_t *) node::Buffer::Data(Nan::To<Object>(value).ToLocalChecked());
  239. unsigned len = node::Buffer::Length(Nan::To<Object>(value).ToLocalChecked());
  240. status = img->loadFromBuffer(buf, len);
  241. }
  242. if (status) {
  243. Local<Value> onerrorFn = Nan::Get(info.This(), Nan::New("onerror").ToLocalChecked()).ToLocalChecked();
  244. if (onerrorFn->IsFunction()) {
  245. Local<Value> argv[1];
  246. CanvasError errorInfo = img->errorInfo;
  247. if (errorInfo.cerrno) {
  248. argv[0] = Nan::ErrnoException(errorInfo.cerrno, errorInfo.syscall.c_str(), errorInfo.message.c_str(), errorInfo.path.c_str());
  249. } else if (!errorInfo.message.empty()) {
  250. argv[0] = Nan::Error(Nan::New(errorInfo.message).ToLocalChecked());
  251. } else {
  252. argv[0] = Nan::Error(Nan::New(cairo_status_to_string(status)).ToLocalChecked());
  253. }
  254. Local<Context> ctx = Nan::GetCurrentContext();
  255. Nan::Call(onerrorFn.As<Function>(), ctx->Global(), 1, argv);
  256. }
  257. } else {
  258. img->loaded();
  259. Local<Value> onloadFn = Nan::Get(info.This(), Nan::New("onload").ToLocalChecked()).ToLocalChecked();
  260. if (onloadFn->IsFunction()) {
  261. Local<Context> ctx = Nan::GetCurrentContext();
  262. Nan::Call(onloadFn.As<Function>(), ctx->Global(), 0, NULL);
  263. }
  264. }
  265. }
  266. /*
  267. * Load image data from `buf` by sniffing
  268. * the bytes to determine format.
  269. */
  270. cairo_status_t
  271. Image::loadFromBuffer(uint8_t *buf, unsigned len) {
  272. uint8_t data[4] = {0};
  273. memcpy(data, buf, (len < 4 ? len : 4) * sizeof(uint8_t));
  274. if (isPNG(data)) return loadPNGFromBuffer(buf);
  275. if (isGIF(data)) {
  276. #ifdef HAVE_GIF
  277. return loadGIFFromBuffer(buf, len);
  278. #else
  279. this->errorInfo.set("node-canvas was built without GIF support");
  280. return CAIRO_STATUS_READ_ERROR;
  281. #endif
  282. }
  283. if (isJPEG(data)) {
  284. #ifdef HAVE_JPEG
  285. if (DATA_IMAGE == data_mode) return loadJPEGFromBuffer(buf, len);
  286. if (DATA_MIME == data_mode) return decodeJPEGBufferIntoMimeSurface(buf, len);
  287. if ((DATA_IMAGE | DATA_MIME) == data_mode) {
  288. cairo_status_t status;
  289. status = loadJPEGFromBuffer(buf, len);
  290. if (status) return status;
  291. return assignDataAsMime(buf, len, CAIRO_MIME_TYPE_JPEG);
  292. }
  293. #else // HAVE_JPEG
  294. this->errorInfo.set("node-canvas was built without JPEG support");
  295. return CAIRO_STATUS_READ_ERROR;
  296. #endif
  297. }
  298. // confirm svg using first 1000 chars
  299. // if a very long comment precedes the root <svg> tag, isSVG returns false
  300. unsigned head_len = (len < 1000 ? len : 1000);
  301. if (isSVG(buf, head_len)) {
  302. #ifdef HAVE_RSVG
  303. return loadSVGFromBuffer(buf, len);
  304. #else
  305. this->errorInfo.set("node-canvas was built without SVG support");
  306. return CAIRO_STATUS_READ_ERROR;
  307. #endif
  308. }
  309. if (isBMP(buf, len))
  310. return loadBMPFromBuffer(buf, len);
  311. this->errorInfo.set("Unsupported image type");
  312. return CAIRO_STATUS_READ_ERROR;
  313. }
  314. /*
  315. * Load PNG data from `buf`.
  316. */
  317. cairo_status_t
  318. Image::loadPNGFromBuffer(uint8_t *buf) {
  319. read_closure_t closure;
  320. closure.len = 0;
  321. closure.buf = buf;
  322. _surface = cairo_image_surface_create_from_png_stream(readPNG, &closure);
  323. cairo_status_t status = cairo_surface_status(_surface);
  324. if (status) return status;
  325. return CAIRO_STATUS_SUCCESS;
  326. }
  327. /*
  328. * Read PNG data.
  329. */
  330. cairo_status_t
  331. Image::readPNG(void *c, uint8_t *data, unsigned int len) {
  332. read_closure_t *closure = (read_closure_t *) c;
  333. memcpy(data, closure->buf + closure->len, len);
  334. closure->len += len;
  335. return CAIRO_STATUS_SUCCESS;
  336. }
  337. /*
  338. * Initialize a new Image.
  339. */
  340. Image::Image() {
  341. filename = NULL;
  342. _data = nullptr;
  343. _data_len = 0;
  344. _surface = NULL;
  345. width = height = 0;
  346. naturalWidth = naturalHeight = 0;
  347. state = DEFAULT;
  348. #ifdef HAVE_RSVG
  349. _rsvg = NULL;
  350. _is_svg = false;
  351. _svg_last_width = _svg_last_height = 0;
  352. #endif
  353. }
  354. /*
  355. * Destroy image and associated surface.
  356. */
  357. Image::~Image() {
  358. clearData();
  359. }
  360. /*
  361. * Initiate image loading.
  362. */
  363. cairo_status_t
  364. Image::load() {
  365. if (LOADING != state) {
  366. state = LOADING;
  367. return loadSurface();
  368. }
  369. return CAIRO_STATUS_READ_ERROR;
  370. }
  371. /*
  372. * Set state, assign dimensions.
  373. */
  374. void
  375. Image::loaded() {
  376. Nan::HandleScope scope;
  377. state = COMPLETE;
  378. width = naturalWidth = cairo_image_surface_get_width(_surface);
  379. height = naturalHeight = cairo_image_surface_get_height(_surface);
  380. _data_len = naturalHeight * cairo_image_surface_get_stride(_surface);
  381. Nan::AdjustExternalMemory(_data_len);
  382. }
  383. /*
  384. * Returns this image's surface.
  385. */
  386. cairo_surface_t *Image::surface() {
  387. #ifdef HAVE_RSVG
  388. if (_is_svg && (_svg_last_width != width || _svg_last_height != height)) {
  389. if (_surface != NULL) {
  390. cairo_surface_destroy(_surface);
  391. _surface = NULL;
  392. }
  393. cairo_status_t status = renderSVGToSurface();
  394. if (status != CAIRO_STATUS_SUCCESS) {
  395. g_object_unref(_rsvg);
  396. Nan::ThrowError(Canvas::Error(status));
  397. return NULL;
  398. }
  399. }
  400. #endif
  401. return _surface;
  402. }
  403. /*
  404. * Load cairo surface from the image src.
  405. *
  406. * TODO: support more formats
  407. * TODO: use node IO or at least thread pool
  408. */
  409. cairo_status_t
  410. Image::loadSurface() {
  411. FILE *stream = fopen(filename, "rb");
  412. if (!stream) {
  413. this->errorInfo.set(NULL, "fopen", errno, filename);
  414. return CAIRO_STATUS_READ_ERROR;
  415. }
  416. uint8_t buf[5];
  417. if (1 != fread(&buf, 5, 1, stream)) {
  418. fclose(stream);
  419. return CAIRO_STATUS_READ_ERROR;
  420. }
  421. rewind(stream);
  422. // png
  423. if (isPNG(buf)) {
  424. fclose(stream);
  425. return loadPNG();
  426. }
  427. if (isGIF(buf)) {
  428. #ifdef HAVE_GIF
  429. return loadGIF(stream);
  430. #else
  431. this->errorInfo.set("node-canvas was built without GIF support");
  432. return CAIRO_STATUS_READ_ERROR;
  433. #endif
  434. }
  435. if (isJPEG(buf)) {
  436. #ifdef HAVE_JPEG
  437. return loadJPEG(stream);
  438. #else
  439. this->errorInfo.set("node-canvas was built without JPEG support");
  440. return CAIRO_STATUS_READ_ERROR;
  441. #endif
  442. }
  443. // confirm svg using first 1000 chars
  444. // if a very long comment precedes the root <svg> tag, isSVG returns false
  445. uint8_t head[1000] = {0};
  446. fseek(stream, 0 , SEEK_END);
  447. long len = ftell(stream);
  448. unsigned head_len = (len < 1000 ? len : 1000);
  449. unsigned head_size = head_len * sizeof(uint8_t);
  450. rewind(stream);
  451. if (head_size != fread(&head, 1, head_size, stream)) {
  452. fclose(stream);
  453. return CAIRO_STATUS_READ_ERROR;
  454. }
  455. rewind(stream);
  456. if (isSVG(head, head_len)) {
  457. #ifdef HAVE_RSVG
  458. return loadSVG(stream);
  459. #else
  460. this->errorInfo.set("node-canvas was built without SVG support");
  461. return CAIRO_STATUS_READ_ERROR;
  462. #endif
  463. }
  464. if (isBMP(buf, 2))
  465. return loadBMP(stream);
  466. fclose(stream);
  467. this->errorInfo.set("Unsupported image type");
  468. return CAIRO_STATUS_READ_ERROR;
  469. }
  470. /*
  471. * Load PNG.
  472. */
  473. cairo_status_t
  474. Image::loadPNG() {
  475. _surface = cairo_image_surface_create_from_png(filename);
  476. return cairo_surface_status(_surface);
  477. }
  478. // GIF support
  479. #ifdef HAVE_GIF
  480. /*
  481. * Return the alpha color for `gif` at `frame`, or -1.
  482. */
  483. int
  484. get_gif_transparent_color(GifFileType *gif, int frame) {
  485. ExtensionBlock *ext = gif->SavedImages[frame].ExtensionBlocks;
  486. int len = gif->SavedImages[frame].ExtensionBlockCount;
  487. for (int x = 0; x < len; ++x, ++ext) {
  488. if ((ext->Function == GRAPHICS_EXT_FUNC_CODE) && (ext->Bytes[0] & 1)) {
  489. return ext->Bytes[3] == 0 ? 0 : (uint8_t) ext->Bytes[3];
  490. }
  491. }
  492. return -1;
  493. }
  494. /*
  495. * Memory GIF reader callback.
  496. */
  497. int
  498. read_gif_from_memory(GifFileType *gif, GifByteType *buf, int len) {
  499. gif_data_t *data = (gif_data_t *) gif->UserData;
  500. if ((data->pos + len) > data->len) len = data->len - data->pos;
  501. memcpy(buf, data->pos + data->buf, len);
  502. data->pos += len;
  503. return len;
  504. }
  505. /*
  506. * Load GIF.
  507. */
  508. cairo_status_t
  509. Image::loadGIF(FILE *stream) {
  510. struct stat s;
  511. int fd = fileno(stream);
  512. // stat
  513. if (fstat(fd, &s) < 0) {
  514. fclose(stream);
  515. return CAIRO_STATUS_READ_ERROR;
  516. }
  517. uint8_t *buf = (uint8_t *) malloc(s.st_size);
  518. if (!buf) {
  519. fclose(stream);
  520. this->errorInfo.set(NULL, "malloc", errno);
  521. return CAIRO_STATUS_NO_MEMORY;
  522. }
  523. size_t read = fread(buf, s.st_size, 1, stream);
  524. fclose(stream);
  525. cairo_status_t result = CAIRO_STATUS_READ_ERROR;
  526. if (1 == read) result = loadGIFFromBuffer(buf, s.st_size);
  527. free(buf);
  528. return result;
  529. }
  530. /*
  531. * Load give from `buf` and the given `len`.
  532. */
  533. cairo_status_t
  534. Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) {
  535. int i = 0;
  536. GifFileType* gif;
  537. gif_data_t gifd = { buf, len, 0 };
  538. #if GIFLIB_MAJOR >= 5
  539. int errorcode;
  540. if ((gif = DGifOpen((void*) &gifd, read_gif_from_memory, &errorcode)) == NULL)
  541. return CAIRO_STATUS_READ_ERROR;
  542. #else
  543. if ((gif = DGifOpen((void*) &gifd, read_gif_from_memory)) == NULL)
  544. return CAIRO_STATUS_READ_ERROR;
  545. #endif
  546. if (GIF_OK != DGifSlurp(gif)) {
  547. GIF_CLOSE_FILE(gif);
  548. return CAIRO_STATUS_READ_ERROR;
  549. }
  550. if (gif->SWidth > canvas_max_side || gif->SHeight > canvas_max_side) {
  551. GIF_CLOSE_FILE(gif);
  552. return CAIRO_STATUS_INVALID_SIZE;
  553. }
  554. width = naturalWidth = gif->SWidth;
  555. height = naturalHeight = gif->SHeight;
  556. uint8_t *data = new uint8_t[naturalWidth * naturalHeight * 4];
  557. if (!data) {
  558. GIF_CLOSE_FILE(gif);
  559. this->errorInfo.set(NULL, "malloc", errno);
  560. return CAIRO_STATUS_NO_MEMORY;
  561. }
  562. GifImageDesc *img = &gif->SavedImages[i].ImageDesc;
  563. // local colormap takes precedence over global
  564. ColorMapObject *colormap = img->ColorMap
  565. ? img->ColorMap
  566. : gif->SColorMap;
  567. if (colormap == nullptr) {
  568. GIF_CLOSE_FILE(gif);
  569. return CAIRO_STATUS_READ_ERROR;
  570. }
  571. int bgColor = 0;
  572. int alphaColor = get_gif_transparent_color(gif, i);
  573. if (gif->SColorMap) bgColor = (uint8_t) gif->SBackGroundColor;
  574. else if(alphaColor >= 0) bgColor = alphaColor;
  575. uint8_t *src_data = (uint8_t*) gif->SavedImages[i].RasterBits;
  576. uint32_t *dst_data = (uint32_t*) data;
  577. if (!gif->Image.Interlace) {
  578. if (naturalWidth == img->Width && naturalHeight == img->Height) {
  579. for (int y = 0; y < naturalHeight; ++y) {
  580. for (int x = 0; x < naturalWidth; ++x) {
  581. *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24
  582. | colormap->Colors[*src_data].Red << 16
  583. | colormap->Colors[*src_data].Green << 8
  584. | colormap->Colors[*src_data].Blue;
  585. dst_data++;
  586. src_data++;
  587. }
  588. }
  589. } else {
  590. // Image does not take up whole "screen" so we need to fill-in the background
  591. int bottom = img->Top + img->Height;
  592. int right = img->Left + img->Width;
  593. uint32_t bgPixel =
  594. ((bgColor == alphaColor) ? 0 : 255) << 24
  595. | colormap->Colors[bgColor].Red << 16
  596. | colormap->Colors[bgColor].Green << 8
  597. | colormap->Colors[bgColor].Blue;
  598. for (int y = 0; y < naturalHeight; ++y) {
  599. for (int x = 0; x < naturalWidth; ++x) {
  600. if (y < img->Top || y >= bottom || x < img->Left || x >= right) {
  601. *dst_data = bgPixel;
  602. dst_data++;
  603. } else {
  604. *dst_data = ((*src_data == alphaColor) ? 0 : 255) << 24
  605. | colormap->Colors[*src_data].Red << 16
  606. | colormap->Colors[*src_data].Green << 8
  607. | colormap->Colors[*src_data].Blue;
  608. dst_data++;
  609. src_data++;
  610. }
  611. }
  612. }
  613. }
  614. } else {
  615. // Image is interlaced so that it streams nice over 14.4k and 28.8k modems :)
  616. // We first load in 1/8 of the image, followed by another 1/8, followed by
  617. // 1/4 and finally the remaining 1/2.
  618. int ioffs[] = { 0, 4, 2, 1 };
  619. int ijumps[] = { 8, 8, 4, 2 };
  620. uint8_t *src_ptr = src_data;
  621. uint32_t *dst_ptr;
  622. for(int z = 0; z < 4; z++) {
  623. for(int y = ioffs[z]; y < naturalHeight; y += ijumps[z]) {
  624. dst_ptr = dst_data + naturalWidth * y;
  625. for(int x = 0; x < naturalWidth; ++x) {
  626. *dst_ptr = ((*src_ptr == alphaColor) ? 0 : 255) << 24
  627. | (colormap->Colors[*src_ptr].Red) << 16
  628. | (colormap->Colors[*src_ptr].Green) << 8
  629. | (colormap->Colors[*src_ptr].Blue);
  630. dst_ptr++;
  631. src_ptr++;
  632. }
  633. }
  634. }
  635. }
  636. GIF_CLOSE_FILE(gif);
  637. // New image surface
  638. _surface = cairo_image_surface_create_for_data(
  639. data
  640. , CAIRO_FORMAT_ARGB32
  641. , naturalWidth
  642. , naturalHeight
  643. , cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, naturalWidth));
  644. cairo_status_t status = cairo_surface_status(_surface);
  645. if (status) {
  646. delete[] data;
  647. return status;
  648. }
  649. _data = data;
  650. return CAIRO_STATUS_SUCCESS;
  651. }
  652. #endif /* HAVE_GIF */
  653. // JPEG support
  654. #ifdef HAVE_JPEG
  655. // libjpeg 6.2 does not have jpeg_mem_src; define it ourselves here unless
  656. // libjpeg 8 is installed.
  657. #if JPEG_LIB_VERSION < 80 && !defined(MEM_SRCDST_SUPPORTED)
  658. /* Read JPEG image from a memory segment */
  659. static void
  660. init_source(j_decompress_ptr cinfo) {}
  661. static boolean
  662. fill_input_buffer(j_decompress_ptr cinfo) {
  663. ERREXIT(cinfo, JERR_INPUT_EMPTY);
  664. return TRUE;
  665. }
  666. static void
  667. skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
  668. struct jpeg_source_mgr* src = (struct jpeg_source_mgr*) cinfo->src;
  669. if (num_bytes > 0) {
  670. src->next_input_byte += (size_t) num_bytes;
  671. src->bytes_in_buffer -= (size_t) num_bytes;
  672. }
  673. }
  674. static void term_source (j_decompress_ptr cinfo) {}
  675. static void jpeg_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes) {
  676. struct jpeg_source_mgr* src;
  677. if (cinfo->src == NULL) {
  678. cinfo->src = (struct jpeg_source_mgr *)
  679. (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
  680. sizeof(struct jpeg_source_mgr));
  681. }
  682. src = (struct jpeg_source_mgr*) cinfo->src;
  683. src->init_source = init_source;
  684. src->fill_input_buffer = fill_input_buffer;
  685. src->skip_input_data = skip_input_data;
  686. src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
  687. src->term_source = term_source;
  688. src->bytes_in_buffer = nbytes;
  689. src->next_input_byte = (JOCTET*)buffer;
  690. }
  691. #endif
  692. void Image::jpegToARGB(jpeg_decompress_struct* args, uint8_t* data, uint8_t* src, JPEGDecodeL decode) {
  693. int stride = naturalWidth * 4;
  694. for (int y = 0; y < naturalHeight; ++y) {
  695. jpeg_read_scanlines(args, &src, 1);
  696. uint32_t *row = (uint32_t*)(data + stride * y);
  697. for (int x = 0; x < naturalWidth; ++x) {
  698. int bx = args->output_components * x;
  699. row[x] = decode(src + bx);
  700. }
  701. }
  702. }
  703. /*
  704. * Takes an initialised jpeg_decompress_struct and decodes the
  705. * data into _surface.
  706. */
  707. cairo_status_t
  708. Image::decodeJPEGIntoSurface(jpeg_decompress_struct *args) {
  709. cairo_status_t status = CAIRO_STATUS_SUCCESS;
  710. uint8_t *data = new uint8_t[naturalWidth * naturalHeight * 4];
  711. if (!data) {
  712. jpeg_abort_decompress(args);
  713. jpeg_destroy_decompress(args);
  714. this->errorInfo.set(NULL, "malloc", errno);
  715. return CAIRO_STATUS_NO_MEMORY;
  716. }
  717. uint8_t *src = new uint8_t[naturalWidth * args->output_components];
  718. if (!src) {
  719. free(data);
  720. jpeg_abort_decompress(args);
  721. jpeg_destroy_decompress(args);
  722. this->errorInfo.set(NULL, "malloc", errno);
  723. return CAIRO_STATUS_NO_MEMORY;
  724. }
  725. // These are the three main cases to handle. libjpeg converts YCCK to CMYK
  726. // and YCbCr to RGB by default.
  727. switch (args->out_color_space) {
  728. case JCS_CMYK:
  729. jpegToARGB(args, data, src, [](uint8_t const* src) {
  730. uint16_t k = static_cast<uint16_t>(src[3]);
  731. uint8_t r = k * src[0] / 255;
  732. uint8_t g = k * src[1] / 255;
  733. uint8_t b = k * src[2] / 255;
  734. return 255 << 24 | r << 16 | g << 8 | b;
  735. });
  736. break;
  737. case JCS_RGB:
  738. jpegToARGB(args, data, src, [](uint8_t const* src) {
  739. uint8_t r = src[0], g = src[1], b = src[2];
  740. return 255 << 24 | r << 16 | g << 8 | b;
  741. });
  742. break;
  743. case JCS_GRAYSCALE:
  744. jpegToARGB(args, data, src, [](uint8_t const* src) {
  745. uint8_t v = src[0];
  746. return 255 << 24 | v << 16 | v << 8 | v;
  747. });
  748. break;
  749. default:
  750. this->errorInfo.set("Unsupported JPEG encoding");
  751. status = CAIRO_STATUS_READ_ERROR;
  752. break;
  753. }
  754. if (!status) {
  755. _surface = cairo_image_surface_create_for_data(
  756. data
  757. , CAIRO_FORMAT_ARGB32
  758. , naturalWidth
  759. , naturalHeight
  760. , cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, naturalWidth));
  761. }
  762. jpeg_finish_decompress(args);
  763. jpeg_destroy_decompress(args);
  764. status = cairo_surface_status(_surface);
  765. delete[] src;
  766. if (status) {
  767. delete[] data;
  768. return status;
  769. }
  770. _data = data;
  771. return CAIRO_STATUS_SUCCESS;
  772. }
  773. /*
  774. * Callback to recover from jpeg errors
  775. */
  776. static void canvas_jpeg_error_exit(j_common_ptr cinfo) {
  777. canvas_jpeg_error_mgr *cjerr = static_cast<canvas_jpeg_error_mgr*>(cinfo->err);
  778. cjerr->output_message(cinfo);
  779. // Return control to the setjmp point
  780. longjmp(cjerr->setjmp_buffer, 1);
  781. }
  782. // Capture libjpeg errors instead of writing stdout
  783. static void canvas_jpeg_output_message(j_common_ptr cinfo) {
  784. canvas_jpeg_error_mgr *cjerr = static_cast<canvas_jpeg_error_mgr*>(cinfo->err);
  785. char buff[JMSG_LENGTH_MAX];
  786. cjerr->format_message(cinfo, buff);
  787. // (Only the last message will be returned to JS land.)
  788. cjerr->image->errorInfo.set(buff);
  789. }
  790. /*
  791. * Takes a jpeg data buffer and assigns it as mime data to a
  792. * dummy surface
  793. */
  794. cairo_status_t
  795. Image::decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len) {
  796. // TODO: remove this duplicate logic
  797. // JPEG setup
  798. struct jpeg_decompress_struct args;
  799. struct canvas_jpeg_error_mgr err;
  800. err.image = this;
  801. args.err = jpeg_std_error(&err);
  802. args.err->error_exit = canvas_jpeg_error_exit;
  803. args.err->output_message = canvas_jpeg_output_message;
  804. // Establish the setjmp return context for canvas_jpeg_error_exit to use
  805. if (setjmp(err.setjmp_buffer)) {
  806. // If we get here, the JPEG code has signaled an error.
  807. // We need to clean up the JPEG object, close the input file, and return.
  808. jpeg_destroy_decompress(&args);
  809. return CAIRO_STATUS_READ_ERROR;
  810. }
  811. jpeg_create_decompress(&args);
  812. jpeg_mem_src(&args, buf, len);
  813. jpeg_read_header(&args, 1);
  814. jpeg_start_decompress(&args);
  815. width = naturalWidth = args.output_width;
  816. height = naturalHeight = args.output_height;
  817. // Data alloc
  818. // 8 pixels per byte using Alpha Channel format to reduce memory requirement.
  819. int buf_size = naturalHeight * cairo_format_stride_for_width(CAIRO_FORMAT_A1, naturalWidth);
  820. uint8_t *data = new uint8_t[buf_size];
  821. if (!data) {
  822. this->errorInfo.set(NULL, "malloc", errno);
  823. return CAIRO_STATUS_NO_MEMORY;
  824. }
  825. // New image surface
  826. _surface = cairo_image_surface_create_for_data(
  827. data
  828. , CAIRO_FORMAT_A1
  829. , naturalWidth
  830. , naturalHeight
  831. , cairo_format_stride_for_width(CAIRO_FORMAT_A1, naturalWidth));
  832. // Cleanup
  833. jpeg_abort_decompress(&args);
  834. jpeg_destroy_decompress(&args);
  835. cairo_status_t status = cairo_surface_status(_surface);
  836. if (status) {
  837. delete[] data;
  838. return status;
  839. }
  840. _data = data;
  841. return assignDataAsMime(buf, len, CAIRO_MIME_TYPE_JPEG);
  842. }
  843. /*
  844. * Helper function for disposing of a mime data closure.
  845. */
  846. void
  847. clearMimeData(void *closure) {
  848. Nan::AdjustExternalMemory(
  849. -static_cast<int>((static_cast<read_closure_t *>(closure)->len)));
  850. free(static_cast<read_closure_t *>(closure)->buf);
  851. free(closure);
  852. }
  853. /*
  854. * Assign a given buffer as mime data against the surface.
  855. * The provided buffer will be copied, and the copy will
  856. * be automatically freed when the surface is destroyed.
  857. */
  858. cairo_status_t
  859. Image::assignDataAsMime(uint8_t *data, int len, const char *mime_type) {
  860. uint8_t *mime_data = (uint8_t *) malloc(len);
  861. if (!mime_data) {
  862. this->errorInfo.set(NULL, "malloc", errno);
  863. return CAIRO_STATUS_NO_MEMORY;
  864. }
  865. read_closure_t *mime_closure = (read_closure_t *) malloc(sizeof(read_closure_t));
  866. if (!mime_closure) {
  867. free(mime_data);
  868. this->errorInfo.set(NULL, "malloc", errno);
  869. return CAIRO_STATUS_NO_MEMORY;
  870. }
  871. memcpy(mime_data, data, len);
  872. mime_closure->buf = mime_data;
  873. mime_closure->len = len;
  874. Nan::AdjustExternalMemory(len);
  875. return cairo_surface_set_mime_data(_surface
  876. , mime_type
  877. , mime_data
  878. , len
  879. , clearMimeData
  880. , mime_closure);
  881. }
  882. /*
  883. * Load jpeg from buffer.
  884. */
  885. cairo_status_t
  886. Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) {
  887. // TODO: remove this duplicate logic
  888. // JPEG setup
  889. struct jpeg_decompress_struct args;
  890. struct canvas_jpeg_error_mgr err;
  891. err.image = this;
  892. args.err = jpeg_std_error(&err);
  893. args.err->error_exit = canvas_jpeg_error_exit;
  894. args.err->output_message = canvas_jpeg_output_message;
  895. // Establish the setjmp return context for canvas_jpeg_error_exit to use
  896. if (setjmp(err.setjmp_buffer)) {
  897. // If we get here, the JPEG code has signaled an error.
  898. // We need to clean up the JPEG object, close the input file, and return.
  899. jpeg_destroy_decompress(&args);
  900. return CAIRO_STATUS_READ_ERROR;
  901. }
  902. jpeg_create_decompress(&args);
  903. jpeg_mem_src(&args, buf, len);
  904. jpeg_read_header(&args, 1);
  905. jpeg_start_decompress(&args);
  906. width = naturalWidth = args.output_width;
  907. height = naturalHeight = args.output_height;
  908. return decodeJPEGIntoSurface(&args);
  909. }
  910. /*
  911. * Load JPEG, convert RGB to ARGB.
  912. */
  913. cairo_status_t
  914. Image::loadJPEG(FILE *stream) {
  915. cairo_status_t status;
  916. #if defined(_MSC_VER)
  917. if (false) { // Force using loadJPEGFromBuffer
  918. #else
  919. if (data_mode == DATA_IMAGE) { // Can lazily read in the JPEG.
  920. #endif
  921. // JPEG setup
  922. struct jpeg_decompress_struct args;
  923. struct canvas_jpeg_error_mgr err;
  924. err.image = this;
  925. args.err = jpeg_std_error(&err);
  926. args.err->error_exit = canvas_jpeg_error_exit;
  927. args.err->output_message = canvas_jpeg_output_message;
  928. // Establish the setjmp return context for canvas_jpeg_error_exit to use
  929. if (setjmp(err.setjmp_buffer)) {
  930. // If we get here, the JPEG code has signaled an error.
  931. // We need to clean up the JPEG object, close the input file, and return.
  932. jpeg_destroy_decompress(&args);
  933. return CAIRO_STATUS_READ_ERROR;
  934. }
  935. jpeg_create_decompress(&args);
  936. jpeg_stdio_src(&args, stream);
  937. jpeg_read_header(&args, 1);
  938. jpeg_start_decompress(&args);
  939. if (args.output_width > canvas_max_side || args.output_height > canvas_max_side) {
  940. jpeg_destroy_decompress(&args);
  941. return CAIRO_STATUS_INVALID_SIZE;
  942. }
  943. width = naturalWidth = args.output_width;
  944. height = naturalHeight = args.output_height;
  945. status = decodeJPEGIntoSurface(&args);
  946. fclose(stream);
  947. } else { // We'll need the actual source jpeg data, so read fully.
  948. uint8_t *buf;
  949. unsigned len;
  950. fseek(stream, 0, SEEK_END);
  951. len = ftell(stream);
  952. fseek(stream, 0, SEEK_SET);
  953. buf = (uint8_t *) malloc(len);
  954. if (!buf) {
  955. this->errorInfo.set(NULL, "malloc", errno);
  956. return CAIRO_STATUS_NO_MEMORY;
  957. }
  958. if (fread(buf, len, 1, stream) != 1) {
  959. status = CAIRO_STATUS_READ_ERROR;
  960. } else if ((DATA_IMAGE | DATA_MIME) == data_mode) {
  961. status = loadJPEGFromBuffer(buf, len);
  962. if (!status) status = assignDataAsMime(buf, len, CAIRO_MIME_TYPE_JPEG);
  963. } else if (DATA_MIME == data_mode) {
  964. status = decodeJPEGBufferIntoMimeSurface(buf, len);
  965. }
  966. #if defined(_MSC_VER)
  967. else if (DATA_IMAGE == data_mode) {
  968. status = loadJPEGFromBuffer(buf, len);
  969. }
  970. #endif
  971. else {
  972. status = CAIRO_STATUS_READ_ERROR;
  973. }
  974. fclose(stream);
  975. free(buf);
  976. }
  977. return status;
  978. }
  979. #endif /* HAVE_JPEG */
  980. #ifdef HAVE_RSVG
  981. /*
  982. * Load SVG from buffer
  983. */
  984. cairo_status_t
  985. Image::loadSVGFromBuffer(uint8_t *buf, unsigned len) {
  986. _is_svg = true;
  987. cairo_status_t status;
  988. GError *gerr = NULL;
  989. if (NULL == (_rsvg = rsvg_handle_new_from_data(buf, len, &gerr))) {
  990. return CAIRO_STATUS_READ_ERROR;
  991. }
  992. RsvgDimensionData *dims = new RsvgDimensionData();
  993. rsvg_handle_get_dimensions(_rsvg, dims);
  994. width = naturalWidth = dims->width;
  995. height = naturalHeight = dims->height;
  996. status = renderSVGToSurface();
  997. if (status != CAIRO_STATUS_SUCCESS) {
  998. g_object_unref(_rsvg);
  999. return status;
  1000. }
  1001. return CAIRO_STATUS_SUCCESS;
  1002. }
  1003. /*
  1004. * Renders the Rsvg handle to this image's surface
  1005. */
  1006. cairo_status_t
  1007. Image::renderSVGToSurface() {
  1008. cairo_status_t status;
  1009. _surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  1010. status = cairo_surface_status(_surface);
  1011. if (status != CAIRO_STATUS_SUCCESS) {
  1012. g_object_unref(_rsvg);
  1013. return status;
  1014. }
  1015. cairo_t *cr = cairo_create(_surface);
  1016. cairo_scale(cr,
  1017. (double)width / (double)naturalWidth,
  1018. (double)height / (double)naturalHeight);
  1019. status = cairo_status(cr);
  1020. if (status != CAIRO_STATUS_SUCCESS) {
  1021. g_object_unref(_rsvg);
  1022. return status;
  1023. }
  1024. gboolean render_ok = rsvg_handle_render_cairo(_rsvg, cr);
  1025. if (!render_ok) {
  1026. g_object_unref(_rsvg);
  1027. cairo_destroy(cr);
  1028. return CAIRO_STATUS_READ_ERROR; // or WRITE?
  1029. }
  1030. cairo_destroy(cr);
  1031. _svg_last_width = width;
  1032. _svg_last_height = height;
  1033. return status;
  1034. }
  1035. /*
  1036. * Load SVG
  1037. */
  1038. cairo_status_t
  1039. Image::loadSVG(FILE *stream) {
  1040. _is_svg = true;
  1041. struct stat s;
  1042. int fd = fileno(stream);
  1043. // stat
  1044. if (fstat(fd, &s) < 0) {
  1045. fclose(stream);
  1046. return CAIRO_STATUS_READ_ERROR;
  1047. }
  1048. uint8_t *buf = (uint8_t *) malloc(s.st_size);
  1049. if (!buf) {
  1050. fclose(stream);
  1051. return CAIRO_STATUS_NO_MEMORY;
  1052. }
  1053. size_t read = fread(buf, s.st_size, 1, stream);
  1054. fclose(stream);
  1055. cairo_status_t result = CAIRO_STATUS_READ_ERROR;
  1056. if (1 == read) result = loadSVGFromBuffer(buf, s.st_size);
  1057. free(buf);
  1058. return result;
  1059. }
  1060. #endif /* HAVE_RSVG */
  1061. /*
  1062. * Load BMP from buffer.
  1063. */
  1064. cairo_status_t Image::loadBMPFromBuffer(uint8_t *buf, unsigned len){
  1065. BMPParser::Parser parser;
  1066. // Reversed ARGB32 with pre-multiplied alpha
  1067. uint8_t pixFmt[5] = {2, 1, 0, 3, 1};
  1068. parser.parse(buf, len, pixFmt);
  1069. if (parser.getStatus() != BMPParser::Status::OK) {
  1070. errorInfo.reset();
  1071. errorInfo.message = parser.getErrMsg();
  1072. return CAIRO_STATUS_READ_ERROR;
  1073. }
  1074. width = naturalWidth = parser.getWidth();
  1075. height = naturalHeight = parser.getHeight();
  1076. uint8_t *data = parser.getImgd();
  1077. _surface = cairo_image_surface_create_for_data(
  1078. data,
  1079. CAIRO_FORMAT_ARGB32,
  1080. width,
  1081. height,
  1082. cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width)
  1083. );
  1084. // No need to delete the data
  1085. cairo_status_t status = cairo_surface_status(_surface);
  1086. if (status) return status;
  1087. _data = data;
  1088. parser.clearImgd();
  1089. return CAIRO_STATUS_SUCCESS;
  1090. }
  1091. /*
  1092. * Load BMP.
  1093. */
  1094. cairo_status_t Image::loadBMP(FILE *stream){
  1095. struct stat s;
  1096. int fd = fileno(stream);
  1097. // Stat
  1098. if (fstat(fd, &s) < 0) {
  1099. fclose(stream);
  1100. return CAIRO_STATUS_READ_ERROR;
  1101. }
  1102. uint8_t *buf = new uint8_t[s.st_size];
  1103. if (!buf) {
  1104. fclose(stream);
  1105. errorInfo.set(NULL, "malloc", errno);
  1106. return CAIRO_STATUS_NO_MEMORY;
  1107. }
  1108. size_t read = fread(buf, s.st_size, 1, stream);
  1109. fclose(stream);
  1110. cairo_status_t result = CAIRO_STATUS_READ_ERROR;
  1111. if (read == 1) result = loadBMPFromBuffer(buf, s.st_size);
  1112. delete[] buf;
  1113. return result;
  1114. }
  1115. /*
  1116. * Return UNKNOWN, SVG, GIF, JPEG, or PNG based on the filename.
  1117. */
  1118. Image::type
  1119. Image::extension(const char *filename) {
  1120. size_t len = strlen(filename);
  1121. filename += len;
  1122. if (len >= 5 && 0 == strcmp(".jpeg", filename - 5)) return Image::JPEG;
  1123. if (len >= 4 && 0 == strcmp(".gif", filename - 4)) return Image::GIF;
  1124. if (len >= 4 && 0 == strcmp(".jpg", filename - 4)) return Image::JPEG;
  1125. if (len >= 4 && 0 == strcmp(".png", filename - 4)) return Image::PNG;
  1126. if (len >= 4 && 0 == strcmp(".svg", filename - 4)) return Image::SVG;
  1127. return Image::UNKNOWN;
  1128. }
  1129. /*
  1130. * Sniff bytes 0..1 for JPEG's magic number ff d8.
  1131. */
  1132. int
  1133. Image::isJPEG(uint8_t *data) {
  1134. return 0xff == data[0] && 0xd8 == data[1];
  1135. }
  1136. /*
  1137. * Sniff bytes 0..2 for "GIF".
  1138. */
  1139. int
  1140. Image::isGIF(uint8_t *data) {
  1141. return 'G' == data[0] && 'I' == data[1] && 'F' == data[2];
  1142. }
  1143. /*
  1144. * Sniff bytes 1..3 for "PNG".
  1145. */
  1146. int
  1147. Image::isPNG(uint8_t *data) {
  1148. return 'P' == data[1] && 'N' == data[2] && 'G' == data[3];
  1149. }
  1150. /*
  1151. * Skip "<?" and "<!" tags to test if root tag starts "<svg"
  1152. */
  1153. int
  1154. Image::isSVG(uint8_t *data, unsigned len) {
  1155. for (unsigned i = 3; i < len; i++) {
  1156. if ('<' == data[i-3]) {
  1157. switch (data[i-2]) {
  1158. case '?':
  1159. case '!':
  1160. break;
  1161. case 's':
  1162. return ('v' == data[i-1] && 'g' == data[i]);
  1163. default:
  1164. return false;
  1165. }
  1166. }
  1167. }
  1168. return false;
  1169. }
  1170. /*
  1171. * Check for valid BMP signatures
  1172. */
  1173. int Image::isBMP(uint8_t *data, unsigned len) {
  1174. if(len < 2) return false;
  1175. std::string sig = std::string(1, (char)data[0]) + (char)data[1];
  1176. return sig == "BM" ||
  1177. sig == "BA" ||
  1178. sig == "CI" ||
  1179. sig == "CP" ||
  1180. sig == "IC" ||
  1181. sig == "PT";
  1182. }