QRPIJpegHandler.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include <QVariant>
  2. #include <QIODevice>
  3. #include <QImage>
  4. #include <QColor>
  5. #include <QDebug>
  6. #include <QElapsedTimer>
  7. #include <QDateTime>
  8. #include "QRPIJpegHandler.h"
  9. QT_BEGIN_NAMESPACE
  10. ///////////////////////////////////////////////////////////////////////////////////////////////////
  11. QRPIJpegHandler::QRPIJpegHandler() : m_quality(100), m_decoder(NULL)
  12. {
  13. setFormat("jpeg");
  14. // initialize decoder parameters
  15. memset(&m_dec_request, 0, sizeof(m_dec_request));
  16. m_dec_request.input = encodedInBuf;
  17. m_dec_request.output = decodedBuf;
  18. m_dec_request.output_handle = 0;
  19. m_dec_request.output_alloc_size = MAX_DECODED;
  20. m_dec_request.pixel_format = PIXEL_FORMAT_RGBA;
  21. BRCMJPEG_STATUS_T status = brcmjpeg_create(BRCMJPEG_TYPE_DECODER, &m_decoder);
  22. if (status != BRCMJPEG_SUCCESS)
  23. {
  24. qWarning() << "QRPIJpegHandler : could not create decoder";
  25. brcmjpeg_release(m_decoder);
  26. m_decoder = NULL;
  27. }
  28. }
  29. ///////////////////////////////////////////////////////////////////////////////////////////////////
  30. QRPIJpegHandler::~QRPIJpegHandler()
  31. {
  32. if (m_decoder)
  33. brcmjpeg_release(m_decoder);
  34. m_decoder = NULL;
  35. }
  36. ///////////////////////////////////////////////////////////////////////////////////////////////////
  37. bool QRPIJpegHandler::canRead() const
  38. {
  39. return canRead(device());
  40. }
  41. ///////////////////////////////////////////////////////////////////////////////////////////////////
  42. bool QRPIJpegHandler::canRead(QIODevice* device)
  43. {
  44. if (!device)
  45. {
  46. qWarning("QRPIJpegHandler::canRead() called with no device");
  47. return false;
  48. }
  49. unsigned char buffer[2];
  50. if (device->peek((char*)buffer, 2) != 2)
  51. return false;
  52. return uchar(buffer[0]) == 0xff && uchar(buffer[1]) == 0xd8;
  53. }
  54. ///////////////////////////////////////////////////////////////////////////////////////////////////
  55. bool QRPIJpegHandler::read(QImage* image)
  56. {
  57. if (device())
  58. {
  59. m_dec_request.buffer_width = 0;
  60. m_dec_request.buffer_height = 0;
  61. m_dec_request.input_size = device()->read((char*)encodedInBuf, sizeof(encodedInBuf));
  62. QElapsedTimer timer;
  63. timer.start();
  64. BRCMJPEG_STATUS_T status = brcmjpeg_process(m_decoder, &m_dec_request);
  65. if (status == BRCMJPEG_SUCCESS)
  66. {
  67. for (int i = 0; i < m_dec_request.height; i++)
  68. {
  69. memcpy(image->scanLine(i), decodedBuf + m_dec_request.buffer_width * i * 4,
  70. m_dec_request.buffer_width * 4);
  71. }
  72. //*image = decodedImage;
  73. qDebug() << QDateTime::currentDateTime().toMSecsSinceEpoch()
  74. << "QRPIJpegHandler : decoded a"
  75. << m_dec_request.width << "x" << m_dec_request.height
  76. << "image in" << timer.elapsed() << "ms";
  77. return true;
  78. }
  79. else
  80. {
  81. qWarning() << "QRPIJpegHandler : Decoding failed with status" << status;
  82. return false;
  83. }
  84. }
  85. else
  86. {
  87. qDebug() << "QRPIJpegHandler : read() was called with NULL device";
  88. return false;
  89. }
  90. }
  91. ///////////////////////////////////////////////////////////////////////////////////////////////////
  92. bool QRPIJpegHandler::write(const QImage& image)
  93. {
  94. Q_UNUSED(image);
  95. qWarning() << "QRPIJpegHandler : call to unsupported write()";
  96. return false;
  97. }
  98. ///////////////////////////////////////////////////////////////////////////////////////////////////
  99. bool QRPIJpegHandler::supportsOption(ImageOption option) const
  100. {
  101. return option == Quality || option == Size || option == ImageFormat;
  102. }
  103. ///////////////////////////////////////////////////////////////////////////////////////////////////
  104. bool QRPIJpegHandler::readJpegSize(QIODevice* device, QSize& size) const
  105. {
  106. if (canRead(device))
  107. {
  108. JFIFHEAD header;
  109. int bytesRead = device->peek((char*)&header, sizeof(header));
  110. if (bytesRead >= (sizeof(header) - JFIF_DATA_SIZE))
  111. {
  112. BYTE* dataptr = header.data;
  113. while (dataptr < ((BYTE*)&header + bytesRead))
  114. {
  115. if (dataptr[0] != 0xFF)
  116. {
  117. qWarning() << "readJpegSize : got wrong marker " << dataptr[0];
  118. return false;
  119. }
  120. // we look for size block marker
  121. if (dataptr[1] == 0xC0 && dataptr[2] == 0x0)
  122. {
  123. size.setWidth(dataptr[8] + dataptr[7] * 256);
  124. size.setHeight(dataptr[6] + dataptr[5] * 256);
  125. return true;
  126. }
  127. dataptr += dataptr[3] + (dataptr[2] * 256) + 2;
  128. }
  129. }
  130. else
  131. {
  132. qWarning() << "readJpegSize : could not read " << sizeof(header) << "bytes, read " << bytesRead;
  133. return false;
  134. }
  135. }
  136. else
  137. {
  138. qWarning() << "readJpegSize : device " << device << "can't be read!" ;
  139. return false;
  140. }
  141. qWarning() << "readJpegSize : could not find the proper size marker";
  142. return false;
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////////////////////////
  145. QVariant QRPIJpegHandler::option(ImageOption option) const
  146. {
  147. switch (option)
  148. {
  149. case Size:
  150. {
  151. QSize size(0, 0);
  152. readJpegSize(device(), size);
  153. return QVariant(size);
  154. break;
  155. }
  156. case ImageFormat:
  157. {
  158. return QImage::Format_RGBA8888_Premultiplied;
  159. }
  160. default:
  161. {
  162. qWarning() << "QRPIJpegHandler : requesting unsupported option" << option;
  163. return QVariant();
  164. break;
  165. }
  166. }
  167. }
  168. ///////////////////////////////////////////////////////////////////////////////////////////////////
  169. void QRPIJpegHandler::setOption(ImageOption option, const QVariant& value)
  170. {
  171. switch (option)
  172. {
  173. case Quality:
  174. m_quality = value.toInt();
  175. break;
  176. default:
  177. qWarning() << "QRPIJpegHandler : setOption unsupported option" << option << "to" << value;
  178. break;
  179. }
  180. }
  181. ///////////////////////////////////////////////////////////////////////////////////////////////////
  182. QByteArray QRPIJpegHandler::name() const { return "RPIjpeg"; }
  183. QT_END_NAMESPACE