Skip to content

Add BMP support #1295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ project adheres to [Semantic Versioning](http://semver.org/).
==================
### Added
* Warn when building with old, unsupported versions of cairo or libjpeg.
* BMP support

2.0.0
==================
Expand Down
6 changes: 6 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ Examples line in the `examples` directory. Most produce a png image of the same

## License

### node-canvas

(The MIT License)

Copyright (c) 2010 LearnBoost, and contributors <[email protected]>
Expand All @@ -546,3 +548,7 @@ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

### BMP parser

See [license](src/bmp/LICENSE.md)
1 change: 1 addition & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
'src/backend/ImageBackend.cc',
'src/backend/PdfBackend.cc',
'src/backend/SvgBackend.cc',
'src/bmp/BMPParser.cc',
'src/Backends.cc',
'src/Canvas.cc',
'src/CanvasGradient.cc',
Expand Down
93 changes: 93 additions & 0 deletions src/Image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "Util.h"
#include "Canvas.h"
#include "Image.h"
#include "bmp/BMPParser.h"

#ifdef HAVE_GIF
typedef struct {
Expand Down Expand Up @@ -313,6 +314,9 @@ Image::loadFromBuffer(uint8_t *buf, unsigned len) {
#endif
}

if (isBMP(buf, len))
return loadBMPFromBuffer(buf, len);

this->errorInfo.set("Unsupported image type");
return CAIRO_STATUS_READ_ERROR;
}
Expand Down Expand Up @@ -489,6 +493,9 @@ Image::loadSurface() {
#endif
}

if (isBMP(buf, 2))
return loadBMP(stream);

fclose(stream);

this->errorInfo.set("Unsupported image type");
Expand Down Expand Up @@ -1223,6 +1230,77 @@ Image::loadSVG(FILE *stream) {

#endif /* HAVE_RSVG */

/*
* Load BMP from buffer.
*/

cairo_status_t Image::loadBMPFromBuffer(uint8_t *buf, unsigned len){
BMPParser::Parser parser;

// Reversed ARGB32 with pre-multiplied alpha
uint8_t pixFmt[5] = {2, 1, 0, 3, 1};
parser.parse(buf, len, pixFmt);

if (parser.getStatus() != BMPParser::Status::OK) {
errorInfo.reset();
errorInfo.message = parser.getErrMsg();
return CAIRO_STATUS_READ_ERROR;
}

width = naturalWidth = parser.getWidth();
height = naturalHeight = parser.getHeight();
uint8_t *data = parser.getImgd();

_surface = cairo_image_surface_create_for_data(
data,
CAIRO_FORMAT_ARGB32,
width,
height,
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width)
);

// No need to delete the data
cairo_status_t status = cairo_surface_status(_surface);
if (status) return status;

_data = data;
parser.clearImgd();

return CAIRO_STATUS_SUCCESS;
}

/*
* Load BMP.
*/

cairo_status_t Image::loadBMP(FILE *stream){
struct stat s;
int fd = fileno(stream);

// Stat
if (fstat(fd, &s) < 0) {
fclose(stream);
return CAIRO_STATUS_READ_ERROR;
}

uint8_t *buf = new uint8_t[s.st_size];

if (!buf) {
fclose(stream);
errorInfo.set(NULL, "malloc", errno);
return CAIRO_STATUS_NO_MEMORY;
}

size_t read = fread(buf, s.st_size, 1, stream);
fclose(stream);

cairo_status_t result = CAIRO_STATUS_READ_ERROR;
if (read == 1) result = loadBMPFromBuffer(buf, s.st_size);
delete[] buf;

return result;
}

/*
* Return UNKNOWN, SVG, GIF, JPEG, or PNG based on the filename.
*/
Expand Down Expand Up @@ -1286,3 +1364,18 @@ Image::isSVG(uint8_t *data, unsigned len) {
}
return false;
}

/*
* Check for valid BMP signatures
*/

int Image::isBMP(uint8_t *data, unsigned len) {
if(len < 2) return false;
string sig = string(1, (char)data[0]) + (char)data[1];
return sig == "BM" ||
sig == "BA" ||
sig == "CI" ||
sig == "CP" ||
sig == "IC" ||
sig == "PT";
}
3 changes: 3 additions & 0 deletions src/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Image: public Nan::ObjectWrap {
static int isJPEG(uint8_t *data);
static int isGIF(uint8_t *data);
static int isSVG(uint8_t *data, unsigned len);
static int isBMP(uint8_t *data, unsigned len);
static cairo_status_t readPNG(void *closure, unsigned char *data, unsigned len);
inline int isComplete(){ return COMPLETE == state; }
cairo_surface_t *surface();
Expand All @@ -87,6 +88,8 @@ class Image: public Nan::ObjectWrap {
cairo_status_t decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len);
cairo_status_t assignDataAsMime(uint8_t *data, int len, const char *mime_type);
#endif
cairo_status_t loadBMPFromBuffer(uint8_t *buf, unsigned len);
cairo_status_t loadBMP(FILE *stream);
CanvasError errorInfo;
void loaded();
cairo_status_t load();
Expand Down
Loading