mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Add amount parameter to Error Diffusion algorithm
This commit is contained in:
		
							parent
							
								
									e1437a20c3
								
							
						
					
					
						commit
						fcf272bb69
					
				|  | @ -237,6 +237,7 @@ | ||||||
|     <section id="quantization"> |     <section id="quantization"> | ||||||
|       <option id="with_alpha" type="bool" default="true" /> |       <option id="with_alpha" type="bool" default="true" /> | ||||||
|       <option id="dithering_algorithm" type="std::string" /> |       <option id="dithering_algorithm" type="std::string" /> | ||||||
|  |       <option id="dithering_factor" type="int" default="100" /> | ||||||
|     </section> |     </section> | ||||||
|     <section id="eyedropper" text="Editor"> |     <section id="eyedropper" text="Editor"> | ||||||
|       <option id="channel" type="EyedropperChannel" default="EyedropperChannel::COLOR_ALPHA" /> |       <option id="channel" type="EyedropperChannel" default="EyedropperChannel::COLOR_ALPHA" /> | ||||||
|  |  | ||||||
|  | @ -482,6 +482,7 @@ delete = &Delete | ||||||
| 
 | 
 | ||||||
| [color_mode] | [color_mode] | ||||||
| title = Color Mode | title = Color Mode | ||||||
|  | amount = Amount: | ||||||
| flatten = Merge layers | flatten = Merge layers | ||||||
| 
 | 
 | ||||||
| [convolution_matrix] | [convolution_matrix] | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| <!-- Aseprite --> | <!-- Aseprite --> | ||||||
| <!-- Copyright (C) 2017 by David Capello --> | <!-- Copyright (C) 2019  Igara Studio S.A. --> | ||||||
|  | <!-- Copyright (C) 2017  David Capello --> | ||||||
| <gui> | <gui> | ||||||
| <window id="color_mode" text="@.title"> | <window id="color_mode" text="@.title"> | ||||||
|   <vbox> |   <vbox> | ||||||
|  | @ -8,6 +9,11 @@ | ||||||
|     </view> |     </view> | ||||||
|     <slider min="0" max="100" id="progress" minwidth="100" /> |     <slider min="0" max="100" id="progress" minwidth="100" /> | ||||||
|     <hbox id="dithering_placeholder" /> |     <hbox id="dithering_placeholder" /> | ||||||
|  |     <hbox id="amount"> | ||||||
|  |       <label text="@.amount" /> | ||||||
|  |       <slider min="0" max="100" id="factor" minwidth="100" /> | ||||||
|  |       <label text="%" /> | ||||||
|  |     </hbox> | ||||||
|     <check text="@.flatten" id="flatten" /> |     <check text="@.flatten" id="flatten" /> | ||||||
|     <separator horizontal="true" /> |     <separator horizontal="true" /> | ||||||
|     <hbox> |     <hbox> | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
|  | // Copyright (C) 2019  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2018  David Capello
 | // Copyright (C) 2001-2018  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -69,6 +70,7 @@ SetPixelFormat::SetPixelFormat(Sprite* sprite, | ||||||
|                                const PixelFormat newFormat, |                                const PixelFormat newFormat, | ||||||
|                                const render::DitheringAlgorithm ditheringAlgorithm, |                                const render::DitheringAlgorithm ditheringAlgorithm, | ||||||
|                                const render::DitheringMatrix& ditheringMatrix, |                                const render::DitheringMatrix& ditheringMatrix, | ||||||
|  |                                const double ditheringFactor, | ||||||
|                                render::TaskDelegate* delegate) |                                render::TaskDelegate* delegate) | ||||||
|   : WithSprite(sprite) |   : WithSprite(sprite) | ||||||
|   , m_oldFormat(sprite->pixelFormat()) |   , m_oldFormat(sprite->pixelFormat()) | ||||||
|  | @ -86,6 +88,7 @@ SetPixelFormat::SetPixelFormat(Sprite* sprite, | ||||||
|       (old_image.get(), nullptr, newFormat, |       (old_image.get(), nullptr, newFormat, | ||||||
|        ditheringAlgorithm, |        ditheringAlgorithm, | ||||||
|        ditheringMatrix, |        ditheringMatrix, | ||||||
|  |        ditheringFactor, | ||||||
|        sprite->rgbMap(cel->frame()), |        sprite->rgbMap(cel->frame()), | ||||||
|        sprite->palette(cel->frame()), |        sprite->palette(cel->frame()), | ||||||
|        cel->layer()->isBackground(), |        cel->layer()->isBackground(), | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
|  | // Copyright (C) 2019  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2017  David Capello
 | // Copyright (C) 2001-2017  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -32,6 +33,7 @@ namespace cmd { | ||||||
|                    const doc::PixelFormat newFormat, |                    const doc::PixelFormat newFormat, | ||||||
|                    const render::DitheringAlgorithm ditheringAlgorithm, |                    const render::DitheringAlgorithm ditheringAlgorithm, | ||||||
|                    const render::DitheringMatrix& ditheringMatrix, |                    const render::DitheringMatrix& ditheringMatrix, | ||||||
|  |                    const double ditheringFactor, | ||||||
|                    render::TaskDelegate* delegate); |                    render::TaskDelegate* delegate); | ||||||
| 
 | 
 | ||||||
|   protected: |   protected: | ||||||
|  |  | ||||||
|  | @ -79,6 +79,7 @@ public: | ||||||
|                 const doc::PixelFormat pixelFormat, |                 const doc::PixelFormat pixelFormat, | ||||||
|                 const render::DitheringAlgorithm ditheringAlgorithm, |                 const render::DitheringAlgorithm ditheringAlgorithm, | ||||||
|                 const render::DitheringMatrix& ditheringMatrix, |                 const render::DitheringMatrix& ditheringMatrix, | ||||||
|  |                 const double ditheringFactor, | ||||||
|                 const gfx::Point& pos, |                 const gfx::Point& pos, | ||||||
|                 const bool newBlend) |                 const bool newBlend) | ||||||
|     : m_image(dstImage) |     : m_image(dstImage) | ||||||
|  | @ -92,11 +93,13 @@ public: | ||||||
|        pixelFormat, |        pixelFormat, | ||||||
|        ditheringAlgorithm, |        ditheringAlgorithm, | ||||||
|        ditheringMatrix, |        ditheringMatrix, | ||||||
|  |        ditheringFactor, | ||||||
|        newBlend]() { // Copy the matrix
 |        newBlend]() { // Copy the matrix
 | ||||||
|         run(sprite, frame, |         run(sprite, frame, | ||||||
|             pixelFormat, |             pixelFormat, | ||||||
|             ditheringAlgorithm, |             ditheringAlgorithm, | ||||||
|             ditheringMatrix, |             ditheringMatrix, | ||||||
|  |             ditheringFactor, | ||||||
|             newBlend); |             newBlend); | ||||||
|       }) |       }) | ||||||
|   { |   { | ||||||
|  | @ -121,6 +124,7 @@ private: | ||||||
|            const doc::PixelFormat pixelFormat, |            const doc::PixelFormat pixelFormat, | ||||||
|            const render::DitheringAlgorithm ditheringAlgorithm, |            const render::DitheringAlgorithm ditheringAlgorithm, | ||||||
|            const render::DitheringMatrix& ditheringMatrix, |            const render::DitheringMatrix& ditheringMatrix, | ||||||
|  |            const double ditheringFactor, | ||||||
|            const bool newBlend) { |            const bool newBlend) { | ||||||
|     doc::ImageRef tmp( |     doc::ImageRef tmp( | ||||||
|       Image::create(sprite->pixelFormat(), |       Image::create(sprite->pixelFormat(), | ||||||
|  | @ -142,6 +146,7 @@ private: | ||||||
|       pixelFormat, |       pixelFormat, | ||||||
|       ditheringAlgorithm, |       ditheringAlgorithm, | ||||||
|       ditheringMatrix, |       ditheringMatrix, | ||||||
|  |       ditheringFactor, | ||||||
|       sprite->rgbMap(frame), |       sprite->rgbMap(frame), | ||||||
|       sprite->palette(frame), |       sprite->palette(frame), | ||||||
|       (sprite->backgroundLayer() != nullptr), |       (sprite->backgroundLayer() != nullptr), | ||||||
|  | @ -208,6 +213,11 @@ public: | ||||||
|       m_ditheringSelector->Change.connect( |       m_ditheringSelector->Change.connect( | ||||||
|         base::Bind<void>(&ColorModeWindow::onDithering, this)); |         base::Bind<void>(&ColorModeWindow::onDithering, this)); | ||||||
|       ditheringPlaceholder()->addChild(m_ditheringSelector); |       ditheringPlaceholder()->addChild(m_ditheringSelector); | ||||||
|  | 
 | ||||||
|  |       factor()->Change.connect(base::Bind<void>(&ColorModeWindow::onDithering, this)); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       amount()->setVisible(false); | ||||||
|     } |     } | ||||||
|     if (from != IMAGE_GRAYSCALE) |     if (from != IMAGE_GRAYSCALE) | ||||||
|       colorMode()->addChild(new ConversionItem(IMAGE_GRAYSCALE)); |       colorMode()->addChild(new ConversionItem(IMAGE_GRAYSCALE)); | ||||||
|  | @ -221,6 +231,9 @@ public: | ||||||
| 
 | 
 | ||||||
|     progress()->setReadOnly(true); |     progress()->setReadOnly(true); | ||||||
| 
 | 
 | ||||||
|  |     // Default dithering factor
 | ||||||
|  |     factor()->setValue(Preferences::instance().quantization.ditheringFactor()); | ||||||
|  | 
 | ||||||
|     // Select first option
 |     // Select first option
 | ||||||
|     colorMode()->selectIndex(0); |     colorMode()->selectIndex(0); | ||||||
|   } |   } | ||||||
|  | @ -244,6 +257,10 @@ public: | ||||||
|                                   render::BayerMatrix(8)); |                                   render::BayerMatrix(8)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   double ditheringFactor() const { | ||||||
|  |     return double(factor()->getValue()) / 100.0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   bool flattenEnabled() const { |   bool flattenEnabled() const { | ||||||
|     return flatten()->isSelected(); |     return flatten()->isSelected(); | ||||||
|   } |   } | ||||||
|  | @ -252,7 +269,14 @@ public: | ||||||
|   void saveDitheringAlgorithm() { |   void saveDitheringAlgorithm() { | ||||||
|     if (m_ditheringSelector) { |     if (m_ditheringSelector) { | ||||||
|       if (auto item = m_ditheringSelector->getSelectedItem()) { |       if (auto item = m_ditheringSelector->getSelectedItem()) { | ||||||
|         Preferences::instance().quantization.ditheringAlgorithm(item->text()); |         Preferences::instance().quantization.ditheringAlgorithm( | ||||||
|  |           item->text()); | ||||||
|  | 
 | ||||||
|  |         if (m_ditheringSelector->ditheringAlgorithm() == | ||||||
|  |             render::DitheringAlgorithm::ErrorDiffusion) { | ||||||
|  |           Preferences::instance().quantization.ditheringFactor( | ||||||
|  |             factor()->getValue()); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | @ -285,8 +309,15 @@ private: | ||||||
| 
 | 
 | ||||||
|     doc::PixelFormat dstPixelFormat = item->pixelFormat(); |     doc::PixelFormat dstPixelFormat = item->pixelFormat(); | ||||||
| 
 | 
 | ||||||
|     if (m_ditheringSelector) |     if (m_ditheringSelector) { | ||||||
|       m_ditheringSelector->setVisible(dstPixelFormat == doc::IMAGE_INDEXED); |       const bool toIndexed = (dstPixelFormat == doc::IMAGE_INDEXED); | ||||||
|  |       m_ditheringSelector->setVisible(toIndexed); | ||||||
|  | 
 | ||||||
|  |       const bool errorDiff = | ||||||
|  |         (m_ditheringSelector->ditheringAlgorithm() == | ||||||
|  |          render::DitheringAlgorithm::ErrorDiffusion); | ||||||
|  |       amount()->setVisible(toIndexed && errorDiff); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     m_image.reset( |     m_image.reset( | ||||||
|       Image::create(dstPixelFormat, |       Image::create(dstPixelFormat, | ||||||
|  | @ -315,6 +346,7 @@ private: | ||||||
|         dstPixelFormat, |         dstPixelFormat, | ||||||
|         ditheringAlgorithm(), |         ditheringAlgorithm(), | ||||||
|         ditheringMatrix(), |         ditheringMatrix(), | ||||||
|  |         ditheringFactor(), | ||||||
|         visibleBounds.origin(), |         visibleBounds.origin(), | ||||||
|         Preferences::instance().experimental.newBlend())); |         Preferences::instance().experimental.newBlend())); | ||||||
| 
 | 
 | ||||||
|  | @ -373,6 +405,7 @@ private: | ||||||
|   doc::PixelFormat m_format; |   doc::PixelFormat m_format; | ||||||
|   render::DitheringAlgorithm m_ditheringAlgorithm; |   render::DitheringAlgorithm m_ditheringAlgorithm; | ||||||
|   render::DitheringMatrix m_ditheringMatrix; |   render::DitheringMatrix m_ditheringMatrix; | ||||||
|  |   double m_ditheringFactor; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ChangePixelFormatCommand::ChangePixelFormatCommand() | ChangePixelFormatCommand::ChangePixelFormatCommand() | ||||||
|  | @ -381,6 +414,7 @@ ChangePixelFormatCommand::ChangePixelFormatCommand() | ||||||
|   m_useUI = true; |   m_useUI = true; | ||||||
|   m_format = IMAGE_RGB; |   m_format = IMAGE_RGB; | ||||||
|   m_ditheringAlgorithm = render::DitheringAlgorithm::None; |   m_ditheringAlgorithm = render::DitheringAlgorithm::None; | ||||||
|  |   m_ditheringFactor = 1.0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ChangePixelFormatCommand::onLoadParams(const Params& params) | void ChangePixelFormatCommand::onLoadParams(const Params& params) | ||||||
|  | @ -483,6 +517,7 @@ void ChangePixelFormatCommand::onExecute(Context* context) | ||||||
|     m_format = window.pixelFormat(); |     m_format = window.pixelFormat(); | ||||||
|     m_ditheringAlgorithm = window.ditheringAlgorithm(); |     m_ditheringAlgorithm = window.ditheringAlgorithm(); | ||||||
|     m_ditheringMatrix = window.ditheringMatrix(); |     m_ditheringMatrix = window.ditheringMatrix(); | ||||||
|  |     m_ditheringFactor = window.ditheringFactor(); | ||||||
|     flatten = window.flattenEnabled(); |     flatten = window.flattenEnabled(); | ||||||
| 
 | 
 | ||||||
|     window.saveDitheringAlgorithm(); |     window.saveDitheringAlgorithm(); | ||||||
|  | @ -520,6 +555,7 @@ void ChangePixelFormatCommand::onExecute(Context* context) | ||||||
|             sprite, m_format, |             sprite, m_format, | ||||||
|             m_ditheringAlgorithm, |             m_ditheringAlgorithm, | ||||||
|             m_ditheringMatrix, |             m_ditheringMatrix, | ||||||
|  |             m_ditheringFactor, | ||||||
|             &job));             // SpriteJob is a render::TaskDelegate
 |             &job));             // SpriteJob is a render::TaskDelegate
 | ||||||
|       }); |       }); | ||||||
|     job.waitJob(); |     job.waitJob(); | ||||||
|  |  | ||||||
|  | @ -283,7 +283,7 @@ void NewLayerCommand::onExecute(Context* context) | ||||||
|               nullptr, |               nullptr, | ||||||
|               sprite->pixelFormat(), |               sprite->pixelFormat(), | ||||||
|               render::DitheringAlgorithm::None, |               render::DitheringAlgorithm::None, | ||||||
|               render::DitheringMatrix(), |               render::DitheringMatrix(), 1.0, | ||||||
|               sprite->rgbMap(dstFrame), |               sprite->rgbMap(dstFrame), | ||||||
|               pasteSpr->palette(fr), |               pasteSpr->palette(fr), | ||||||
|               (pasteSpr->backgroundLayer() ? true: false), |               (pasteSpr->backgroundLayer() ? true: false), | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
|  | // Copyright (C) 2019  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2018  David Capello
 | // Copyright (C) 2001-2018  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -184,7 +185,7 @@ void PasteTextCommand::onExecute(Context* ctx) | ||||||
|           render::convert_pixel_format( |           render::convert_pixel_format( | ||||||
|             image.get(), NULL, sprite->pixelFormat(), |             image.get(), NULL, sprite->pixelFormat(), | ||||||
|             render::DitheringAlgorithm::None, |             render::DitheringAlgorithm::None, | ||||||
|             render::DitheringMatrix(), |             render::DitheringMatrix(), 1.0, | ||||||
|             rgbmap, sprite->palette(editor->frame()), |             rgbmap, sprite->palette(editor->frame()), | ||||||
|             false, 0)); |             false, 0)); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | @ -744,7 +744,7 @@ void DocExporter::renderTexture(Context* ctx, const Samples& samples, Image* tex | ||||||
|         sample.sprite(), |         sample.sprite(), | ||||||
|         textureImage->pixelFormat(), |         textureImage->pixelFormat(), | ||||||
|         render::DitheringAlgorithm::None, |         render::DitheringAlgorithm::None, | ||||||
|         render::DitheringMatrix(), |         render::DitheringMatrix(), 1.0, | ||||||
|         nullptr)                // TODO add a delegate to show progress
 |         nullptr)                // TODO add a delegate to show progress
 | ||||||
|         .execute(ctx); |         .execute(ctx); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -746,7 +746,7 @@ private: | ||||||
|         render::convert_pixel_format |         render::convert_pixel_format | ||||||
|         (oldImage, NULL, IMAGE_RGB, |         (oldImage, NULL, IMAGE_RGB, | ||||||
|          render::DitheringAlgorithm::None, |          render::DitheringAlgorithm::None, | ||||||
|          render::DitheringMatrix(), |          render::DitheringMatrix(), 1.0, | ||||||
|          nullptr, |          nullptr, | ||||||
|          m_sprite->palette(cel->frame()), |          m_sprite->palette(cel->frame()), | ||||||
|          m_opaque, |          m_opaque, | ||||||
|  | @ -759,7 +759,7 @@ private: | ||||||
|       render::convert_pixel_format |       render::convert_pixel_format | ||||||
|       (m_currentImage.get(), NULL, IMAGE_RGB, |       (m_currentImage.get(), NULL, IMAGE_RGB, | ||||||
|        render::DitheringAlgorithm::None, |        render::DitheringAlgorithm::None, | ||||||
|        render::DitheringMatrix(), |        render::DitheringMatrix(), 1.0, | ||||||
|        nullptr, |        nullptr, | ||||||
|        m_sprite->palette(m_frameNum), |        m_sprite->palette(m_frameNum), | ||||||
|        m_opaque, |        m_opaque, | ||||||
|  | @ -769,7 +769,7 @@ private: | ||||||
|       render::convert_pixel_format |       render::convert_pixel_format | ||||||
|       (m_previousImage.get(), NULL, IMAGE_RGB, |       (m_previousImage.get(), NULL, IMAGE_RGB, | ||||||
|        render::DitheringAlgorithm::None, |        render::DitheringAlgorithm::None, | ||||||
|        render::DitheringMatrix(), |        render::DitheringMatrix(), 1.0, | ||||||
|        nullptr, |        nullptr, | ||||||
|        m_sprite->palette(MAX(0, m_frameNum-1)), |        m_sprite->palette(MAX(0, m_frameNum-1)), | ||||||
|        m_opaque, |        m_opaque, | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
|  | // Copyright (C) 2019  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2017  David Capello
 | // Copyright (C) 2017  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -101,7 +102,8 @@ private: | ||||||
|       doc::clear_image(image2.get(), 0); |       doc::clear_image(image2.get(), 0); | ||||||
|       render::convert_pixel_format( |       render::convert_pixel_format( | ||||||
|         image1.get(), image2.get(), IMAGE_INDEXED, |         image1.get(), image2.get(), IMAGE_INDEXED, | ||||||
|         m_algo, m_matrix, nullptr, palette, true, -1, nullptr); |         m_algo, m_matrix, 1.0, | ||||||
|  |         nullptr, palette, true, -1, nullptr); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     m_preview = os::instance()->createRgbaSurface(w, h); |     m_preview = os::instance()->createRgbaSurface(w, h); | ||||||
|  |  | ||||||
|  | @ -367,7 +367,7 @@ void paste() | ||||||
|           render::convert_pixel_format( |           render::convert_pixel_format( | ||||||
|             clipboard_image.get(), NULL, dstSpr->pixelFormat(), |             clipboard_image.get(), NULL, dstSpr->pixelFormat(), | ||||||
|             render::DitheringAlgorithm::None, |             render::DitheringAlgorithm::None, | ||||||
|             render::DitheringMatrix(), |             render::DitheringMatrix(), 1.0, | ||||||
|             dst_rgbmap, clipboard_palette.get(), |             dst_rgbmap, clipboard_palette.get(), | ||||||
|             false, |             false, | ||||||
|             0)); |             0)); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Aseprite
 | // Aseprite
 | ||||||
|  | // Copyright (C) 2019  Igara Studio S.A.
 | ||||||
| // Copyright (C) 2001-2018  David Capello
 | // Copyright (C) 2001-2018  David Capello
 | ||||||
| //
 | //
 | ||||||
| // This program is distributed under the terms of
 | // This program is distributed under the terms of
 | ||||||
|  | @ -54,7 +55,7 @@ Cel* create_cel_copy(const Cel* srcCel, | ||||||
|       tmpImage.get(), |       tmpImage.get(), | ||||||
|       IMAGE_RGB, |       IMAGE_RGB, | ||||||
|       render::DitheringAlgorithm::None, |       render::DitheringAlgorithm::None, | ||||||
|       render::DitheringMatrix(), |       render::DitheringMatrix(), 1.0, | ||||||
|       srcCel->sprite()->rgbMap(srcCel->frame()), |       srcCel->sprite()->rgbMap(srcCel->frame()), | ||||||
|       srcCel->sprite()->palette(srcCel->frame()), |       srcCel->sprite()->palette(srcCel->frame()), | ||||||
|       srcCel->layer()->isBackground(), |       srcCel->layer()->isBackground(), | ||||||
|  | @ -65,7 +66,7 @@ Cel* create_cel_copy(const Cel* srcCel, | ||||||
|       dstCel->image(), |       dstCel->image(), | ||||||
|       IMAGE_INDEXED, |       IMAGE_INDEXED, | ||||||
|       render::DitheringAlgorithm::None, |       render::DitheringAlgorithm::None, | ||||||
|       render::DitheringMatrix(), |       render::DitheringMatrix(), 1.0, | ||||||
|       dstSprite->rgbMap(dstFrame), |       dstSprite->rgbMap(dstFrame), | ||||||
|       dstSprite->palette(dstFrame), |       dstSprite->palette(dstFrame), | ||||||
|       srcCel->layer()->isBackground(), |       srcCel->layer()->isBackground(), | ||||||
|  |  | ||||||
|  | @ -25,13 +25,15 @@ ErrorDiffusionDither::ErrorDiffusionDither(int transparentIndex) | ||||||
| 
 | 
 | ||||||
| void ErrorDiffusionDither::start( | void ErrorDiffusionDither::start( | ||||||
|   const doc::Image* srcImage, |   const doc::Image* srcImage, | ||||||
|   doc::Image* dstImage) |   doc::Image* dstImage, | ||||||
|  |   const double factor) | ||||||
| { | { | ||||||
|   m_srcImage = srcImage; |   m_srcImage = srcImage; | ||||||
|   m_width = 2+srcImage->width(); |   m_width = 2+srcImage->width(); | ||||||
|   for (int i=0; i<kChannels; ++i) |   for (int i=0; i<kChannels; ++i) | ||||||
|     m_err[i].resize(m_width*2, 0); |     m_err[i].resize(m_width*2, 0); | ||||||
|   m_lastY = -1; |   m_lastY = -1; | ||||||
|  |   m_factor = int(factor * 100.0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ErrorDiffusionDither::finish() | void ErrorDiffusionDither::finish() | ||||||
|  | @ -89,11 +91,11 @@ doc::color_t ErrorDiffusionDither::ditherRgbToIndex2D( | ||||||
|   // TODO using Floyd-Steinberg matrix here but it should be configurable
 |   // TODO using Floyd-Steinberg matrix here but it should be configurable
 | ||||||
|   for (int i=0; i<kChannels; ++i) { |   for (int i=0; i<kChannels; ++i) { | ||||||
|     int* err = &m_err[i][x]; |     int* err = &m_err[i][x]; | ||||||
| 
 |     const int q = quantError[i] * m_factor / 100; | ||||||
|     const int a = quantError[i] * 7 / 16; |     const int a = q * 7 / 16; | ||||||
|     const int b = quantError[i] * 3 / 16; |     const int b = q * 3 / 16; | ||||||
|     const int c = quantError[i] * 5 / 16; |     const int c = q * 5 / 16; | ||||||
|     const int d = quantError[i] * 1 / 16; |     const int d = q * 1 / 16; | ||||||
| 
 | 
 | ||||||
|     if (y & 1) { |     if (y & 1) { | ||||||
|       err[0        ] += a; |       err[0        ] += a; | ||||||
|  |  | ||||||
|  | @ -23,7 +23,8 @@ namespace render { | ||||||
|     bool zigZag() const override { return true; } |     bool zigZag() const override { return true; } | ||||||
|     void start( |     void start( | ||||||
|       const doc::Image* srcImage, |       const doc::Image* srcImage, | ||||||
|       doc::Image* dstImage) override; |       doc::Image* dstImage, | ||||||
|  |       const double factor) override; | ||||||
|     void finish() override; |     void finish() override; | ||||||
|     doc::color_t ditherRgbToIndex2D( |     doc::color_t ditherRgbToIndex2D( | ||||||
|       const int x, const int y, |       const int x, const int y, | ||||||
|  | @ -35,6 +36,7 @@ namespace render { | ||||||
|     int m_width, m_lastY; |     int m_width, m_lastY; | ||||||
|     static const int kChannels = 4; |     static const int kChannels = 4; | ||||||
|     std::vector<int> m_err[kChannels]; |     std::vector<int> m_err[kChannels]; | ||||||
|  |     int m_factor; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| } // namespace render
 | } // namespace render
 | ||||||
|  |  | ||||||
|  | @ -229,6 +229,7 @@ doc::color_t OrderedDither2::ditherRgbPixelToIndex( | ||||||
| void dither_rgb_image_to_indexed( | void dither_rgb_image_to_indexed( | ||||||
|   DitheringAlgorithmBase& algorithm, |   DitheringAlgorithmBase& algorithm, | ||||||
|   const DitheringMatrix& matrix, |   const DitheringMatrix& matrix, | ||||||
|  |   const double factor, | ||||||
|   const doc::Image* srcImage, |   const doc::Image* srcImage, | ||||||
|   doc::Image* dstImage, |   doc::Image* dstImage, | ||||||
|   const doc::RgbMap* rgbmap, |   const doc::RgbMap* rgbmap, | ||||||
|  | @ -238,7 +239,7 @@ void dither_rgb_image_to_indexed( | ||||||
|   const int w = srcImage->width(); |   const int w = srcImage->width(); | ||||||
|   const int h = srcImage->height(); |   const int h = srcImage->height(); | ||||||
| 
 | 
 | ||||||
|   algorithm.start(srcImage, dstImage); |   algorithm.start(srcImage, dstImage, factor); | ||||||
| 
 | 
 | ||||||
|   if (algorithm.dimensions() == 1) { |   if (algorithm.dimensions() == 1) { | ||||||
|     const doc::LockImageBits<doc::RgbTraits> srcBits(srcImage); |     const doc::LockImageBits<doc::RgbTraits> srcBits(srcImage); | ||||||
|  |  | ||||||
|  | @ -29,7 +29,8 @@ namespace render { | ||||||
| 
 | 
 | ||||||
|     virtual void start( |     virtual void start( | ||||||
|       const doc::Image* srcImage, |       const doc::Image* srcImage, | ||||||
|       doc::Image* dstImage) { } |       doc::Image* dstImage, | ||||||
|  |       const double factor) { } | ||||||
| 
 | 
 | ||||||
|     virtual void finish() { } |     virtual void finish() { } | ||||||
| 
 | 
 | ||||||
|  | @ -77,6 +78,7 @@ namespace render { | ||||||
|   void dither_rgb_image_to_indexed( |   void dither_rgb_image_to_indexed( | ||||||
|     DitheringAlgorithmBase& algorithm, |     DitheringAlgorithmBase& algorithm, | ||||||
|     const DitheringMatrix& matrix, |     const DitheringMatrix& matrix, | ||||||
|  |     const double factor, | ||||||
|     const doc::Image* srcImage, |     const doc::Image* srcImage, | ||||||
|     doc::Image* dstImage, |     doc::Image* dstImage, | ||||||
|     const doc::RgbMap* rgbmap, |     const doc::RgbMap* rgbmap, | ||||||
|  |  | ||||||
|  | @ -86,6 +86,7 @@ Image* convert_pixel_format( | ||||||
|   PixelFormat pixelFormat, |   PixelFormat pixelFormat, | ||||||
|   DitheringAlgorithm ditheringAlgorithm, |   DitheringAlgorithm ditheringAlgorithm, | ||||||
|   const DitheringMatrix& ditheringMatrix, |   const DitheringMatrix& ditheringMatrix, | ||||||
|  |   const double ditheringFactor, | ||||||
|   const RgbMap* rgbmap, |   const RgbMap* rgbmap, | ||||||
|   const Palette* palette, |   const Palette* palette, | ||||||
|   bool is_background, |   bool is_background, | ||||||
|  | @ -114,7 +115,8 @@ Image* convert_pixel_format( | ||||||
|     } |     } | ||||||
|     if (dither) |     if (dither) | ||||||
|       dither_rgb_image_to_indexed( |       dither_rgb_image_to_indexed( | ||||||
|         *dither, ditheringMatrix, image, new_image, rgbmap, palette, delegate); |         *dither, ditheringMatrix, ditheringFactor, | ||||||
|  |         image, new_image, rgbmap, palette, delegate); | ||||||
|     return new_image; |     return new_image; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -55,6 +55,7 @@ namespace render { | ||||||
|     doc::PixelFormat pixelFormat, |     doc::PixelFormat pixelFormat, | ||||||
|     render::DitheringAlgorithm ditheringAlgorithm, |     render::DitheringAlgorithm ditheringAlgorithm, | ||||||
|     const render::DitheringMatrix& ditheringMatrix, |     const render::DitheringMatrix& ditheringMatrix, | ||||||
|  |     const double ditheringFactor, | ||||||
|     const doc::RgbMap* rgbmap, |     const doc::RgbMap* rgbmap, | ||||||
|     const doc::Palette* palette, |     const doc::Palette* palette, | ||||||
|     bool is_background, |     bool is_background, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue