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();
}
Exemple #4
0
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);
}