@@ -4761,18 +4761,118 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
4761
4761
}
4762
4762
4763
4763
4764
- /*
4765
- This code is contributed by Philipp Lang,
4766
- GeneriCom Software Germany (www.generi.com)
4767
- under the terms of the QPL, Version 1.0
4768
- */
4769
-
4770
4764
/* !
4771
4765
\fn QImage QImage::mirror(bool horizontal, bool vertical) const
4772
4766
4773
4767
Use mirrored() instead.
4774
4768
*/
4775
4769
4770
+ template <class T > inline void do_mirror_data (QImageData *dst, QImageData *src,
4771
+ int dstX0, int dstY0,
4772
+ int dstXIncr, int dstYIncr,
4773
+ int w, int h)
4774
+ {
4775
+ if (dst == src) {
4776
+ // When mirroring in-place, stop in the middle for one of the directions, since we
4777
+ // are swapping the bytes instead of merely copying.
4778
+ const int srcXEnd = dstX0 ? w / 2 : w;
4779
+ const int srcYEnd = !dstX0 && dstY0 ? h / 2 : h;
4780
+ for (int srcY = 0 , dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
4781
+ T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line );
4782
+ T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line );
4783
+ for (int srcX = 0 , dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
4784
+ std::swap (srcPtr[srcX], dstPtr[dstX]);
4785
+ }
4786
+ } else {
4787
+ for (int srcY = 0 , dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
4788
+ T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line );
4789
+ T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line );
4790
+ for (int srcX = 0 , dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
4791
+ dstPtr[dstX] = srcPtr[srcX];
4792
+ }
4793
+ }
4794
+ }
4795
+
4796
+ inline void do_mirror (QImageData *dst, QImageData *src, bool horizontal, bool vertical)
4797
+ {
4798
+ Q_ASSERT (src->width == dst->width && src->height == dst->height && src->depth == dst->depth );
4799
+ int w = src->width ;
4800
+ int h = src->height ;
4801
+ int depth = src->depth ;
4802
+
4803
+ if (src->depth == 1 ) {
4804
+ w = (w + 7 ) / 8 ; // byte aligned width
4805
+ depth = 8 ;
4806
+ }
4807
+
4808
+ int dstX0 = 0 , dstXIncr = 1 ;
4809
+ int dstY0 = 0 , dstYIncr = 1 ;
4810
+ if (horizontal) {
4811
+ // 0 -> w-1, 1 -> w-2, 2 -> w-3, ...
4812
+ dstX0 = w - 1 ;
4813
+ dstXIncr = -1 ;
4814
+ }
4815
+ if (vertical) {
4816
+ // 0 -> h-1, 1 -> h-2, 2 -> h-3, ...
4817
+ dstY0 = h - 1 ;
4818
+ dstYIncr = -1 ;
4819
+ }
4820
+
4821
+ switch (depth) {
4822
+ case 32 :
4823
+ do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
4824
+ break ;
4825
+ case 24 :
4826
+ do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
4827
+ break ;
4828
+ case 16 :
4829
+ do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
4830
+ break ;
4831
+ case 8 :
4832
+ do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
4833
+ break ;
4834
+ default :
4835
+ Q_ASSERT (false );
4836
+ break ;
4837
+ }
4838
+
4839
+ // The bytes are now all in the correct place. In addition, the bits in the individual
4840
+ // bytes have to be flipped too when horizontally mirroring a 1 bit-per-pixel image.
4841
+ if (horizontal && dst->depth == 1 ) {
4842
+ Q_ASSERT (dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
4843
+ const int shift = 8 - (dst->width % 8 );
4844
+ const uchar *bitflip = qt_get_bitflip_array ();
4845
+ for (int y = 0 ; y < h; ++y) {
4846
+ uchar *begin = dst->data + y * dst->bytes_per_line ;
4847
+ uchar *end = begin + dst->bytes_per_line ;
4848
+ for (uchar *p = begin; p < end; ++p) {
4849
+ *p = bitflip[*p];
4850
+ // When the data is non-byte aligned, an extra bit shift (of the number of
4851
+ // unused bits at the end) is needed for the entire scanline.
4852
+ if (shift != 8 && p != begin) {
4853
+ if (dst->format == QImage::Format_Mono) {
4854
+ for (int i = 0 ; i < shift; ++i) {
4855
+ p[-1 ] <<= 1 ;
4856
+ p[-1 ] |= (*p & (128 >> i)) >> (7 - i);
4857
+ }
4858
+ } else {
4859
+ for (int i = 0 ; i < shift; ++i) {
4860
+ p[-1 ] >>= 1 ;
4861
+ p[-1 ] |= (*p & (1 << i)) << (7 - i);
4862
+ }
4863
+ }
4864
+ }
4865
+ }
4866
+ if (shift != 8 ) {
4867
+ if (dst->format == QImage::Format_Mono)
4868
+ end[-1 ] <<= shift;
4869
+ else
4870
+ end[-1 ] >>= shift;
4871
+ }
4872
+ }
4873
+ }
4874
+ }
4875
+
4776
4876
/* !
4777
4877
Returns a mirror of the image, mirrored in the horizontal and/or
4778
4878
the vertical direction depending on whether \a horizontal and \a
@@ -4790,8 +4890,6 @@ QImage QImage::mirrored(bool horizontal, bool vertical) const
4790
4890
if ((d->width <= 1 && d->height <= 1 ) || (!horizontal && !vertical))
4791
4891
return *this ;
4792
4892
4793
- int w = d->width ;
4794
- int h = d->height ;
4795
4893
// Create result image, copy colormap
4796
4894
QImage result (d->width , d->height , d->format );
4797
4895
QIMAGE_SANITYCHECK_MEMORY (result);
@@ -4802,88 +4900,10 @@ QImage QImage::mirrored(bool horizontal, bool vertical) const
4802
4900
4803
4901
result.d ->colortable = d->colortable ;
4804
4902
result.d ->has_alpha_clut = d->has_alpha_clut ;
4903
+ result.d ->dpmx = d->dpmx ;
4904
+ result.d ->dpmy = d->dpmy ;
4805
4905
4806
- if (depth () == 1 )
4807
- w = (w+7 )/8 ;
4808
- int dxi = horizontal ? -1 : 1 ;
4809
- int dxs = horizontal ? w-1 : 0 ;
4810
- int dyi = vertical ? -1 : 1 ;
4811
- int dy = vertical ? h-1 : 0 ;
4812
-
4813
- // 1 bit, 8 bit
4814
- if (d->depth == 1 || d->depth == 8 ) {
4815
- for (int sy = 0 ; sy < h; sy++, dy += dyi) {
4816
- quint8* ssl = (quint8*)(d->data + sy*d->bytes_per_line );
4817
- quint8* dsl = (quint8*)(result.d ->data + dy*result.d ->bytes_per_line );
4818
- int dx = dxs;
4819
- for (int sx = 0 ; sx < w; sx++, dx += dxi)
4820
- dsl[dx] = ssl[sx];
4821
- }
4822
- }
4823
- // 16 bit
4824
- else if (d->depth == 16 ) {
4825
- for (int sy = 0 ; sy < h; sy++, dy += dyi) {
4826
- quint16* ssl = (quint16*)(d->data + sy*d->bytes_per_line );
4827
- quint16* dsl = (quint16*)(result.d ->data + dy*result.d ->bytes_per_line );
4828
- int dx = dxs;
4829
- for (int sx = 0 ; sx < w; sx++, dx += dxi)
4830
- dsl[dx] = ssl[sx];
4831
- }
4832
- }
4833
- // 24 bit
4834
- else if (d->depth == 24 ) {
4835
- for (int sy = 0 ; sy < h; sy++, dy += dyi) {
4836
- quint24* ssl = (quint24*)(d->data + sy*d->bytes_per_line );
4837
- quint24* dsl = (quint24*)(result.d ->data + dy*result.d ->bytes_per_line );
4838
- int dx = dxs;
4839
- for (int sx = 0 ; sx < w; sx++, dx += dxi)
4840
- dsl[dx] = ssl[sx];
4841
- }
4842
- }
4843
- // 32 bit
4844
- else if (d->depth == 32 ) {
4845
- for (int sy = 0 ; sy < h; sy++, dy += dyi) {
4846
- quint32* ssl = (quint32*)(d->data + sy*d->bytes_per_line );
4847
- quint32* dsl = (quint32*)(result.d ->data + dy*result.d ->bytes_per_line );
4848
- int dx = dxs;
4849
- for (int sx = 0 ; sx < w; sx++, dx += dxi)
4850
- dsl[dx] = ssl[sx];
4851
- }
4852
- }
4853
-
4854
- // special handling of 1 bit images for horizontal mirroring
4855
- if (horizontal && d->depth == 1 ) {
4856
- int shift = width () % 8 ;
4857
- for (int y = h-1 ; y >= 0 ; y--) {
4858
- quint8* a0 = (quint8*)(result.d ->data + y*d->bytes_per_line );
4859
- // Swap bytes
4860
- quint8* a = a0+dxs;
4861
- while (a >= a0) {
4862
- *a = bitflip[*a];
4863
- a--;
4864
- }
4865
- // Shift bits if unaligned
4866
- if (shift != 0 ) {
4867
- a = a0+dxs;
4868
- quint8 c = 0 ;
4869
- if (format () == Format_MonoLSB) {
4870
- while (a >= a0) {
4871
- quint8 nc = *a << shift;
4872
- *a = (*a >> (8 -shift)) | c;
4873
- --a;
4874
- c = nc;
4875
- }
4876
- } else {
4877
- while (a >= a0) {
4878
- quint8 nc = *a >> shift;
4879
- *a = (*a << (8 -shift)) | c;
4880
- --a;
4881
- c = nc;
4882
- }
4883
- }
4884
- }
4885
- }
4886
- }
4906
+ do_mirror (result.d , d, horizontal, vertical);
4887
4907
4888
4908
return result;
4889
4909
}
0 commit comments