Kstars

videowg.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "videowg.h"
8 
9 #include "kstars_debug.h"
10 
11 #include <QImageReader>
12 #include <QMouseEvent>
13 #include <QResizeEvent>
14 #include <QRubberBand>
15 
16 VideoWG::VideoWG(QWidget *parent) : QLabel(parent)
17 {
18  streamImage.reset(new QImage());
19 
20  grayTable.resize(256);
21 
22  for (int i = 0; i < 256; i++)
23  grayTable[i] = qRgb(i, i, i);
24 }
25 
26 bool VideoWG::newBayerFrame(IBLOB *bp, const BayerParams &params)
27 {
28  return debayer(bp, params);
29 }
30 
31 bool VideoWG::newFrame(IBLOB *bp)
32 {
33  if (bp->size <= 0)
34  return false;
35 
36  bool rc = false;
37  QString format(bp->format);
38  if (m_RawFormat != format)
39  {
40  format.remove('.');
41  format.remove("stream_");
42  m_RawFormatSupported = QImageReader::supportedImageFormats().contains(format.toLatin1());
43  m_RawFormat = format;
44  }
45 
46  if (m_RawFormatSupported)
47  rc = streamImage->loadFromData(static_cast<uchar *>(bp->blob), bp->size);
48  else if (static_cast<uint32_t>(bp->size) == totalBaseCount)
49  {
50  streamImage.reset(new QImage(static_cast<uchar *>(bp->blob), streamW, streamH, QImage::Format_Indexed8));
51  streamImage->setColorTable(grayTable);
52  rc = !streamImage->isNull();
53  }
54  else if (static_cast<uint32_t>(bp->size) == totalBaseCount * 3)
55  {
56  streamImage.reset(new QImage(static_cast<uchar *>(bp->blob), streamW, streamH, QImage::Format_RGB888));
57  rc = !streamImage->isNull();
58  }
59 
60  if (rc)
61  {
62  kPix = QPixmap::fromImage(streamImage->scaled(size(), Qt::KeepAspectRatio));
63  setPixmap(kPix);
64  }
65 
66  emit imageChanged(streamImage);
67 
68  return rc;
69 }
70 
71 bool VideoWG::save(const QString &filename, const char *format)
72 {
73  return kPix.save(filename, format);
74 }
75 
76 void VideoWG::setSize(uint16_t w, uint16_t h)
77 {
78  streamW = w;
79  streamH = h;
80  totalBaseCount = w * h;
81 }
82 
83 //void VideoWG::resizeEvent(QResizeEvent *ev)
84 //{
85 // setPixmap(QPixmap::fromImage(streamImage->scaled(ev->size(), Qt::KeepAspectRatio)));
86 // ev->accept();
87 //}
88 
89 void VideoWG::mousePressEvent(QMouseEvent *event)
90 {
91  origin = event->pos();
92  if (!rubberBand)
93  rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
94  rubberBand->setGeometry(QRect(origin, QSize()));
95  rubberBand->show();
96 }
97 
98 void VideoWG::mouseMoveEvent(QMouseEvent *event)
99 {
100  rubberBand->setGeometry(QRect(origin, event->pos()).normalized());
101 }
102 
103 void VideoWG::mouseReleaseEvent(QMouseEvent *event)
104 {
105  rubberBand->hide();
106 
107  if (event->button() == Qt::RightButton)
108  {
109  emit newSelection(QRect());
110  return;
111  }
112 
113  QRect rawSelection = rubberBand->geometry();
114  int pixmapX = (width() - kPix.width()) / 2;
115  int pixmapY = (height() - kPix.height()) / 2;
116 
117  QRect finalSelection;
118 
119  double scaleX = static_cast<double>(streamImage->width()) / kPix.width();
120  double scaleY = static_cast<double>(streamImage->height()) / kPix.height();
121 
122  finalSelection.setX((rawSelection.x() - pixmapX) * scaleX);
123  finalSelection.setY((rawSelection.y() - pixmapY) * scaleY);
124  finalSelection.setWidth(rawSelection.width() * scaleX);
125  finalSelection.setHeight(rawSelection.height() * scaleY);
126 
127  emit newSelection(finalSelection);
128  // determine selection, for example using QRect::intersects()
129  // and QRect::contains().
130 }
131 
132 bool VideoWG::debayer(const IBLOB *bp, const BayerParams &params)
133 {
134  uint32_t rgb_size = streamW * streamH * 3;
135  auto * destinationBuffer = new uint8_t[rgb_size];
136 
137  if (destinationBuffer == nullptr)
138  {
139  qCCritical(KSTARS) << "Unable to allocate memory for temporary bayer buffer.";
140  return false;
141  }
142 
143  int ds1394_height = streamH;
144 
145  uint8_t * dc1394_source = reinterpret_cast<uint8_t*>(bp->blob);
146  if (params.offsetY == 1)
147  {
148  dc1394_source += streamW;
149  ds1394_height--;
150  }
151  if (params.offsetX == 1)
152  {
153  dc1394_source++;
154  }
155  dc1394error_t error_code = dc1394_bayer_decoding_8bit(dc1394_source, destinationBuffer, streamW, ds1394_height,
156  params.filter, params.method);
157 
158  if (error_code != DC1394_SUCCESS)
159  {
160  qCCritical(KSTARS) << "Debayer failed" << error_code;
161  delete[] destinationBuffer;
162  return false;
163  }
164 
165  streamImage.reset(new QImage(destinationBuffer, streamW, streamH, QImage::Format_RGB888));
166  bool rc = !streamImage->isNull();
167 
168  if (rc)
169  {
170  kPix = QPixmap::fromImage(streamImage->scaled(size(), Qt::KeepAspectRatio));
171  setPixmap(kPix);
172  }
173 
174  emit imageChanged(streamImage);
175 
176  delete[] destinationBuffer;
177  return rc;
178 }
179 
void setWidth(int width)
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
int width() const const
int x() const const
int y() const const
RightButton
bool contains(const T &value) const const
QList< QByteArray > supportedImageFormats()
KeepAspectRatio
void setHeight(int height)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void resize(int w, int h)
int height() const const
void setX(int x)
void setY(int y)
QRect normalized() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:58 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.