Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Технологии > Общие вопросы по программированию, компьютерным наукам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 18.12.2017, 22:41   #1
Daniela Daniela
Пользователь
 
Регистрация: 24.11.2017
Сообщений: 11
Репутация: 42
По умолчанию Где ошибка: Изменение размера BMP изображения (язык Си, ВМР, jpeg)

Здравствуйте!
Суть вопроса.
Ознакомиться с вводом и выводом файлов (были лекции и семинар); ознакомиться с форматами BMP, GIF, JPEG, PNG (самостоятельно). Выполнить задания: 1. убрать "шум" с изображения BMP; 2. изменить размер изображения BMP; 3. восстановить JPEG изображения.

Скажу сразу, самостоятельное изучение форматов BMP, GIF, JPEG, PNG малоэффективно: информации , которая действительно помогла бы - минимум, по большей части какие-то общие фразы непонятные "новичкам".

Первое задание с трудом и методом тыка , но сделала.
С вторым заданием полная засада. Руки опускаются.
Третье даже не представляю как делать.

Условие второго задания. Напишите в resize.c под названием resize, которая меняет размер 24-битного несжатого ВМР по коэффициенту n. Ваша программа должна принимать ровно три аргумента командной строки, причем первый (n) должен быть целым числом не более 100, второй - именем файла, который будет изменен, а третий - названием сохраненной версии измененного файла.

Понимаю, что есть заголовки BITMAPFILEHEADER, BITMAPINFOHEADER , RGBTRIPLE (которые могут при необходимости меняться). До сих пор не пойму , почему одни данные даются в байтах, а другие в пикселях и как их приводить к единому в рассчетах?

Мое решение:
1. проверка правильности ввода аргументов
2. чтение заголовков входного файла
рассчеты заголовков и запись в выходной файл
3. чтение входного файла построчно и попиксельно с записью увеличенных значений в выходной файл, учитывая выравнивание и используя изменение текущей позиции во входном файле.
К сожалению, мой вариант не дает результата

Код:

#include <stdio.h>
#include <stdlib.h>

#include "bmp.h"

int main(int argc, char* argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
        printf("Usage: ./resize n infile outfile\n");
        return 1;
    }

    // remember filenames
    int n = atoi(argv[1]);
    char* infile = argv[2];
    char* outfile = argv[3];

    if (n < 0)
    {
        printf("Usage: n is positive\n");
        return 1;
    }

    // open input file
    FILE* inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        printf("Could not open %s.\n", infile);
        return 2;
    }

    // open output file
    FILE* outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
        fclose(inptr);
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 3;
    }

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

    BITMAPFILEHEADER bf1=bf; // bf dla novogo image

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);

    BITMAPINFOHEADER bi1=bi; //bi dla novogo image

    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
    if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
        bi.biBitCount != 24 || bi.biCompression != 0)
    {
        fclose(outptr);
        fclose(inptr);
        fprintf(stderr, "Unsupported file format.\n");
        return 4;
    }

    // izmenenia dla novogo image

    bi1.biHeight = bi.biHeight * n; // uveli4enie visoti
    bi1.biWidth = bi.biWidth * n; // uveli4enie shirini

    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr); // write outfile's BITMAPFILEHEADER
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr); // write outfile's BITMAPINFOHEADER

    int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; // determine padding for scanlines

    int padding1 = (4 - (bi1.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; // viravnivanie v novom image

    bi1.biSizeImage = (bi1.biWidth * sizeof(RGBTRIPLE) + padding1) * abs(bi1.biHeight);
    bf1.bfSize = bi1.biSizeImage + 54;

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        for (int h=0 ; h<n-1 ; h++)
        {
            // iterate over pixels in scanline
            for (int j = 0; j < bi.biWidth; j++)
            {
                RGBTRIPLE triple; // temporary storage

                fread(&triple, sizeof(RGBTRIPLE), 1, inptr); // read RGB triple from infile

                for (int pic = 0 ; pic < n ; pic ++)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); // write RGB triple to outfile
                }
            }
            fseek(inptr, -(bi.biHeight * sizeof(RGBTRIPLE) + padding), SEEK_CUR);
        }

        fseek(inptr, padding, SEEK_CUR);  // skip over padding, if any
        for (int k = 0; k < padding1; k++) // then add it back (to demonstrate how)
            {
                fputc(0x00, outptr);
            }
    }
    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

Прошу помочь и объяснить почему так?
Daniela Daniela вне форума   Ответить с цитированием
Старый 18.12.2017, 22:43   #2
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 15,806
Репутация: 3110

icq: 512-765
skype: alexp.frl
По умолчанию

Цитата:
Сообщение от Daniela Daniela Посмотреть сообщение
почему одни данные даются в байтах, а другие в пикселях
какие?
Alex11223 вне форума   Ответить с цитированием
Старый 19.12.2017, 00:22   #3
Daniela Daniela
Пользователь
 
Регистрация: 24.11.2017
Сообщений: 11
Репутация: 42
По умолчанию

ну, например:
biSizeImage - полный размер изображения в байтах
biWidth - ширина в пикселях
biHeight - высота в пикселях

А почему мой вопрос перенесли из раздела "Помощь студентам"? Мне как раз такая помощь и нужна, потому что сама я не могу найти ошибку в своем коде...
Daniela Daniela вне форума   Ответить с цитированием
Старый 19.12.2017, 00:29   #4
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 15,806
Репутация: 3110

icq: 512-765
skype: alexp.frl
По умолчанию

Дык а в чем еще размеру изображению быть если не в пикселях?
Сколько байтов занимает 1 пиксель вроде зависит от варианта BMP (обычно 3 или 4, или только 4, не помню, ну или наверно можно просто вычислить biSizeImage /(biWidth*biHeight)). В википедии и т.п. посмотрите что там и как. Вообще у BMP нет какого-то единого формата, есть несколько вариантов, в общем бардак (особенно если вдруг понадобится прозрачность)

Цитата:
Сообщение от Daniela Daniela Посмотреть сообщение
А почему мой вопрос перенесли из раздела "Помощь студентам"?
Это в основном помойка для "Помогите спасите решите мою лабу".

Последний раз редактировалось Alex11223; 19.12.2017 в 00:33.
Alex11223 вне форума   Ответить с цитированием
Старый 19.12.2017, 00:58   #5
Daniela Daniela
Пользователь
 
Регистрация: 24.11.2017
Сообщений: 11
Репутация: 42
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Дык а в чем еще размеру изображению быть если не в пикселях?
Сколько байтов занимает 1 пиксель вроде зависит от варианта BMP (обычно 3 или 4, или только 4, не помню, ну или наверно можно просто вычислить biSizeImage /(biWidth*biHeight)). В википедии и т.п. посмотрите что там и как. Вообще у BMP нет какого-то единого формата, есть несколько вариантов, в общем бардак (особенно если вдруг понадобится прозрачность)
Каждый пиксель - 3 байта (по одному на каждый цвет RGB), а размер каждой строки должен быть кратен 4, иначе добавляется выравнивание. По крайней мере это я так поняла.

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Это в основном помойка для "Помогите спасите решите мою лабу".
ой, я как раз из тех, кто роет землю в поисках ответа, а не просит готовое решение.
Хотя в том разделе мне быстро помогли.
Вы вселяете мне надежду на квалифицированную помощь , спасибо!
Daniela Daniela вне форума   Ответить с цитированием
Старый 19.12.2017, 03:24   #6
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 782
Репутация: 570
По умолчанию

Я не совсем понял это решение. Разве не нужно пересчитывать растр, делать какую-то интерполяцию? Но даже если Вы хотите просто обрезать/дополнить растр, это ведь не сделано..

Мой совет: сначала разберитесь с преобразованием растров как матриц, а потом уже прикидывайте, как эту матрицу читать/писать при работе с bmp.
Black Fregat вне форума   Ответить с цитированием
Старый 19.12.2017, 22:29   #7
Daniela Daniela
Пользователь
 
Регистрация: 24.11.2017
Сообщений: 11
Репутация: 42
По умолчанию

Цитата:
Сообщение от Black Fregat Посмотреть сообщение
Разве не нужно пересчитывать растр, делать какую-то интерполяцию?
Именно так. Картинка рассматривается как матрица из пикселей. Посредством цикла из входящего файла считывается линия за линией, пиксель за пикселем ,а потом записывается в выходной файл с учетом коэффициента n.
Код:

for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)//
считываются строки
    {
        for (int h=0 ; h<n-1 ; h++) // это для перемещения из текщей позиции (??? Этот момент вызывает у меня сомнение в правильности местонахождения этого цикла)
        {
            
            for (int j = 0; j < bi.biWidth; j++)// перебирается пиксель за пикселем
            {
                RGBTRIPLE triple; 

                fread(&triple, sizeof(RGBTRIPLE), 1, inptr); // read RGB triple from infile

                for (int pic = 0 ; pic < n ; pic ++) //увеличивается количество каждого пикселя в n раз и записывается в выходной файл
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);                }
            }
            fseek(inptr, -(bi.biHeight * sizeof(RGBTRIPLE) + padding), SEEK_CUR); //возврат текущей позиции в конце строки в ее начало и повторная запись этой же строки для увеличения по высоте
        }

        fseek(inptr, padding, SEEK_CUR);  // skip over padding, if any
        for (int k = 0; k < padding1; k++) // добавление выравнивания в выходной файл
            {
                fputc(0x00, outptr);
            }

Но... по факту ничего не увеличивается ((
Кроме того нашла ошибку в заголовках: при коэффициенте увеличения 1 (т.е. выходной файл такой же как и входной) значения заголовков должны быть неизменны, а у меня они разные. Значит ошибка и в рассчетах размеров.
Daniela Daniela вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Изображения BMP и JPEG OmegaBerkut C# (си шарп) 9 29.05.2017 14:52
Изменение размера изображения ramsesjol БД в Delphi 3 12.06.2013 14:36
изменение размера изображения voron.kz Общие вопросы Delphi 2 06.09.2010 08:15
Качественное изменение размера изображения... Dr. MefistO Мультимедиа в Delphi 5 15.07.2009 17:22
Изменение размера - Сжатие BMP в TImage Air Помощь студентам 2 02.03.2008 18:00


03:11.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru