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內核的瀏覽器支持不夠,並且低版本的瀏覽器很多都不支持的