/** * Resizes the image so that the resulting sheet has a new size and the image * content is zoomed to fit best into the sheet, while keeping it's aspect ration. * * @param w the new width to resize to * @param h the new height to resize to */ void resize(int w, int h, struct IMAGE* image) { struct IMAGE newimage; int ww; int hh; float wRat; float hRat; if (verbose >= VERBOSE_NORMAL) { printf("resizing %dx%d -> %dx%d\n", image->width, image->height, w, h); } wRat = (float)w / image->width; hRat = (float)h / image->height; if (wRat < hRat) { // horizontally more shrinking/less enlarging is needed: fill width fully, adjust height ww = w; hh = image->height * w / image->width; } else if (hRat < wRat) { ww = image->width * h / image->height; hh = h; } else { // wRat == hRat ww = w; hh = h; } stretch(ww, hh, image); initImage(&newimage, w, h, image->bitdepth, image->color, image->background); centerImage(image, 0, 0, w, h, &newimage); replaceImage(image, &newimage); }
void ExploreFrame::OnReplaceClicked( wxCommandEvent& event ) { const WADArchiveEntry& entry = GetSelectedEntry(); wxFileName entryFN(entry.GetFileName()); wxFileDialog fileDlg(this, wxString::Format(_("Select file to replace %s"), entry.GetFileName()), wxString(), entryFN.GetFullName(), "*." + entryFN.GetExt(), wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST); if (fileDlg.ShowModal() == wxID_OK) { if (entryFN.GetExt().IsSameAs("png", false)) { wxString imgErrors; // Do some sanity checks on the replacement image wxImage replaceImage(fileDlg.GetPath()); if (replaceImage.IsOk()) { if (replaceImage.HasAlpha()) imgErrors += _("- Image may not have an alpha mask\n"); wxMemoryOutputStream oStr; m_archive->Extract(entry, oStr); wxStreamBuffer* buffer = oStr.GetOutputStreamBuffer(); wxMemoryInputStream iStr(buffer->GetBufferStart(), buffer->GetBufferSize()); wxImage orgImage(iStr); if (orgImage.GetSize() != replaceImage.GetSize()) imgErrors += wxString::Format(_("- Image has to be %dx%d in size\n"), orgImage.GetSize().x, orgImage.GetSize().y); if (orgImage.HasMask() != replaceImage.HasMask()) imgErrors += _("- Image must have transparency\n"); } else imgErrors = _("Image could not be loaded"); if (!imgErrors.empty()) { wxMessageDialog msgDlg(this, wxString::Format( _("Image Errors\n\nThe replacement image contains erros which might crash the game\n\n%s\n\nDo you want't to replace anyway?"), imgErrors), _("Warning"), wxICON_WARNING | wxYES_NO | wxNO_DEFAULT); msgDlg.SetYesNoLabels(_("Replace"), _("Don't Replace")); if (msgDlg.ShowModal() != wxID_YES) return; } } size_t index = (size_t) m_fileListCtrl->GetSelection().GetID() - 1; m_archive->ReplaceFiltered(index, fileDlg.GetPath()); static_cast<FileDataModel*>(m_fileListCtrl->GetModel())->RowChanged(index); wxDataViewEvent evt(wxEVT_DATAVIEW_SELECTION_CHANGED); OnFileListSelectionChanged(evt); UpdateTitle(); } }
/** * Shifts the image. * * @param shiftX horizontal shifting * @param shiftY vertical shifting */ void shift(int shiftX, int shiftY, struct IMAGE* image) { struct IMAGE newimage; int x; int y; int pixel; // allocate new buffer's memory initImage(&newimage, image->width, image->height, image->bitdepth, image->color, image->background); for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { pixel = getPixel(x, y, image); setPixel(pixel, x + shiftX, y + shiftY, &newimage); } } replaceImage(image, &newimage); }
/** * Stretches the image so that the resulting image has a new size. * * @param w the new width to stretch to * @param h the new height to stretch to */ void stretch(int w, int h, struct IMAGE* image) { struct IMAGE newimage; int x; int y; int matrixX; int matrixY; int matrixWidth; int matrixHeight; int blockWidth; int blockHeight; int blockWidthRest; int blockHeightRest; int fillIndexWidth; int fillIndexHeight; int fill; int xx; int yy; int sum; int sumR; int sumG; int sumB; int sumCount; int pixel; if (verbose >= VERBOSE_MORE) { printf("stretching %dx%d -> %dx%d\n", image->width, image->height, w, h); } // allocate new buffer's memory initImage(&newimage, w, h, image->bitdepth, image->color, WHITE); blockWidth = image->width / w; // (0 if enlarging, i.e. w > image->width) blockHeight = image->height / h; if (w <= image->width) { blockWidthRest = (image->width) % w; } else { // modulo-operator doesn't work as expected: (3680 % 7360)==3680 ! (not 7360 as expected) // shouldn't always be a % b = b if a < b ? blockWidthRest = w; } if (h <= image->height) { blockHeightRest = (image->height) % h; } else { blockHeightRest = h; } // for each new pixel, get a matrix of pixels from which the new pixel should be derived // (when enlarging, this matrix is always of size 1x1) matrixY = 0; fillIndexHeight = 0; for (y = 0; y < h; y++) { fillIndexWidth = 0; matrixX = 0; if ( ( (y * blockHeightRest) / h ) == fillIndexHeight ) { // next fill index? // (If our optimizer is cool, the above "* blockHeightRest / h" will disappear // when images are enlarged, because in that case blockHeightRest = h has been set before, // thus we're in a Kripke-branch where blockHeightRest and h are the same variable. // No idea if gcc's optimizer does this...) (See again below.) fillIndexHeight++; fill = 1; } else { fill = 0; } matrixHeight = blockHeight + fill; for (x = 0; x < w; x++) { if ( ( (x * blockWidthRest) / w ) == fillIndexWidth ) { // next fill index? fillIndexWidth++; fill = 1; } else { fill = 0; } matrixWidth = blockWidth + fill; // if enlarging, map corrdinates directly if (blockWidth == 0) { // enlarging matrixX = (x * image->width) / w; } if (blockHeight == 0) { // enlarging matrixY = (y * image->height) / h; } // calculate average pixel value in source matrix if ((matrixWidth == 1) && (matrixHeight == 1)) { // optimization: quick version pixel = getPixel(matrixX, matrixY, image); } else { sumCount = 0; if (!image->color) { sum = 0; for (yy = 0; yy < matrixHeight; yy++) { for (xx = 0; xx < matrixWidth; xx++) { sum += getPixelGrayscale(matrixX + xx, matrixY + yy, image); sumCount++; } } sum = sum / sumCount; pixel = pixelGrayscaleValue(sum); } else { // color sumR = 0; sumG = 0; sumB = 0; for (yy = 0; yy < matrixHeight; yy++) { for (xx = 0; xx < matrixWidth; xx++) { pixel = getPixel(matrixX + xx, matrixY + yy, image); sumR += (pixel >> 16) & 0xff; sumG += (pixel >> 8) & 0xff; sumB += pixel & 0xff; //sumR += getPixelComponent(matrixX + xx, matrixY + yy, RED, image); //sumG += getPixelComponent(matrixX + xx, matrixY + yy, GREEN, image); //sumB += getPixelComponent(matrixX + xx, matrixY + yy, BLUE, image); sumCount++; } } pixel = pixelValue( sumR/sumCount, sumG/sumCount, sumB/sumCount ); } } setPixel(pixel, x, y, &newimage); // pixel may have resulted in a gray value, which will be converted to 1-bit // when the file gets saved, if .pbm format requested. black-threshold will apply. if (blockWidth > 0) { // shrinking matrixX += matrixWidth; } } if (blockHeight > 0) { // shrinking matrixY += matrixHeight; } } replaceImage(image, &newimage); }