Changeset View
Changeset View
Standalone View
Standalone View
source/blender/imbuf/intern/bmp.c
| Context not available. | |||||
| #include "IMB_colormanagement.h" | #include "IMB_colormanagement.h" | ||||
| #include "IMB_colormanagement_intern.h" | #include "IMB_colormanagement_intern.h" | ||||
| /* Some code copied from article on microsoft.com, | |||||
| * copied here for enhanced BMP support in the future: | |||||
| * http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm | |||||
| */ | |||||
| typedef struct BMPINFOHEADER { | typedef struct BMPINFOHEADER { | ||||
| unsigned int biSize; | unsigned int biSize; | ||||
| unsigned int biWidth; | unsigned int biWidth; | ||||
| Context not available. | |||||
| unsigned int biClrImportant; | unsigned int biClrImportant; | ||||
| } BMPINFOHEADER; | } BMPINFOHEADER; | ||||
| #if 0 | |||||
| typedef struct BMPHEADER { | |||||
| unsigned short biType; | |||||
| unsigned int biSize; | |||||
| unsigned short biRes1; | |||||
| unsigned short biRes2; | |||||
| unsigned int biOffBits; | |||||
| } BMPHEADER; | |||||
| #endif | |||||
| #define BMP_FILEHEADER_SIZE 14 | #define BMP_FILEHEADER_SIZE 14 | ||||
| #define CHECK_HEADER_FIELD(_mem, _field) ((_mem[0] == _field[0]) && (_mem[1] == _field[1])) | #define CHECK_HEADER_FIELD(_mem, _field) ((_mem[0] == _field[0]) && (_mem[1] == _field[1])) | ||||
| Context not available. | |||||
| return putc((us >> 8) & 0xFF, ofile); | return putc((us >> 8) & 0xFF, ofile); | ||||
| } | } | ||||
| /* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ | |||||
| int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) | int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) | ||||
| { | { | ||||
| BMPINFOHEADER infoheader; | BMPINFOHEADER infoheader; | ||||
| size_t bytesize, extrabytes, ptr; | size_t byte_size, extra_bytes, ptr, bytes_per_pixel, palette_size, pixel_array_start; | ||||
| uchar *data; | uchar *data; | ||||
| FILE *ofile; | FILE *ofile; | ||||
| bool is_grayscale; | |||||
| (void)flags; /* unused */ | (void)flags; /* unused */ | ||||
| extrabytes = (4 - ibuf->x * 3 % 4) % 4; | bytes_per_pixel = (ibuf->planes + 7) >> 3; | ||||
| bytesize = (ibuf->x * 3 + extrabytes) * ibuf->y; | BLI_assert(bytes_per_pixel == 1 || bytes_per_pixel == 3); | ||||
| extra_bytes = (4 - ibuf->x * bytes_per_pixel % 4) % 4; | |||||
| byte_size = (ibuf->x * bytes_per_pixel + extra_bytes) * ibuf->y; | |||||
| data = (uchar *)ibuf->rect; | data = (uchar *)ibuf->rect; | ||||
| ofile = BLI_fopen(name, "wb"); | ofile = BLI_fopen(name, "wb"); | ||||
| Context not available. | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| putShortLSB(19778, ofile); /* "BM" */ | is_grayscale = bytes_per_pixel == 1; | ||||
| putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); /* Total file size */ | palette_size = is_grayscale ? 255 * 4 : 0; /* RGBA32 */ | ||||
| putShortLSB(0, ofile); /* Res1 */ | pixel_array_start = BMP_FILEHEADER_SIZE + sizeof(infoheader) + palette_size; | ||||
| putShortLSB(0, ofile); /* Res2 */ | |||||
| putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); | putShortLSB(19778, ofile); /* "BM" */ | ||||
| putIntLSB(byte_size + pixel_array_start, ofile); /* Total file size */ | |||||
| putShortLSB(0, ofile); /* Res1 */ | |||||
| putShortLSB(0, ofile); /* Res2 */ | |||||
| putIntLSB(pixel_array_start, ofile); /* offset to start of pixel array */ | |||||
| putIntLSB(sizeof(infoheader), ofile); | putIntLSB(sizeof(infoheader), ofile); | ||||
| putIntLSB(ibuf->x, ofile); | putIntLSB(ibuf->x, ofile); | ||||
| putIntLSB(ibuf->y, ofile); | putIntLSB(ibuf->y, ofile); | ||||
| putShortLSB(1, ofile); | putShortLSB(1, ofile); | ||||
| putShortLSB(24, ofile); | putShortLSB(ibuf->planes, ofile); | ||||
campbellbarton: This value may be 32, which is currently never written, this patch should only handle the… | |||||
| putIntLSB(0, ofile); | putIntLSB(0, ofile); | ||||
| putIntLSB(bytesize, ofile); | putIntLSB(byte_size, ofile); | ||||
| putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile); | putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile); | ||||
| putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile); | putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile); | ||||
| putIntLSB(0, ofile); | putIntLSB(0, ofile); | ||||
| putIntLSB(0, ofile); | putIntLSB(0, ofile); | ||||
| /* color palette table, which is just every grayscale color, full alpha */ | |||||
| if (is_grayscale) { | |||||
| for (char i = 0; i < 255; i++) { | |||||
| putc(i, ofile); | |||||
| putc(i, ofile); | |||||
| putc(i, ofile); | |||||
| putc(0xFF, ofile); | |||||
| } | |||||
| } | |||||
| /* Need to write out padded image data in bgr format */ | /* Need to write out padded image data in bgr format */ | ||||
| for (size_t y = 0; y < ibuf->y; y++) { | for (size_t y = 0; y < ibuf->y; y++) { | ||||
| for (size_t x = 0; x < ibuf->x; x++) { | for (size_t x = 0; x < ibuf->x; x++) { | ||||
| ptr = (x + y * ibuf->x) * 4; | ptr = (x + y * ibuf->x) * 4; | ||||
| if (putc(data[ptr + 2], ofile) == EOF) { | |||||
| return 0; | for (int i = 0; i < bytes_per_pixel; i++) { | ||||
| } | size_t offset = bytes_per_pixel - i - 1; // RGB -> BGR | ||||
| if (putc(data[ptr + 1], ofile) == EOF) { | if (putc(data[ptr + offset], ofile) == EOF) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (putc(data[ptr], ofile) == EOF) { | |||||
| return 0; | |||||
| } | } | ||||
| } | } | ||||
| /* add padding here */ | /* add padding here */ | ||||
| for (size_t t = 0; t < extrabytes; t++) { | for (size_t t = 0; t < extra_bytes; t++) { | ||||
| if (putc(0, ofile) == EOF) { | if (putc(0, ofile) == EOF) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (ofile) { | if (ofile) { | ||||
| fflush(ofile); | fflush(ofile); | ||||
| fclose(ofile); | fclose(ofile); | ||||
| } | } | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| Context not available. | |||||
Not Done Inline ActionsI split this into two loops to avoid calculations multiple times per-pixel. campbellbarton: I split this into two loops to avoid calculations multiple times per-pixel. | |||||
This value may be 32, which is currently never written, this patch should only handle the greyscale case.
Suggest to only write fixed values based on is_grayscale.