writer_jpg.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "main.h"
  2. #include "writer_jpg.h"
  3. #include "api__jpeg.h"
  4. #include <api/memmgr/api_memmgr.h>
  5. #include <shlwapi.h>
  6. #include <strsafe.h>
  7. /*BIG BIG THING TO NOTE
  8. I have modified jmorecfg.h line 319 to specify 4 bytes per pixel with RGB. it is normally three.
  9. */
  10. extern "C" {
  11. #undef FAR
  12. #include "jpeglib.h"
  13. };
  14. JpgWrite::JpgWrite() : quality(80) {}
  15. // valid items include "quality" for jpeg files with value "0" to "100", "lossless" returns "1" if it is "0" otherwise
  16. // return value is 1 if the config item is supported, 0 if it is not.
  17. int JpgWrite::setConfig(const wchar_t * item, const wchar_t * value) {
  18. if(!_wcsicmp(item,L"quality")) quality = _wtoi(value);
  19. else return 0;
  20. return 1;
  21. }
  22. int JpgWrite::getConfig(const wchar_t * item, wchar_t * value, int valuelen) {
  23. if(!_wcsicmp(item,L"lossless")) lstrcpynW(value,L"0",valuelen);
  24. else if(!_wcsicmp(item,L"quality")) StringCchPrintfW(value,valuelen,L"%d",quality);
  25. else return 0;
  26. return 1;
  27. }
  28. int JpgWrite::bitDepthSupported(int depth) {
  29. if(depth == 32 || depth == 24) return 1;
  30. return 0;
  31. }
  32. extern "C" {
  33. typedef struct {
  34. jpeg_destination_mgr pub;
  35. BYTE *buf;
  36. int len;
  37. } my_destination_mgr;
  38. void init_destination(j_compress_ptr cinfo){}
  39. boolean empty_output_buffer(j_compress_ptr cinfo) {
  40. my_destination_mgr* m = (my_destination_mgr*)cinfo->dest;
  41. int used = m->len;
  42. int d = ((m->len / 4) & 0xffffff00) + 0x100;
  43. if(d < 4096) d = 4096;
  44. m->len+=d;
  45. m->buf = (BYTE*)WASABI_API_MEMMGR->sysRealloc(m->buf,m->len);
  46. m->pub.next_output_byte = m->buf + used;
  47. m->pub.free_in_buffer = d;
  48. return TRUE;
  49. }
  50. void term_destination(j_compress_ptr cinfo){}
  51. };
  52. // returns the image in our format, free the returned buffer with api_memmgr::sysFree()
  53. void * JpgWrite::convert(const void *pixels, int bitDepth, int w, int h, int *length) {
  54. if(bitDepth != 32 && bitDepth != 24) return 0;
  55. jpeg_compress_struct cinfo={0};
  56. jpeg_error_mgr jerr;
  57. cinfo.err = jpeg_std_error(&jerr);
  58. jpeg_create_compress(&cinfo);
  59. // a guess at the final size...
  60. int allocsize = (int(double(w*h)*0.2) & 0xffffff00) + 0x100;
  61. if (allocsize < 4096) allocsize = 4096;
  62. // set up our output stream
  63. my_destination_mgr dest = {{0,(size_t)allocsize,init_destination,empty_output_buffer,term_destination},0,allocsize};
  64. dest.buf = (BYTE*)WASABI_API_MEMMGR->sysMalloc(allocsize);
  65. dest.pub.next_output_byte = dest.buf;
  66. cinfo.dest = (jpeg_destination_mgr*)&dest;
  67. // image parameters
  68. cinfo.image_width = w;
  69. cinfo.image_height = h;
  70. cinfo.input_components = 4;
  71. cinfo.in_color_space = JCS_RGB;
  72. jpeg_set_defaults(&cinfo);
  73. jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
  74. jpeg_start_compress(&cinfo, TRUE);
  75. int row_stride = w * 4;
  76. BYTE * scanline = (BYTE *)malloc(row_stride);
  77. if(bitDepth == 32) {
  78. const ARGB32 * p = ((const ARGB32*)pixels);// + (h * w);
  79. while (cinfo.next_scanline < cinfo.image_height) {
  80. //p-=w;
  81. memcpy(scanline,p,row_stride);
  82. for(unsigned int i=0; i < cinfo.image_width; i++)
  83. ((ARGB32*)scanline)[i] = ((p[i] & 0x0000ff) << 16) | (p[i] & 0x00ff00) | ((p[i] & 0xff0000) >> 16);
  84. jpeg_write_scanlines(&cinfo, &scanline, 1);
  85. p+=w;
  86. }
  87. } else if(bitDepth == 24) { // FUCKO: untested
  88. const BYTE * p = ((const BYTE*)pixels);// + (h * w * 3);
  89. while (cinfo.next_scanline < cinfo.image_height) {
  90. //p-=w*3;
  91. memcpy(scanline,p,row_stride);
  92. int l = cinfo.image_width * 4;
  93. for(int i=0,j=0; j < l; i+=3,j+=4) {
  94. scanline[j] = p[i+2];
  95. scanline[j+1] = p[i+1];
  96. scanline[j+2] = p[i];
  97. }
  98. jpeg_write_scanlines(&cinfo, &scanline, 1);
  99. p+=w*3;
  100. }
  101. }
  102. free(scanline);
  103. jpeg_finish_compress(&cinfo);
  104. if(length) *length = int(dest.len - dest.pub.free_in_buffer);
  105. jpeg_destroy_compress(&cinfo);
  106. return dest.buf;
  107. }
  108. #define CBCLASS JpgWrite
  109. START_DISPATCH;
  110. CB(GETIMAGETYPENAME, getImageTypeName);
  111. CB(GETEXTENSIONS, getExtensions);
  112. CB(SETCONFIG, setConfig);
  113. CB(GETCONFIG, getConfig);
  114. CB(BITDEPTHSUPPORTED, bitDepthSupported);
  115. CB(CONVERT, convert);
  116. END_DISPATCH;
  117. #undef CBCLASS