Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==========================================================
- // BMPRL Loader and Writer
- //
- // Design and implementation by
- // - Djeman
- //
- // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
- // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
- // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
- // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
- // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
- // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
- // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
- // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
- // THIS DISCLAIMER.
- //
- // Use at your own risk!
- // ==========================================================
- #include "FreeImage.h"
- #include "Utilities.h"
- #include "Quantizers.h"
- // ----------------------------------------------------------
- // Constants + headers
- // ----------------------------------------------------------
- #define MAX_PALETTE_COUNT 261
- #define MAX_PALETTE_SIZE 251
- #define MAX_PALETTE_TOTAL_SIZE (MAX_PALETTE_COUNT * MAX_PALETTE_SIZE)
- static const BYTE RLE_PALETTE = 0xFD;
- static const BYTE RLE_COMMAND = 0xFE;
- static const BYTE RLE_DELTA = 0xFF;
- static const BYTE RLE_EMPTY = 0;
- static const WORD HAVE_ALPHA_MASK = 0x0001;
- static const WORD HAVE_PALETTE_16 = 0x0002;
- // ----------------------------------------------------------
- #ifdef _WIN32
- #pragma pack(push, 1)
- #else
- #pragma pack(1)
- #endif
- typedef struct tagBITMAPRLHEADER {
- WORD bType; //! The file type
- WORD bOptions; //! Image format options
- WORD bWidth;
- WORD bHeight;
- WORD bClrUsed; //! Colors used
- WORD bRLRowsUsed; //! RL Rows used
- } BITMAPRLHEADER, *PBITMAPRLHEADER;
- #ifdef _WIN32
- #pragma pack(pop)
- #else
- #pragma pack()
- #endif
- // ==========================================================
- // Plugin Interface
- // ==========================================================
- static int s_format_id;
- // ==========================================================
- // Internal functions
- // ==========================================================
- #ifdef FREEIMAGE_BIGENDIAN
- static void
- SwapFileHeader(BITMAPRLHEADER *header) {
- SwapShort(&header->bType);
- SwapShort(&header->bReserved1);
- SwapShort(&header->bWidth);
- SwapShort(&header->bHeight);
- SwapShort(&header->bClrUsed);
- SwapShort(&header->bRLRowsUsed);
- }
- #endif
- // --------------------------------------------------------------------------
- /**
- Load image pixels for RL compressed dib
- @param io FreeImage IO
- @param handle FreeImage IO handle
- @param width Image width
- @param height Image height
- @param dib Image to be loaded
- @return Returns TRUE if successful, returns FALSE otherwise
- */
- static BOOL
- LoadPixelData(FreeImageIO *io, fi_handle handle, int width, int height, FIBITMAP *dib, BYTE *pal, int bpp) {
- BYTE status_byte = 0;
- BYTE second_byte = 0;
- WORD pal_pos = 0;
- int scanline = height-1;
- int bits = 0;
- WORD *pal16 = (WORD*)pal;
- DWORD *pal32 = (DWORD*)pal;
- for (;;) {
- if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
- switch (status_byte) {
- case RLE_COMMAND:
- {
- if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
- if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
- int count = MIN((int)second_byte, width - bits);
- BYTE *sline = FreeImage_GetScanLine(dib, scanline);
- for (int m = 0; m < count; m++) {
- if (bpp == 32)
- *(DWORD*)(sline + (bits * sizeof(DWORD))) = pal32[pal_pos + status_byte];
- else
- *(WORD*)(sline + (bits * sizeof(WORD))) = pal16[pal_pos + status_byte];
- bits++;
- }
- break;
- }
- case RLE_DELTA:
- {
- // read the delta value
- if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
- return FALSE;
- }
- int count = MIN((int)second_byte, width - bits);
- bits += count;
- break;
- }
- case RLE_PALETTE:
- {
- // read new palette position
- if (io->read_proc(&pal_pos, sizeof(WORD), 1, handle) != 1) {
- return FALSE;
- }
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(&pal_pos);
- #endif
- break;
- }
- case RLE_EMPTY:
- {
- bits++;
- break;
- }
- default:
- {
- BYTE *sline = FreeImage_GetScanLine(dib, scanline);
- if (bpp == 32)
- *(DWORD*)(sline + (bits * sizeof(DWORD))) = pal32[pal_pos + status_byte];
- else
- *(WORD*)(sline + (bits * sizeof(WORD))) = pal16[pal_pos + status_byte];
- bits++;
- break;
- }
- }
- if (bits == width) {
- pal_pos = 0;
- bits = 0;
- scanline--;
- if (scanline < 0) return TRUE;
- }
- }
- return TRUE;
- }
- // ==========================================================
- // Plugin Implementation
- // ==========================================================
- static const char * DLL_CALLCONV
- Format() {
- return "BMPRL";
- }
- static const char * DLL_CALLCONV
- Description() {
- return "NNG Bitmap";
- }
- static const char * DLL_CALLCONV
- Extension() {
- return "bmp";
- }
- static const char * DLL_CALLCONV
- RegExpr() {
- return "^RL";
- }
- static const char * DLL_CALLCONV
- MimeType() {
- return "image/bmprl";
- }
- static BOOL DLL_CALLCONV
- Validate(FreeImageIO *io, fi_handle handle) {
- BYTE bmprl_signature[] = { 0x52, 0x4C };
- BYTE signature[2] = { 0, 0 };
- io->read_proc(signature, 1, sizeof(bmprl_signature), handle);
- if (memcmp(bmprl_signature, signature, sizeof(bmprl_signature)) == 0)
- return TRUE;
- return FALSE;
- }
- static BOOL DLL_CALLCONV
- SupportsExportDepth(int depth) {
- return (
- (depth == 16) ||
- (depth == 24) ||
- (depth == 32)
- );
- }
- static BOOL DLL_CALLCONV
- SupportsExportType(FREE_IMAGE_TYPE type) {
- return (type == FIT_BITMAP) ? TRUE : FALSE;
- }
- static BOOL DLL_CALLCONV
- SupportsNoPixels() {
- return TRUE;
- }
- // ----------------------------------------------------------
- static FIBITMAP * DLL_CALLCONV
- Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
- if (handle == NULL)
- return NULL;
- BITMAPRLHEADER bitmaprlheader;
- // read the fileheader
- io->read_proc(&bitmaprlheader, sizeof(BITMAPRLHEADER), 1, handle);
- #ifdef FREEIMAGE_BIGENDIAN
- SwapFileHeader(&bitmapfileheader);
- #endif
- // check the signature
- if ((bitmaprlheader.bType != 0x4C52)) {
- FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_MAGIC_NUMBER);
- return NULL;
- }
- // load the BMP RL
- int bpp = 0;
- FIBITMAP *dib = NULL;
- BYTE *pal = NULL;
- try {
- BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
- // allocate enough memory to hold the bitmap
- if (bitmaprlheader.bOptions & HAVE_ALPHA_MASK) {
- bpp = 32;
- dib = FreeImage_AllocateHeader(header_only, bitmaprlheader.bWidth, bitmaprlheader.bHeight, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
- }
- else {
- bpp = 16;
- dib = FreeImage_AllocateHeader(header_only, bitmaprlheader.bWidth, bitmaprlheader.bHeight, 16, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK);
- }
- if (dib == NULL) {
- throw FI_MSG_ERROR_DIB_MEMORY;
- }
- if (header_only) {
- // header only mode
- return dib;
- }
- // load the 16 bits color palette
- pal = (BYTE*)malloc(bitmaprlheader.bClrUsed * sizeof(WORD));
- io->read_proc(pal, bitmaprlheader.bClrUsed * sizeof(WORD), 1, handle);
- #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
- for (int i = 0; i < bitmaprlheader.bClrUsed; i++) {
- SwapShort(&pal);
- }
- #endif
- if (bitmaprlheader.bOptions & HAVE_ALPHA_MASK) {
- // load the alpha layer
- BYTE *layerAlpha = (BYTE*)malloc(bitmaprlheader.bClrUsed);
- io->read_proc(layerAlpha, bitmaprlheader.bClrUsed, 1, handle);
- // convert color palette to 32 bits RGBA
- BYTE *oldpal = pal;
- pal = (BYTE*)malloc(bitmaprlheader.bClrUsed * sizeof(DWORD));
- WORD *bits = (WORD *)oldpal;
- BYTE *newpal = pal;
- for (int i = 0; i < bitmaprlheader.bClrUsed; i++) {
- newpal[FI_RGBA_RED] = (BYTE)((((bits[i] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F);
- newpal[FI_RGBA_GREEN] = (BYTE)((((bits[i] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F);
- newpal[FI_RGBA_BLUE] = (BYTE)((((bits[i] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
- newpal[FI_RGBA_ALPHA] = (layerAlpha[i] >= 32) ? 0xFF : (layerAlpha[i] * 8);
- newpal += 4;
- }
- free(oldpal);
- free(layerAlpha);
- // check if the bitmap contains transparency, if so enable it in the header
- FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA));
- }
- // ignore array rows length
- WORD rowLen = 0;
- for (int i = 0; i < bitmaprlheader.bRLRowsUsed; i++){
- io->read_proc(&rowLen, sizeof(BYTE), 1, handle);
- if ((rowLen & 0xff) == 0xff) {
- io->read_proc(&rowLen, sizeof(WORD), 1, handle);
- }
- }
- if (!LoadPixelData(io, handle, bitmaprlheader.bWidth, bitmaprlheader.bHeight, dib, pal, bpp)) {
- throw "Error encountered while decoding RL BMP data";
- }
- if (pal)
- free(pal);
- return dib;
- }
- catch (const char *message) {
- if (pal)
- free(pal);
- if (dib)
- FreeImage_Unload(dib);
- FreeImage_OutputMessageProc(s_format_id, message);
- }
- return NULL;
- }
- // ----------------------------------------------------------
- static int
- GetPaletteIndexRGBA(WORD color, BYTE alpha, WORD *colorpal, BYTE *alphapal, int palSize) {
- for (int i = 0; i < palSize; i++) {
- if (color == colorpal[i] && alpha == alphapal[i])
- return i;
- }
- return -1;
- }
- static int
- GetPaletteIndexRGB(WORD color, WORD *colorpal, int palSize) {
- for (int i = 0; i < palSize; i++) {
- if (color == colorpal[i])
- return i;
- }
- return -1;
- }
- static BOOL DLL_CALLCONV
- Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
- if ((dib != NULL) && (handle != NULL)) {
- int width, height, bpp, npitch;
- width = FreeImage_GetWidth(dib);
- height = FreeImage_GetHeight(dib);
- bpp = FreeImage_GetBPP(dib);
- int palDefSize = 65536; // 16-bit
- // Allocate pixels array
- WORD* pixels = (WORD*)malloc(height * width * sizeof(WORD));
- // Convert to 16-bit
- FIBITMAP *tmp = FreeImage_ConvertTo16Bits565(dib);
- npitch = FreeImage_GetPitch(tmp);
- BYTE *fbits, *fpixs;
- for (int y = 0; y < height; y++) {
- fbits = FreeImage_GetBits(tmp) + (y * npitch);
- fpixs = (BYTE*)pixels + (y * width * sizeof(WORD));
- memcpy(fpixs, fbits, width * sizeof(WORD));
- }
- FreeImage_Unload(tmp);
- // Allocate palette
- BYTE *newalphapal = NULL;
- WORD *newpal = (WORD*)malloc(palDefSize * sizeof(WORD));
- BYTE *bits = (BYTE*)malloc(height * width * sizeof(BYTE));
- WORD *palIndex = (WORD*)malloc(height * sizeof(WORD));
- memset(palIndex, 0, height * sizeof(WORD));
- newpal[0] = 0xF81F;
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[0]);
- #endif
- BYTE *palSize = (BYTE*)malloc(MAX_PALETTE_COUNT * sizeof(BYTE));
- memset(palSize, 1, MAX_PALETTE_COUNT * sizeof(BYTE));
- int palTotalSize = 1;
- BOOL isAlpha = FALSE;
- if (bpp == 32) { // RGBA
- BYTE *layerAlpha = (BYTE*)malloc(width*height);
- newalphapal = (BYTE*)malloc(palDefSize * sizeof(BYTE));
- newalphapal[0] = 0;
- npitch = FreeImage_GetPitch(dib);
- /////////////////////////////////////////////////////////////////////
- // Generate all palettes
- for (int y = 0, yinv = (height - 1); y < height; y++, yinv--) {
- BYTE* oribits = FreeImage_GetBits(dib) + (yinv * npitch);
- BYTE rowPalSize = palSize[palIndex[y]];
- int x = 0;
- for (; x < width; x++) {
- if (palTotalSize == MAX_PALETTE_TOTAL_SIZE) {
- WuQuantizer16 Q(dib);
- if (palDefSize == 0 || !Q.Quantize(pixels, palDefSize, 0, NULL)) {
- free(newalphapal);
- free(newpal);
- free(bits);
- free(palIndex);
- free(palSize);
- free(pixels);
- return FALSE;
- }
- if (palDefSize > 8192)
- palDefSize -= 4096;
- else
- palDefSize -= (palDefSize >> 2);
- memset(palIndex, 0, height * sizeof(WORD));
- y = -1;
- yinv = height;
- palTotalSize = 1;
- memset(palSize, 1, MAX_PALETTE_COUNT * sizeof(BYTE));
- break;
- }
- if (oribits[FI_RGBA_ALPHA] < 7) {
- pixels[yinv * width + x] = 0xF81F;
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(pixels[yinv * width + x]);
- #endif
- layerAlpha[yinv * width + x] = 0;
- isAlpha = TRUE;
- } else {
- layerAlpha[yinv * width + x] = (oribits[FI_RGBA_ALPHA] + 1) / 8;
- if (layerAlpha[yinv * width + x] < 32) isAlpha = TRUE;
- }
- int jo = palTotalSize - (palIndex[y] * MAX_PALETTE_SIZE);
- int rc = GetPaletteIndexRGBA(pixels[yinv * width + x], layerAlpha[yinv * width + x],
- &newpal[palIndex[y] * MAX_PALETTE_SIZE], &newalphapal[palIndex[y] * MAX_PALETTE_SIZE], rowPalSize);
- if (rc == -1) {
- if (palSize[palIndex[y]] == 0 && rowPalSize == MAX_PALETTE_SIZE) {
- palTotalSize = MAX_PALETTE_TOTAL_SIZE;
- } else if (rowPalSize == MAX_PALETTE_SIZE && jo == MAX_PALETTE_SIZE) {
- palIndex[y]++;
- newpal[palTotalSize] = 0xF81F;
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[newpalSize]);
- #endif
- newalphapal[palTotalSize] = 0;
- palTotalSize++;
- y--;
- yinv++;
- break;
- } else if (jo < MAX_PALETTE_SIZE) {
- newpal[palTotalSize] = pixels[yinv * width + x];
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[newpalSize]);
- #endif
- newalphapal[palTotalSize] = layerAlpha[yinv * width + x];
- bits[y * width + x] = jo;
- palTotalSize++;
- rowPalSize++;
- } else if (rowPalSize < MAX_PALETTE_SIZE) {
- newpal[palIndex[y] * MAX_PALETTE_SIZE + rowPalSize] = pixels[yinv * width + x];
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[palIndex[y] * MAX_PALETTE_SIZE + rowPalSize]);
- #endif
- newalphapal[palIndex[y] * MAX_PALETTE_SIZE + rowPalSize] = layerAlpha[yinv * width + x];
- bits[y * width + x] = rowPalSize;
- rowPalSize++;
- } else {
- palIndex[y]++;
- y--;
- yinv++;
- break;
- }
- } else {
- bits[y * width + x] = rc;
- }
- oribits += 4;
- }
- if (x == width)
- palSize[palIndex[y]] = rowPalSize;
- }
- free(layerAlpha);
- if (!isAlpha) free(newalphapal);
- } else { // RGB
- /////////////////////////////////////////////////////////////////////
- // Generate all palettes
- for (int y = 0, yinv = (height - 1); y < height; y++, yinv--) {
- BYTE rowPalSize = palSize[palIndex[y]];
- int x = 0;
- for (; x < width; x++) {
- if (palTotalSize == MAX_PALETTE_TOTAL_SIZE) {
- WuQuantizer16 Q(dib);
- if (palDefSize == 0 || !Q.Quantize(pixels, palDefSize, 0, NULL)) {
- free(newpal);
- free(bits);
- free(palIndex);
- free(palSize);
- free(pixels);
- return FALSE;
- }
- if (palDefSize > 8192)
- palDefSize -= 4096;
- else
- palDefSize -= (palDefSize >> 2);
- memset(palIndex, 0, height * sizeof(WORD));
- y = -1;
- yinv = height;
- palTotalSize = 1;
- memset(palSize, 1, MAX_PALETTE_COUNT * sizeof(BYTE));
- break;
- }
- int jo = palTotalSize - (palIndex[y] * MAX_PALETTE_SIZE);
- int rc = GetPaletteIndexRGB(pixels[yinv * width + x],
- &newpal[palIndex[y] * MAX_PALETTE_SIZE], rowPalSize);
- if (rc == -1) {
- if (palSize[palIndex[y]] == 0 && rowPalSize == MAX_PALETTE_SIZE) {
- palTotalSize = MAX_PALETTE_TOTAL_SIZE;
- } else if (rowPalSize == MAX_PALETTE_SIZE && jo == MAX_PALETTE_SIZE) {
- palIndex[y]++;
- newpal[palTotalSize] = 0xF81F;
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[newpalSize]);
- #endif
- palTotalSize++;
- y--;
- yinv++;
- break;
- } else if (jo < MAX_PALETTE_SIZE) {
- newpal[palTotalSize] = pixels[yinv * width + x];
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[newpalSize]);
- #endif
- bits[y * width + x] = jo;
- palTotalSize++;
- rowPalSize++;
- } else if (rowPalSize < MAX_PALETTE_SIZE) {
- newpal[palIndex[y] * MAX_PALETTE_SIZE + rowPalSize] = pixels[yinv * width + x];
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(newpal[palIndex[y] * MAX_PALETTE_SIZE + rowPalSize]);
- #endif
- bits[y * width + x] = rowPalSize;
- rowPalSize++;
- } else {
- palIndex[y]++;
- y--;
- yinv++;
- break;
- }
- } else {
- bits[y * width + x] = rc;
- }
- }
- if (x == width)
- palSize[palIndex[y]] = rowPalSize;
- }
- }
- free(palSize);
- free(pixels);
- // write the file header
- BITMAPRLHEADER bitmaprlheader;
- bitmaprlheader.bType = 0x4C52;
- bitmaprlheader.bOptions = (((palTotalSize > 250) ? 1 : 0) << 1) | ((isAlpha) ? 1 : 0);
- bitmaprlheader.bWidth = width;
- bitmaprlheader.bHeight = height;
- bitmaprlheader.bClrUsed = palTotalSize;
- bitmaprlheader.bRLRowsUsed = height;
- #ifdef FREEIMAGE_BIGENDIAN
- SwapFileHeader(&bitmaprlheader);
- #endif
- if (io->write_proc(&bitmaprlheader, sizeof(BITMAPRLHEADER), 1, handle) != 1) {
- free(newpal);
- if (isAlpha) free(newalphapal);
- free(bits);
- free(palIndex);
- return FALSE;
- }
- // write the RGB palette
- if (io->write_proc(newpal, palTotalSize * sizeof(WORD), 1, handle) != 1) {
- free(newpal);
- if (isAlpha) free(newalphapal);
- free(bits);
- free(palIndex);
- return FALSE;
- }
- free(newpal);
- // write the alpha palette
- if (isAlpha) {
- if (io->write_proc(newalphapal, palTotalSize * sizeof(BYTE), 1, handle) != 1) {
- free(newalphapal);
- free(bits);
- free(palIndex);
- return FALSE;
- }
- free(newalphapal);
- }
- // RLE compression
- WORD *rowspitch = (WORD*)malloc(height * sizeof(WORD));
- BYTE *newbits = (BYTE*)malloc(height * width * sizeof(BYTE) + (height * 3));
- memset(rowspitch, 0, height * sizeof(WORD));
- int newbitsIndex = 0;
- int newbitsLen = 0;
- for (int y = 0; y < height; y++) {
- if (palIndex[y] > 0) {
- newbits[newbitsIndex++] = RLE_PALETTE;
- WORD val = (palIndex[y] * MAX_PALETTE_SIZE);
- #ifdef FREEIMAGE_BIGENDIAN
- SwapShort(&val);
- #endif
- *(WORD*)(newbits + newbitsIndex) = val;
- newbitsIndex += 2;
- rowspitch[y] += 3;
- }
- for (int x = 0; x < width; x++) {
- if ((x < width - 1) && (bits[y * width + x] == bits[y * width + x + 1])) {
- // find a solid block of same bytes
- int j = x + 1;
- int jmax = 254 + x;
- while ((j < width - 1) && (j < jmax) && (bits[y * width + j] == bits[y * width + j + 1]))
- ++j;
- // if the block is larger than 3 bytes, use it
- // else put the data into the larger pool
- if (((j - x) + 1) > 3) {
- // write the continuous data
- if (bits[y * width + x] == 0) {
- newbits[newbitsIndex++] = RLE_DELTA;
- newbits[newbitsIndex++] = (BYTE)((j - x) + 1);
- rowspitch[y] += 2;
- } else {
- newbits[newbitsIndex++] = RLE_COMMAND;
- newbits[newbitsIndex++] = bits[y * width + x];
- newbits[newbitsIndex++] = (BYTE)((j - x) + 1);
- rowspitch[y] += 3;
- }
- } else {
- for (int k = 0; k < (j - x) + 1; ++k) {
- newbits[newbitsIndex++] = bits[y * width + x + k];
- rowspitch[y]++;
- }
- }
- x = j;
- } else {
- newbits[newbitsIndex++] = bits[y * width + x];
- rowspitch[y]++;
- }
- }
- }
- free(bits);
- free(palIndex);
- // Write the row pitch array
- for (int y = 0; y < height; y++) {
- if (rowspitch[y] > 0xFD) {
- BYTE bob = 0xFF;
- if (io->write_proc(&bob, sizeof(BYTE), 1, handle) != 1) {
- free(rowspitch);
- free(newbits);
- return FALSE;
- }
- WORD val = rowspitch[y];
- #ifndef FREEIMAGE_BIGENDIAN
- SwapShort(&val);
- #endif
- if (io->write_proc(&val, sizeof(WORD), 1, handle) != 1) {
- free(rowspitch);
- free(newbits);
- return FALSE;
- }
- } else {
- if (io->write_proc(&rowspitch[y], sizeof(BYTE), 1, handle) != 1) {
- free(rowspitch);
- free(newbits);
- return FALSE;
- }
- }
- }
- // Write bitmap bits
- unsigned ii = 0;
- for (int y = 0; y < height; y++) {
- if (io->write_proc(&newbits[ii], rowspitch[y] * sizeof(BYTE), 1, handle) != 1) {
- free(rowspitch);
- free(newbits);
- return FALSE;
- }
- ii += rowspitch[y];
- }
- free(rowspitch);
- free(newbits);
- return TRUE;
- } else {
- return FALSE;
- }
- }
- // ==========================================================
- // Init
- // ==========================================================
- void DLL_CALLCONV
- InitBMPRL(Plugin *plugin, int format_id) {
- s_format_id = format_id;
- plugin->format_proc = Format;
- plugin->description_proc = Description;
- plugin->extension_proc = Extension;
- plugin->regexpr_proc = RegExpr;
- plugin->open_proc = NULL;
- plugin->close_proc = NULL;
- plugin->pagecount_proc = NULL;
- plugin->pagecapability_proc = NULL;
- plugin->load_proc = Load;
- plugin->save_proc = Save;
- plugin->validate_proc = Validate;
- plugin->mime_proc = MimeType;
- plugin->supports_export_bpp_proc = SupportsExportDepth;
- plugin->supports_export_type_proc = SupportsExportType;
- plugin->supports_icc_profiles_proc = NULL; // not implemented yet;
- plugin->supports_no_pixels_proc = SupportsNoPixels;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement