~ubuntu-branches/ubuntu/quantal/imagemagick/quantal

« back to all changes in this revision

Viewing changes to magick/resize.c

  • Committer: Bazaar Package Importer
  • Author(s): Muharem Hrnjadovic
  • Date: 2009-06-04 13:01:13 UTC
  • mfrom: (1.1.5 upstream) (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090604130113-my9114jxmafpwew3
Tags: 7:6.5.1.0-1.1ubuntu1
* Merge from debian unstable, remaining changes:
  - (Build-)depend on libltdl7-dev instead of libltdl3-dev (the armel buildds
    currently have both available).
  - Don't build-dep on librsvg, it brings in excessive dependencies

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
%                                 July 1992                                   %
18
18
%                                                                             %
19
19
%                                                                             %
20
 
%  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
 
20
%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21
21
%  dedicated to making software imaging solutions freely available.           %
22
22
%                                                                             %
23
23
%  You may not use this file except in compliance with the License.  You may  %
42
42
#include "magick/studio.h"
43
43
#include "magick/artifact.h"
44
44
#include "magick/blob.h"
 
45
#include "magick/cache.h"
45
46
#include "magick/cache-view.h"
46
47
#include "magick/color.h"
47
48
#include "magick/color-private.h"
446
447
%
447
448
%    o radial: 1D orthogonal filter (Sinc) or 2D radial filter (Bessel)
448
449
%
449
 
%    o exception: Return any errors or warnings in this structure.
 
450
%    o exception: return any errors or warnings in this structure.
450
451
%
451
452
*/
452
453
MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
778
779
%
779
780
%    o rows: the number of rows in the resized image.
780
781
%
781
 
%    o exception: Return any errors or warnings in this structure.
 
782
%    o exception: return any errors or warnings in this structure.
782
783
%
783
784
*/
784
785
MagickExport Image *AdaptiveResizeImage(const Image *image,
846
847
  resize_view=AcquireCacheView(resize_image);
847
848
  for (y=0; y < (long) resize_image->rows; y++)
848
849
  {
849
 
    q=SetCacheViewPixels(resize_view,0,y,resize_image->columns,1);
 
850
    q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
 
851
      exception);
850
852
    if (q == (PixelPacket *) NULL)
851
853
      break;
852
 
    resize_indexes=GetCacheViewIndexes(resize_view);
 
854
    resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view);
853
855
    offset.y=((MagickRealType) y*image->rows/resize_image->rows);
854
856
    for (x=0; x < (long) resize_image->columns; x++)
855
857
    {
859
861
      SetPixelPacket(resize_image,&pixel,q,resize_indexes+x);
860
862
      q++;
861
863
    }
862
 
    if (SyncCacheViewPixels(resize_view) == MagickFalse)
 
864
    if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
863
865
      break;
864
866
    proceed=SetImageProgress(image,AdaptiveResizeImageTag,y,image->rows);
865
867
    if (proceed == MagickFalse)
1182
1184
  */
1183
1185
  assert(resize_filter != (ResizeFilter *) NULL);
1184
1186
  assert(resize_filter->signature == MagickSignature);
1185
 
  blur=fabs(x)/resize_filter->blur;  /* X position with blur scaling */
 
1187
  blur=fabs(x)/resize_filter->blur;  /* X offset with blur scaling */
1186
1188
  if ((resize_filter->window_support < MagickEpsilon) ||
1187
1189
      (resize_filter->window == Box))
1188
 
    scale=1.0; /* Point/Box Filter -- avoid division by zero */
 
1190
    scale=1.0;  /* Point/Box Filter -- avoid division by zero */
1189
1191
  else
1190
1192
    {
1191
1193
      scale=resize_filter->scale/resize_filter->window_support;
1192
1194
      scale=resize_filter->window(blur*scale,resize_filter);
1193
1195
    }
1194
 
  /*
1195
 
    Weighting for the filter at this position.
1196
 
  */
1197
1196
  return(scale*resize_filter->filter(blur,resize_filter));
1198
1197
}
1199
1198
 
1219
1218
%
1220
1219
%    o image: the image.
1221
1220
%
1222
 
%    o exception: Return any errors or warnings in this structure.
 
1221
%    o exception: return any errors or warnings in this structure.
1223
1222
%
1224
1223
*/
1225
1224
MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
1260
1259
%
1261
1260
%    o image: the image.
1262
1261
%
1263
 
%    o exception: Return any errors or warnings in this structure.
 
1262
%    o exception: return any errors or warnings in this structure.
1264
1263
%
1265
1264
*/
1266
1265
MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception)
1506
1505
  (void) lqr_carver_scan_reset(carver);
1507
1506
  while (lqr_carver_scan(carver,&x,&y,&packet) != 0)
1508
1507
  {
1509
 
    q=SetImagePixels(rescale_image,x,y,1,1);
 
1508
    q=QueueAuthenticPixels(rescale_image,x,y,1,1,exception);
1510
1509
    if (q == (PixelPacket *) NULL)
1511
1510
      break;
1512
 
    rescale_indexes=GetIndexes(rescale_image);
 
1511
    rescale_indexes=GetAuthenticIndexQueue(rescale_image);
1513
1512
    pixel.red=QuantumRange*(packet[0]/255.0);
1514
1513
    pixel.green=QuantumRange*(packet[1]/255.0);
1515
1514
    pixel.blue=QuantumRange*(packet[2]/255.0);
1525
1524
          pixel.opacity=QuantumRange*(packet[4]/255.0);
1526
1525
      }
1527
1526
    SetPixelPacket(rescale_image,&pixel,q,rescale_indexes);
1528
 
    if (SyncImagePixels(rescale_image) == MagickFalse)
 
1527
    if (SyncAuthenticPixels(rescale_image,exception) == MagickFalse)
1529
1528
      break;
1530
1529
  }
1531
1530
  /*
1563
1562
%                                                                             %
1564
1563
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565
1564
%
1566
 
%  ResizeImage() scales an image to the desired dimensions, using
1567
 
%  the given filter (see AcquireFilterInfo() ).
 
1565
%  ResizeImage() scales an image to the desired dimensions, using the given
 
1566
%  filter (see AcquireFilterInfo() ).
1568
1567
%
1569
1568
%  If an undefined filter is given the filter defaults to Mitchell for a
1570
1569
%  colormapped image, a image with a matte channel, or if the image is
1591
1590
%    o blur: the blur factor where > 1 is blurry, < 1 is sharp.
1592
1591
%            Typically set this to 1.0.
1593
1592
%
1594
 
%    o exception: Return any errors or warnings in this structure.
 
1593
%    o exception: return any errors or warnings in this structure.
1595
1594
%
1596
1595
*/
1597
1596
 
1611
1610
    i;
1612
1611
 
1613
1612
  assert(contribution != (ContributionInfo **) NULL);
1614
 
  for (i=0; i < (long) GetCacheViewMaximumThreads(); i++)
 
1613
  for (i=0; i < (long) GetPixelCacheMaximumThreads(); i++)
1615
1614
    if (contribution[i] != (ContributionInfo *) NULL)
1616
1615
      contribution[i]=(ContributionInfo *) RelinquishMagickMemory(
1617
1616
        contribution[i]);
1626
1625
  ContributionInfo
1627
1626
    **contribution;
1628
1627
 
1629
 
  contribution=(ContributionInfo **) AcquireQuantumMemory(
1630
 
    GetCacheViewMaximumThreads(),sizeof(*contribution));
 
1628
  unsigned long
 
1629
    number_threads;
 
1630
 
 
1631
  number_threads=GetPixelCacheMaximumThreads();
 
1632
  contribution=(ContributionInfo **) AcquireQuantumMemory(number_threads,
 
1633
    sizeof(*contribution));
1631
1634
  if (contribution == (ContributionInfo **) NULL)
1632
1635
    return((ContributionInfo **) NULL);
1633
 
  (void) ResetMagickMemory(contribution,0,GetCacheViewMaximumThreads()*
1634
 
    sizeof(*contribution));
1635
 
  for (i=0; i < (long) GetCacheViewMaximumThreads(); i++)
 
1636
  (void) ResetMagickMemory(contribution,0,number_threads*sizeof(*contribution));
 
1637
  for (i=0; i < (long) number_threads; i++)
1636
1638
  {
1637
1639
    contribution[i]=(ContributionInfo *) AcquireQuantumMemory(count,
1638
1640
      sizeof(**contribution));
1666
1668
    storage_class;
1667
1669
 
1668
1670
  ContributionInfo
1669
 
    **contribution;
 
1671
    **contributions;
1670
1672
 
1671
1673
  long
1672
1674
    x;
1682
1684
    support;
1683
1685
 
1684
1686
  ViewInfo
1685
 
    **image_view,
1686
 
    **resize_view;
 
1687
    *image_view,
 
1688
    *resize_view;
1687
1689
 
1688
1690
  /*
1689
1691
    Apply filter to resize horizontally from image to resize image.
1704
1706
      support=(MagickRealType) 0.5;
1705
1707
      scale=1.0;
1706
1708
    }
1707
 
  contribution=AcquireContributionThreadSet((size_t) (2.0*support+3.0));
1708
 
  if (contribution == (ContributionInfo **) NULL)
 
1709
  contributions=AcquireContributionThreadSet((size_t) (2.0*support+3.0));
 
1710
  if (contributions == (ContributionInfo **) NULL)
1709
1711
    {
1710
1712
      (void) ThrowMagickException(exception,GetMagickModule(),
1711
1713
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1714
1716
  status=MagickTrue;
1715
1717
  scale=1.0/scale;
1716
1718
  (void) ResetMagickMemory(&zero,0,sizeof(zero));
1717
 
  image_view=AcquireCacheViewThreadSet(image);
1718
 
  resize_view=AcquireCacheViewThreadSet(resize_image);
 
1719
  image_view=AcquireCacheView(image);
 
1720
  resize_view=AcquireCacheView(resize_image);
1719
1721
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1720
1722
  #pragma omp parallel for shared(status)
1721
1723
#endif
1722
1724
  for (x=0; x < (long) resize_image->columns; x++)
1723
1725
  {
1724
 
    const IndexPacket
1725
 
      *indexes;
1726
 
 
1727
 
    IndexPacket
1728
 
      *resize_indexes;
1729
 
 
1730
1726
    long
1731
 
      id,
1732
1727
      n,
1733
1728
      start,
1734
1729
      stop;
1737
1732
      center,
1738
1733
      density;
1739
1734
 
 
1735
    register const IndexPacket
 
1736
      *indexes;
 
1737
 
1740
1738
    register const PixelPacket
1741
1739
      *p;
1742
1740
 
 
1741
    register ContributionInfo
 
1742
      *contribution;
 
1743
 
 
1744
    register IndexPacket
 
1745
      *resize_indexes;
 
1746
 
1743
1747
    register long
1744
1748
      y;
1745
1749
 
1752
1756
    density=0.0;
1753
1757
    if (status == MagickFalse)
1754
1758
      continue;
1755
 
    id=GetCacheViewThreadId();
 
1759
    contribution=contributions[GetPixelCacheThreadId()];
1756
1760
    for (n=0; n < (stop-start); n++)
1757
1761
    {
1758
 
      contribution[id][n].pixel=start+n;
1759
 
      contribution[id][n].weight=GetResizeFilterWeight(resize_filter,scale*
 
1762
      contribution[n].pixel=start+n;
 
1763
      contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
1760
1764
        ((MagickRealType) (start+n)-center+0.5));
1761
 
      density+=contribution[id][n].weight;
 
1765
      density+=contribution[n].weight;
1762
1766
    }
1763
1767
    if ((density != 0.0) && (density != 1.0))
1764
1768
      {
1770
1774
        */
1771
1775
        density=1.0/density;
1772
1776
        for (i=0; i < n; i++)
1773
 
          contribution[id][i].weight*=density;
 
1777
          contribution[i].weight*=density;
1774
1778
      }
1775
 
    p=AcquireCacheViewPixels(image_view[id],contribution[id][0].pixel,0,
1776
 
      (unsigned long) (contribution[id][n-1].pixel-contribution[id][0].pixel+1),
 
1779
    p=GetCacheViewVirtualPixels(image_view,contribution[0].pixel,0,
 
1780
      (unsigned long) (contribution[n-1].pixel-contribution[0].pixel+1),
1777
1781
      image->rows,exception);
1778
 
    q=SetCacheViewPixels(resize_view[id],x,0,1,resize_image->rows);
 
1782
    q=QueueCacheViewAuthenticPixels(resize_view,x,0,1,resize_image->rows,
 
1783
      exception);
1779
1784
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
1780
1785
      {
1781
1786
        status=MagickFalse;
1782
1787
        continue;
1783
1788
      }
1784
 
    indexes=AcquireCacheViewIndexes(image_view[id]);
1785
 
    resize_indexes=GetCacheViewIndexes(resize_view[id]);
 
1789
    indexes=GetCacheViewVirtualIndexQueue(image_view);
 
1790
    resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view);
1786
1791
    for (y=0; y < (long) resize_image->rows; y++)
1787
1792
    {
1788
1793
      long
1802
1807
        {
1803
1808
          for (i=0; i < n; i++)
1804
1809
          {
1805
 
            j=y*(contribution[id][n-1].pixel-contribution[id][0].pixel+1)+
1806
 
              (contribution[id][i].pixel-contribution[id][0].pixel);
1807
 
            alpha=contribution[id][i].weight;
 
1810
            j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
 
1811
              (contribution[i].pixel-contribution[0].pixel);
 
1812
            alpha=contribution[i].weight;
1808
1813
            pixel.red+=alpha*(p+j)->red;
1809
1814
            pixel.green+=alpha*(p+j)->green;
1810
1815
            pixel.blue+=alpha*(p+j)->blue;
1819
1824
            {
1820
1825
              for (i=0; i < n; i++)
1821
1826
              {
1822
 
                j=y*(contribution[id][n-1].pixel-contribution[id][0].pixel+1)+
1823
 
                  (contribution[id][i].pixel-contribution[id][0].pixel);
1824
 
                alpha=contribution[id][i].weight;
 
1827
                j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
 
1828
                  (contribution[i].pixel-contribution[0].pixel);
 
1829
                alpha=contribution[i].weight;
1825
1830
                pixel.index+=alpha*indexes[j];
1826
1831
              }
1827
1832
              resize_indexes[y]=(IndexPacket) RoundToQuantum(pixel.index);
1835
1840
          gamma=0.0;
1836
1841
          for (i=0; i < n; i++)
1837
1842
          {
1838
 
            j=y*(contribution[id][n-1].pixel-contribution[id][0].pixel+1)+
1839
 
              (contribution[id][i].pixel-contribution[id][0].pixel);
1840
 
            alpha=contribution[id][i].weight*QuantumScale*((MagickRealType)
 
1843
            j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
 
1844
              (contribution[i].pixel-contribution[0].pixel);
 
1845
            alpha=contribution[i].weight*QuantumScale*((MagickRealType)
1841
1846
              QuantumRange-(p+j)->opacity);
1842
1847
            pixel.red+=alpha*(p+j)->red;
1843
1848
            pixel.green+=alpha*(p+j)->green;
1844
1849
            pixel.blue+=alpha*(p+j)->blue;
1845
 
            pixel.opacity+=contribution[id][i].weight*(p+j)->opacity;
 
1850
            pixel.opacity+=contribution[i].weight*(p+j)->opacity;
1846
1851
            gamma+=alpha;
1847
1852
          }
1848
1853
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
1855
1860
            {
1856
1861
              for (i=0; i < n; i++)
1857
1862
              {
1858
 
                j=y*(contribution[id][n-1].pixel-contribution[id][0].pixel+1)+
1859
 
                  (contribution[id][i].pixel-contribution[id][0].pixel);
1860
 
                alpha=contribution[id][i].weight*QuantumScale*((MagickRealType)
 
1863
                j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
 
1864
                  (contribution[i].pixel-contribution[0].pixel);
 
1865
                alpha=contribution[i].weight*QuantumScale*((MagickRealType)
1861
1866
                  QuantumRange-(p+j)->opacity);
1862
1867
                gamma+=alpha;
1863
1868
              }
1869
1874
        {
1870
1875
          i=(long) (MagickMin(MagickMax(center,(double) start),(double) stop-
1871
1876
            1.0)+0.5);
1872
 
          j=y*(contribution[id][n-1].pixel-contribution[id][0].pixel+1)+
1873
 
            (contribution[id][i-start].pixel-contribution[id][0].pixel);
 
1877
          j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
 
1878
            (contribution[i-start].pixel-contribution[0].pixel);
1874
1879
          resize_indexes[y]=indexes[j];
1875
1880
        }
1876
1881
      q++;
1877
1882
    }
1878
 
    if (SyncCacheViewPixels(resize_view[id]) == MagickFalse)
 
1883
    if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
1879
1884
      status=MagickFalse;
1880
1885
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
1881
1886
      {
1883
1888
          proceed;
1884
1889
 
1885
1890
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1886
 
        #pragma omp critical
 
1891
  #pragma omp critical (MagickCore_HorizontalFilter)
1887
1892
#endif
1888
1893
        proceed=SetImageProgress(image,ResizeImageTag,(*quantum)++,span);
1889
1894
        if (proceed == MagickFalse)
1890
1895
          status=MagickFalse;
1891
1896
      }
1892
1897
  }
1893
 
  resize_view=DestroyCacheViewThreadSet(resize_view);
1894
 
  image_view=DestroyCacheViewThreadSet(image_view);
1895
 
  contribution=DestroyContributionThreadSet(contribution);
 
1898
  resize_view=DestroyCacheView(resize_view);
 
1899
  image_view=DestroyCacheView(image_view);
 
1900
  contributions=DestroyContributionThreadSet(contributions);
1896
1901
  return(status);
1897
1902
}
1898
1903
 
1904
1909
    storage_class;
1905
1910
 
1906
1911
  ContributionInfo
1907
 
    **contribution;
 
1912
    **contributions;
1908
1913
 
1909
1914
  long
1910
1915
    y;
1920
1925
    support;
1921
1926
 
1922
1927
  ViewInfo
1923
 
    **image_view,
1924
 
    **resize_view;
 
1928
    *image_view,
 
1929
    *resize_view;
1925
1930
 
1926
1931
  /*
1927
1932
    Apply filter to resize vertically from image to resize_image.
1942
1947
      support=(MagickRealType) 0.5;
1943
1948
      scale=1.0;
1944
1949
    }
1945
 
  contribution=AcquireContributionThreadSet((size_t) (2.0*support+3.0));
1946
 
  if (contribution == (ContributionInfo **) NULL)
 
1950
  contributions=AcquireContributionThreadSet((size_t) (2.0*support+3.0));
 
1951
  if (contributions == (ContributionInfo **) NULL)
1947
1952
    {
1948
1953
      (void) ThrowMagickException(exception,GetMagickModule(),
1949
1954
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1952
1957
  status=MagickTrue;
1953
1958
  scale=1.0/scale;
1954
1959
  (void) ResetMagickMemory(&zero,0,sizeof(zero));
1955
 
  image_view=AcquireCacheViewThreadSet(image);
1956
 
  resize_view=AcquireCacheViewThreadSet(resize_image);
 
1960
  image_view=AcquireCacheView(image);
 
1961
  resize_view=AcquireCacheView(resize_image);
1957
1962
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1958
1963
  #pragma omp parallel for shared(status)
1959
1964
#endif
1960
1965
  for (y=0; y < (long) resize_image->rows; y++)
1961
1966
  {
1962
 
    const IndexPacket
1963
 
      *indexes;
1964
 
 
1965
 
    IndexPacket
1966
 
      *resize_indexes;
1967
 
 
1968
1967
    long
1969
 
      id,
1970
1968
      n,
1971
1969
      start,
1972
1970
      stop;
1975
1973
      center,
1976
1974
      density;
1977
1975
 
 
1976
    register const IndexPacket
 
1977
      *indexes;
 
1978
 
1978
1979
    register const PixelPacket
1979
1980
      *p;
1980
1981
 
 
1982
    register ContributionInfo
 
1983
      *contribution;
 
1984
 
 
1985
    register IndexPacket
 
1986
      *resize_indexes;
 
1987
 
1981
1988
    register long
1982
1989
      x;
1983
1990
 
1990
1997
    density=0.0;
1991
1998
    if (status == MagickFalse)
1992
1999
      continue;
1993
 
    id=GetCacheViewThreadId();
 
2000
    contribution=contributions[GetPixelCacheThreadId()];
1994
2001
    for (n=0; n < (stop-start); n++)
1995
2002
    {
1996
 
      contribution[id][n].pixel=start+n;
1997
 
      contribution[id][n].weight=GetResizeFilterWeight(resize_filter,scale*
 
2003
      contribution[n].pixel=start+n;
 
2004
      contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
1998
2005
        ((MagickRealType) (start+n)-center+0.5));
1999
 
      density+=contribution[id][n].weight;
 
2006
      density+=contribution[n].weight;
2000
2007
    }
2001
2008
    if ((density != 0.0) && (density != 1.0))
2002
2009
      {
2008
2015
        */
2009
2016
        density=1.0/density;
2010
2017
        for (i=0; i < n; i++)
2011
 
          contribution[id][i].weight*=density;
 
2018
          contribution[i].weight*=density;
2012
2019
      }
2013
 
    p=AcquireCacheViewPixels(image_view[id],0,contribution[id][0].pixel,
2014
 
      image->columns,(unsigned long) (contribution[id][n-1].pixel-
2015
 
      contribution[id][0].pixel+1),exception);
2016
 
    q=SetCacheViewPixels(resize_view[id],0,y,resize_image->columns,1);
 
2020
    p=GetCacheViewVirtualPixels(image_view,0,contribution[0].pixel,
 
2021
      image->columns,(unsigned long) (contribution[n-1].pixel-
 
2022
      contribution[0].pixel+1),exception);
 
2023
    q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
 
2024
      exception);
2017
2025
    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
2018
2026
      {
2019
2027
        status=MagickFalse;
2020
2028
        continue;
2021
2029
      }
2022
 
    indexes=AcquireCacheViewIndexes(image_view[id]);
2023
 
    resize_indexes=GetCacheViewIndexes(resize_view[id]);
 
2030
    indexes=GetCacheViewVirtualIndexQueue(image_view);
 
2031
    resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view);
2024
2032
    for (x=0; x < (long) resize_image->columns; x++)
2025
2033
    {
2026
2034
      long
2040
2048
        {
2041
2049
          for (i=0; i < n; i++)
2042
2050
          {
2043
 
            j=(long) ((contribution[id][i].pixel-contribution[id][0].pixel)*
 
2051
            j=(long) ((contribution[i].pixel-contribution[0].pixel)*
2044
2052
              image->columns+x);
2045
 
            alpha=contribution[id][i].weight;
 
2053
            alpha=contribution[i].weight;
2046
2054
            pixel.red+=alpha*(p+j)->red;
2047
2055
            pixel.green+=alpha*(p+j)->green;
2048
2056
            pixel.blue+=alpha*(p+j)->blue;
2057
2065
            {
2058
2066
              for (i=0; i < n; i++)
2059
2067
              {
2060
 
                j=(long) ((contribution[id][i].pixel-contribution[id][0].pixel)*
 
2068
                j=(long) ((contribution[i].pixel-contribution[0].pixel)*
2061
2069
                  image->columns+x);
2062
 
                alpha=contribution[id][i].weight;
 
2070
                alpha=contribution[i].weight;
2063
2071
                pixel.index+=alpha*indexes[j];
2064
2072
              }
2065
2073
              resize_indexes[x]=(IndexPacket) RoundToQuantum(pixel.index);
2073
2081
          gamma=0.0;
2074
2082
          for (i=0; i < n; i++)
2075
2083
          {
2076
 
            j=(long) ((contribution[id][i].pixel-contribution[id][0].pixel)*
 
2084
            j=(long) ((contribution[i].pixel-contribution[0].pixel)*
2077
2085
              image->columns+x);
2078
 
            alpha=contribution[id][i].weight*QuantumScale*((MagickRealType)
 
2086
            alpha=contribution[i].weight*QuantumScale*((MagickRealType)
2079
2087
              QuantumRange-(p+j)->opacity);
2080
2088
            pixel.red+=alpha*(p+j)->red;
2081
2089
            pixel.green+=alpha*(p+j)->green;
2082
2090
            pixel.blue+=alpha*(p+j)->blue;
2083
 
            pixel.opacity+=contribution[id][i].weight*(p+j)->opacity;
 
2091
            pixel.opacity+=contribution[i].weight*(p+j)->opacity;
2084
2092
            gamma+=alpha;
2085
2093
          }
2086
2094
          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
2093
2101
            {
2094
2102
              for (i=0; i < n; i++)
2095
2103
              {
2096
 
                j=(long) ((contribution[id][i].pixel-contribution[id][0].pixel)*
 
2104
                j=(long) ((contribution[i].pixel-contribution[0].pixel)*
2097
2105
                  image->columns+x);
2098
 
                alpha=contribution[id][i].weight*QuantumScale*((MagickRealType)
 
2106
                alpha=contribution[i].weight*QuantumScale*((MagickRealType)
2099
2107
                  QuantumRange-(p+j)->opacity);
2100
2108
                pixel.index+=alpha*indexes[j];
2101
2109
              }
2107
2115
        {
2108
2116
          i=(long) (MagickMin(MagickMax(center,(double) start),(double) stop-
2109
2117
            1.0)+0.5);
2110
 
          j=(long) ((contribution[id][i-start].pixel-contribution[id][0].pixel)*
 
2118
          j=(long) ((contribution[i-start].pixel-contribution[0].pixel)*
2111
2119
            image->columns+x);
2112
2120
          resize_indexes[x]=indexes[j];
2113
2121
        }
2114
2122
      q++;
2115
2123
    }
2116
 
    if (SyncCacheViewPixels(resize_view[id]) == MagickFalse)
 
2124
    if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
2117
2125
      status=MagickFalse;
2118
2126
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
2119
2127
      {
2121
2129
          proceed;
2122
2130
 
2123
2131
#if defined(MAGICKCORE_OPENMP_SUPPORT)
2124
 
        #pragma omp critical
 
2132
  #pragma omp critical (MagickCore_VerticalFilter)
2125
2133
#endif
2126
2134
        proceed=SetImageProgress(image,ResizeImageTag,(*quantum)++,span);
2127
2135
        if (proceed == MagickFalse)
2128
2136
          status=MagickFalse;
2129
2137
      }
2130
2138
  }
2131
 
  resize_view=DestroyCacheViewThreadSet(resize_view);
2132
 
  image_view=DestroyCacheViewThreadSet(image_view);
2133
 
  contribution=DestroyContributionThreadSet(contribution);
 
2139
  resize_view=DestroyCacheView(resize_view);
 
2140
  image_view=DestroyCacheView(image_view);
 
2141
  contributions=DestroyContributionThreadSet(contributions);
2134
2142
  return(status);
2135
2143
}
2136
2144
 
2138
2146
  const unsigned long rows,const FilterTypes filter,const double blur,
2139
2147
  ExceptionInfo *exception)
2140
2148
{
 
2149
#define WorkLoadFactor  0.265
 
2150
 
2141
2151
  FilterTypes
2142
2152
    filter_type;
2143
2153
 
2162
2172
    quantum;
2163
2173
 
2164
2174
  /*
2165
 
    Acquire resize filter.
 
2175
    Acquire resize image.
2166
2176
  */
2167
2177
  assert(image != (Image *) NULL);
2168
2178
  assert(image->signature == MagickSignature);
2175
2185
  if ((columns == image->columns) && (rows == image->rows) &&
2176
2186
      (filter == UndefinedFilter) && (blur == 1.0))
2177
2187
    return(CloneImage(image,0,0,MagickTrue,exception));
 
2188
  resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
 
2189
  if (resize_image == (Image *) NULL)
 
2190
    return(resize_image);
 
2191
  /*
 
2192
    Acquire resize filter.
 
2193
  */
2178
2194
  x_factor=(MagickRealType) columns/(MagickRealType) image->columns;
2179
2195
  y_factor=(MagickRealType) rows/(MagickRealType) image->rows;
 
2196
  if ((x_factor*y_factor) > WorkLoadFactor)
 
2197
    filter_image=CloneImage(image,columns,image->rows,MagickTrue,exception);
 
2198
  else
 
2199
    filter_image=CloneImage(image,image->columns,rows,MagickTrue,exception);
 
2200
  if (filter_image == (Image *) NULL)
 
2201
    return(DestroyImage(resize_image));
2180
2202
  filter_type=LanczosFilter;
2181
2203
  if (filter != UndefinedFilter)
2182
2204
    filter_type=filter;
2193
2215
    Resize image.
2194
2216
  */
2195
2217
  quantum=0;
2196
 
  if ((columns*((MagickSizeType) image->rows+rows)) >
2197
 
      (rows*((MagickSizeType) image->columns+columns)))
 
2218
  if ((x_factor*y_factor) > WorkLoadFactor)
2198
2219
    {
2199
 
      filter_image=CloneImage(image,columns,image->rows,MagickTrue,exception);
2200
 
      if (filter_image == (Image *) NULL)
2201
 
        {
2202
 
          resize_filter=DestroyResizeFilter(resize_filter);
2203
 
          return((Image *) NULL);
2204
 
        }
2205
2220
      span=(MagickSizeType) (filter_image->columns+rows);
2206
2221
      status=HorizontalFilter(resize_filter,image,filter_image,x_factor,span,
2207
2222
        &quantum,exception);
2208
 
      resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
2209
 
      if (resize_image != (Image *) NULL)
2210
 
        status|=VerticalFilter(resize_filter,filter_image,resize_image,y_factor,
2211
 
          span,&quantum,exception);
 
2223
      status&=VerticalFilter(resize_filter,filter_image,resize_image,y_factor,
 
2224
        span,&quantum,exception);
2212
2225
    }
2213
2226
  else
2214
2227
    {
2215
 
      filter_image=CloneImage(image,image->columns,rows,MagickTrue,exception);
2216
 
      if (filter_image == (Image *) NULL)
2217
 
        {
2218
 
          resize_filter=DestroyResizeFilter(resize_filter);
2219
 
          return((Image *) NULL);
2220
 
        }
2221
2228
      span=(MagickSizeType) (filter_image->rows+columns);
2222
2229
      status=VerticalFilter(resize_filter,image,filter_image,y_factor,span,
2223
2230
        &quantum,exception);
2224
 
      resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
2225
 
      if (resize_image != (Image *) NULL)
2226
 
        status|=HorizontalFilter(resize_filter,filter_image,resize_image,
2227
 
          x_factor,span,&quantum,exception);
 
2231
      status&=HorizontalFilter(resize_filter,filter_image,resize_image,x_factor,
 
2232
        span,&quantum,exception);
2228
2233
    }
2229
2234
  /*
2230
2235
    Free resources.
2231
2236
  */
2232
2237
  filter_image=DestroyImage(filter_image);
2233
2238
  resize_filter=DestroyResizeFilter(resize_filter);
2234
 
  if (status == MagickFalse)
2235
 
    {
2236
 
      if (resize_image != (Image *) NULL)
2237
 
        resize_image=DestroyImage(resize_image);
2238
 
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
2239
 
    }
 
2239
  if ((status == MagickFalse) || (resize_image == (Image *) NULL))
 
2240
    return((Image *) NULL);
2240
2241
  resize_image->type=image->type;
2241
2242
  return(resize_image);
2242
2243
}
2269
2270
%
2270
2271
%    o rows: the number of rows in the sampled image.
2271
2272
%
2272
 
%    o exception: Return any errors or warnings in this structure.
 
2273
%    o exception: return any errors or warnings in this structure.
2273
2274
%
2274
2275
*/
2275
2276
MagickExport Image *SampleImage(const Image *image,const unsigned long columns,
2345
2346
    Sample each row.
2346
2347
  */
2347
2348
  j=(-1);
2348
 
  pixels=AcquireImagePixels(image,0,0,image->columns,1,exception);
2349
 
  indexes=AcquireIndexes(image);
 
2349
  pixels=GetVirtualPixels(image,0,0,image->columns,1,exception);
 
2350
  indexes=GetVirtualIndexQueue(image);
2350
2351
  for (y=0; y < (long) sample_image->rows; y++)
2351
2352
  {
2352
 
    sample_pixels=SetImagePixels(sample_image,0,y,sample_image->columns,1);
 
2353
    sample_pixels=QueueAuthenticPixels(sample_image,0,y,sample_image->columns,1,
 
2354
      exception);
2353
2355
    if (sample_pixels == (PixelPacket *) NULL)
2354
2356
      break;
2355
 
    sample_indexes=GetIndexes(sample_image);
 
2357
    sample_indexes=GetAuthenticIndexQueue(sample_image);
2356
2358
    if (j != y_offset[y])
2357
2359
      {
2358
2360
        /*
2359
2361
          Read a scan line.
2360
2362
        */
2361
2363
        j=y_offset[y];
2362
 
        pixels=AcquireImagePixels(image,0,j,image->columns,1,exception);
 
2364
        pixels=GetVirtualPixels(image,0,j,image->columns,1,exception);
2363
2365
        if (pixels == (const PixelPacket *) NULL)
2364
2366
          break;
2365
 
        indexes=AcquireIndexes(image);
 
2367
        indexes=GetVirtualIndexQueue(image);
2366
2368
      }
2367
2369
    /*
2368
2370
      Sample each column.
2373
2375
        (image->colorspace == CMYKColorspace))
2374
2376
      for (x=0; x < (long) sample_image->columns; x++)
2375
2377
        sample_indexes[x]=indexes[x_offset[x]];
2376
 
    if (SyncImagePixels(sample_image) == MagickFalse)
 
2378
    if (SyncAuthenticPixels(sample_image,exception) == MagickFalse)
2377
2379
      break;
2378
2380
    proceed=SetImageProgress(image,SampleImageTag,y,image->rows);
2379
2381
    if (proceed == MagickFalse)
2411
2413
%
2412
2414
%    o rows: the number of rows in the scaled image.
2413
2415
%
2414
 
%    o exception: Return any errors or warnings in this structure.
 
2416
%    o exception: return any errors or warnings in this structure.
2415
2417
%
2416
2418
*/
2417
2419
MagickExport Image *ScaleImage(const Image *image,const unsigned long columns,
2439
2441
    *y_vector,
2440
2442
    zero;
2441
2443
 
 
2444
  MagickRealType
 
2445
    alpha,
 
2446
    gamma;
 
2447
 
2442
2448
  PointInfo
2443
2449
    scale,
2444
2450
    span;
2520
2526
  i=0;
2521
2527
  for (y=0; y < (long) scale_image->rows; y++)
2522
2528
  {
2523
 
    q=SetImagePixels(scale_image,0,y,scale_image->columns,1);
 
2529
    q=QueueAuthenticPixels(scale_image,0,y,scale_image->columns,1,exception);
2524
2530
    if (q == (PixelPacket *) NULL)
2525
2531
      break;
2526
 
    scale_indexes=GetIndexes(scale_image);
 
2532
    scale_indexes=GetAuthenticIndexQueue(scale_image);
2527
2533
    if (scale_image->rows == image->rows)
2528
2534
      {
2529
2535
        /*
2530
2536
          Read a new scanline.
2531
2537
        */
2532
 
        p=AcquireImagePixels(image,0,i++,image->columns,1,exception);
 
2538
        p=GetVirtualPixels(image,0,i++,image->columns,1,exception);
2533
2539
        if (p == (const PixelPacket *) NULL)
2534
2540
          break;
2535
 
        indexes=AcquireIndexes(image);
 
2541
        indexes=GetVirtualIndexQueue(image);
2536
2542
        for (x=0; x < (long) image->columns; x++)
2537
2543
        {
2538
2544
          x_vector[x].red=(MagickRealType) p->red;
2557
2563
              /*
2558
2564
                Read a new scanline.
2559
2565
              */
2560
 
              p=AcquireImagePixels(image,0,i++,image->columns,1,exception);
 
2566
              p=GetVirtualPixels(image,0,i++,image->columns,1,exception);
2561
2567
              if (p == (const PixelPacket *) NULL)
2562
2568
                break;
2563
 
              indexes=AcquireIndexes(image);
 
2569
              indexes=GetVirtualIndexQueue(image);
2564
2570
              for (x=0; x < (long) image->columns; x++)
2565
2571
              {
2566
2572
                x_vector[x].red=(MagickRealType) p->red;
2593
2599
            /*
2594
2600
              Read a new scanline.
2595
2601
            */
2596
 
            p=AcquireImagePixels(image,0,i++,image->columns,1,exception);
 
2602
            p=GetVirtualPixels(image,0,i++,image->columns,1,exception);
2597
2603
            if (p == (const PixelPacket *) NULL)
2598
2604
              break;
2599
 
            indexes=AcquireIndexes(image);
 
2605
            indexes=GetVirtualIndexQueue(image);
2600
2606
            for (x=0; x < (long) image->columns; x++)
2601
2607
            {
2602
2608
              x_vector[x].red=(MagickRealType) p->red;
2743
2749
      t=scale_scanline;
2744
2750
      for (x=0; x < (long) scale_image->columns; x++)
2745
2751
      {
2746
 
        q->red=RoundToQuantum(t->red);
2747
 
        q->green=RoundToQuantum(t->green);
2748
 
        q->blue=RoundToQuantum(t->blue);
 
2752
        alpha=1.0;
 
2753
        if (image->matte != MagickFalse)
 
2754
          alpha=(MagickRealType) (QuantumScale*(QuantumRange-t->opacity));
 
2755
        gamma=1.0/(fabs((double) alpha) <= MagickEpsilon ? 1.0 : alpha);
 
2756
        q->red=RoundToQuantum(gamma*t->red);
 
2757
        q->green=RoundToQuantum(gamma*t->green);
 
2758
        q->blue=RoundToQuantum(gamma*t->blue);
2749
2759
        if (scale_image->matte != MagickFalse)
2750
2760
          q->opacity=RoundToQuantum(t->opacity);
2751
2761
        if (scale_indexes != (IndexPacket *) NULL)
2752
 
          scale_indexes[x]=(IndexPacket) RoundToQuantum(t->index);
 
2762
          scale_indexes[x]=(IndexPacket) RoundToQuantum(gamma*t->index);
2753
2763
        t++;
2754
2764
        q++;
2755
2765
      }
2756
2766
    }
2757
 
    if (SyncImagePixels(scale_image) == MagickFalse)
 
2767
    if (SyncAuthenticPixels(scale_image,exception) == MagickFalse)
2758
2768
      break;
2759
2769
    proceed=SetImageProgress(image,ScaleImageTag,y,image->rows);
2760
2770
    if (proceed == MagickFalse)
2833
2843
%
2834
2844
%    o rows: the number of rows in the scaled image.
2835
2845
%
2836
 
%    o exception: Return any errors or warnings in this structure.
 
2846
%    o exception: return any errors or warnings in this structure.
2837
2847
%
2838
2848
*/
2839
2849
MagickExport Image *ThumbnailImage(const Image *image,
2957
2967
%    o rows: An integer that specifies the number of rows in the scaled
2958
2968
%      image.
2959
2969
%
2960
 
%    o exception: Return any errors or warnings in this structure.
 
2970
%    o exception: return any errors or warnings in this structure.
2961
2971
%
2962
2972
*/
2963
2973
MagickExport Image *ZoomImage(const Image *image,const unsigned long columns,