static size_t rgb2type(ss_t **out, enum ImgTypes ot, const ss_t *rgb0, const struct RGB_Info *ri, const int f) { ss_t *rgb_aux = NULL; const ss_t *rgb; switch (f) { /* Apply filter, if any */ case F_HDPCM: case F_HRDPCM: case F_HDXOR: case F_HRDXOR: case F_VDPCM: case F_VRDPCM: case F_VDXOR: case F_VRDXOR: case F_AVG3: case F_RAVG3: case F_PAETH: case F_RPAETH: case F_RSUB: case F_RRSUB: case F_GSUB: case F_RGSUB: case F_BSUB: case F_RBSUB: rgb = (f == F_HDPCM ? hrgb2dpcm : f == F_HRDPCM ? hdpcm2rgb : f == F_HDXOR ? hrgb2dxor : f == F_HRDXOR ? hdxor2rgb : f == F_VDPCM ? vrgb2dpcm : f == F_VRDPCM ? vdpcm2rgb : f == F_VDXOR ? vrgb2dxor : f == F_VRDXOR ? vdxor2rgb : f == F_AVG3 ? rgb2davg : f == F_RAVG3 ? davg2rgb : f == F_PAETH ? rgb2paeth : f == F_RPAETH ? paeth2rgb : f == F_RSUB ? rgb2rsub : f == F_RRSUB ? rsub2rgb : f == F_GSUB ? rgb2gsub : f == F_RGSUB ? gsub2rgb : f == F_BSUB ? rgb2bsub : bsub2rgb)(&rgb_aux, rgb0, ri) ? rgb_aux : rgb0; if (rgb == rgb0) fprintf(stderr, "filter error! (%i)\n", f); break; default:rgb = rgb0; break; } size_t r = ot == IMG_tga ? rgb2tga(out, rgb, ri) : ot == IMG_ppm || ot == IMG_pgm ? rgb2ppm(out, rgb, ri) : IF_PNG(ot == IMG_png ? rgb2png(out, rgb, ri) :) IF_JPG(ot == IMG_jpg ? rgb2jpg(out, rgb, ri) :) IF_LL1(ot == IMG_ll1 ? rgb2ll1(out, rgb, ri) :) ot == IMG_raw ? ss_size(ss_cpy(out, rgb)) : ot == IMG_none ? rgb_info(rgb, ri) : 0; ss_free(&rgb_aux); return r; }
void dib_img_writer(const char *contents, FILE *out, drawingStates *states, PU_BITMAPINFOHEADER BmiSrc, const unsigned char *BmpSrc, size_t size, bool assign_mono_colors_from_dc) { char *b64Bmp = NULL; size_t b64s; char *tmp = NULL; // Handle simple cases first, no treatment needed for them switch (BmiSrc->biCompression) { case U_BI_JPEG: b64Bmp = base64_encode(BmpSrc, size, &b64s); fprintf(out, "xlink:href=\"data:image/jpg;base64,"); break; case U_BI_PNG: b64Bmp = base64_encode(BmpSrc, size, &b64s); fprintf(out, "xlink:href=\"data:image/png;base64,"); break; } if (b64Bmp != NULL) { fprintf(out, "%s\" ", b64Bmp); free(b64Bmp); return; } // more complexe treatment, with conversion to png RGBBitmap convert_in; convert_in.size = size; convert_in.width = BmiSrc->biWidth; convert_in.height = BmiSrc->biHeight; convert_in.pixels = (RGBPixel *)BmpSrc; convert_in.bytewidth = BmiSrc->biWidth * 3; convert_in.bytes_per_pixel = 3; RGBBitmap convert_out; convert_out.pixels = NULL; const U_RGBQUAD *ct = NULL; U_RGBQUAD monoCt[2]; uint32_t width, height, colortype, numCt, invert; char *rgba_px = NULL; int dibparams; char *in; size_t img_size; RGBABitmap convert_inpng; // In any cases after that, we get a png blob fprintf(out, "xlink:href=\"data:image/png;base64,"); switch (BmiSrc->biCompression) { case U_BI_RLE8: convert_out = rle8ToRGB8(convert_in); break; case U_BI_RLE4: convert_out = rle4ToRGB(convert_in); break; } if (convert_out.pixels != NULL) { in = (char *)convert_out.pixels; img_size = convert_out.size; } else { in = (char *)convert_in.pixels; img_size = convert_in.size; } dibparams = e2s_get_DIB_params((PU_BITMAPINFO)BmiSrc, (const U_RGBQUAD **)&ct, &numCt, &width, &height, &colortype, &invert); // if enable to read header, then exit if (dibparams || width > MAX_BMP_WIDTH || height > MAX_BMP_HEIGHT) { free(convert_out.pixels); states->Error = true; return; } // check that what we will read in the DIB_to_RGBA conversion is actually // there size_t offset_check = (size_t)((float)width * (float)height * get_pixel_size(colortype)); if (((in + img_size) < in + offset_check)) { free(convert_out.pixels); states->Error = true; return; } if (colortype == U_BCBM_MONOCHROME) { if (assign_mono_colors_from_dc) { monoCt[0].Red = states->currentDeviceContext.text_red; monoCt[0].Green = states->currentDeviceContext.text_green; monoCt[0].Blue = states->currentDeviceContext.text_blue; monoCt[0].Reserved = 0xff; monoCt[1].Red = states->currentDeviceContext.bk_red; monoCt[1].Green = states->currentDeviceContext.bk_green; monoCt[1].Blue = states->currentDeviceContext.bk_blue; monoCt[1].Reserved = 0xff; // states->currentDeviceContext.bk_mode ? 0xff : 0; ct = monoCt; } } DIB_to_RGBA(in, ct, numCt, &rgba_px, width, height, colortype, numCt, invert); if (rgba_px != NULL) { convert_inpng.size = width * 4 * height; convert_inpng.width = width; convert_inpng.height = height; convert_inpng.pixels = (RGBAPixel *)rgba_px; convert_inpng.bytewidth = BmiSrc->biWidth * 3; convert_inpng.bytes_per_pixel = 3; rgb2png(&convert_inpng, &b64Bmp, &b64s); tmp = (char *)b64Bmp; b64Bmp = base64_encode((unsigned char *)b64Bmp, b64s, &b64s); free(convert_out.pixels); free(tmp); free(rgba_px); } if (b64Bmp != NULL) { fprintf(out, "%s\" ", b64Bmp); free(b64Bmp); } else { // transparent 5x5 px png fprintf(out, "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABGdBTUEAA" "LGPC/xhBQAAAAZiS0dEAP8A/wD/" "oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+" "ABFREtOJX7FAkAAAAIdEVYdENvbW1lbnQA9syWvwAAAAxJREFUCNdjYKA" "TAAAAaQABwB3y+AAAAABJRU5ErkJggg==\" "); } }