📄 picture.cc
字号:
//// Copyright (c) 2003 by Istv醤 V醨adi//// This file is part of dxr3Player, a DVD player written specifically // for the DXR3 (aka Hollywood+) decoder card.// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//------------------------------------------------------------------------------#include "Picture.h"#include "SPUBuffer.h"#include <algorithm>#include <cassert>//------------------------------------------------------------------------------using dvd::spu::Picture;using std::min;using std::max;//------------------------------------------------------------------------------Picture::Picture() : referenceCount(0), data(0), topFieldLength(0), bottomFieldLength(0){}//------------------------------------------------------------------------------Picture::~Picture(){ delete[] data;}//------------------------------------------------------------------------------Picture& Picture::operator=(const Picture& other){ invalidateCompressed(); delete[] data; data = 0; setArea(other.area); memcpy(data, other.data, getWidth()*getHeight()); return *this;}//------------------------------------------------------------------------------void Picture::setArea(const Area& a){ assert(data==0); invalidateCompressed(); area = a; visibleStartX = area.getEndX(); visibleStartY = area.getEndY(); visibleEndX = 0; visibleEndY = 0; size_t size = area.getWidth() * area.getHeight(); data = new unsigned char[size]; for(size_t i = 0; i < size; ++i) { data[i] = 0; }}//------------------------------------------------------------------------------void Picture::setArea(size_t startX, size_t endX, size_t startY, size_t endY){ setArea(Area(startX, endX, startY, endY));}//------------------------------------------------------------------------------void Picture::setArea(SPUBufferBitReader& reader){ size_t startX = reader.readBits(12); size_t endX = reader.readBits(12); size_t startY = reader.readBits(12); size_t endY = reader.readBits(12); setArea(startX, endX, startY, endY);}//------------------------------------------------------------------------------size_t Picture::encode(DynamicBufferBitWriter& writer, size_t& tfl) const{ if (!isValid()) { tfl = 0; return 0; } else { return compress(writer, tfl); }}//------------------------------------------------------------------------------unsigned Picture::decodeVLC(SPUBufferBitReader& reader) const{ unsigned vlc = reader.readBits(4); if (vlc<0x0004) { vlc = (vlc<<4) | reader.readBits(4); if (vlc<0x0010) { vlc = (vlc<<4) | reader.readBits(4); if (vlc<0x0040) { vlc = (vlc<<4) | reader.readBits(4); } } } return vlc;}//------------------------------------------------------------------------------void Picture::decodeField(SPUBufferBitReader& reader, size_t line, unsigned contrast){ invalidateCompressed(); size_t width = getWidth(); size_t height = getHeight(); unsigned char* dataLine = data + line * width; while(line<height) { size_t column = 0; unsigned char* pixel = dataLine; while(column<width) { unsigned vlc = decodeVLC(reader); unsigned len = vlc>>2; if (len==0) len = width-column; unsigned color = vlc&0x03; if (column<visibleStartX || (column+len)>(visibleEndX+1) || line<visibleStartY || line>visibleEndY) { unsigned colorContrast = ((contrast)>>(4*color))&0x0f; if (colorContrast>0) { visibleStartX = min(column, visibleStartX); visibleEndX = max(column+len-1, visibleEndX); visibleStartY = min(line, visibleStartY); visibleEndY = max(line, visibleStartX); } } memset(pixel, color, len); pixel += len; column += len; } reader.discardCurrentByte(); line+=2; dataLine += width*2; }}//------------------------------------------------------------------------------void Picture::invalidateCompressed(){ compressedData.reset(); topFieldLength = bottomFieldLength = 0;}//------------------------------------------------------------------------------void Picture::compress(){ if (topFieldLength>0 || bottomFieldLength>0) return; DynamicBufferBitWriter writer; writer.setBuffer(compressedData); compressField(writer, 0); topFieldLength = writer.getOffset(); compressField(writer, 1); bottomFieldLength = writer.getOffset() - topFieldLength;}//------------------------------------------------------------------------------size_t Picture::compress(DynamicBufferBitWriter& writer, size_t& tfl) const{ size_t offset0 = writer.getOffset(); compressField(writer, 0); tfl = writer.getOffset() - offset0; compressField(writer, 1); return writer.getOffset() - offset0;}//------------------------------------------------------------------------------void Picture::compressField(DynamicBufferBitWriter& writer, size_t line) const{ size_t height = getHeight(); while(line<height) { compressLine(writer, line); line+=2; }}//------------------------------------------------------------------------------void Picture::compressLine(DynamicBufferBitWriter& writer, size_t line) const{ size_t width = getWidth(); unsigned previousColor = 0; size_t previousLength = 0; for(size_t x = 0; x<width; ++x) { unsigned color = getColor(x, line); if (color!=previousColor) { addVLC(writer, previousColor, previousLength); previousColor = color; previousLength = 1; } else ++previousLength; } if (previousLength>63) { addVLCLineEnd(writer, previousColor); } else { addVLC(writer, previousColor, previousLength); } writer.finishCurrentByte();}//------------------------------------------------------------------------------void Picture::addVLC(DynamicBufferBitWriter& writer, unsigned color, size_t length) const{ while(length>0) { size_t partLength = length; if (partLength>255) partLength = 255; if (partLength<=3) { writer.writeBits(partLength, 2); } else if (partLength<=15) { writer.writeBits(0, 2); writer.writeBits(partLength, 4); } else if (partLength<=63) { writer.writeBits(0, 4); writer.writeBits(partLength, 6); } else { writer.writeBits(0, 6); writer.writeBits(partLength, 8); } writer.writeBits(color, 2); length -= partLength; }}//------------------------------------------------------------------------------void Picture::addVLCLineEnd(DynamicBufferBitWriter& writer, unsigned color) const{ writer.writeBits(0, 14); writer.writeBits(color, 2);}//------------------------------------------------------------------------------//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -