A. photoshop可以用来编程序吗
不可以简闭吵,Photoshop只是拦侍态哗图片处理,没有编程的功能。下载地址: http://down.52pk.com/xiazai/751.shtml
B. c++对图像文件进行滤镜处理
给你CDib class, 自己调用,可以读,写 BMP。
滤镜功能只是简单的矩阵变换。读入,变换,写出。
CDib 里的函数,看英文名和里面的注解应当能懂。
头文件:
/歼祥神/ cdib.h declaration for Inside Visual C++ CDib class
#ifndef _INSIDE_VISUAL_CPP_CDIB
#define _INSIDE_VISUAL_CPP_CDIB
class CDib : public CObject
{
enum Alloc {noAlloc, crtAlloc, heapAlloc};
DECLARE_SERIAL(CDib)
public:
LPVOID m_lpvColorTable;
HBITMAP m_hBitmap;
LPBYTE m_lpImage; // starting address of DIB bits
LPBITMAPINFOHEADER m_lpBMIH; //氏亏 buffer containing the BITMAPINFOHEADER
private:
HGLOBAL m_hGlobal; // For external windows we need to free;
//宴烂 could be allocated by this class or allocated externally
Alloc m_nBmihAlloc;
Alloc m_nImageAlloc;
DWORD m_dwSizeImage; // of bits -- not BITMAPINFOHEADER or BITMAPFILEHEADER
int m_nColorTableEntries;
HANDLE m_hFile;
HANDLE m_hMap;
LPVOID m_lpvFile;
HPALETTE m_hPalette;
public:
CDib();
CDib(CSize size, int nBitCount); // builds BITMAPINFOHEADER
~CDib();
int GetSizeImage() {return m_dwSizeImage;}
int GetSizeHeader()
{return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;}
CSize GetDimensions();
BOOL AttachMapFile(const char* strPathname, BOOL bShare = FALSE);
BOOL CopyToMapFile(const char* strPathname);
BOOL AttachMemory(LPVOID lpvMem, BOOL bMustDelete = FALSE, HGLOBAL hGlobal = NULL);
BOOL Draw(CDC* pDC, CPoint origin, CSize size); // until we implemnt CreateDibSection
HBITMAP CreateSection(CDC* pDC = NULL);
UINT UsePalette(CDC* pDC, BOOL bBackground = FALSE);
BOOL MakePalette();
BOOL SetSystemPalette(CDC* pDC);
BOOL Compress(CDC* pDC, BOOL bCompress = TRUE); // FALSE means decompress
HBITMAP CreateBitmap(CDC* pDC);
BOOL Read(CFile* pFile);
BOOL ReadSection(CFile* pFile, CDC* pDC = NULL);
BOOL Write(CFile* pFile);
void Serialize(CArchive& ar);
void Empty();
private:
void DetachMapFile();
void ComputePaletteSize(int nBitCount);
void ComputeMetrics();
};
#endif // _INSIDE_VISUAL_CPP_CDIB
cpp 文件:
// cdib.cpp
// new version for WIN32
#include "stdafx.h"
#include "cdib.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_SERIAL(CDib, CObject, 0);
CDib::CDib()
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
}
CDib::CDib(CSize size, int nBitCount)
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
ComputePaletteSize(nBitCount);
m_lpBMIH = (LPBITMAPINFOHEADER) new
char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries];
m_nBmihAlloc = crtAlloc;
m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
m_lpBMIH->biWidth = size.cx;
m_lpBMIH->biHeight = size.cy;
m_lpBMIH->biPlanes = 1;
m_lpBMIH->biBitCount = nBitCount;
m_lpBMIH->biCompression = BI_RGB;
m_lpBMIH->biSizeImage = 0;
m_lpBMIH->biXPelsPerMeter = 0;
m_lpBMIH->biYPelsPerMeter = 0;
m_lpBMIH->biClrUsed = m_nColorTableEntries;
m_lpBMIH->biClrImportant = m_nColorTableEntries;
ComputeMetrics();
memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries);
m_lpImage = NULL; // no data yet
}
CDib::~CDib()
{
Empty();
}
CSize CDib::GetDimensions()
{
if(m_lpBMIH == NULL) return CSize(0, 0);
return CSize((int) m_lpBMIH->biWidth, (int) m_lpBMIH->biHeight);
}
BOOL CDib::AttachMapFile(const char* strPathname, BOOL bShare) // for reading
{
// if we open the same file twice, Windows treats it as 2 separate files
// doesn't work with rare BMP files where # palette entries > biClrUsed
HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ,
bShare ? FILE_SHARE_READ : 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT(hFile != INVALID_HANDLE_VALUE);
DWORD dwFileSize = ::GetFileSize(hFile, NULL);
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
DWORD dwErr = ::GetLastError();
if(hMap == NULL) {
AfxMessageBox("Empty bitmap file");
return FALSE;
}
LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file
ASSERT(lpvFile != NULL);
if(((LPBITMAPFILEHEADER) lpvFile)->bfType != 0x4d42) {
AfxMessageBox("Invalid bitmap file");
DetachMapFile();
return FALSE;
}
AttachMemory((LPBYTE) lpvFile + sizeof(BITMAPFILEHEADER));
m_lpvFile = lpvFile;
m_hFile = hFile;
m_hMap = hMap;
return TRUE;
}
BOOL CDib::CopyToMapFile(const char* strPathname)
{
// copies DIB to a new file, releases prior pointers
// if you previously used CreateSection, the HBITMAP will be NULL (and unusable)
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; // 'BM'
bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER);
// meaning of bfSize open to interpretation
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries;
HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT(hFile != INVALID_HANDLE_VALUE);
int nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries + m_dwSizeImage;
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL);
DWORD dwErr = ::GetLastError();
ASSERT(hMap != NULL);
LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file
ASSERT(lpvFile != NULL);
LPBYTE lpbCurrent = (LPBYTE) lpvFile;
memcpy(lpbCurrent, &bmfh, sizeof(BITMAPFILEHEADER)); // file header
lpbCurrent += sizeof(BITMAPFILEHEADER);
LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpbCurrent;
memcpy(lpbCurrent, m_lpBMIH,
sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries); // info
lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
memcpy(lpbCurrent, m_lpImage, m_dwSizeImage); // bit image
DWORD dwSizeImage = m_dwSizeImage;
Empty();
m_dwSizeImage = dwSizeImage;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
m_lpBMIH = lpBMIH;
m_lpImage = lpbCurrent;
m_hFile = hFile;
m_hMap = hMap;
m_lpvFile = lpvFile;
ComputePaletteSize(m_lpBMIH->biBitCount);
ComputeMetrics();
MakePalette();
return TRUE;
}
BOOL CDib::AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal)
{
// assumes contiguous BITMAPINFOHEADER, color table, image
// color table could be zero length
Empty();
m_hGlobal = hGlobal;
if(bMustDelete == FALSE) {
m_nBmihAlloc = noAlloc;
}
else {
m_nBmihAlloc = ((hGlobal == NULL) ? crtAlloc : heapAlloc);
}
try {
m_lpBMIH = (LPBITMAPINFOHEADER) lpvMem;
ComputeMetrics();
ComputePaletteSize(m_lpBMIH->biBitCount);
m_lpImage = (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries;
MakePalette();
}
catch(CException* pe) {
AfxMessageBox("AttachMemory error");
pe->Delete();
return FALSE;
}
return TRUE;
}
UINT CDib::UsePalette(CDC* pDC, BOOL bBackground /* = FALSE */)
{
if(m_hPalette == NULL) return 0;
HDC hdc = pDC->GetSafeHdc();
::SelectPalette(hdc, m_hPalette, bBackground);
return ::RealizePalette(hdc);
}
BOOL CDib::Draw(CDC* pDC, CPoint origin, CSize size)
{
if(m_lpBMIH == NULL) return FALSE;
if(m_hPalette != NULL) {
::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
}
pDC->SetStretchBltMode(COLORONCOLOR);
::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
0, 0, m_lpBMIH->biWidth, m_lpBMIH->biHeight,
m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, SRCCOPY);
return TRUE;
}
HBITMAP CDib::CreateSection(CDC* pDC /* = NULL */)
{
if(m_lpBMIH == NULL) return NULL;
if(m_lpImage != NULL) return NULL; // can only do this if image doesn't exist
m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0);
ASSERT(m_lpImage != NULL);
return m_hBitmap;
}
BOOL CDib::MakePalette()
{
// makes a logical palette (m_hPalette) from the DIB's color table
// this palette will be selected and realized prior to drawing the DIB
if(m_nColorTableEntries == 0) return FALSE;
if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
TRACE("CDib::MakePalette -- m_nColorTableEntries = %d\n", m_nColorTableEntries);
LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
m_nColorTableEntries * sizeof(PALETTEENTRY)];
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nColorTableEntries;
LPRGBQUAD pDibQuad = (LPRGBQUAD) m_lpvColorTable;
for(int i = 0; i < m_nColorTableEntries; i++) {
pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
pDibQuad++;
}
m_hPalette = ::CreatePalette(pLogPal);
delete pLogPal;
return TRUE;
}
BOOL CDib::SetSystemPalette(CDC* pDC)
{
// if the DIB doesn't have a color table, we can use the system's halftone palette
if(m_nColorTableEntries != 0) return FALSE;
m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc());
return TRUE;
}
HBITMAP CDib::CreateBitmap(CDC* pDC)
{
if (m_dwSizeImage == 0) return NULL;
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), m_lpBMIH,
CBM_INIT, m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS);
ASSERT(hBitmap != NULL);
return hBitmap;
}
BOOL CDib::Compress(CDC* pDC, BOOL bCompress /* = TRUE */)
{
// 1. makes GDI bitmap from existing DIB
// 2. makes a new DIB from GDI bitmap with compression
// 3. cleans up the original DIB
// 4. puts the new DIB in the object
if((m_lpBMIH->biBitCount != 4) && (m_lpBMIH->biBitCount != 8)) return FALSE;
// compression supported only for 4 bpp and 8 bpp DIBs
if(m_hBitmap) return FALSE; // can't compress a DIB Section!
TRACE("Compress: original palette size = %d\n", m_nColorTableEntries);
HDC hdc = pDC->GetSafeHdc();
HPALETTE hOldPalette = ::SelectPalette(hdc, m_hPalette, FALSE);
HBITMAP hBitmap; // temporary
if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE;
int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
memcpy(lpBMIH, m_lpBMIH, nSize); // new header
if(bCompress) {
switch (lpBMIH->biBitCount) {
case 4:
lpBMIH->biCompression = BI_RLE4;
break;
case 8:
lpBMIH->biCompression = BI_RLE8;
break;
default:
ASSERT(FALSE);
}
// calls GetDIBits with null data pointer to get size of compressed DIB
if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,
NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) {
AfxMessageBox("Unable to compress this DIB");
// probably a problem with the color table
::DeleteObject(hBitmap);
delete [] lpBMIH;
::SelectPalette(hdc, hOldPalette, FALSE);
return FALSE;
}
if (lpBMIH->biSizeImage == 0) {
AfxMessageBox("Driver can't do compression");
::DeleteObject(hBitmap);
delete [] lpBMIH;
::SelectPalette(hdc, hOldPalette, FALSE);
return FALSE;
}
else {
m_dwSizeImage = lpBMIH->biSizeImage;
}
}
else {
lpBMIH->biCompression = BI_RGB; // decompress
// figure the image size from the bitmap width and height
DWORD dwBytes = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32;
if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
m_dwSizeImage = dwBytes * lpBMIH->biHeight; // no compression
lpBMIH->biSizeImage = m_dwSizeImage;
}
// second GetDIBits call to make DIB
LPBYTE lpImage = (LPBYTE) new char[m_dwSizeImage];
VERIFY(::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,
lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS));
TRACE("dib successfully created - height = %d\n", lpBMIH->biHeight);
::DeleteObject(hBitmap);
Empty();
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
m_lpBMIH = lpBMIH;
m_lpImage = lpImage;
ComputeMetrics();
ComputePaletteSize(m_lpBMIH->biBitCount);
MakePalette();
::SelectPalette(hdc, hOldPalette, FALSE);
TRACE("Compress: new palette size = %d\n", m_nColorTableEntries);
return TRUE;
}
BOOL CDib::Read(CFile* pFile)
{
// 1. read file header to get size of info hdr + color table
// 2. read info hdr (to get image size) and color table
// 3. read image
// can't use bfSize in file header
Empty();
int nCount, nSize;
BITMAPFILEHEADER bmfh;
try {
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
if(bmfh.bfType != 0x4d42) {
throw new CException;
}
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
nCount = pFile->Read(m_lpBMIH, nSize); // info hdr & color table
ComputeMetrics();
ComputePaletteSize(m_lpBMIH->biBitCount);
MakePalette();
m_lpImage = (LPBYTE) new char[m_dwSizeImage];
nCount = pFile->Read(m_lpImage, m_dwSizeImage); // image only
}
catch(CException* pe) {
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}
return TRUE;
}
BOOL CDib::ReadSection(CFile* pFile, CDC* pDC /* = NULL */)
{
// new function reads BMP from disk and creates a DIB section
// allows modification of bitmaps from disk
// 1. read file header to get size of info hdr + color table
// 2. read info hdr (to get image size) and color table
// 3. create DIB section based on header parms
// 4. read image into memory that CreateDibSection allocates
Empty();
int nCount, nSize;
BITMAPFILEHEADER bmfh;
try {
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
if(bmfh.bfType != 0x4d42) {
throw new CException;
}
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
m_nBmihAlloc = crtAlloc;
m_nImageAlloc = noAlloc;
nCount = pFile->Read(m_lpBMIH, nSize); // info hdr & color table
if(m_lpBMIH->biCompression != BI_RGB) {
throw new CException;
}
ComputeMetrics();
ComputePaletteSize(m_lpBMIH->biBitCount);
MakePalette();
UsePalette(pDC);
m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0);
ASSERT(m_lpImage != NULL);
nCount = pFile->Read(m_lpImage, m_dwSizeImage); // image only
}
catch(CException* pe) {
AfxMessageBox("ReadSection error");
pe->Delete();
return FALSE;
}
return TRUE;
}
BOOL CDib::Write(CFile* pFile)
{
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; // 'BM'
int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
bmfh.bfSize = 0;
// bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage;
// meaning of bfSize open to interpretation (bytes, words, dwords?) -- we won't use it
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries;
try {
pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
pFile->Write((LPVOID) m_lpBMIH, nSizeHdr);
pFile->Write((LPVOID) m_lpImage, m_dwSizeImage);
}
catch(CException* pe) {
pe->Delete();
AfxMessageBox("write error");
return FALSE;
}
return TRUE;
}
void CDib::Serialize(CArchive& ar)
{
DWORD dwPos;
dwPos = ar.GetFile()->GetPosition();
TRACE("CDib::Serialize -- pos = %d\n", dwPos);
ar.Flush();
dwPos = ar.GetFile()->GetPosition();
TRACE("CDib::Serialize -- pos = %d\n", dwPos);
if(ar.IsStoring()) {
Write(ar.GetFile());
}
else {
Read(ar.GetFile());
}
}
// helper functions
void CDib::ComputePaletteSize(int nBitCount)
{
if((m_lpBMIH == NULL) || (m_lpBMIH->biClrUsed == 0)) {
switch(nBitCount) {
case 1:
m_nColorTableEntries = 2;
break;
case 4:
m_nColorTableEntries = 16;
break;
case 8:
m_nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
m_nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
}
else {
m_nColorTableEntries = m_lpBMIH->biClrUsed;
}
ASSERT((m_nColorTableEntries >= 0) && (m_nColorTableEntries <= 256));
}
void CDib::ComputeMetrics()
{
if(m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
throw new CException;
}
m_dwSizeImage = m_lpBMIH->biSizeImage;
if(m_dwSizeImage == 0) {
DWORD dwBytes = ((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) / 32;
if(((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
m_dwSizeImage = dwBytes * m_lpBMIH->biHeight; // no compression
}
m_lpvColorTable = (LPBYTE) m_lpBMIH + sizeof(BITMAPINFOHEADER);
}
void CDib::Empty()
{
// this is supposed to clean up whatever is in the DIB
DetachMapFile();
if(m_nBmihAlloc == crtAlloc) {
delete [] m_lpBMIH;
}
else if(m_nBmihAlloc == heapAlloc) {
::GlobalUnlock(m_hGlobal);
::GlobalFree(m_hGlobal);
}
if(m_nImageAlloc == crtAlloc) delete [] m_lpImage;
if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap);
m_nBmihAlloc = m_nImageAlloc = noAlloc;
m_hGlobal = NULL;
m_lpBMIH = NULL;
m_lpImage = NULL;
m_lpvColorTable = NULL;
m_nColorTableEntries = 0;
m_dwSizeImage = 0;
m_lpvFile = NULL;
m_hMap = NULL;
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
}
void CDib::DetachMapFile()
{
if(m_hFile == NULL) return;
::UnmapViewOfFile(m_lpvFile);
::CloseHandle(m_hMap);
::CloseHandle(m_hFile);
m_hFile = NULL;
}
C. 编程调用Photoshop滤镜
机器性能如何朋友,CS4对性能和内存要求挺高的。 设置首选项没?photoshop使逗段用内存和记录顷斗这一块山乎誉设置没有?把暂存盘设在系统盘以外的盘试试。方法:编辑>
D. Photoshop中8bf格式的文件怎么制作
一般滤镜都是两个文件吧,一个是8bf文件,还有衫橡一个是对应的.dll文件是放在安装目录主目录下面的。
很多滤镜可以直接保存到相应的文件:Program FilesAdobePhotoshopCS增效工具滤镜里面,这是PSCS 和PS CSII里面的位置 。
第一种 只要将文件拷贝到Photoshop目录下的“Plug-ins”目录就可以了。重新启动Photoshop后,会发现滤镜菜单下已经自动载入了安装的滤镜。7.0以前的版本是在 C:Program FilesAdobePhotoshop7.0Plug-InsCS和CS2是安装在
C:Program FilesAdobePhotoshop CS增效工具滤镜
在photoshop cs里,磨皮滤镜是放在 增效工具/滤镜 里面的,画笔工具是放在 预置/画笔 里面的
在PHOTOSHOP CS2里,磨皮滤镜工具是放在碧塌改Plug-Ins/滤镜 里的,画笔工具是放在 预置/画笔 里面的
在PHOTOSHOP CS3里,磨皮滤镜工具安装的位置和cs版的是同一个地方,画笔也是
CS5也是只要COPY到 Plug-Ins 下面就可以了。
第二种 打开PS,选择编辑-预设-增效工具与暂存盘-附加的增效工具文件-然悔判后连接到你存放滤镜的文件夹,就行了。
E. 新手如何入门编程
首先,入门编程需要一个循序渐进的过程,需要先了解基本的编程语法,从解决基本的数学问题开始,进而展开编程语言的学习。
其次,入门编程要构建一个初步的编程思维。所谓的编程思维就是通过编程语言来解决问题的思路和方式,简单的说就是一个抽象的过程。锻炼编程思罩滚胡维一个最为有效的办法就是完成大量的实验,通过对于实验的不断总结从而形成自己的编程思路。所以,学习编程如果有捷径的话,那么就是不停地做实验。
最后,入门编程需要有一个完整的知识结构,这个知识结构涉及到操作系统、计算机网络、数据库、算法设计和数据结构,在当前的大数据、云计算时代背景下,还需要掌握大数据和云计算的相关知识,尤其是IaaS和PaaS。这些知识完全可以在学习编程语言的过程中同时学习,这些内容的掌握程度对于编程能力会有较大的影响。
最后,目前编程语言比较多,对于基础比较薄弱的初学者来说,可以从python语言开始学起。
推荐教程:北京尚学堂Python400集,内容多并且系统。从入门开始,适合小白上手,有项目,不枯燥。老牌机构讲师,专业并且干货多。在他们的官网上或者B站上都有,可以去看看,评价不错,是我目前看到的最值得推荐的教程。
跟对人,选对书!我是码农阿勇,一个致力于分享编程知识的平台!
编程的话,是一种技能,理论上,和其它技能学习的方式都差不多,以练习为主,但注意的是,编程有个编程思维的东西,你得用这个思维去理解,否则,是入不了门的。
练习编程思维
这种感觉,就像是武侠小说里面的任督二脉,编程思维会了之后,你就开始真正入门了,它就像你的地基,至于其它语言,都是在上面建房子而以。我记得大一刚入门编程时,全班半期考就一个人及格,就是因为编程思维,大家大脑转不过弯。对了,如果你数学基础好,这里是有加分的,如果基础不好也没关系,慢慢的,一边编程,一边也会提高你的数学能力。
现在网络比较发达,资料很多,你可以找几篇编程思维的文章看下,语言不限。
选择一门语言
我是二十年前上的大学,所以当初的入门语言物拦是C语言,如果你不是科班出身,我觉得就不要选C了,科班会教很多语言,我数了下,当年学了有不下七、八种语言,其实用的不多,有些也淘汰了。你可以选择当下最热的语言进行,个人建议Python,学习Python的话,即使你不是做编程工作,它也可以成为你的助手。
当然,如果你对Web开发比较感兴趣,你也可以学习javaScript。
学习的话,可以看书和上网查资料,但对于新手来说,直接看视频是比较好的,基础视频基本是不用钱的,可以上慕课网,搜索些基础视频,一边看视频一边写代码,记住,编程是个工程活,一定要写代码,不写的话,看完就忘。
开始一个项目
语言学会后,不代表你会编程,你可能会写几行代码,或者一些小工具,但要做项目,是需要掌握一个语言生态体系的,而生态体系,又需要找一个方向。
我这边举个Web方向的例子,你想做Web前端开发,你得知道
什么是HTML、CSS、JavaScript
什么是ES6、7等
什么是NPM、Node.js
什么是模块化、什么是组件化、什么是函数式编程
什么是React、什么是Vue等等
当然,这些可以是你做完项目后知道的,也可以是你买本成体系的专业书籍知道的,是的,开始项目后,才开始你的成长之路,这时候,你得开始读书了。如果你不喜欢读书,那真的不适合编程了,编程真正上体现了什么叫做终身学习。
如果你没有比较好的项目,我建议,你如果学习JavsScript的Web方向编程,建议你做个Web版本的ToDO试下,一个比较简单,但是可以涉及很多方面的项目,网上也有很多例子,你可以一边做一边学习。
如果是Python,我建议你先做爬虫类的项目,自己做个电影站之类的工具,爬取一些数据,试验下。
不断的坚持
最后就是不断的坚持了,你会碰到很多问题,这些问题,你一定得去Google和StackOverflow,然后经常翻一翻备袭Github上别人的一些代码,基本上就开始成长之路。
先要了解编程是要干什么。编程,就是让计算机代为解决某个问题,对某个计算体系规定一定的运算方式,使计算体系按照该计算方式运行,并最终得到相应结果的过程。
为了使计算机能够理解人的意图,人类就必须将需解决的问题的思路、方法和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算体系之间交流的过程就是编程。
对于计算机来说,一切不过都是数字。那我们编写代码的目的其实就是告诉计算机两件事,一是有哪些数,二是该怎么算!因此程序的组成也就是两个部分:数和数的组织方式,即数据结构,和运算的逻辑,即算法。而所有的编程语言就是要把这两个部分的内容表达好。
一个完整的编程语言,一般会包含如下内容:数据的声明与类型、运算符与关键词、3大语句(赋值、选择、循环)、数据结构、方法、类等。其中数据的声明与类型、数据结构是用于表达数和数的组织方式;剩余的除了类以外则是表达运算的逻辑;而类是最特殊的,它既包含数据结构又包含运算逻辑。
有了以上对编程语言的整体了解了以后,就是逐个理解掌握相关的知识点。而这些知识点往往是一个拉一个,理解了一个后面那个也就好理解:
一切根源是数。数要分类型->类型,数要存储->变量、常量,数之间有关系->数据结构,数要计算->运算符,数要按照规则计算->3大语句,计算规则要整理出来重复使用->方法,数与方法关系紧密要在一起->类、封装,类与类之间有相似性->继承,继承的各子类有差异->多态,封装、继承、多态搞到一起->面向对象编程
我们要把握这些语言知识点之间的这种脉络,知道他们因何而来,又会往哪里去发展,最重要的是知道它们的出现是为了解决什么问题。
在掌握语言的基础上,还要学习如何运用计算机的资源。计算机资源是由各种平台进行封装,以SDK的形式提供的。编程语言是一种表达的能力,而JDK、androidSDK等SDK则是资源的使用,也就是表达的内容。我们要分清语言与资源的区别,才能最终运用自如。学习其实就是一个学会分类的过程,知道哪是哪,知道分门别类,找起来才不会找错。
在学习编程时往往会遇到一个难题:计算机专业相关的知识点非常多,看起来又高深莫测的样子。要能够掌握而且快速掌握大量的编程知识,我们要有一个干净利落的切入角度。
我们首先要弄清楚一个问题:什么是知识?知识就是解决问题办法的总结。我们接触到的所有知识都是为了解决某个问题才出现的,你知道了那个问题,明白了别人解决问题的思路,这个解决办法也就掌握了。很多同学陷入知识的海洋弄得云里雾里辨不清方向,就是因为不知道这些个知识是干嘛用的,不知道它们是为解决什么问题而出现的。而计算机技术里的很多知识更是这样,为了解决问题而出现,出现就是一大串。你不知道它要解决什么问题,就等着被绕晕吧。所以我们先要把编程中遇到的问题找出来,再理解这个问题是怎么解决的,而这个解决的办法就是所谓的“知识点”。因此要经常发出“灵魂三问”
这种学习的方法叫做“面向问题的学习方法”。用这种学习方法,在学习中接触到新知识的时候,马上意识到这是某种问题的解决办法,并且从问题切入,相信很快就能把新知识理解并加以运用。
最后,也最根本的一条,编程的学习是拿来用的,也只有会用才能真正掌握语言,理解编程相关知识。想学编程的话,可以来看看我发布的零基础学编程课程,学起来既简单又很好玩喔。
传统的教室培训有许多好处,但它不适合持续学习的模式或当今IT人员繁忙的日程安排教室学习有时需要提前几个月安排,具体取决于课程可用性和员工的工作重点而且,固定时间的小组培训课程也不太可能是最适合你学习速度的理想之选课程的许多部分甚至可能与你在企业中的特定职业角色无关随着业务和IT需求的快速变化,你是否能够确保在教室培训结束后马上就能用到课堂上学到的知识?你是否需要在不久的将来刷新一些知识,例如在实施和升级之前或是在解决新出现的业务问题时?一次性教室学习的局限性使其非常不适合今天的许多IT专业人士数字化培训正在迅速普及,因为它非常适合时间紧迫的IT人员,能够满足其持续学习的需求它可以让您只在您需要的时候学习您需要的东西,无需参加整个课程或花时间前往异地按照您自己的节奏,根据需要随时暂停和重复分段按照您自己的时间表,根据您的工作日历将培训分成几天或几周数字化学习的越来越显着的优势在于其地点上的灵活性你可以在自己的书桌前、员工培训室或家庭办公室中舒适地学习也许你经常外出,往返于业务地点或客户项目现场?或者在日常通勤中学习?无论在哪里学习,自考总是不建议的,谁试谁哭
我建议你可以选择一门简单的容易入门的语言python。头条上一搜一大把入门视频。可以帮你快速找到编程的乐趣和感觉。最重要的是建立你的自信心。
有了兴趣和自信以后,如果还想深入和提高。就可以尝试学习数据结构和算法。头条里也有很多视频教程。这样可以帮你步入专业。
之后你可以尝试学习Java或者go。多学一门语言可以让你有不同的体验和认识。
之后你可以尝试学习架构知识,阅读DDIA。我正在分享阅读这本书,挑战的是英文版。你可以到我的主页里看看。
想学编程,首先得选一门编程语言,常见的编程语言有:
c/c++,擅长性能,但是开发效率低
java,性能略差,但是开发效率较高,基础库非常完善,可用框架非常多。
python,性能差,但是开发效率高。常言道,人生苦短,我用Python就是因为这个。
js,主要用在前段,后端可以用但是很少。
php,主要用在后端。
go,主要用在后端,兼顾性能和开发效率。
dart,非常有竞争力的编程语言,flutter框架使用的语言,未来跨平台领域大有可为
Kotlin,goole力挺的替代java开发androidapp的编程语言。
还有很多。
根据自己的需求,选择一门,然后学习基础语法,基本用熟练,然后就可以尝试一些简单的项目了,这个时候一定要多阅读别人的代码,学习别人的数据结构的设计,语法的运用之类的,同时也要自己多动手练习。做出来几个简单项目后,你的自信心会大增,兴趣也会更加盎然。接着就可以尝试稍微复杂点的项目,实现自己设想的一些idea了。
如果你选择在工作中提升,切记:工作可能会让你失去编程的乐趣。但是,记住,这不是编程发生了变化,而是压力、质疑、辛苦等让它失去了乐趣。希望你能坚持下去,终能拨开云雾,进入新的更高的境界。
PS、AI是UI设计师必不可少的两项技能,对于想要学习UI设计的人来说,首先就是要学会使用PS和AI。如何才能快速学会这两样呢?下面,千锋UI设计培训就给大家分享20天学会UI设计(PS+AI)入门教程。
课程介绍
本套课程主要讲解了PS的工具使用,介绍了蒙版,通道,滤镜,图层样式和图层混合模式等的基础和应用案例。重点讲解了AI的基础使用方法,并结合AI软件讲解了如何进行品牌形象设计。
学完课程可以让你熟练使用PS,掌握人像修图,高级抠图,图像合成,海报制作,轻质感图标制作等。熟练使用AI软件,并能掌握logo设计、名片设计、单页、折页、易拉宝等设计,掌握VIS手册的组成及设计制作。
课程目录
第1章PS
1.初识Adobe
2.PS的版本迭代
3.PS入门介绍和用途
04PS界面及工作区介绍
05PS首选项设置
06文件的新建与打开
07文件的存储和格式
08图层的认识
09图层的分类及功能
10PS软件的基本操作
11移动工具的基本使用
12图层的对齐
13图层的分布对齐
14选框工具及选区的加减运算
15选框与填色的综合使用
16选区的羽化
17套索和多边形套索工具
18磁性套索工具
19魔棒工具的使用
20快速选择工具
21选择并遮住-细化毛发
22抠头发
23PS的色彩范围
24裁剪工具
25透视裁剪工具
26切片及切片选择工具
27图框工具
28画笔工具
29画笔面板
30定义画笔预设和载入画笔
31颜色替换工具
32橡皮擦工具
33背景橡皮擦
34魔术橡皮擦工具
35污点修复画笔工具
36修复画笔工具
37修补工具
38内容感知移动工具
39红眼工具
40仿制图章工具
41图案图章工具
42历史记录画笔工具
43渐变工具
44油漆桶工具
45钢笔工具的基础使用
46形状工具的基础使用
47形状工具的应用
48布尔运算应用
49布尔运算应用2
50文字工具
51字符和段落面板
52路径文字
53模糊与锐化工具
54涂抹工具
55加深减淡工具
56海绵工具
57图层蒙版
58剪贴蒙版的应用
59蒙版的应用
60图层蒙版的应用-加倒影
61色相饱和度
62色彩平衡
63可选颜色
64色阶
65曲线
66通道
67通道应用-抠头发
68表面模糊滤镜
69高斯模糊滤镜
70动感模糊滤镜
71径向模糊滤镜
72扭曲-波纹
73扭曲-极坐标
74扭曲-球面化
75风格化-风
76风格化-凸出
77液化
78液化-瘦脸
79高反差保留磨皮
80图层样式(一)
81图层样式(二)
82图层样式(三)
83图层样式(四)
84图层样式(五)
85溶解模式
86去亮、去暗型原理解析
87去亮型应用案例
88去暗型应用
89叠加和柔光模式
90图层混合模式应用(一)
91图层混合模式应用(二)
92什么是AI
93界面分布和功能介绍
94新建文档
95打开文件
96存储文件
97AI的基础操作
98填色与描边
99矩形工具组
100选择工具与直接选择工具
101卡通形象绘制
102魔棒与套索工具
103钢笔工具组
104剪刀与刻刀工具
105文字工具
106直线工具组
107画笔工具组
108旋转与镜像工具
109摩天轮插画制作
110形状生成器
111形状生成器的应用
112形状生成器应用(二)
113实时上色工具
114实时上色工具的应用
115渐变工具
116混合工具
117混合工具的应用
118渐变与混合工具的应用
119路径查找器(一)
120路径查找器(二)
121路径查找器的应用
122AI综合应用-MBE风格图标
123综合应用-logo图标的制作
124综合应用-炫彩字制作
125综合应用-2.5D字体
126综合应用-偏移路径
127综合应用-圆形切图形
128综合应用-剪切蒙版制作纹理背景
129综合应用-网格工具制作渐变背景
130综合应用-符号
131综合应用-飞出的粒子
132综合应用-流光星球
133综合应用-炫彩渐变线条
134AI夜景插画-背景打造
135AI夜景插画-树木制作
136AI夜景插画-树木制作(二)
137AI夜景插画-月亮和萤火虫制作
138AI夜景插画-麋鹿制作
139AI夜景插画-叶子制作
140什么是字体
141字体设计的重要性与方法
142字体的性格
143基础造字法
144矩形造字法
145钢笔造字法
146几何元素法
147笔画减细法
148形象替代法
149笔画的简化
150了解LOGO设计
151LOGO设计创意手法
152首字母创意手法
153首字母创意手法(二)
154具象手法
155徽章设计手法
156徽章设计手法(二)
157名片设计规范
158名片设计排版设计
159名片设计(一)
160名片设计(二)
161名片设计(三)
162名片设计(四)
163什么是DM单页
164DM单页制作规范
165DM单页页头设计
166DM单页排版设计
167DM单页页头设计
168宣传单页设计(二)
169三折页设计规范
170三折页设计(一)
171折页设计(二)
172折页设计(三)
173折页设计(四)
174易拉宝设计规范
175易拉宝设计(一)
176易拉宝设计(二)
177企业VIS
178基础识别系统
179应用设计系统
编程是个很广泛的词吧,编程其实是有很多语言的,如果不看语言的话,大致也可以分为前端与后端(注:其实编程不只是前端和后端,但是新手入门的话,建议还是从前后端会比较容易点,之后就会牵扯到框架等复杂的技术)。前端是指Web页面(网站页面)或app等前端界面,后端就是负责实现前端的功能业务,将前端需要的数据返回给前端显示或做出反应。
新手编程入门可以从这几点出发:
1.知道自己想要做什么编程(前端或后端);
2.知道是前端还是后端之后,还要知道想要先从什么语言入手。前端的话,建议可以先从HTML+CSS入手,后端的话,建议可以从C#入手,这只是本人的建议,并不是绝对的;
3.知道了自己想从哪个语言入手的话,就可以上官网查看文档,看demo,如果还是不明白的话,就可以上网去搜索该语言的入门视频,现在网络教程都是很详细的;
4.编程入门之后就可以尝试去实现下自己想的页面或功能,这会增强自己的信心。
编程语言其实是有共通性的,如果你做到后面的话,就会发现学习其它语言就会快很多了,新手入门,不要急,慢慢来,坚持就会有收获的。
刚开始学习编程语言,要怎么去做,动手编写一个编译器,学习一下较为底层的编程方式,是一种学习计算机到底是如何工作的非常有效方法。编译器通常被看作是十分复杂的工程。事实上,编写一个产品级的编译器也确实是一个庞大的任务。但是写一个小巧可用的编译器却不是这么困难。踏出了编程入门教程第一步,接下去怎么做就全看自己了。可以按照文章所指导的全部做一遍,然后制作一个更加复杂的编译器。需要去写一个更加精巧的语法树来生成汇编代码。接下去的几步分别是:(1)允许返回任意的值(比如,return3;一些可执行代码);(2)添加对“非”的支持(比如,return~1;一些可执行代码)。每一个额外的特性都可以教你关于C语言的更多知识,编译器到底是怎么执行的,以及世界上其他编写编译器的人是如何想的。这是构建babyc的方法。Babyc现在已经拥有了if语句,循环,变量以及最基础的数据结构。下面给大家展示一下国内最权威的.net训练营学习路线图:
F. 怎么用ps/photoshop调出snapseed胶片滤镜效果
工具/原料
photoshop
snapseed-3dlut
方法/步骤
手机修图导出会损伤画质,于是想可不可以把滤镜提取出来在ps里用,答案氏渗是可以的。
其实ps、pr和final cut等调色软件通用的色彩预设文件叫3D LUT,可以记录RGB偏移的函数,所有的调色方案都可以借助3dlut格式保留。 因此我们可以把snapseed中的滤镜通过编程歼瞎脊转化为3dlut文件,这样ps里就可以直接使用了。
3dlut只能记录线性调色,也就是全照片同样权重的改变,比如曝光,对比度,以及色彩。但非线性调整比如暗角、晕影、颗粒是没法记录的。所以我把snapseed里线性调整的滤镜【粗粒胶片】【黑白电影】一共32款全部抽出,去掉颗粒效果,转化为了3dlut文件,和手机滤镜效果完全无差别神裂,大大加速了后期流程。
这是转换好的snapseed滤镜lut文件,提供3dl和cube文件,ps、pr、ae、final cut、达芬奇都可以用
大家关心的效果对比,以下是同一张照片在手机snapseed里加了滤镜,传到电脑上和ps加相同滤镜的lut文件 对比。右下角是ps中套3dlut的效果截图。
5
效果完全无差别,ps里使用也很简单。有问题欢迎咨询,可参考我其他链接:http://jingyan..com/article/335530daed212619cb41c33e.html 最后有获取方式
G. PSCC磨皮滤镜怎么设置成中文
磨皮滤镜设置成中文需要复杂的流程,每个环节都要注意,要细致。
具体方法如做伍逗下:
1、正常下载的滤镜在PS里面是显示英文的,如图:其中Nature Light,显示为英文。
接下来打开CrystalTile2 软件,CrystalTile2在有的系统会提示缺少插件,根据提示进行下载。
如下图:
改完之后放到PS安装目录下Plug-In下,替换即可。此时如果出现多余的小数点【........】,则数清有
几个【........】,再次用CrystalTile2打开,全部替换为空格就可以了。
至此,磨皮滤纯卖镜已经设置成中文。
H. PS中怎么用滤镜把图片分解成色块
你说的是把照片编程一种插画效果颜色是平涂的带有边缘线条象绘画一样 你可以使用很多办法达成上述目的首先你可以使用色调分离这个功能在PHOTOSHOP 图像菜单的 调整下你可以定义一个颜色数目比如 三那么PHOTOSHOP将使用三种颜色的色块氏岩来概括 亮部(通常会变成白色)中间 调子 和暗调子另歼亮御外PHOTOSHOP自带滤镜钟有很多插件可以实现这个效果比如PHOTOCOPY 影印效果另外 一些第三方插件也可以键唯实现比如ALIEN SKIN SNAPARTVirtual Painter 5.0等非常多ALIEN SNAPART 是目前模拟绘画效果最真实 最强大的一款软件效果非常棒你可以下载安装方法是 双击安装 输入用户名 公司信息 和序列号然后指认安装路径为 C:\GRAM FILES\ADOBE\增效工具某些版本没有增效工具文件夹 那么可以安装在C:\GRAM FILES\ADOBE\PLUG INS下安装之后 启动PHOTOSHOP在滤镜菜单下你会看到这个新安装的插件ALIEN SKIN SNAPART回答完毕
I. 求一个C语言图形变换程序,先进行图形绘制,后能进行图形复制、移动、缩放、旋转,跪求啦。。。
从这一部分开始,进入了图形编程的比较烦琐的部分,要真正对图形编程有所了解,这一部分的内容是必须要掌握的。
在计算机绘图过程中,经常需要进行绘图变换,主要包括二维图形变换和三维图形变换。这一部分讨论二维图形变换,其内容有用户坐标到屏幕坐标的变换、图形的比例变换、对称变换、错切变换、旋转变换、平移变换和复合变换等。后面讲到了二维剪裁,即线段裁剪与多边形裁剪。
第一节 用户坐标到屏幕坐标变换
假设纸上有一个图形,要用计算机把它在屏幕上画出来。那么首先遇到的问题是,纸上的图形采用的坐标是实数域域中的直角坐标系或是极坐标系,统称为用户坐标系。而屏幕上采用的坐标系是整数域中直角坐标系,这类坐标系统称为设备坐标系。因此用户坐标系中图形需要经过变换才能绘制在屏幕上,显然这个变换的内容包括: 1)将用户坐标系中任意范围区域转换到屏幕某个范围区域,从而用户坐标系此范围区域内的图形也转换到屏幕上该范围区域内。 2)用户坐标系此区域内图形上的坐标值转换到屏幕上该范围区域内后不一定是整数,取整后才成为该范围区域内的屏幕坐标值。 3)用户坐标右手系到屏幕坐标左手系的坐标轴方向变换。 4)当屏幕坐标系水平方向与垂直方向刻度不等(即像素间距不等)时,为保持图形不敏穗走样,还要进行比例变换。下面介绍这些内容的具体计算问题。
1.窗口到视隐逗口的变换
更确切地说,是实际图形到屏幕图形的转换。有时也称为数据规格化。
在用户坐标系中,指定一矩形域以确定要显示(或绘制)的图形部分,这个矩形区域称为窗口。在屏幕上可任选一矩形域以显示(或绘制)窗口内的图形,该域称为视口。如图2-1所示。
一般视窗口的四条边界分别为:
左边界 x=x1、右边界 x=x2.下边界 y=y1,上边界y=y2。
视口的四条边界分别为:
左边界sx=sx1,右边界sx=sx2,上边界sy=sy1,下边界sy=sy2。
经变换后应有,窗口的上边界线段(或下边界线段)长x2-x1变换成视口上边界线段(或下边界线段)长sx2-sx1。设其比例变换因子为k1,则可得
k1*(x2-x1)=sx2-sx1
k1=(sx2-sx1)/(x2-x1)
对窗口内任一x坐标(x1<=x<=x2)变换后为视口内水平方向sx坐标(sx1<=sx<=sx2)。由上述有:
k1*(x-x1)=sx-sx1
sx=sx1+k1*(x-x1)
=sx1+(x-x1)*(sx2-sx1)/(x2-x1)
同样,经变换后窗灶拿卖口的左边界线段(或右边界线段)长y2-y1变换成视口左边界线段(或右边界线段)长sy2-sy1。设其比例变换因子为k2,则可得
k2*(y2-y1)=sy2-sy1
k2=(sy2-sy1)/(y2-y1)
对窗口内任一y坐标(y1<=y<=y2)变换后为视口内垂直sy坐标(sy1<=sy<=sy2),应有
k2*(y-y1)=sy-sy1
sy=sy1+k2*(y-y1)
=sy1+(y-y1)*(sy2-sy1)/(y2-y1)
于是对窗口内图形上任一点坐标(x,y)变换到屏幕上视口内成为(sx,sy),则
sx=sx1+(x-x1)*(sx2-sx1)/(x2-x1)
sy=sy1+(y-y1)*(sy2-sy1)/(y2-y1)
写成简式
sx=k1*x+a
sy=k2*y+b
这里
a=sx1-k1*x1
b-sy1-k2*y1
k1=(sx2-sx1)/(x2-x1)
k2=(sy2-sy1)/(y2-y1)
2. 实型值到整型值的变换
上面对窗口内图形上任一点坐标(x,y)变换到屏幕上视口内成为(sx,sy),
sx=k1*x+a
sy=k2*y+b k1,k2,a,b同上
这样计算出来的sx,sy一般是实型值,而屏幕上视口内屏幕坐标是整型值,因此要将sx,sy实型值转换成屏幕坐标系的整型值。这可以通过四舍五入的方法将实型值的绝对值圆整化。由于C语言中已经替我们想到了这点,它提供的函数可以自动取整,因此用户在调用标准函数在屏幕上绘图时一般不需要考虑这个问题。当然也可以用赋值的类型转换规则来实现实型值到整型值的变换。
3. y坐标值方向变换
一般屏幕坐标系是直角左手系,y轴方向向下为正,原点在屏幕的左上角,如图2-2所示。
窗口内图形上任一点(x,y)变换到视口内成为(sx,xy),而(x,y)是相对用户坐标系(直角右手系)的。(sx,sy)是相对屏幕坐标系(直角左手系)的,因此y轴方向相反。为使窗口内图形变换到视口上图形其形状一致,需将视口上图形y轴方向变换成窗口内图形y轴方向。这只要将求得的视口内各点的sy整型坐标均用sy2去减,即sy2-sy(整型)代替sy(整型)即可,经这样的坐标轴方向变换后得到的视口内图形与窗口内图形一致。
4.长宽比例变换
屏幕坐标系x方向与y方向上的刻度可能不一样,这取决于水平方向像素间距与垂直方向偈素间距大小是否一致。如果两个方向的刻度不相等,那么用户坐标系下一个正方形将显示(或绘制)成为一个长方形有,一个圆将成为一个椭圆。
为保持原图形的长宽比。使图形显示(或绘制)后不走样,需求出屏幕上两侍标轴刻度的比值(即纵横比)。可以用函数getaspectratio()(见前文所述)返回x方向和y方向的比例数,从而求得这个比值。再瘵原图形y方向坐标乘以该比值,这样显示(或绘制)出来的图形应不走样。若不考虑图形的走样,就不必作这个变换。
第二节 二维几何变换
图形的几何变换一般是指对图形的几何信息经过变换后产生新的图形,图形几何变换既可以看作是坐标系不动而图形变动,变动后的图形在坐标系中的坐标值发生变化;出可以看作图形不动而坐标系变动,变动后的图形在新坐标系下具有新的坐标值。这两种情况本质上都是一样的,都是图形由新的坐标值表示,因此是新产生的图形。图形几何变换包括比例变换、对称变换、错切变换、旋转变换、平移变换及其复合变换。图形上所有的点在几何变换前后的坐标关系一般用解析几何方法可以求得,但这些几何关系用矩阵方法表示,运算更为方便。
一、基本变换
图形基本几何变换是指比例变换、对称变换、错切变换、旋转变换和平移变换等。除平移变换外,这里其它四种几何变换都可以用组成图形的点向量(或称1×2阶矩阵)和2×2阶变换矩阵相乘表示,而平移变换需引入新方法来实现。
1、比例变换
设图形上一点P(x,y),经比例变换后成为新的菜上一点P'(x',y'),即有
x'=a*x
y'=d*y
式中a,d为比例因子
将此比例变换式写成矩阵式得
a 0
[x' y']=[x y] = [x y] * T
0 d
a 0
这里 T= 叫做比例变换矩阵。若a=d,则x,y坐标按同一比例变换。
0 d
当a=d>1时,图形放大;当0<a=d<1时,图形缩小。
若a≠d,则x,y坐标按各自不同比例变换。
3 0
例 1: 设有比例变换矩阵 T= , 三角形abc经过比例变换成为三角形a'b'c'。
0 1
如图2-3所示。
3 0
a [1 2] = [3 2] a'
0 1
3 0
b [2 2] = [6 2] b'
0 1
3 0
c [2 3] = [6 3] c'
0 1
2. 对称变换
图形上一点P(x,y)经关于原点对称变换后成为新图形上一点P'(x',y'),则
x' = -x
y' = -y
写成矩阵形式成为
-1 0
[x' y'] = [x y] = [x y] * T
0 -1
-1 0
这里 T = 为关于原点对称变换矩阵。
0 -1
若关于x轴对称,则对称变换的矩阵表示为
1 0
[x' y'] = [x y] = [x y] * T
0 -1
1 0
于是关于x轴对称变换矩阵 T =
0 -1
若关于y轴对称,则对称变换的矩阵表示为
-1 0
[x' y'] = [x y] = [x y] * T
0 1
-1 0
于是关于y轴对称变换矩阵 T =
0 1
若关于直线y = -x对称,则对称变换矩阵表示为
0 -1
[x' y'] = [x y] = [x y] * T
-1 0
0 1
于是关于直线 y = x对称变换矩阵 T =
1 0
各种对称变换的图形均可由实例程序绘出,参见实例程序图形。
3. 错切变换
对图形的任一点P(x,y),作线性变换如下
x' = x + by
y' = y + dx
式中b,d为不全为零的常 数,点P'(x',y')为新图形上相应的点,这个变换称为图形的错切变换。
错切变换的矩阵表示为
1 d
[x' y'] = [x y] = [x y] * T
b 1
1 d
T = 叫做错切变换矩阵(b,d不全为零)。
b 1
① 当d=0时,x'=x+by,y'=y,这时图形的y坐标不变,x坐标值随(x,y)及系数b作线性变化。若b>0时,图形沿x轴作错切位移;若b<0,图形沿x轴负向作错切位移。
② 当b=0时,x'=x,y'=dx+y,此时图形的x坐标不变y坐标随(x,y)及系数d作线性变化。如d>0,图形沿y轴正向作错切位移;如d<0,图形沿y轴负向作错切位移。
③ 当b≠0且d≠0时,x'=x+by,y'=y+dx,图形沿x,y两个方向作错切位移。
1 2
例 2: 设有错切变换 矩阵 T = ,正方形abcd经此错切变换成为四边形a'b'c'd',
0 1
如图2-4所示。
1 2
a [0 0] = [0 0] a'
0 1
1 2
b [1 0] = [1 2] b'
0 1
1 2
c [1 1] = [1 3] c'
0 1
1 2
d [0 1] = [0 1] d'
0 1
4. 旋转变换
设图形上一点P(x,y)绕原点逆时针旋转θ角后成为新的图形上一点P'(x',y'),则由解析几何方法可得
x' = xcosθ + ysinθ
y' = -xsinθ + ycosθ
用矩阵表示为
cosθ -sinθ
[x' y'] = [x y] = [x y] * T
sinθ cosθ
cosθ -sinθ
这里 T = 为绕原点逆时针变换矩阵。若顺时针旋转时,θ角为负值。
sinθ cosθ
5. 平移变换
若图形上一点P(x,y)沿x轴平移 l距离,沿y轴平移m距离后成为新的图形上一点P'(x',y'),则有
x' = x + l
y' = y + m
式中l,m不全为零,这称为平移变换。但此变换无法用组成图形的点向量和2×2阶变换矩阵相乘来实现。
用二维点向量和2×2阶矩阵相乘不能表示图形的平移变换,那么自然会想到用三维点向量和3×3阶矩阵相乘来实现图形的平移变换。因此对图形上二个坐标的点向量需要添加一个坐标,使之成为三维点向量以便与三阶矩阵相乘,进而实现用矩阵表示平移变换。实际上就是对上面的二个坐标变换式添加第三个坐标变换式,即成为
x' = x + l
y' = y + m
k = k
这第三个坐标变换式(即k=k)必须是恒等式,因为不需作变换,本质上是为了进行矩阵运算而引入的。
将此三个变换式(仍然是图形的平移变换,不妨将k = k取成1=1)写成矩阵得
1 0 0
[x' y' l] = [x y l] 0 1 0 = [x y 1] * T
l m 1
1 0 0
显然 T = 0 1 0 为图形的平移变换矩阵。
l m 1
这里通过对原图形上二维点向量引进第三个坐标成为三维点向量,从而使原图形的平移变换 能用矩阵表示。同样其它基本变换也可以如此用矩阵表示。因此图形的基本变换都可以在这样的三维点向量下统一、整齐用矩阵表示。这样的三维点向量称为齐次点向量,也叫三维齐次坐标点,简称三维齐次坐标。只有在三维齐次坐标下,二维几何变换才都可以用矩阵表示。下面再进一步讨论一下齐次坐标的优点。
引用齐次坐标后,可将上面各种基本变换矩阵统一在一个三阶矩阵中。即
a b 0
T = c d 0
l m 1
式中左上角二阶矩阵实现比例、对称、错切、旋转等变换,左下角1×2阶矩阵实现平移变换,其中a,b,c,d,l,m只要赋以相应的值,并建立图形上点的齐次坐标(即在图形上点的坐标后引入第三个坐标1),这样就可以用图形上点的三维齐次坐标与此三阶矩阵相乘来表示三维图形的基本几何变换了。而变换后,不用考虑第三个坐标1,前面两个坐标就反映了图形的整个变换情况。
用齐次坐标表示一个图形上的点,可以有多种表示,如(6,8,1)、(12,16,2)、(30,40,5)等均表示图形上同一个点(6,8)。这样,齐次坐标可以表示计算机无法容纳的数。例如当计算机的字长为16位时,它能表示的最大整数为216-1=32767。若点坐标为(80 000,40 000),则计算机无法表示。但用齐次坐标可表示为(20 000,10 000,1/4),经过处理后再用第三个坐标支除前面两个坐标,从而得到原来通常的坐标。
齐次坐标优点很多,在计算机绘图中都采用这种表示来处理图形。下面介绍的图形复合几何变换就是如此。
二、复合变换
图形的复合几何变换是指图形作一次以上的基本几何变换,变换结果是每次基本变换矩阵的乘积。图殂的复合几何变换简称复合变换。
1. 复合平移
若对图形首先作平移变换 T1,然后再作平移变换T2,相应的平移变换矩阵分别为
1 0 0
T1 = 0 1 0
l1 m1 1
1 0 0
T2 = 0 1 0
l2 m2 1
则变换结果为复合平移变换T,其复合平移变换矩阵为
T = T1 * T2
1 0 0 1 0 0
= 0 1 0 * 0 1 0
l1 m1 1 l2 m2 1
1 0 0
= 0 1 0
l1+l2 m1|m2 1
J. 如何在android中用CSS滤镜将图片编程灰色的
滤镜效果建议凯拿都使用作激桥图软件来实现
因为用CSS和HTML来实现的话,IE浏明孙猛览器的支持比较好,但其他的如火狐等非IE内核的浏览器支持不够,并且低版本的浏览器很多都不支持的