30 bit display feature
This commit is contained in:
parent
795c8cae04
commit
a55f60e466
14 changed files with 747 additions and 73 deletions
|
@ -942,6 +942,454 @@ void doQuickPutNoFilter(const TRaster32P &dn, const TRasterGR8P &up,
|
||||||
up->unlock();
|
up->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void doQuickPutNoFilter(const TRaster64P &dn, const TRaster64P &up,
|
||||||
|
const TAffine &aff, bool doPremultiply,
|
||||||
|
bool firstColumn) {
|
||||||
|
// se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
|
||||||
|
// di up e' un segmento (o un punto)
|
||||||
|
if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
|
||||||
|
|
||||||
|
// contatore bit di shift
|
||||||
|
const int PADN = 16;
|
||||||
|
|
||||||
|
// max dimensioni di up gestibili (limite imposto dal numero di bit
|
||||||
|
// disponibili per la parte intera di xL, yL)
|
||||||
|
assert(std::max(up->getLx(), up->getLy()) <
|
||||||
|
(1 << (8 * sizeof(int) - PADN - 1)));
|
||||||
|
|
||||||
|
TRectD boundingBoxD =
|
||||||
|
TRectD(convert(dn->getBounds())) *
|
||||||
|
(aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
|
||||||
|
|
||||||
|
// clipping
|
||||||
|
if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// clipping y su dn
|
||||||
|
int yMin = std::max(tfloor(boundingBoxD.y0), 0);
|
||||||
|
|
||||||
|
// clipping y su dn
|
||||||
|
int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
|
||||||
|
|
||||||
|
// clipping x su dn
|
||||||
|
int xMin = std::max(tfloor(boundingBoxD.x0), 0);
|
||||||
|
|
||||||
|
// clipping x su dn
|
||||||
|
int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
|
||||||
|
|
||||||
|
// inversa di aff
|
||||||
|
TAffine invAff = inv(aff);
|
||||||
|
|
||||||
|
// nel disegnare la y-esima scanline di dn, il passaggio al pixel
|
||||||
|
// successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
|
||||||
|
// pixel corrispondente di up
|
||||||
|
double deltaXD = invAff.a11;
|
||||||
|
double deltaYD = invAff.a21;
|
||||||
|
|
||||||
|
// deltaXD "TLonghizzato" (round)
|
||||||
|
int deltaXL = tround(deltaXD * (1 << PADN));
|
||||||
|
|
||||||
|
// deltaYD "TLonghizzato" (round)
|
||||||
|
int deltaYL = tround(deltaYD * (1 << PADN));
|
||||||
|
|
||||||
|
// se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
|
||||||
|
// segmento (o un punto)
|
||||||
|
if ((deltaXL == 0) && (deltaYL == 0)) return;
|
||||||
|
|
||||||
|
// TINT32 predecessore di up->getLx()
|
||||||
|
int lxPred = up->getLx() * (1 << PADN) - 1;
|
||||||
|
|
||||||
|
// TINT32 predecessore di up->getLy()
|
||||||
|
int lyPred = up->getLy() * (1 << PADN) - 1;
|
||||||
|
|
||||||
|
int dnWrap = dn->getWrap();
|
||||||
|
int upWrap = up->getWrap();
|
||||||
|
dn->lock();
|
||||||
|
up->lock();
|
||||||
|
|
||||||
|
TPixel64 *dnRow = dn->pixels(yMin);
|
||||||
|
TPixel64 *upBasePix = up->pixels();
|
||||||
|
|
||||||
|
// scorre le scanline di boundingBoxD
|
||||||
|
for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
|
||||||
|
// (1) equazione k-parametrica della y-esima scanline di boundingBoxD:
|
||||||
|
// (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin)
|
||||||
|
|
||||||
|
// (2) equazione k-parametrica dell'immagine mediante invAff di (1):
|
||||||
|
// invAff*(xMin, y) + k*(deltaXD, deltaYD),
|
||||||
|
// k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
|
||||||
|
|
||||||
|
// calcola kMin, kMax per la scanline corrente
|
||||||
|
// intersecando la (2) con i lati di up
|
||||||
|
|
||||||
|
// il segmento [a, b] di up e' la controimmagine mediante aff della
|
||||||
|
// porzione di scanline [ (xMin, y), (xMax, y) ] di dn
|
||||||
|
|
||||||
|
// TPointD b = invAff*TPointD(xMax, y);
|
||||||
|
TPointD a = invAff * TPointD(xMin, y);
|
||||||
|
|
||||||
|
// (xL0, yL0) sono le coordinate di a (inizializzate per il round)
|
||||||
|
// in versione "TLonghizzata"
|
||||||
|
// 0 <= xL0 + k*deltaXL
|
||||||
|
// < up->getLx()*(1<<PADN)
|
||||||
|
//
|
||||||
|
// 0 <= kMinX
|
||||||
|
// <= kMin
|
||||||
|
// <= k
|
||||||
|
// <= kMax
|
||||||
|
// <= kMaxX
|
||||||
|
// <= (xMax - xMin)
|
||||||
|
//
|
||||||
|
// 0 <= yL0 + k*deltaYL
|
||||||
|
// < up->getLy()*(1<<PADN)
|
||||||
|
|
||||||
|
// 0 <= kMinY
|
||||||
|
// <= kMin
|
||||||
|
// <= k
|
||||||
|
// <= kMax
|
||||||
|
// <= kMaxY
|
||||||
|
// <= (xMax - xMin)
|
||||||
|
|
||||||
|
// xL0 inizializzato per il round
|
||||||
|
int xL0 = tround((a.x + 0.5) * (1 << PADN));
|
||||||
|
|
||||||
|
// yL0 inizializzato per il round
|
||||||
|
int yL0 = tround((a.y + 0.5) * (1 << PADN));
|
||||||
|
|
||||||
|
// calcola kMinX, kMaxX, kMinY, kMaxY
|
||||||
|
int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn
|
||||||
|
int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn
|
||||||
|
|
||||||
|
// 0 <= xL0 + k*deltaXL
|
||||||
|
// < up->getLx()*(1<<PADN)
|
||||||
|
// <=>
|
||||||
|
// 0 <= xL0 + k*deltaXL
|
||||||
|
// <= lxPred
|
||||||
|
//
|
||||||
|
// 0 <= yL0 + k*deltaYL
|
||||||
|
// < up->getLy()*(1<<PADN)
|
||||||
|
// <=>
|
||||||
|
// 0 <= yL0 + k*deltaYL
|
||||||
|
// <= lyPred
|
||||||
|
|
||||||
|
// calcola kMinX, kMaxX
|
||||||
|
if (deltaXL == 0) {
|
||||||
|
// [a, b] verticale esterno ad up+(bordo destro/basso)
|
||||||
|
if ((xL0 < 0) || (lxPred < xL0)) continue;
|
||||||
|
// altrimenti usa solo
|
||||||
|
// kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
|
||||||
|
} else if (deltaXL > 0) {
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (lxPred < xL0) continue;
|
||||||
|
|
||||||
|
kMaxX = (lxPred - xL0) / deltaXL; // floor
|
||||||
|
if (xL0 < 0) {
|
||||||
|
kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil
|
||||||
|
}
|
||||||
|
} else // (deltaXL < 0)
|
||||||
|
{
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (xL0 < 0) continue;
|
||||||
|
|
||||||
|
kMaxX = xL0 / (-deltaXL); // floor
|
||||||
|
if (lxPred < xL0) {
|
||||||
|
kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcola kMinY, kMaxY
|
||||||
|
if (deltaYL == 0) {
|
||||||
|
// [a, b] orizzontale esterno ad up+(bordo destro/basso)
|
||||||
|
if ((yL0 < 0) || (lyPred < yL0)) continue;
|
||||||
|
// altrimenti usa solo
|
||||||
|
// kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
|
||||||
|
} else if (deltaYL > 0) {
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (lyPred < yL0) continue;
|
||||||
|
|
||||||
|
kMaxY = (lyPred - yL0) / deltaYL; // floor
|
||||||
|
if (yL0 < 0) {
|
||||||
|
kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil
|
||||||
|
}
|
||||||
|
} else // (deltaYL < 0)
|
||||||
|
{
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (yL0 < 0) continue;
|
||||||
|
|
||||||
|
kMaxY = yL0 / (-deltaYL); // floor
|
||||||
|
if (lyPred < yL0) {
|
||||||
|
kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcola kMin, kMax effettuando anche il clippind su dn
|
||||||
|
int kMin = std::max({kMinX, kMinY, (int)0});
|
||||||
|
int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
|
||||||
|
|
||||||
|
TPixel64 *dnPix = dnRow + xMin + kMin;
|
||||||
|
TPixel64 *dnEndPix = dnRow + xMin + kMax + 1;
|
||||||
|
|
||||||
|
// (xL, yL) sono le coordinate (inizializzate per il round)
|
||||||
|
// in versione "TLonghizzata" del pixel corrente di up
|
||||||
|
int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL
|
||||||
|
int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL
|
||||||
|
|
||||||
|
// scorre i pixel sulla y-esima scanline di boundingBoxD
|
||||||
|
for (; dnPix < dnEndPix; ++dnPix) {
|
||||||
|
xL += deltaXL;
|
||||||
|
yL += deltaYL;
|
||||||
|
|
||||||
|
// il punto di up TPointD(xL/(1<<PADN), yL/(1<<PADN)) e'
|
||||||
|
// approssimato con (xI, yI)
|
||||||
|
int xI = xL >> PADN; // round
|
||||||
|
int yI = yL >> PADN; // round
|
||||||
|
|
||||||
|
assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
|
||||||
|
(yI <= up->getLy() - 1));
|
||||||
|
|
||||||
|
TPixel64 upPix = *(upBasePix + (yI * upWrap + xI));
|
||||||
|
|
||||||
|
if (firstColumn) upPix.m = 65535;
|
||||||
|
if (upPix.m == 0) continue;
|
||||||
|
|
||||||
|
if (upPix.m == 65535)
|
||||||
|
*dnPix = upPix;
|
||||||
|
else if (doPremultiply)
|
||||||
|
*dnPix = quickOverPixPremult(*dnPix, upPix);
|
||||||
|
else
|
||||||
|
*dnPix = quickOverPix(*dnPix, upPix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dn->unlock();
|
||||||
|
up->unlock();
|
||||||
|
}
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void doQuickPutNoFilter(const TRaster64P &dn, const TRaster32P &up,
|
||||||
|
const TAffine &aff, bool doPremultiply,
|
||||||
|
bool firstColumn) {
|
||||||
|
// se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine
|
||||||
|
// di up e' un segmento (o un punto)
|
||||||
|
if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return;
|
||||||
|
|
||||||
|
// contatore bit di shift
|
||||||
|
const int PADN = 16;
|
||||||
|
|
||||||
|
// max dimensioni di up gestibili (limite imposto dal numero di bit
|
||||||
|
// disponibili per la parte intera di xL, yL)
|
||||||
|
assert(std::max(up->getLx(), up->getLy()) <
|
||||||
|
(1 << (8 * sizeof(int) - PADN - 1)));
|
||||||
|
|
||||||
|
TRectD boundingBoxD =
|
||||||
|
TRectD(convert(dn->getBounds())) *
|
||||||
|
(aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5));
|
||||||
|
|
||||||
|
// clipping
|
||||||
|
if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// clipping y su dn
|
||||||
|
int yMin = std::max(tfloor(boundingBoxD.y0), 0);
|
||||||
|
|
||||||
|
// clipping y su dn
|
||||||
|
int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1);
|
||||||
|
|
||||||
|
// clipping x su dn
|
||||||
|
int xMin = std::max(tfloor(boundingBoxD.x0), 0);
|
||||||
|
|
||||||
|
// clipping x su dn
|
||||||
|
int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1);
|
||||||
|
|
||||||
|
// inversa di aff
|
||||||
|
TAffine invAff = inv(aff);
|
||||||
|
|
||||||
|
// nel disegnare la y-esima scanline di dn, il passaggio al pixel
|
||||||
|
// successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del
|
||||||
|
// pixel corrispondente di up
|
||||||
|
double deltaXD = invAff.a11;
|
||||||
|
double deltaYD = invAff.a21;
|
||||||
|
|
||||||
|
// deltaXD "TLonghizzato" (round)
|
||||||
|
int deltaXL = tround(deltaXD * (1 << PADN));
|
||||||
|
|
||||||
|
// deltaYD "TLonghizzato" (round)
|
||||||
|
int deltaYL = tround(deltaYD * (1 << PADN));
|
||||||
|
|
||||||
|
// se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un
|
||||||
|
// segmento (o un punto)
|
||||||
|
if ((deltaXL == 0) && (deltaYL == 0)) return;
|
||||||
|
|
||||||
|
// TINT32 predecessore di up->getLx()
|
||||||
|
int lxPred = up->getLx() * (1 << PADN) - 1;
|
||||||
|
|
||||||
|
// TINT32 predecessore di up->getLy()
|
||||||
|
int lyPred = up->getLy() * (1 << PADN) - 1;
|
||||||
|
|
||||||
|
int dnWrap = dn->getWrap();
|
||||||
|
int upWrap = up->getWrap();
|
||||||
|
dn->lock();
|
||||||
|
up->lock();
|
||||||
|
|
||||||
|
TPixel64 *dnRow = dn->pixels(yMin);
|
||||||
|
TPixel32 *upBasePix = up->pixels();
|
||||||
|
|
||||||
|
// scorre le scanline di boundingBoxD
|
||||||
|
for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) {
|
||||||
|
// (1) equazione k-parametrica della y-esima scanline di boundingBoxD:
|
||||||
|
// (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin)
|
||||||
|
|
||||||
|
// (2) equazione k-parametrica dell'immagine mediante invAff di (1):
|
||||||
|
// invAff*(xMin, y) + k*(deltaXD, deltaYD),
|
||||||
|
// k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin)
|
||||||
|
|
||||||
|
// calcola kMin, kMax per la scanline corrente
|
||||||
|
// intersecando la (2) con i lati di up
|
||||||
|
|
||||||
|
// il segmento [a, b] di up e' la controimmagine mediante aff della
|
||||||
|
// porzione di scanline [ (xMin, y), (xMax, y) ] di dn
|
||||||
|
|
||||||
|
// TPointD b = invAff*TPointD(xMax, y);
|
||||||
|
TPointD a = invAff * TPointD(xMin, y);
|
||||||
|
|
||||||
|
// (xL0, yL0) sono le coordinate di a (inizializzate per il round)
|
||||||
|
// in versione "TLonghizzata"
|
||||||
|
// 0 <= xL0 + k*deltaXL
|
||||||
|
// < up->getLx()*(1<<PADN)
|
||||||
|
//
|
||||||
|
// 0 <= kMinX
|
||||||
|
// <= kMin
|
||||||
|
// <= k
|
||||||
|
// <= kMax
|
||||||
|
// <= kMaxX
|
||||||
|
// <= (xMax - xMin)
|
||||||
|
//
|
||||||
|
// 0 <= yL0 + k*deltaYL
|
||||||
|
// < up->getLy()*(1<<PADN)
|
||||||
|
|
||||||
|
// 0 <= kMinY
|
||||||
|
// <= kMin
|
||||||
|
// <= k
|
||||||
|
// <= kMax
|
||||||
|
// <= kMaxY
|
||||||
|
// <= (xMax - xMin)
|
||||||
|
|
||||||
|
// xL0 inizializzato per il round
|
||||||
|
int xL0 = tround((a.x + 0.5) * (1 << PADN));
|
||||||
|
|
||||||
|
// yL0 inizializzato per il round
|
||||||
|
int yL0 = tround((a.y + 0.5) * (1 << PADN));
|
||||||
|
|
||||||
|
// calcola kMinX, kMaxX, kMinY, kMaxY
|
||||||
|
int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn
|
||||||
|
int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn
|
||||||
|
|
||||||
|
// 0 <= xL0 + k*deltaXL
|
||||||
|
// < up->getLx()*(1<<PADN)
|
||||||
|
// <=>
|
||||||
|
// 0 <= xL0 + k*deltaXL
|
||||||
|
// <= lxPred
|
||||||
|
//
|
||||||
|
// 0 <= yL0 + k*deltaYL
|
||||||
|
// < up->getLy()*(1<<PADN)
|
||||||
|
// <=>
|
||||||
|
// 0 <= yL0 + k*deltaYL
|
||||||
|
// <= lyPred
|
||||||
|
|
||||||
|
// calcola kMinX, kMaxX
|
||||||
|
if (deltaXL == 0) {
|
||||||
|
// [a, b] verticale esterno ad up+(bordo destro/basso)
|
||||||
|
if ((xL0 < 0) || (lxPred < xL0)) continue;
|
||||||
|
// altrimenti usa solo
|
||||||
|
// kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0))
|
||||||
|
} else if (deltaXL > 0) {
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (lxPred < xL0) continue;
|
||||||
|
|
||||||
|
kMaxX = (lxPred - xL0) / deltaXL; // floor
|
||||||
|
if (xL0 < 0) {
|
||||||
|
kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil
|
||||||
|
}
|
||||||
|
} else // (deltaXL < 0)
|
||||||
|
{
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (xL0 < 0) continue;
|
||||||
|
|
||||||
|
kMaxX = xL0 / (-deltaXL); // floor
|
||||||
|
if (lxPred < xL0) {
|
||||||
|
kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcola kMinY, kMaxY
|
||||||
|
if (deltaYL == 0) {
|
||||||
|
// [a, b] orizzontale esterno ad up+(bordo destro/basso)
|
||||||
|
if ((yL0 < 0) || (lyPred < yL0)) continue;
|
||||||
|
// altrimenti usa solo
|
||||||
|
// kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0))
|
||||||
|
} else if (deltaYL > 0) {
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (lyPred < yL0) continue;
|
||||||
|
|
||||||
|
kMaxY = (lyPred - yL0) / deltaYL; // floor
|
||||||
|
if (yL0 < 0) {
|
||||||
|
kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil
|
||||||
|
}
|
||||||
|
} else // (deltaYL < 0)
|
||||||
|
{
|
||||||
|
// [a, b] esterno ad up+(bordo destro/basso)
|
||||||
|
if (yL0 < 0) continue;
|
||||||
|
|
||||||
|
kMaxY = yL0 / (-deltaYL); // floor
|
||||||
|
if (lyPred < yL0) {
|
||||||
|
kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcola kMin, kMax effettuando anche il clippind su dn
|
||||||
|
int kMin = std::max({kMinX, kMinY, (int)0});
|
||||||
|
int kMax = std::min({kMaxX, kMaxY, xMax - xMin});
|
||||||
|
|
||||||
|
TPixel64 *dnPix = dnRow + xMin + kMin;
|
||||||
|
TPixel64 *dnEndPix = dnRow + xMin + kMax + 1;
|
||||||
|
|
||||||
|
// (xL, yL) sono le coordinate (inizializzate per il round)
|
||||||
|
// in versione "TLonghizzata" del pixel corrente di up
|
||||||
|
int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL
|
||||||
|
int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL
|
||||||
|
|
||||||
|
// scorre i pixel sulla y-esima scanline di boundingBoxD
|
||||||
|
for (; dnPix < dnEndPix; ++dnPix) {
|
||||||
|
xL += deltaXL;
|
||||||
|
yL += deltaYL;
|
||||||
|
|
||||||
|
// il punto di up TPointD(xL/(1<<PADN), yL/(1<<PADN)) e'
|
||||||
|
// approssimato con (xI, yI)
|
||||||
|
int xI = xL >> PADN; // round
|
||||||
|
int yI = yL >> PADN; // round
|
||||||
|
|
||||||
|
assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) &&
|
||||||
|
(yI <= up->getLy() - 1));
|
||||||
|
|
||||||
|
TPixel32 upPix = *(upBasePix + (yI * upWrap + xI));
|
||||||
|
|
||||||
|
if (firstColumn) upPix.m = 255;
|
||||||
|
if (upPix.m == 0) continue;
|
||||||
|
|
||||||
|
TPixel64 upPix64 = toPixel64(upPix);
|
||||||
|
if (upPix.m == 255)
|
||||||
|
*dnPix = upPix64;
|
||||||
|
else if (doPremultiply)
|
||||||
|
*dnPix = quickOverPixPremult(*dnPix, upPix64);
|
||||||
|
else
|
||||||
|
*dnPix = quickOverPix(*dnPix, upPix64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dn->unlock();
|
||||||
|
up->unlock();
|
||||||
|
}
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void doQuickPutFilter(const TRaster32P &dn, const TRaster32P &up, double sx,
|
void doQuickPutFilter(const TRaster32P &dn, const TRaster32P &up, double sx,
|
||||||
|
@ -4268,6 +4716,7 @@ void quickPut(const TRasterP &dn, const TRasterP &up, const TAffine &aff,
|
||||||
TRaster32P up32 = up;
|
TRaster32P up32 = up;
|
||||||
TRasterGR8P dn8 = dn;
|
TRasterGR8P dn8 = dn;
|
||||||
TRasterGR8P up8 = up;
|
TRasterGR8P up8 = up;
|
||||||
|
TRaster64P dn64 = dn;
|
||||||
TRaster64P up64 = up;
|
TRaster64P up64 = up;
|
||||||
|
|
||||||
if (up8 && dn32) {
|
if (up8 && dn32) {
|
||||||
|
@ -4294,6 +4743,10 @@ void quickPut(const TRasterP &dn, const TRasterP &up, const TAffine &aff,
|
||||||
}
|
}
|
||||||
} else if (dn32 && up64)
|
} else if (dn32 && up64)
|
||||||
doQuickPutNoFilter(dn32, up64, aff, doPremultiply, firstColumn);
|
doQuickPutNoFilter(dn32, up64, aff, doPremultiply, firstColumn);
|
||||||
|
else if (dn64 && up64)
|
||||||
|
doQuickPutNoFilter(dn64, up64, aff, doPremultiply, firstColumn);
|
||||||
|
else if (dn64 && up32)
|
||||||
|
doQuickPutNoFilter(dn64, up32, aff, doPremultiply, firstColumn);
|
||||||
else
|
else
|
||||||
throw TRopException("raster type mismatch");
|
throw TRopException("raster type mismatch");
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,12 @@ class TCubic;
|
||||||
#define TGL_TYPE GL_UNSIGNED_BYTE
|
#define TGL_TYPE GL_UNSIGNED_BYTE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// settings for 30bit display
|
||||||
|
|
||||||
|
#define TGL_TexFmt10 GL_RGB10_A2
|
||||||
|
#define TGL_TYPE16 GL_UNSIGNED_SHORT
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|
|
@ -234,6 +234,7 @@ public:
|
||||||
}
|
}
|
||||||
void setColorCalibrationLutPath(QString monitorName, QString path);
|
void setColorCalibrationLutPath(QString monitorName, QString path);
|
||||||
QString getColorCalibrationLutPath(QString &monitorName) const;
|
QString getColorCalibrationLutPath(QString &monitorName) const;
|
||||||
|
bool is30bitDisplayEnabled() const { return getBoolValue(displayIn30bit); }
|
||||||
|
|
||||||
bool isViewerIndicatorEnabled() const {
|
bool isViewerIndicatorEnabled() const {
|
||||||
return getBoolValue(viewerIndicatorEnabled);
|
return getBoolValue(viewerIndicatorEnabled);
|
||||||
|
|
|
@ -45,6 +45,7 @@ enum PreferencesItemId {
|
||||||
colorCalibrationEnabled,
|
colorCalibrationEnabled,
|
||||||
colorCalibrationLutPaths,
|
colorCalibrationLutPaths,
|
||||||
showIconsInMenu,
|
showIconsInMenu,
|
||||||
|
displayIn30bit,
|
||||||
viewerIndicatorEnabled,
|
viewerIndicatorEnabled,
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
|
|
|
@ -236,6 +236,12 @@ inline TPixel32 quickOverPixPremult(const TPixel32 &bot, const TPixel32 &top) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline TPixel64 quickOverPixPremult(const TPixel64 &bot, const TPixel64 &top) {
|
||||||
|
return quickOverPixPremultT<TPixel64, USHORT>(bot, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
inline TPixel64 quickOverPix(const TPixel64 &bot, const TPixel64 &top) {
|
inline TPixel64 quickOverPix(const TPixel64 &bot, const TPixel64 &top) {
|
||||||
return quickOverPixT<TPixel64, USHORT>(bot, top);
|
return quickOverPixT<TPixel64, USHORT>(bot, top);
|
||||||
}
|
}
|
||||||
|
@ -532,20 +538,24 @@ void mult(T &pixout, const T &pixin, double v) {
|
||||||
g = pixin.g + v;
|
g = pixin.g + v;
|
||||||
b = pixin.b + v;
|
b = pixin.b + v;
|
||||||
m = pixin.m + v;
|
m = pixin.m + v;
|
||||||
pixout.r =
|
pixout.r = (r < 0)
|
||||||
(r < 0) ? 0 : ((r < T::maxChannelValue)
|
? 0
|
||||||
|
: ((r < T::maxChannelValue)
|
||||||
? troundp(r * (pixout.r / (double)T::maxChannelValue))
|
? troundp(r * (pixout.r / (double)T::maxChannelValue))
|
||||||
: pixout.r);
|
: pixout.r);
|
||||||
pixout.g =
|
pixout.g = (g < 0)
|
||||||
(g < 0) ? 0 : ((g < T::maxChannelValue)
|
? 0
|
||||||
|
: ((g < T::maxChannelValue)
|
||||||
? troundp(g * (pixout.g / (double)T::maxChannelValue))
|
? troundp(g * (pixout.g / (double)T::maxChannelValue))
|
||||||
: pixout.g);
|
: pixout.g);
|
||||||
pixout.b =
|
pixout.b = (b < 0)
|
||||||
(b < 0) ? 0 : ((b < T::maxChannelValue)
|
? 0
|
||||||
|
: ((b < T::maxChannelValue)
|
||||||
? troundp(b * (pixout.b / (double)T::maxChannelValue))
|
? troundp(b * (pixout.b / (double)T::maxChannelValue))
|
||||||
: pixout.b);
|
: pixout.b);
|
||||||
pixout.m =
|
pixout.m = (m < 0)
|
||||||
(m < 0) ? 0 : ((m < T::maxChannelValue)
|
? 0
|
||||||
|
: ((m < T::maxChannelValue)
|
||||||
? troundp(m * (pixout.m / (double)T::maxChannelValue))
|
? troundp(m * (pixout.m / (double)T::maxChannelValue))
|
||||||
: pixout.m);
|
: pixout.m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,34 +163,33 @@ inline TRectD getImageBoundsD(const TImageP &img) {
|
||||||
FlipBook::FlipBook(QWidget *parent, QString viewerTitle,
|
FlipBook::FlipBook(QWidget *parent, QString viewerTitle,
|
||||||
std::vector<int> flipConsoleButtonMask, UCHAR flags,
|
std::vector<int> flipConsoleButtonMask, UCHAR flags,
|
||||||
bool isColorModel) //, bool showOnlyPlayBackgroundButton)
|
bool isColorModel) //, bool showOnlyPlayBackgroundButton)
|
||||||
: QWidget(parent),
|
: QWidget(parent)
|
||||||
m_viewerTitle(viewerTitle),
|
, m_viewerTitle(viewerTitle)
|
||||||
m_levelNames(),
|
, m_levelNames()
|
||||||
m_levels(),
|
, m_levels()
|
||||||
m_playSound(false),
|
, m_playSound(false)
|
||||||
m_snd(0),
|
, m_snd(0)
|
||||||
m_player(0)
|
, m_player(0)
|
||||||
//, m_doCompare(false)
|
//, m_doCompare(false)
|
||||||
,
|
, m_currentFrameToSave(0)
|
||||||
m_currentFrameToSave(0),
|
, m_lw()
|
||||||
m_lw(),
|
, m_lr()
|
||||||
m_lr(),
|
, m_loadPopup(0)
|
||||||
m_loadPopup(0),
|
, m_savePopup(0)
|
||||||
m_savePopup(0),
|
, m_shrink(1)
|
||||||
m_shrink(1),
|
, m_isPreviewFx(false)
|
||||||
m_isPreviewFx(false),
|
, m_previewedFx(0)
|
||||||
m_previewedFx(0),
|
, m_previewXsh(0)
|
||||||
m_previewXsh(0),
|
, m_previewUpdateTimer(this)
|
||||||
m_previewUpdateTimer(this),
|
, m_xl(0)
|
||||||
m_xl(0),
|
, m_title1()
|
||||||
m_title1(),
|
, m_poolIndex(-1)
|
||||||
m_poolIndex(-1),
|
, m_freezed(false)
|
||||||
m_freezed(false),
|
, m_loadbox()
|
||||||
m_loadbox(),
|
, m_dim()
|
||||||
m_dim(),
|
, m_loadboxes()
|
||||||
m_loadboxes(),
|
, m_freezeButton(0)
|
||||||
m_freezeButton(0),
|
, m_flags(flags) {
|
||||||
m_flags(flags) {
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
|
||||||
|
@ -1141,8 +1140,7 @@ void FlipBook::setLevel(const TFilePath &fp, TPalette *palette, int from,
|
||||||
levelToPush.m_incrementalIndexing = incrementalIndexing;
|
levelToPush.m_incrementalIndexing = incrementalIndexing;
|
||||||
|
|
||||||
int formatIdx = Preferences::instance()->matchLevelFormat(fp);
|
int formatIdx = Preferences::instance()->matchLevelFormat(fp);
|
||||||
if (formatIdx >= 0 &&
|
if (formatIdx >= 0 && Preferences::instance()
|
||||||
Preferences::instance()
|
|
||||||
->levelFormat(formatIdx)
|
->levelFormat(formatIdx)
|
||||||
.m_options.m_premultiply) {
|
.m_options.m_premultiply) {
|
||||||
levelToPush.m_premultiply = true;
|
levelToPush.m_premultiply = true;
|
||||||
|
@ -1595,6 +1593,9 @@ TImageP FlipBook::getCurrentImage(int frame) {
|
||||||
lx = m_loadbox.getLx();
|
lx = m_loadbox.getLx();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled())
|
||||||
|
ir->enable16BitRead(true);
|
||||||
|
|
||||||
TImageP img = ir->load();
|
TImageP img = ir->load();
|
||||||
|
|
||||||
if (img) {
|
if (img) {
|
||||||
|
|
|
@ -244,6 +244,11 @@ ImageViewer::ImageViewer(QWidget *parent, FlipBook *flipbook,
|
||||||
|
|
||||||
if (Preferences::instance()->isColorCalibrationEnabled())
|
if (Preferences::instance()->isColorCalibrationEnabled())
|
||||||
m_lutCalibrator = new LutCalibrator();
|
m_lutCalibrator = new LutCalibrator();
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x051000
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled())
|
||||||
|
setTextureFormat(TGL_TexFmt10);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -488,6 +493,11 @@ void ImageViewer::resizeGL(int w, int h) {
|
||||||
// remake fbo with new size
|
// remake fbo with new size
|
||||||
if (m_lutCalibrator && m_lutCalibrator->isValid()) {
|
if (m_lutCalibrator && m_lutCalibrator->isValid()) {
|
||||||
if (m_fbo) delete m_fbo;
|
if (m_fbo) delete m_fbo;
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled()) {
|
||||||
|
QOpenGLFramebufferObjectFormat format;
|
||||||
|
format.setInternalTextureFormat(TGL_TexFmt10);
|
||||||
|
m_fbo = new QOpenGLFramebufferObject(w, h, format);
|
||||||
|
} else // normally, initialize with GL_RGBA8 format
|
||||||
m_fbo = new QOpenGLFramebufferObject(w, h);
|
m_fbo = new QOpenGLFramebufferObject(w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,6 +505,7 @@ void ImageViewer::resizeGL(int w, int h) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ImageViewer::paintGL() {
|
void ImageViewer::paintGL() {
|
||||||
|
initializeOpenGLFunctions();
|
||||||
if (m_lutCalibrator && m_lutCalibrator->isValid()) m_fbo->bind();
|
if (m_lutCalibrator && m_lutCalibrator->isValid()) m_fbo->bind();
|
||||||
|
|
||||||
TDimension viewerSize(width(), height());
|
TDimension viewerSize(width(), height());
|
||||||
|
@ -1422,8 +1433,14 @@ void ImageViewer::onPreferenceChanged(const QString& prefName) {
|
||||||
m_lutCalibrator->initialize();
|
m_lutCalibrator->initialize();
|
||||||
connect(context(), SIGNAL(aboutToBeDestroyed()), this,
|
connect(context(), SIGNAL(aboutToBeDestroyed()), this,
|
||||||
SLOT(onContextAboutToBeDestroyed()));
|
SLOT(onContextAboutToBeDestroyed()));
|
||||||
if (m_lutCalibrator->isValid() && !m_fbo)
|
if (m_lutCalibrator->isValid() && !m_fbo) {
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled()) {
|
||||||
|
QOpenGLFramebufferObjectFormat format;
|
||||||
|
format.setInternalTextureFormat(TGL_TexFmt10);
|
||||||
|
m_fbo = new QOpenGLFramebufferObject(width(), height(), format);
|
||||||
|
} else // normally, initialize with GL_RGBA8 format
|
||||||
m_fbo = new QOpenGLFramebufferObject(width(), height());
|
m_fbo = new QOpenGLFramebufferObject(width(), height());
|
||||||
|
}
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
|
@ -528,6 +528,16 @@ int main(int argc, char *argv[]) {
|
||||||
crInstall(&pInfo);
|
crInstall(&pInfo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// prepare for 30bit display
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled()) {
|
||||||
|
QSurfaceFormat sFmt = QSurfaceFormat::defaultFormat();
|
||||||
|
sFmt.setRedBufferSize(10);
|
||||||
|
sFmt.setGreenBufferSize(10);
|
||||||
|
sFmt.setBlueBufferSize(10);
|
||||||
|
sFmt.setAlphaBufferSize(2);
|
||||||
|
QSurfaceFormat::setDefaultFormat(sFmt);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize thread components
|
// Initialize thread components
|
||||||
TThread::init();
|
TThread::init();
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,89 @@ Preferences::LevelFormat PreferencesPopup::FormatProperties::levelFormat()
|
||||||
return lf;
|
return lf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//**********************************************************************************
|
||||||
|
// PreferencesPopup::Display30bitCheckerView implementation
|
||||||
|
//**********************************************************************************
|
||||||
|
|
||||||
|
PreferencesPopup::Display30bitChecker::GLView::GLView(QWidget* parent,
|
||||||
|
bool is30bit)
|
||||||
|
: QOpenGLWidget(parent), m_is30bit(is30bit) {
|
||||||
|
setFixedSize(500, 100);
|
||||||
|
#if QT_VERSION >= 0x051000
|
||||||
|
if (m_is30bit) setTextureFormat(TGL_TexFmt10);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreferencesPopup::Display30bitChecker::GLView::initializeGL() {
|
||||||
|
initializeOpenGLFunctions();
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
void PreferencesPopup::Display30bitChecker::GLView::resizeGL(int width,
|
||||||
|
int height) {
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, 1, 0, 1, -1, 1);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
void PreferencesPopup::Display30bitChecker::GLView::paintGL() {
|
||||||
|
initializeOpenGLFunctions();
|
||||||
|
glPushMatrix();
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor3d(0.071, 0.153, 0.0);
|
||||||
|
glVertex3d(0, 0, 0);
|
||||||
|
glVertex3d(0, 1, 0);
|
||||||
|
glColor3d(0.141, 0.239, 0.0);
|
||||||
|
glVertex3d(1, 1, 0);
|
||||||
|
glVertex3d(1, 0, 0);
|
||||||
|
glEnd();
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
PreferencesPopup::Display30bitChecker::Display30bitChecker(
|
||||||
|
PreferencesPopup* parent)
|
||||||
|
: QDialog(parent) {
|
||||||
|
setModal(true);
|
||||||
|
m_currentDefaultFormat = QSurfaceFormat::defaultFormat();
|
||||||
|
|
||||||
|
setWindowTitle(tr("Check 30bit display availability"));
|
||||||
|
|
||||||
|
QSurfaceFormat sFmt = m_currentDefaultFormat;
|
||||||
|
sFmt.setRedBufferSize(10);
|
||||||
|
sFmt.setGreenBufferSize(10);
|
||||||
|
sFmt.setBlueBufferSize(10);
|
||||||
|
sFmt.setAlphaBufferSize(2);
|
||||||
|
QSurfaceFormat::setDefaultFormat(sFmt);
|
||||||
|
|
||||||
|
GLView* view8bit = new GLView(this, false);
|
||||||
|
GLView* view10bit = new GLView(this, true);
|
||||||
|
QPushButton* closeBtn = new QPushButton(tr("Close"), this);
|
||||||
|
QString infoLabel = tr(
|
||||||
|
"If the lower gradient looks smooth and has no banding compared to the upper gradient,\n\
|
||||||
|
30bit display is available in the current configuration.");
|
||||||
|
|
||||||
|
QVBoxLayout* lay = new QVBoxLayout();
|
||||||
|
lay->setMargin(10);
|
||||||
|
lay->setSpacing(10);
|
||||||
|
{
|
||||||
|
lay->addWidget(view8bit);
|
||||||
|
lay->addWidget(view10bit);
|
||||||
|
lay->addWidget(new QLabel(infoLabel, this));
|
||||||
|
lay->addWidget(closeBtn, 0, Qt::AlignCenter);
|
||||||
|
}
|
||||||
|
setLayout(lay);
|
||||||
|
lay->setSizeConstraint(QLayout::SetFixedSize);
|
||||||
|
|
||||||
|
connect(closeBtn, SIGNAL(clicked()), this, SLOT(accept()));
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferencesPopup::Display30bitChecker::~Display30bitChecker() {
|
||||||
|
QSurfaceFormat::setDefaultFormat(m_currentDefaultFormat);
|
||||||
|
}
|
||||||
|
|
||||||
//**********************************************************************************
|
//**********************************************************************************
|
||||||
// PreferencesPopup implementation
|
// PreferencesPopup implementation
|
||||||
//**********************************************************************************
|
//**********************************************************************************
|
||||||
|
@ -691,6 +774,13 @@ void PreferencesPopup::onLutPathChanged() {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void PreferencesPopup::onCheck30bitDisplay() {
|
||||||
|
Display30bitChecker checker(this);
|
||||||
|
checker.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PreferencesPopup::onAddLevelFormat() {
|
void PreferencesPopup::onAddLevelFormat() {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
QString formatName = DVGui::getText(tr("New Level Format"),
|
QString formatName = DVGui::getText(tr("New Level Format"),
|
||||||
|
@ -1016,6 +1106,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
|
||||||
{colorCalibrationLutPaths,
|
{colorCalibrationLutPaths,
|
||||||
tr("3DLUT File for [%1]:")
|
tr("3DLUT File for [%1]:")
|
||||||
.arg(LutManager::instance()->getMonitorName())},
|
.arg(LutManager::instance()->getMonitorName())},
|
||||||
|
{displayIn30bit, tr("30bit Display*")},
|
||||||
{showIconsInMenu, tr("Show Icons In Menu*")},
|
{showIconsInMenu, tr("Show Icons In Menu*")},
|
||||||
{viewerIndicatorEnabled, tr("Show Viewer Indicators")},
|
{viewerIndicatorEnabled, tr("Show Viewer Indicators")},
|
||||||
|
|
||||||
|
@ -1456,11 +1547,14 @@ QWidget* PreferencesPopup::createInterfacePage() {
|
||||||
for (const QString& name : m_pref->getLanguageList())
|
for (const QString& name : m_pref->getLanguageList())
|
||||||
languageItemList.push_back(ComboBoxItem(name, name));
|
languageItemList.push_back(ComboBoxItem(name, name));
|
||||||
|
|
||||||
|
QPushButton* check30bitBtn = new QPushButton(tr("Check Availability"));
|
||||||
|
|
||||||
QWidget* widget = new QWidget(this);
|
QWidget* widget = new QWidget(this);
|
||||||
QGridLayout* lay = new QGridLayout();
|
QGridLayout* lay = new QGridLayout();
|
||||||
setupLayout(lay);
|
setupLayout(lay);
|
||||||
|
|
||||||
insertUI(CurrentStyleSheetName, lay, styleSheetItemList);
|
insertUI(CurrentStyleSheetName, lay, styleSheetItemList);
|
||||||
|
int row = lay->rowCount();
|
||||||
|
|
||||||
// lay->addWidget(new QLabel(tr("Icon Theme*:"), this), 2, 0,
|
// lay->addWidget(new QLabel(tr("Icon Theme*:"), this), 2, 0,
|
||||||
// Qt::AlignRight | Qt::AlignVCenter);
|
// Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
@ -1488,6 +1582,11 @@ QWidget* PreferencesPopup::createInterfacePage() {
|
||||||
// insertUI(interfaceFontStyle, lay, buildFontStyleList());
|
// insertUI(interfaceFontStyle, lay, buildFontStyleList());
|
||||||
QGridLayout* colorCalibLay = insertGroupBoxUI(colorCalibrationEnabled, lay);
|
QGridLayout* colorCalibLay = insertGroupBoxUI(colorCalibrationEnabled, lay);
|
||||||
{ insertUI(colorCalibrationLutPaths, colorCalibLay); }
|
{ insertUI(colorCalibrationLutPaths, colorCalibLay); }
|
||||||
|
#if QT_VERSION >= 0x051000
|
||||||
|
insertUI(displayIn30bit, lay);
|
||||||
|
row = lay->rowCount();
|
||||||
|
lay->addWidget(check30bitBtn, row - 1, 3);
|
||||||
|
#endif
|
||||||
// insertUI(showIconsInMenu, lay);
|
// insertUI(showIconsInMenu, lay);
|
||||||
|
|
||||||
lay->setRowStretch(lay->rowCount(), 1);
|
lay->setRowStretch(lay->rowCount(), 1);
|
||||||
|
@ -1504,6 +1603,8 @@ QWidget* PreferencesPopup::createInterfacePage() {
|
||||||
ret = ret && connect(TApp::instance()->getCurrentScene(),
|
ret = ret && connect(TApp::instance()->getCurrentScene(),
|
||||||
SIGNAL(pixelUnitSelected(bool)), this,
|
SIGNAL(pixelUnitSelected(bool)), this,
|
||||||
SLOT(onPixelUnitExternallySelected(bool)));
|
SLOT(onPixelUnitExternallySelected(bool)));
|
||||||
|
ret = ret && connect(check30bitBtn, SIGNAL(clicked()), this,
|
||||||
|
SLOT(onCheck30bitDisplay()));
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
m_onEditedFuncMap.insert(CurrentStyleSheetName,
|
m_onEditedFuncMap.insert(CurrentStyleSheetName,
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QFontComboBox>
|
#include <QFontComboBox>
|
||||||
|
#include <QOpenGLWidget>
|
||||||
|
#include <QSurfaceFormat>
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
|
||||||
//==============================================================
|
//==============================================================
|
||||||
|
|
||||||
|
@ -65,6 +68,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class FormatProperties;
|
class FormatProperties;
|
||||||
|
class Display30bitChecker;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Preferences* m_pref;
|
Preferences* m_pref;
|
||||||
|
@ -173,6 +177,7 @@ private slots:
|
||||||
void onPixelUnitExternallySelected(bool on);
|
void onPixelUnitExternallySelected(bool on);
|
||||||
void onInterfaceFontChanged(const QString& text);
|
void onInterfaceFontChanged(const QString& text);
|
||||||
void onLutPathChanged();
|
void onLutPathChanged();
|
||||||
|
void onCheck30bitDisplay();
|
||||||
|
|
||||||
void onAddLevelFormat();
|
void onAddLevelFormat();
|
||||||
void onRemoveLevelFormat();
|
void onRemoveLevelFormat();
|
||||||
|
@ -212,4 +217,36 @@ private slots:
|
||||||
void updateEnabledStatus();
|
void updateEnabledStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//**********************************************************************************
|
||||||
|
// PreferencesPopup::Display30bitCheckerView definition
|
||||||
|
//**********************************************************************************
|
||||||
|
|
||||||
|
class PreferencesPopup::Display30bitChecker final : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QSurfaceFormat m_currentDefaultFormat;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class GLView;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Display30bitChecker(PreferencesPopup* parent);
|
||||||
|
~Display30bitChecker();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PreferencesPopup::Display30bitChecker::GLView final
|
||||||
|
: public QOpenGLWidget,
|
||||||
|
protected QOpenGLFunctions {
|
||||||
|
Q_OBJECT
|
||||||
|
bool m_is30bit;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GLView(QWidget* parent, bool is30bit);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initializeGL() override;
|
||||||
|
void resizeGL(int width, int height) override;
|
||||||
|
void paintGL() override;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // PREFERENCESPOPUP_H
|
#endif // PREFERENCESPOPUP_H
|
||||||
|
|
|
@ -1070,7 +1070,9 @@ void PreviewFxInstance::doOnRenderRasterCompleted(
|
||||||
/*-- 16bpcで計算された場合、結果をDitheringする --*/
|
/*-- 16bpcで計算された場合、結果をDitheringする --*/
|
||||||
TRasterP rasA = renderData.m_rasA;
|
TRasterP rasA = renderData.m_rasA;
|
||||||
TRasterP rasB = renderData.m_rasB;
|
TRasterP rasB = renderData.m_rasB;
|
||||||
if (rasA->getPixelSize() == 8) // render in 64 bits
|
// dither the 16bpc image IF the "30bit display" prefernce option is OFF
|
||||||
|
if (rasA->getPixelSize() == 8 &&
|
||||||
|
!Preferences::instance()->is30bitDisplayEnabled()) // render in 64 bits
|
||||||
{
|
{
|
||||||
TRaster32P auxA(rasA->getLx(), rasA->getLy());
|
TRaster32P auxA(rasA->getLx(), rasA->getLy());
|
||||||
TRop::convert(auxA, rasA); // dithering
|
TRop::convert(auxA, rasA); // dithering
|
||||||
|
|
|
@ -835,6 +835,10 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent)
|
||||||
|
|
||||||
if (Preferences::instance()->isColorCalibrationEnabled())
|
if (Preferences::instance()->isColorCalibrationEnabled())
|
||||||
m_lutCalibrator = new LutCalibrator();
|
m_lutCalibrator = new LutCalibrator();
|
||||||
|
#if QT_VERSION >= 0x051000
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled())
|
||||||
|
setTextureFormat(TGL_TexFmt10);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1220,8 +1224,14 @@ void SceneViewer::onPreferenceChanged(const QString &prefName) {
|
||||||
m_lutCalibrator->initialize();
|
m_lutCalibrator->initialize();
|
||||||
connect(context(), SIGNAL(aboutToBeDestroyed()), this,
|
connect(context(), SIGNAL(aboutToBeDestroyed()), this,
|
||||||
SLOT(onContextAboutToBeDestroyed()));
|
SLOT(onContextAboutToBeDestroyed()));
|
||||||
if (m_lutCalibrator->isValid() && !m_fbo)
|
if (m_lutCalibrator->isValid() && !m_fbo) {
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled()) {
|
||||||
|
QOpenGLFramebufferObjectFormat format;
|
||||||
|
format.setInternalTextureFormat(TGL_TexFmt10);
|
||||||
|
m_fbo = new QOpenGLFramebufferObject(width(), height(), format);
|
||||||
|
} else // normally, initialize with GL_RGBA8 format
|
||||||
m_fbo = new QOpenGLFramebufferObject(width(), height());
|
m_fbo = new QOpenGLFramebufferObject(width(), height());
|
||||||
|
}
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
@ -1279,6 +1289,11 @@ void SceneViewer::resizeGL(int w, int h) {
|
||||||
// remake fbo with new size
|
// remake fbo with new size
|
||||||
if (m_lutCalibrator && m_lutCalibrator->isValid()) {
|
if (m_lutCalibrator && m_lutCalibrator->isValid()) {
|
||||||
if (m_fbo) delete m_fbo;
|
if (m_fbo) delete m_fbo;
|
||||||
|
if (Preferences::instance()->is30bitDisplayEnabled()) {
|
||||||
|
QOpenGLFramebufferObjectFormat format;
|
||||||
|
format.setInternalTextureFormat(TGL_TexFmt10);
|
||||||
|
m_fbo = new QOpenGLFramebufferObject(w, h, format);
|
||||||
|
} else // normally, initialize with GL_RGBA8 format
|
||||||
m_fbo = new QOpenGLFramebufferObject(w, h);
|
m_fbo = new QOpenGLFramebufferObject(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,7 +363,8 @@ void Painter::doFlushRasterImages(const TRasterP &rin, int bg,
|
||||||
TRect rect(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1), tceil(bbox.y1));
|
TRect rect(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1), tceil(bbox.y1));
|
||||||
if (rect.isEmpty()) return;
|
if (rect.isEmpty()) return;
|
||||||
|
|
||||||
TRaster32P ras;
|
TRasterP ras;
|
||||||
|
// TRaster32P ras;
|
||||||
TRasterP _rin = rin;
|
TRasterP _rin = rin;
|
||||||
TAffine aff;
|
TAffine aff;
|
||||||
if (m_vSettings.m_useTexture) {
|
if (m_vSettings.m_useTexture) {
|
||||||
|
@ -398,6 +399,17 @@ void Painter::doFlushRasterImages(const TRasterP &rin, int bg,
|
||||||
// a quickput approximation?
|
// a quickput approximation?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when the "30bit display" preference option is enabled,
|
||||||
|
// image previewed in 16bpc is not dithered & converted to 8bpc,
|
||||||
|
// but is kept the channel depth as 16bpc.
|
||||||
|
bool is16bpc = false;
|
||||||
|
if (_rin->getPixelSize() == 8) {
|
||||||
|
TRaster64P rasAux(ras->getLx(), ras->getLy());
|
||||||
|
TRop::convert(rasAux, ras);
|
||||||
|
ras = rasAux;
|
||||||
|
is16bpc = true;
|
||||||
|
}
|
||||||
|
|
||||||
ras->lock();
|
ras->lock();
|
||||||
|
|
||||||
bool showChannelsOnMatte =
|
bool showChannelsOnMatte =
|
||||||
|
@ -433,9 +445,14 @@ void Painter::doFlushRasterImages(const TRasterP &rin, int bg,
|
||||||
// Image size is a 0 point. Do nothing
|
// Image size is a 0 point. Do nothing
|
||||||
if (rect.x0 == rect.x1 && rect.y0 == rect.y1) return;
|
if (rect.x0 == rect.x1 && rect.y0 == rect.y1) return;
|
||||||
|
|
||||||
|
if (is16bpc) {
|
||||||
|
TRaster64P raux = ras->extract(rect);
|
||||||
|
raux->fill(bg == 0x40000 ? TPixel64::Black : TPixel64::White);
|
||||||
|
} else {
|
||||||
TRaster32P raux = ras->extract(rect);
|
TRaster32P raux = ras->extract(rect);
|
||||||
raux->fill(bg == 0x40000 ? TPixel::Black : TPixel::White);
|
raux->fill(bg == 0x40000 ? TPixel::Black : TPixel::White);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (showChannelsOnMatte)
|
if (showChannelsOnMatte)
|
||||||
quickput(ras, keepChannels(_rin, m_palette, chan), m_palette,
|
quickput(ras, keepChannels(_rin, m_palette, chan), m_palette,
|
||||||
|
@ -463,8 +480,9 @@ void Painter::doFlushRasterImages(const TRasterP &rin, int bg,
|
||||||
glRasterPos2d(rect.x0, rect.y0);
|
glRasterPos2d(rect.x0, rect.y0);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
|
||||||
glDrawPixels(ras->getWrap(), ras->getLy(), TGL_FMT, TGL_TYPE,
|
glDrawPixels(ras->getWrap(), ras->getLy(), TGL_FMT,
|
||||||
ras->getRawData());
|
(is16bpc) ? TGL_TYPE16 : TGL_TYPE,
|
||||||
|
(GLvoid *)ras->getRawData());
|
||||||
|
|
||||||
CHECK_ERRORS_BY_GL
|
CHECK_ERRORS_BY_GL
|
||||||
|
|
||||||
|
@ -657,7 +675,8 @@ void ImagePainter::paintImage(const TImageP &image, const TDimension &imageSize,
|
||||||
// be done on black bg!
|
// be done on black bg!
|
||||||
if (!vimg)
|
if (!vimg)
|
||||||
painter.flushRasterImages(
|
painter.flushRasterImages(
|
||||||
loadbox, visualSettings.m_doCompare ? compareSettings.m_compareX
|
loadbox,
|
||||||
|
visualSettings.m_doCompare ? compareSettings.m_compareX
|
||||||
: DefaultCompareValue,
|
: DefaultCompareValue,
|
||||||
visualSettings.m_doCompare ? compareSettings.m_compareY
|
visualSettings.m_doCompare ? compareSettings.m_compareY
|
||||||
: DefaultCompareValue,
|
: DefaultCompareValue,
|
||||||
|
|
|
@ -439,6 +439,7 @@ void Preferences::definePreferenceItems() {
|
||||||
false);
|
false);
|
||||||
define(colorCalibrationLutPaths, "colorCalibrationLutPaths",
|
define(colorCalibrationLutPaths, "colorCalibrationLutPaths",
|
||||||
QMetaType::QVariantMap, QVariantMap());
|
QMetaType::QVariantMap, QVariantMap());
|
||||||
|
define(displayIn30bit, "displayIn30bit", QMetaType::Bool, false);
|
||||||
|
|
||||||
// hide menu icons by default in macOS since the icon color may not match with
|
// hide menu icons by default in macOS since the icon color may not match with
|
||||||
// the system color theme
|
// the system color theme
|
||||||
|
|
Loading…
Reference in a new issue