Skip to content

Instantly share code, notes, and snippets.

@crispy-computing-machine
Created May 27, 2024 09:10
Show Gist options
  • Save crispy-computing-machine/0d9e51c05024c07260f58028991ca748 to your computer and use it in GitHub Desktop.
Save crispy-computing-machine/0d9e51c05024c07260f58028991ca748 to your computer and use it in GitHub Desktop.
diff -bur gd.c gd.c
--- gd.c 2024-04-10 10:19:28.000000000 -0400
+++ gd.c 2024-04-19 08:41:01.205119300 -0400
@@ -129,6 +129,13 @@
/* output streaming (formerly gd_ctx.c) */
static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn);
+
+/* Functions for BITMAP 24bits */
+static inline unsigned char *_gdex_write_uint16le(unsigned char *ptr, uint16_t n);
+static inline unsigned char *_gdex_write_int32le(unsigned char *ptr, int32_t n);
+static inline unsigned char *_gdex_write_uint32le(unsigned char *ptr, uint32_t n);
+static unsigned char *_gdex_gdimage_to_bmp24(gdImagePtr im, size_t *size);
+
/*********************************************************
*
* GD Object Representation
@@ -634,6 +641,7 @@
}
/* }}} */
+
/* {{{ Set the line drawing styles for use with imageline and IMG_COLOR_STYLED. */
PHP_FUNCTION(imagesetstyle)
{
@@ -3955,6 +3963,134 @@
/* }}} */
+/* {{{ Get BITMAP 24bit matrix. */
+PHP_FUNCTION(imagegetbitmap24)
+{
+ zval *im_zval;
+ gdImagePtr im;
+ gdImagePtr imtmp = NULL;
+ unsigned char *buffer = NULL;
+ size_t buffer_size, written_size;
+ int x1, y1, x2, y2;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &im_zval, gd_image_ce) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ im = php_gd_libgdimageptr_from_zval_p(im_zval);
+
+ if (!gdImageTrueColor(im)) {
+ imtmp = gdImageCreateTrueColor(gdImageSX(im),gdImageSY(im));
+ gdImageCopyResampled(imtmp,im,0,0,0,0,gdImageSX(im),gdImageSY(im),gdImageSX(im),gdImageSY(im));
+ buffer = _gdex_gdimage_to_bmp24(imtmp, &buffer_size);
+ gdImageDestroy(imtmp);
+ } else {
+ buffer = _gdex_gdimage_to_bmp24(im, &buffer_size);
+ }
+ if (buffer == NULL) {
+ RETURN_BOOL(0);
+ }
+
+ RETURN_STRINGL(buffer,buffer_size,1);
+ efree(buffer);
+}
+/* }}} */
+
+
+
+
+static inline unsigned char *_gdex_write_uint16le(unsigned char *ptr, uint16_t n) {
+ *ptr++ = (unsigned char)(0xff & n);
+ *ptr++ = (unsigned char)(0xff & (n >> 8));
+ return ptr;
+}
+
+static inline unsigned char *_gdex_write_int32le(unsigned char *ptr, int32_t n) {
+ *ptr++ = (unsigned char)(0xff & n);
+ *ptr++ = (unsigned char)(0xff & (n >> 8));
+ *ptr++ = (unsigned char)(0xff & (n >> 16));
+ *ptr++ = (unsigned char)(0xff & (n >> 24));
+ return ptr;
+}
+
+static inline unsigned char *_gdex_write_uint32le(unsigned char *ptr, uint32_t n) {
+ *ptr++ = (unsigned char)(0xff & n);
+ *ptr++ = (unsigned char)(0xff & (n >> 8));
+ *ptr++ = (unsigned char)(0xff & (n >> 16));
+ *ptr++ = (unsigned char)(0xff & (n >> 24));
+ return ptr;
+}
+
+
+
+static unsigned char *_gdex_gdimage_to_bmp24(gdImagePtr im, size_t *size) {
+ unsigned char *buffer, *ptr;
+ size_t buffer_size, image_offset, image_size, line_size;
+ int x, y, width, height;
+
+ /* get image size */
+ width = gdImageSX(im);
+ height = gdImageSY(im);
+
+ /* calculate required memory size */
+ image_offset = 14 + 40;
+ line_size = ((size_t)width * 24 + 31) / 32 * 4;
+ image_size = line_size * (size_t)height;
+ buffer_size = image_offset + image_size;
+
+ /* allocate */
+ buffer = (unsigned char *)emalloc(buffer_size);
+ if (buffer == NULL) {
+ php_error_docref(NULL, E_WARNING,
+ "Failed to allocate memory for %zu bytes", buffer_size);
+ return NULL;
+ }
+ ptr = buffer;
+
+ /* write BITMAPFILEHEADER */
+ *ptr++ = 'B'; /* bfType */
+ *ptr++ = 'M'; /* bfType */
+ ptr = _gdex_write_uint32le(ptr, (uint32_t)buffer_size); /* bfSize */
+ ptr = _gdex_write_uint16le(ptr, 0); /* bfReserved1 */
+ ptr = _gdex_write_uint16le(ptr, 0); /* bfReserved2 */
+ ptr = _gdex_write_uint32le(ptr, (uint32_t)image_offset); /* bfOffBits */
+
+ /* write BITMAPINFOHEADER */
+ ptr = _gdex_write_uint32le(ptr, 40); /* biSize */
+ ptr = _gdex_write_int32le(ptr, (int32_t)width); /* biWidth */
+ ptr = _gdex_write_int32le(ptr, (int32_t)height); /* biHeight */
+ ptr = _gdex_write_uint16le(ptr, 1); /* biPlanes */
+ ptr = _gdex_write_uint16le(ptr, 24); /* biBitCount: 24bpp */
+ ptr = _gdex_write_uint32le(ptr, 0); /* biCopmression: BI_RGB */
+ ptr = _gdex_write_uint32le(ptr, (uint32_t)image_size); /* biSizeImage */
+ ptr = _gdex_write_int32le(ptr, 3780); /* biXPixPerMeter: 96dpi */
+ ptr = _gdex_write_int32le(ptr, 3780); /* biYPixPerMeter: 96dpi */
+ ptr = _gdex_write_uint32le(ptr, 0); /* biClrUsed */
+ ptr = _gdex_write_uint32le(ptr, 0); /* biCirImportant */
+
+ /* write image data */
+ y = height;
+ while (y > 0) {
+ unsigned char *eol = ptr + line_size;
+ --y;
+ for (x = 0; x < width; x++) {
+ int tpixel = gdImageTrueColorPixel(im, x, y);
+ *ptr++ = (unsigned char)(0xff & gdTrueColorGetBlue(tpixel));
+ *ptr++ = (unsigned char)(0xff & gdTrueColorGetGreen(tpixel));
+ *ptr++ = (unsigned char)(0xff & gdTrueColorGetRed(tpixel));
+ }
+ while (ptr < eol) {
+ *ptr++ = '\0';
+ }
+ }
+
+ if (size != NULL) {
+ *size = buffer_size;
+ }
+ return buffer;
+}
+
+
/*********************************************************
*
* Stream Handling
diff -bur gd_arginfo.h gd_arginfo.h
--- gd_arginfo.h 2024-04-10 10:19:28.000000000 -0400
+++ gd_arginfo.h 2024-04-19 08:44:41.264103900 -0400
@@ -576,6 +576,12 @@
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagegetbitmap24, 0, 1, IS_STRING, 0)
+ ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
+ZEND_END_ARG_INFO()
+
+
+
ZEND_FUNCTION(gd_info);
ZEND_FUNCTION(imageloadfont);
ZEND_FUNCTION(imagesetstyle);
@@ -715,6 +721,10 @@
ZEND_FUNCTION(imagesetinterpolation);
ZEND_FUNCTION(imageresolution);
+ZEND_FUNCTION(imagegetbitmap24);
+
+
+
static const zend_function_entry ext_functions[] = {
ZEND_FE(gd_info, arginfo_gd_info)
@@ -861,6 +871,10 @@
ZEND_FE(imagegetinterpolation, arginfo_imagegetinterpolation)
ZEND_FE(imagesetinterpolation, arginfo_imagesetinterpolation)
ZEND_FE(imageresolution, arginfo_imageresolution)
+
+ ZEND_FE(imagegetbitmap24, arginfo_imagegetbitmap24)
+
+
ZEND_FE_END
};
@@ -957,6 +971,9 @@
REGISTER_LONG_CONSTANT("IMG_FILTER_SMOOTH", IMAGE_FILTER_SMOOTH, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_FILTER_PIXELATE", IMAGE_FILTER_PIXELATE, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_FILTER_SCATTER", IMAGE_FILTER_SCATTER, CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("GD_BITMAP24_HEADER", 14, CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("GD_BITMAP24_BITS", 54, CONST_PERSISTENT);
+
#if defined(GD_VERSION_STRING)
REGISTER_STRING_CONSTANT("GD_VERSION", GD_VERSION_STRING, CONST_PERSISTENT);
#endif
Only in ext\gd: test.patch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment