gvdevice_webp.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include "config.h"
  11. #include <gvc/gvplugin_device.h>
  12. #include <gvc/gvio.h>
  13. #ifdef HAVE_WEBP
  14. #include "webp/encode.h"
  15. static const char* const kErrorMessages[] = {
  16. "OK",
  17. "OUT_OF_MEMORY: Out of memory allocating objects",
  18. "BITSTREAM_OUT_OF_MEMORY: Out of memory re-allocating byte buffer",
  19. "NULL_PARAMETER: NULL parameter passed to function",
  20. "INVALID_CONFIGURATION: configuration is invalid",
  21. "BAD_DIMENSION: Bad picture dimension. Maximum width and height "
  22. "allowed is 16383 pixels.",
  23. "PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k.\n"
  24. "To reduce the size of this partition, try using less segments "
  25. "with the -segments option, and eventually reduce the number of "
  26. "header bits using -partition_limit. More details are available "
  27. "in the manual (`man cwebp`)",
  28. "PARTITION_OVERFLOW: Partition is too big to fit 16M",
  29. "BAD_WRITE: Picture writer returned an I/O error",
  30. "FILE_TOO_BIG: File would be too big to fit in 4G",
  31. "USER_ABORT: encoding abort requested by user"
  32. };
  33. typedef enum {
  34. FORMAT_WEBP,
  35. } format_type;
  36. static int writer(const uint8_t* data, size_t data_size, const WebPPicture* const pic) {
  37. return gvwrite(pic->custom_ptr, (const char *)data, data_size) == data_size ? 1 : 0;
  38. }
  39. static void webp_format(GVJ_t * job)
  40. {
  41. WebPPicture picture;
  42. WebPPreset preset;
  43. WebPConfig config;
  44. int stride;
  45. if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) {
  46. fprintf(stderr, "Error! Version mismatch!\n");
  47. goto Error;
  48. }
  49. // if either dimension exceeds the WebP API, map this to one of its errors
  50. if ((unsigned)INT_MAX / 4 < job->width || job->height > (unsigned)INT_MAX) {
  51. int error = VP8_ENC_ERROR_BAD_DIMENSION;
  52. fprintf(stderr, "Error! Cannot encode picture as WebP\n");
  53. fprintf(stderr, "Error code: %d (%s)\n", error, kErrorMessages[error]);
  54. goto Error;
  55. }
  56. picture.width = (int)job->width;
  57. picture.height = (int)job->height;
  58. stride = 4 * (int)job->width;
  59. picture.writer = writer;
  60. picture.custom_ptr = job;
  61. preset = WEBP_PRESET_DRAWING;
  62. if (!WebPConfigPreset(&config, preset, config.quality)) {
  63. fprintf(stderr, "Error! Could initialize configuration with preset.\n");
  64. goto Error;
  65. }
  66. if (!WebPValidateConfig(&config)) {
  67. fprintf(stderr, "Error! Invalid configuration.\n");
  68. goto Error;
  69. }
  70. if (!WebPPictureAlloc(&picture)) {
  71. fprintf(stderr, "Error! Cannot allocate memory\n");
  72. return;
  73. }
  74. if (!WebPPictureImportBGRA(&picture,
  75. (const uint8_t * const)job->imagedata, stride)) {
  76. fprintf(stderr, "Error! Cannot import picture\n");
  77. goto Error;
  78. }
  79. if (!WebPEncode(&config, &picture)) {
  80. fprintf(stderr, "Error! Cannot encode picture as WebP\n");
  81. fprintf(stderr, "Error code: %d (%s)\n",
  82. picture.error_code, kErrorMessages[picture.error_code]);
  83. goto Error;
  84. }
  85. Error:
  86. WebPPictureFree(&picture);
  87. }
  88. static gvdevice_engine_t webp_engine = {
  89. NULL, /* webp_initialize */
  90. webp_format,
  91. NULL, /* webp_finalize */
  92. };
  93. static gvdevice_features_t device_features_webp = {
  94. GVDEVICE_BINARY_FORMAT
  95. | GVDEVICE_NO_WRITER
  96. | GVDEVICE_DOES_TRUECOLOR,/* flags */
  97. {0.,0.}, /* default margin - points */
  98. {0.,0.}, /* default page width, height - points */
  99. {96.,96.}, /* 96 dpi */
  100. };
  101. #endif
  102. gvplugin_installed_t gvdevice_webp_types[] = {
  103. #ifdef HAVE_WEBP
  104. {FORMAT_WEBP, "webp:cairo", 1, &webp_engine, &device_features_webp},
  105. #endif
  106. {0, NULL, 0, NULL, NULL}
  107. };