Skip to content

Commit

Permalink
Fixes the sixel aspect ratio.
Browse files Browse the repository at this point in the history
  • Loading branch information
Utkarsh-khambra committed Sep 23, 2022
1 parent aa3b8e0 commit a586bfb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 34 deletions.
60 changes: 35 additions & 25 deletions src/terminal/SixelParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,16 @@ void SixelParser::leaveState()
case State::RepeatIntroducer: break;

case State::RasterSettings:
if (params_.size() == 4)
if (params_.size() > 1 && params_.size() < 5)
{
auto const pan = params_[0];
auto const pad = params_[1];
auto const xPixels = Width(params_[2]);
auto const yPixels = Height(params_[3]);
events_.setRaster((int) pan, (int) pad, ImageSize { xPixels, yPixels });

auto const imageSize =
params_.size() > 2
? std::optional<ImageSize> { ImageSize { Width(params_[2]), Height(params_[3]) } }
: std::nullopt;
events_.setRaster((int) pan, (int) pad, imageSize);
state_ = State::Ground;
}
break;
Expand Down Expand Up @@ -370,7 +373,8 @@ SixelImageBuilder::SixelImageBuilder(ImageSize _maxSize,
buffer_(maxSize_.area() * 4),
sixelCursor_ {},
currentColor_ { 0 },
aspectRatio_ { _aspectVertical, _aspectHorizontal }
aspectRatio_(std::ceil(static_cast<float>(_aspectVertical) / static_cast<float>(_aspectHorizontal))),
sixelBandHeight_(6 * aspectRatio_)
{
clear(_backgroundColor);
}
Expand Down Expand Up @@ -412,18 +416,15 @@ void SixelImageBuilder::write(CellLocation const& _coord, RGBColor const& _value
size_.width = Width::cast_from(_coord.column + 1);
}

for (auto i = 0; i < aspectRatio_.nominator; ++i)
for (auto i = 0; i < aspectRatio_; ++i)
{
auto const base = unbox<unsigned>(_coord.line + i)
* unbox<unsigned>((explicitSize_ ? size_.width : maxSize_.width)) * 4
+ unbox<unsigned>(_coord.column) * 4;
for (auto j = 0; j < aspectRatio_.denominator; ++j)
{
buffer_[base + 0 + 4 * static_cast<unsigned int>(j)] = _value.red;
buffer_[base + 1 + 4 * static_cast<unsigned int>(j)] = _value.green;
buffer_[base + 2 + 4 * static_cast<unsigned int>(j)] = _value.blue;
buffer_[base + 3 + 4 * static_cast<unsigned int>(j)] = 0xFF;
}
buffer_[base + 0] = _value.red;
buffer_[base + 1] = _value.green;
buffer_[base + 2] = _value.blue;
buffer_[base + 3] = 0xFF;
}
}
}
Expand All @@ -446,19 +447,28 @@ void SixelImageBuilder::rewind()
void SixelImageBuilder::newline()
{
sixelCursor_.column = {};
if (unbox<int>(sixelCursor_.line) + 6 < unbox<int>(explicitSize_ ? size_.height : maxSize_.height))
sixelCursor_.line.value += 6;
if (unbox<int>(sixelCursor_.line) + sixelBandHeight_
< unbox<int>(explicitSize_ ? size_.height : maxSize_.height))
sixelCursor_.line.value += sixelBandHeight_;
}

void SixelImageBuilder::setRaster(int _pan, int _pad, ImageSize _imageSize)
void SixelImageBuilder::setRaster(int _pan, int _pad, std::optional<ImageSize> _imageSize)
{
aspectRatio_.nominator = _pan;
aspectRatio_.denominator = _pad;
size_.width = clamp(_imageSize.width, Width(0), maxSize_.width);
size_.height = clamp(_imageSize.height, Height(0), maxSize_.height);

buffer_.resize(size_.area() * static_cast<size_t>(_pad * _pan) * 4);
explicitSize_ = true;
if (_pad != 0)
{
aspectRatio_ = std::ceil(static_cast<float>(_pan) / static_cast<float>(_pad));
if (aspectRatio_ == 0)
aspectRatio_ = 1;
}
sixelBandHeight_ = 6 * aspectRatio_;
if (_imageSize)
{
_imageSize->height = Height::cast_from(_imageSize->height.value * aspectRatio_);
size_.width = clamp(_imageSize->width, Width(0), maxSize_.width);
size_.height = clamp(_imageSize->height, Height(0), maxSize_.height);
buffer_.resize(size_.area() * 4);
explicitSize_ = true;
}
}

void SixelImageBuilder::render(int8_t _sixel)
Expand All @@ -469,7 +479,7 @@ void SixelImageBuilder::render(int8_t _sixel)
{
for (int i = 0; i < 6; ++i)
{
auto const y = sixelCursor_.line + i;
auto const y = sixelCursor_.line + i * aspectRatio_;
auto const pos = CellLocation { y, x };
auto const pin = 1 << i;
auto const pinned = (_sixel & pin) != 0;
Expand All @@ -484,7 +494,7 @@ void SixelImageBuilder::finalize()
{
if (unbox<int>(size_.height) == 1)
{
size_.height = Height::cast_from(sixelCursor_.line * aspectRatio_.nominator);
size_.height = Height::cast_from(sixelCursor_.line * aspectRatio_);
buffer_.resize(size_.area() * 4);
return;
}
Expand Down
15 changes: 6 additions & 9 deletions src/terminal/SixelParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <array>
#include <memory>
#include <optional>
#include <string_view>
#include <vector>

Expand Down Expand Up @@ -71,7 +72,7 @@ class SixelParser: public ParserExtension

/// Defines the aspect ratio (pan / pad = aspect ratio) and image dimensions in pixels for
/// the upcoming pixel data.
virtual void setRaster(int _pan, int _pad, ImageSize _imageSize) = 0;
virtual void setRaster(int _pan, int _pad, std::optional<ImageSize> _imageSize) = 0;

/// renders a given sixel at the current sixel-cursor position.
virtual void render(int8_t _sixel) = 0;
Expand Down Expand Up @@ -162,8 +163,7 @@ class SixelImageBuilder: public SixelParser::Events

[[nodiscard]] ImageSize maxSize() const noexcept { return maxSize_; }
[[nodiscard]] ImageSize size() const noexcept { return size_; }
[[nodiscard]] int aspectRatioNominator() const noexcept { return aspectRatio_.nominator; }
[[nodiscard]] int aspectRatioDenominator() const noexcept { return aspectRatio_.denominator; }
[[nodiscard]] int aspectRatio() const noexcept { return aspectRatio_; }
[[nodiscard]] RGBColor currentColor() const noexcept { return colors_->at(currentColor_); }

[[nodiscard]] RGBAColor at(CellLocation _coord) const noexcept;
Expand All @@ -177,7 +177,7 @@ class SixelImageBuilder: public SixelParser::Events
void useColor(unsigned _index) override;
void rewind() override;
void newline() override;
void setRaster(int _pan, int _pad, ImageSize _imageSize) override;
void setRaster(int _pan, int _pad, std::optional<ImageSize> _imageSize) override;
void render(int8_t _sixel) override;
void finalize() override;

Expand All @@ -193,12 +193,9 @@ class SixelImageBuilder: public SixelParser::Events
Buffer buffer_; /// RGBA buffer
CellLocation sixelCursor_;
unsigned currentColor_;
struct
{
int nominator;
int denominator;
} aspectRatio_;
bool explicitSize_ = false;
int aspectRatio_;
int sixelBandHeight_;
};

} // namespace terminal

0 comments on commit a586bfb

Please sign in to comment.