QTransform ImageTransformation::calcPostScaleXform(Dpi const& target_dpi) { if (target_dpi.isNull()) { return QTransform(); } // We are going to measure the effective DPI after the previous transforms. // Normally m_preScaledDpi would be symmetric, so we could just // use that, but just in case ... QTransform const to_orig(m_postScaleXform * m_transform.inverted()); // IMPORTANT: in the above line we assume post-scale is the last transform. QLineF const hor_unit(QPointF(0, 0), QPointF(1, 0)); QLineF const vert_unit(QPointF(0, 0), QPointF(0, 1)); QLineF const orig_hor_unit(to_orig.map(hor_unit)); QLineF const orig_vert_unit(to_orig.map(vert_unit)); double const xscale = target_dpi.horizontal() * orig_hor_unit.length() / m_origDpi.horizontal(); double const yscale = target_dpi.vertical() * orig_vert_unit.length() / m_origDpi.vertical(); QTransform xform; xform.scale(xscale, yscale); return xform; }
void FixDpiDialog::setDpiForm(ImageMetadata const& metadata) { Dpi const dpi(metadata.dpi()); if (dpi.isNull()) { resetDpiForm(); return; } m_xDpiInitialValue = QString::number(dpi.horizontal()); m_yDpiInitialValue = QString::number(dpi.vertical()); m_selectedItemPixelSize = metadata.size(); xDpi->setText(m_xDpiInitialValue); yDpi->setText(m_yDpiInitialValue); dpiValueChanged(); }
void ImageTransformation::preScaleToDpi(Dpi const& dpi) { if (m_origDpi.isNull() || dpi.isNull()) { return; } m_preScaledDpi = dpi; double const xscale = (double)dpi.horizontal() / m_origDpi.horizontal(); double const yscale = (double)dpi.vertical() / m_origDpi.vertical(); QSizeF const new_pre_scaled_image_size( m_origRect.width() * xscale, m_origRect.height() * yscale ); // Undo's for the specified steps. QTransform const undo21(m_preRotateXform.inverted() * m_preScaleXform.inverted()); QTransform const undo4321(m_postRotateXform.inverted() * m_preCropXform.inverted() * undo21); // Update transform #1: pre-scale. m_preScaleXform.reset(); m_preScaleXform.scale(xscale, yscale); // Update transform #2: pre-rotate. m_preRotateXform = m_preRotation.transform(new_pre_scaled_image_size); // Update transform #3: pre-crop. QTransform const redo12(m_preScaleXform * m_preRotateXform); m_preCropArea = (undo21 * redo12).map(m_preCropArea); m_preCropXform = calcCropXform(m_preCropArea); // Update transform #4: post-rotate. m_postRotateXform = calcPostRotateXform(m_postRotation); // Update transform #5: post-crop. QTransform const redo1234(redo12 * m_preCropXform * m_postRotateXform); m_postCropArea = (undo4321 * redo1234).map(m_postCropArea); m_postCropXform = calcCropXform(m_postCropArea); // Update transform #6: post-scale. m_postScaleXform = calcPostScaleXform(m_postScaledDpi); update(); }
void ImageTransformation::preScaleToDpi(Dpi const& dpi) { if (m_origDpi.isNull() || dpi.isNull()) { return; } m_preScaledDpi = dpi; double const xscale = (double)dpi.horizontal() / m_origDpi.horizontal(); double const yscale = (double)dpi.vertical() / m_origDpi.vertical(); QSizeF const new_pre_scaled_image_size( m_origRect.width() * xscale, m_origRect.height() * yscale ); // Reverse pre-rotation. QPolygonF tmp_crop_area(m_preRotateXform.inverted().map(m_cropArea)); // Reverse pre-scaling. tmp_crop_area = m_preScaleXform.inverted().map(tmp_crop_area); // Update m_preScaleXform and m_preRotateXform. m_preScaleXform.reset(); m_preScaleXform.scale(xscale, yscale); m_preRotateXform = m_preRotation.transform(new_pre_scaled_image_size); // Apply new pre-scaling. tmp_crop_area = m_preScaleXform.map(tmp_crop_area); // Re-apply pre-rotation. m_cropArea = m_preRotateXform.map(tmp_crop_area); m_cropXform = calcCropXform(m_cropArea); m_postRotateXform = calcPostRotateXform(m_postRotation); update(); }
GrayImage TextLineTracer::downscale(GrayImage const& input, Dpi const& dpi) { // Downscale to 200 DPI. QSize downscaled_size(input.size()); if (dpi.horizontal() < 180 || dpi.horizontal() > 220 || dpi.vertical() < 180 || dpi.vertical() > 220) { downscaled_size.setWidth(std::max<int>(1, input.width() * 200 / dpi.horizontal())); downscaled_size.setHeight(std::max<int>(1, input.height() * 200 / dpi.vertical())); } return scaleToGray(input, downscaled_size); }